Skip to content

Morse

Notochord + Language Model + Morse Code.

Authors

Victor Shepardson Intelligent Instruments Lab 2024

MorseNode

Source code in src/notochord/app/morse.py
class MorseNode:
    def __init__(self, 
            char:str=None, 
            prob:float=0, 
            dit:'MorseNode'=None, 
            dah:'MorseNode'=None
        ):
        self.char = char
        self.prob = prob
        self.dit = dit
        self.dah = dah

    def subtree_prob(self):
        prob = self.prob
        for d in (self.dit, self.dah):
            if d is not None: 
                prob += d.subtree_prob()
        return prob

    def children_prob(self):
        return self.subtree_prob() - self.prob

    def is_leaf(self):
        return self.dit is None and self.dah is None

    def nodes(self):
        nodes = [self]
        for d in (self.dit, self.dah):
            if d is not None:
                nodes.extend(d.nodes())
        return nodes

    def chars(self):
        return ''.join(
            MorseNode.char for MorseNode in self.nodes() if MorseNode.char is not None)

    def children_chars(self):
        chars = ''
        for d in (self.dit, self.dah):
            if d is not None:
                chars += d.chars()
        return chars

    def traverse(self, *seq):
        if not len(seq):
            return self
        b, *seq = seq
        d = self.dit if b else self.dah
        # print(b, seq, d)
        return MorseNode() if d is None else d.traverse(*seq)

    def __repr__(self):
        s = f'{self.char} {self.prob}'
        for d in (self.dit, self.dah):
            if d is not None: 
                s += f' {d.char}'
        return s

    def make_code(self, path=None):
        """return a mapping from characters to morse"""
        code = {}
        if path is None: path = tuple()
        if self.char is not None:
            code[self.char] = path
        for d,b in ((self.dit, True), (self.dah, False)):
            if d is not None:
                code.update(d.make_code(path+(b,)))
        return code

    @classmethod
    def make_tree(cls):
        return MorseNode(
            dit=MorseNode('e', 12.7,
                dit=MorseNode('i', 7.0,
                    dit=MorseNode('s', 6.3,
                        dit=MorseNode('h', 6.1,
                            dit=MorseNode('5'),
                            dah=MorseNode('4'),
                        ),
                        dah=MorseNode('v', 1.0,
                            # dit=MorseNode('ŝ'),
                            dah=MorseNode('3'),
                        ),
                    ),
                    dah=MorseNode('u', 2.8,
                        dit=MorseNode('f', 2.2,
                            dit=MorseNode('é'),
                            dah=MorseNode('4'),
                        ),
                        dah=MorseNode(#'ü',
                            dit=MorseNode('ð',
                                dit=MorseNode('?')
                            ),
                            dah=MorseNode('2'),
                        ),
                    ),
                ),
                dah=MorseNode('a', 8.2,
                    dit=MorseNode('r', 6.0,
                        dit=MorseNode('l', 4.0,
                            # dit=MorseNode(),
                            dah=MorseNode(#'è',
                                dit=MorseNode('"')
                            ),
                        ),
                        dah=MorseNode('æ',
                            dit=MorseNode('+',
                                dah=MorseNode('.')
                            )
                        ),
                    ),
                    dah=MorseNode('w', 2.4,
                        dit=MorseNode('p', 1.9,
                            dit=MorseNode('þ'),
                            dah=MorseNode(#'à',
                                dit=MorseNode('@'),
                            ),
                        ),
                        dah=MorseNode('j', 0.2,
                            # dit=MorseNode('ĵ'),
                            dah=MorseNode('1',
                                dit=MorseNode("'")
                            ),
                        ),
                    ),
                ),
            ),
            dah=MorseNode('t', 9.1,
                dit=MorseNode('n', 6.7,
                    dit=MorseNode('d', 4.3,
                        dit=MorseNode('b', 1.5,
                            dit=MorseNode('6',
                                dah=MorseNode('-')
                            ),
                            dah=MorseNode('='),
                        ),
                        dah=MorseNode('x', 0.2,
                            dit=MorseNode('/')
                        ),
                    ),
                    dah=MorseNode('k', 0.8,
                        dit=MorseNode('c', 2.8,
                            # dit=MorseNode('ç'),
                            dah=MorseNode(#empty MorseNode
                                dit=MorseNode(';'),
                                dah=MorseNode('!')
                            ),
                        ),
                        dah=MorseNode('y', 2.0,
                            dit=MorseNode('(',
                                dah=MorseNode(')')
                            )
                        ),
                    ),
                ),
                dah=MorseNode('m', 2.4,
                    dit=MorseNode('g', 2.0,
                        dit=MorseNode('z', 0.1,
                            dit=MorseNode('7'),
                            dah=MorseNode(
                                dah=MorseNode(',')
                            ),
                        ),
                        dah=MorseNode('q', 0.1),
                    ),
                    dah=MorseNode('o', 7.5,
                        dit=MorseNode('ö',
                            dit=MorseNode('8',
                                dit=MorseNode(':')
                            ),         
                        ),
                        dah=MorseNode(
                            dit=MorseNode('9'),
                            dah=MorseNode('0')
                        ),
                    ),
                ),
            )
        )

make_code(path=None)

return a mapping from characters to morse

Source code in src/notochord/app/morse.py
def make_code(self, path=None):
    """return a mapping from characters to morse"""
    code = {}
    if path is None: path = tuple()
    if self.char is not None:
        code[self.char] = path
    for d,b in ((self.dit, True), (self.dah, False)):
        if d is not None:
            code.update(d.make_code(path+(b,)))
    return code