Graham Knapp

🎼Trouver un musicothérapeute🎼

written by Graham Knapp on 2021-07-20

Ma femme est non seulement une superbe musicienne mais aussi une musicothérapeute : elle soigne les gens, ou les aide à se soigner eux-mêmes, avec de la musique!

J'ai crée cette carte des musicothérapeutes français avec la méthode suivante:

J'utilise la fonction suivantes pour générer mes tags HTML pour les marqueurs:

def tagged(txt:str, tag:str):
    str = txt.strip()
    if str:
        return f"<{tag}>{txt}</{tag}>\n"
    else:
        return ""

Voici le script complet sous forme de Jupyter Notebook.

Here comes the sun

written by Graham Knapp on 2019-03-23

I spend too much of my life sitting alone in an office working on my conputer or looking at my smartphone. My regular dose of fresh air comes from my bike - I ride to work and back regularly - but I also enjoy getting out into the garden when I can. Trouble is, I dont really enjoy gardening! I do get a lot of satisfaction from pruning the trees and shrubs, especially if it involves some climbing and as a result we now have an enormous pile of branches, leaves and twigs in the bottom of the garden. I recently found a new activity which satisfies my creative side and starts to diminish the stack o' cuttings : building 'dead hedge' style walls and fences.

garden03

garden02

First I sharpen a set of stakes and drive them into the ground, then I weave branches beween the stakes and finally I stuff twigs and leaves between the branches. I always end up full of splinters with a big grin on my face.

garden04

Before and after

garden05

garden06

Any way the wind blows

written by Graham Knapp on 2019-03-20

Adding leading zeros with Python

Various ways to add leading zeros to a number, for instance a wind direction, using Python. Available as a Jupyter Notebook

Generate a list of wind directions

First some definitions. The wind direction is measured in degrees clockwise from north and represents the direction the wind is blowing from. For instance an easterly wind, ie wind blowing from the east has a direction of 90 degrees. Let's generate 16 wind directions from 0 (north) to 337.5 (north by northwest).

interval = 22.5
assert 360 % interval < 0.001

directions = [interval * x for x in range(0,int(360/interval))]
print(directions)
[0.0, 22.5, 45.0, 67.5, 90.0, 112.5, 135.0, 157.5, 180.0, 202.5, 225.0, 247.5, 270.0, 292.5, 315.0, 337.5]

String zfill method

No doubt the most pythonic way to add leading zeros to a bare string, the built-in str.zfill() method is designed to do just that.

for direction in directions:
    print(str(int(direction)).zfill(3), str(direction).zfill(5))
000 000.0
022 022.5
045 045.0
067 067.5
090 090.0
112 112.5
135 135.0
157 157.5
180 180.0
202 202.5
225 225.0
247 247.5
270 270.0
292 292.5
315 315.0
337 337.5

We can immediately see our first quirk: the integer representation truncates decimal values rather than rounding up (as I learned to do at school) or rounding towards the nearest even number (as the Python round() funtion would do).

String slicing

Very fast and arguably even more readable for people with a good understanding of basic python syntax but no desire to read the docs or explore the obscure corners of the language. Add the maximum possible number of leading zeros and then slice the desired number of digits.

for direction in directions:
    print(('00'+str(int(direction)))[-3:],
    ('00'+str(direction))[-5:])
000 000.0
022 022.5
045 045.0
067 067.5
090 090.0
112 112.5
135 135.0
157 157.5
180 180.0
202 202.5
225 225.0
247 247.5
270 270.0
292 292.5
315 315.0
337 337.5

String format : integers

As part of a longer string this allows the number to be inserted with leading zeros. Compatible with all current versions of Python.

for direction in directions:
    print('As integer: {:03d}  |  As float: {:05.1f}'.format(int(direction), direction))
As integer: 000  |  As float: 000.0
As integer: 022  |  As float: 022.5
As integer: 045  |  As float: 045.0
As integer: 067  |  As float: 067.5
As integer: 090  |  As float: 090.0
As integer: 112  |  As float: 112.5
As integer: 135  |  As float: 135.0
As integer: 157  |  As float: 157.5
As integer: 180  |  As float: 180.0
As integer: 202  |  As float: 202.5
As integer: 225  |  As float: 225.0
As integer: 247  |  As float: 247.5
As integer: 270  |  As float: 270.0
As integer: 292  |  As float: 292.5
As integer: 315  |  As float: 315.0
As integer: 337  |  As float: 337.5

F Strings

From Python 3.6 this is even terser.

for direction in directions:
    print(f'As integer: {int(direction):03d}  |  As float: {direction:05.1f}')
As integer: 000  |  As float: 000.0
As integer: 022  |  As float: 022.5
As integer: 045  |  As float: 045.0
As integer: 067  |  As float: 067.5
As integer: 090  |  As float: 090.0
As integer: 112  |  As float: 112.5
As integer: 135  |  As float: 135.0
As integer: 157  |  As float: 157.5
As integer: 180  |  As float: 180.0
As integer: 202  |  As float: 202.5
As integer: 225  |  As float: 225.0
As integer: 247  |  As float: 247.5
As integer: 270  |  As float: 270.0
As integer: 292  |  As float: 292.5
As integer: 315  |  As float: 315.0
As integer: 337  |  As float: 337.5

Class

By overloading the built-in __str__() method for the class we can create our own custom string representation of the value.

class WindRecord(int):
    def __init__(self, direction):
        self.direction = direction

    def __str__(self):
        return f'Wind direction: {self.direction:05.1f} degrees'


for direction in directions:
    d = WindRecord(direction)
    print(d)
Wind direction: 000.0 degrees
Wind direction: 022.5 degrees
Wind direction: 045.0 degrees
Wind direction: 067.5 degrees
Wind direction: 090.0 degrees
Wind direction: 112.5 degrees
Wind direction: 135.0 degrees
Wind direction: 157.5 degrees
Wind direction: 180.0 degrees
Wind direction: 202.5 degrees
Wind direction: 225.0 degrees
Wind direction: 247.5 degrees
Wind direction: 270.0 degrees
Wind direction: 292.5 degrees
Wind direction: 315.0 degrees
Wind direction: 337.5 degrees

Thanks to @clement for comments

Building a blog

written by Graham Knapp on 2019-03-18

I have had a few ideas for content to share recently and wanted a good way to do so. I wanted to find a good solution for blog publishing with a few criteria:

I saw that the static site generators Pelican and Lektor were available. That sounds like a good solution as it should be quick and have few moving parts which could break. Lektor looked simple, welcoming and modern enough so I downloaded and installed it. I listened to Talk Python episode 160 as I did so and that encouraged me that I was on a good path.

My initial experience has been great - I got going with no problem except that at the time of writing I have been waiting over a week for free to get around to setting up my personal web space so I can deploy the site. At least that has given me enough time to configure a basic blog and write my first 2 posts.