1. Morse - Codificador y Decodificador con Python



1. Morse Concepto

Referencia: Leon-Couch, 5–9 Señalización Pasabanda Modulada Binaria (OOK), Código Morse Wikipedia , Telégrafo Wikipedia, Recommendation ITU-R M.1677-1 (10/2009) International Morse code,

telegrafollave

Dato Histórico - 1844 Samuel F. B. Morse muestra la línea de telégrafo en Baltimore, MD y Washington, DC

El código Morse fue muy usado en telegrafía, transmisiones por radio marítimas y aéreas.

Conocido también como alfabeto Morse, cambia los caracteres alfanuméricos a códigos morse combinando puntos '.' y rayas '-'.

La separación entre códigos morse se realiza con un espacio ' ', mientras que en la separación entre palabras se usan 3 espacios ' '.

Ejemplo:
un mensaje: ESPOL impulsando la sociedad del conocimiento
. ... .--. --- .-..   .. -- .--. ..- .-.. ... .- -. -.. ---   .-.. .-   ... --- -.-. .. . -.. .- -..   -.. . .-..   -.-. --- -. --- -.-. .. -- .. . -. - --- 

Un tema que permite revisar varios conceptos de telecomunicaciones es el telégrafo y el código Morse.

Los bloques de desarrollo usados en ésta sección se presentan el el siguiente diagrama

morsebloques

Referencia: Telégrafo armónico - Gigantes de las máquinas. History Latinoamérica. 12 enero 2022


2. Codificador - Algoritmo con Python

La traducción entre un caracter del alfabeto a un código morse se puede facilitar con una función dedicada a ésta tarea.

Para buscar un equivalente de un caracter en una tabla de conversión a código, por facilidad de usar como índice un caracter se propone usar un diccionario de Python.

# Código Morse -  codificador
# propuesta: edelros@espol.edu.ec

def morsecodec(caracter):
    equivale={
        'A':'.-', 'B':'-...', 'C':'-.-.', 
        'CH':'----', 'D':'-..', 'E':'.', 
        'F':'..-.', 'G':'--.', 'H':'....', 
        'I':'..', 'J':'.---', 'K':'-.-',
        'L':'.-..', 'M':'--', 'N':'-.', 
        'Ñ':'--.--', 'O':'---', 'P':'.--.', 
        'Q':'--.-', 'R':'.-.', 'S':'...', 
        'T':'-', 'U':'..-', 'V':'...-',
        'W':'.--', 'X':'-..-', 'Y':'-.--', 
        'Z':'--..',
        '0':'-----', '1':'.----', '2':'..---', 
        '3':'...--', '4':'....-', '5':'.....', 
        '6':'-....', '7':'--...', '8':'---..', 
        '9':'----.', 
        '.':'.-.-.-', ',':'-.-.--', '?':'..--..', 
        '"':'.-..-.', '!':'--..--', ' ':' '}
    caracter=caracter.upper()
    codigo=equivale[caracter]
    return(codigo)

El programa para cambiar un mensaje a su versión morse se simplifica usando la función anterior.

# INGRESO
mensaje = input('un mensaje: ')
# mensaje= 'ESPOL impulsando la sociedad del conocimiento'

# PROCEDIMIENTO
n = len(mensaje)
traducido = ''
for caracter in mensaje:
    traducido = traducido + morsecodec(caracter) + ' '

# SALIDA
print(traducido)

La ejecución del programa y la función tiene el resultado mostrado en el ejemplo.

un mensaje: ESPOL impulsando la sociedad del conocimiento
. ... .--. --- .-..   .. -- .--. ..- .-.. ... .- -. -.. ---   .-.. .-   ... --- -.-. .. . -.. .- -..   -.. . .-..   -.-. --- -. --- -.-. .. -- .. . -. - --- 

3. Decodificador - algoritmo con Python

Para realizar el proceso inverso al codificador, se ingresa un código morse obtenido de un receptor a un decodificador. Ejemplo:

mensaje en morse:
. ... .--. --- .-.. .. -- .--. ..- .-.. ... .- -. -.. --- .-.. .- ... --- -.-. .. . -.. .- -.. -.. . .-.. -.-. --- -. --- -.-. .. -- .. . -. - ---
ESPOL IMPULSANDO LA SOCIEDAD DEL CONOCIMIENTO
telegraforeceptor
telégrafo receptor

Decodificar Morse requiere usar una tabla de equivalentes descrita en el estándar internacional (ITU), en el orden contrario al codificador.

En un mensaje morse, las palabras son separadas por tres espacios ' '; en una palabra, cada código se separa por un espacio ' '.

La traducción de un código morse a un caracter del alfabeto, se puede realizar con una función. De forma semejante al codificador, se usa la tabla de equivalentes como un diccionario.

# Código Morse -  DECOdificador
# propuesta: edelros@espol.edu.ec

def morsedeco(codigo): 
    equivale={ 
        '.-':'A', '-...':'B', '-.-.':'C', 
        '----':'CH', '-..':'D', '.':'E', 
        '..-.':'F', '--.':'G', '....':'H', 
        '..':'I', '.---':'J', '-.-':'K',
        '.-..':'L', '--':'M', '-.':'N', 
        '--.--':'Ñ', '---':'O', '.--.':'P', 
        '--.-':'Q', '.-.':'R', '...':'S', 
        '-':'T', '..-':'U', '...-':'V',
        '.--':'W', '-..-':'X', '-.--':'Y', 
        '--..':'Z',
        '-----':'0', '.----':'1', '..---':'2', 
        '...--':'3', '....-':'4', '.....':'5', 
        '-....':'6', '--...':'7', '---..':'8', 
        '----.':'9', 
        '.-.-.-':'.', '-.-.--':',', '..--..':'?', 
        '.-..-.':'"', '--..--':'!', '   ':' ', 
        ' ':' '}
    caracter=equivale[codigo]
    return(caracter)

El programa para cambiar un mensaje morse al alfabeto se simplifica usando la función anterior.

La ejecución del programa y la función tiene el resultado mostrado en el ejemplo.

# INGRESO
traducido = input('mensaje en morse: ')
# traducido='. ... .--. --- .-..   .. -- .--. ..- .-.. ... .- -. -.. ---   .-.. .-   ... --- -.-. .. . -.. .- -..   -.. . .-..   -.-. --- -. --- -.-. .. -- .. . -. - --- '
    
# PROCEDIMIENTO
mensaje  = ''
palabras = traducido.split('   ')
for unapalabra in palabras:
    letras = unapalabra.split(' ')
    for unaletra in letras:
        mensaje = mensaje+morsedeco(unaletra)
    mensaje = mensaje + ' '

# SALIDA
print('mensaje decodificado: ')
print(mensaje)

resultado:

mensaje en morse:
. ... .--. --- .-..   .. -- .--. ..- .-.. ... .- -. -.. ---   .-.. .-   ... --- -.-. .. . -.. .- -..   -.. . .-..   -.-. --- -. --- -.-. .. -- .. . -. - --- 
mensaje decodificado:
ESPOL IMPULSANDO LA SOCIEDAD DEL CONOCIMIENTO

 

Morse codificador texto

Para la transmisión de texto, por ejemplo la letra de una canción, se puede codificar a Morse usando inicialmente el procedo de los ejemplos anteriores.

Por ejemplo, una parte del archivo origen: elaguacate_Letra.txt

Tu eres mi amor 
mi dicha y mi tesoro 
mi sólo encanto 
y mi ilusión.

se convertiría en: elaguacate_morse.txt

- ..- . .-. . ... -- .. .- -- --- .-. 
-- .. -.. .. -.-. .... .- -.-- -- .. - . ... --- .-. --- 
-- .. ... --- .-.. --- . -. -.-. .- -. - --- 
-.-- -- .. .. .-.. ..- ... .. --- -. .-.-.-

que puede ser guardado en otro archivo  y procesado como un proceso estocástico.

Hay que considerar que en la codificación estándar Morse, no existen las letras con tildes ('áéíóú') que para la transmisión se debe quitar las tildes.


Funciones complementarias

Se usa como función básica como codificador Morse la descrita en el problema básico.

Cuando el tema a tratar es un texto más largo, se abordan más detalles del procesamiento del texto, como el quitar las tildes antes de codificar la letra. En el estándar de la codificación Morse (origen en inglés) no se usaban las tildes en las letras, para ésta operación se usa la función quitatildes().

Como complemento se añaden las funciones de codificación por línea, otra función para el conteo de símbolos,

La codificación en Python usada para el ejemplo se adjunta:

# Código Morse -  codificador de texto
# propuesta: edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt

def morsecodec(caracter):
    equivale={
        'A':'.-', 'B':'-...', 'C':'-.-.', 
        'CH':'----', 'D':'-..', 'E':'.', 
        'F':'..-.', 'G':'--.', 'H':'....', 
        'I':'..', 'J':'.---', 'K':'-.-',
        'L':'.-..', 'M':'--', 'N':'-.', 
        'Ñ':'--.--', 'O':'---', 'P':'.--.', 
        'Q':'--.-', 'R':'.-.', 'S':'...', 
        'T':'-', 'U':'..-', 'V':'...-',
        'W':'.--', 'X':'-..-', 'Y':'-.--', 
        'Z':'--..',
        '0':'-----', '1':'.----', '2':'..---', 
        '3':'...--', '4':'....-', '5':'.....', 
        '6':'-....', '7':'--...', '8':'---..', 
        '9':'----.', 
        '.':'.-.-.-', ',':'-.-.--', '?':'..--..', 
        '"':'.-..-.', '!':'--..--', ' ':' '}
    # Si caracter no está en equivale
    codigo = caracter
    # codifica a morse
    caracter = caracter.upper()
    if (caracter in equivale):
        codigo = equivale[caracter]    
    return(codigo)

def quitatildes(linea):
    sintilde = {'á':'a', 'é':'e', 'í':'i',
                'ó':'o', 'ú':'u'}
    nueva = ''
    for caracter in linea:
        if (caracter in sintilde):
            caracter = sintilde[caracter]
        nueva = nueva + caracter
    return(nueva)

def morselinea(linea):
    linea = linea.strip('\n')
    linea = linea.strip(' ')
    linea = quitatildes(linea)
    lineamorse = ''
    for caracter in linea:
        enmorse = morsecodec(caracter)
        lineamorse = lineamorse + enmorse + ' '
    return(lineamorse)

def cuentasimbolo(texto,simbolos):
    k = len(simbolos)
    veces = np.zeros(k,dtype=int)
    n = len(texto)
    for fila in range(0,n,1):
        unalinea = texto[fila]
        unalinea = unalinea.strip('\n')
        m = len(unalinea)
        for caracter in unalinea:
            donde = simbolos.find(caracter)
            if (donde>=0): #Si no encuentra es negativo
                veces[donde] = veces[donde]+1
    total = np.sum(veces)
    return(veces)

# PROGRAMA -----------------------------

# INGRESO
nombrearchivo = 'elaguacate_Letra.txt'

# PROCEDIMIENTO
# procesa el archivo
archivo  = open(nombrearchivo,'r')
unalinea = archivo.readline()
codificado = []
while not(unalinea==''):
    unalinea = unalinea.strip('\n')
    unalinea = unalinea.lower()
    lineamorse = morselinea(unalinea)
    codificado.append(lineamorse)
    unalinea = archivo.readline()
archivo.close()

# cuenta símbolos
simbolos = '.- '
conteo   = cuentasimbolo(codificado,simbolos)
total    = np.sum(conteo)
pmf      = conteo/total

# SALIDA
print('Texto en morse: ')
n = len(codificado)
etiquetas = ['punto','raya','espacio']
for i in range(0,n,1):
    print(codificado[i])

# PMF
print('PMF')
print(etiquetas)
print(pmf)

# GRAFICA
x = np.arange(0,len(conteo),1)
plt.stem(x,pmf)
plt.xticks(x,etiquetas)
plt.title('pmf')
plt.show()

# ARCHIVO
narchivo = 'morsetexto.txt'
archivo  = open(narchivo,'w')
for i in range(0,n,1):
    linea = codificado[i]+'\n'
    archivo.write(linea)
archivo.close()

Al final se presenta la pmf, sus valores y gráficas, junto al archivo morsetexto.txt como resultado.

PMF
['punto', 'raya', 'espacio']
[ 0.3588785   0.2953271   0.34579439]

Tarea: Procese los datos necesarios para generar la función de distribución acumulada (cdf), el valor esperado, varianza y desviación estándar.

Realice las observaciones y recomendaciones necesarias para mejorar el algoritmo que haya encontrado al usar su propio texto.



4. Morse cadena de Markov - Ejercicio

Para el texto en código Morse obtenido en el ejercicio "Morse codificador texto", se requiere realizar la correspondiente cadena de Markov.

Se tiene como archivo de entrada: elaguacate_morse.txt

- ..- . .-. . ... -- .. .- -- --- .-. 
-- .. -.. .. -.-. .... .- -.-- -- .. - . ... --- .-. --- 
-- .. ... --- .-.. --- . -. -.-. .- -. - --- 
-.-- -- .. .. .-.. ..- ... .. --- -. .-.-.-
  1. Determine el espacio de estados: S= {...}
  2. Realice el diagrama de transición de estados.
  3. Realice el conteo correspondiente de las transiciones entre estados
  4. Elabore la matriz de transición usando el resultado anterior
  5. Ubique en el diagrama los valores correspondientes a las transiciones
  6. Encuentre la matriz de transición en estado estable, o largo plazo.
  7. Compare los resultados de estado estable con la pmf obtenida en el ejercicio "Morse codificador texto"
  8. Presente las observaciones
  9. Escriba las recomendaciones.

4.1 Algoritmo en Python

Un ejemplo de instrucciones para realizar el conteo de las transiciones.

# Matriz de transicion de Código Morse
# Tarea: Realizar la matriz de transición
# para la cadena de Markov
import numpy as np

# INGRESO
narchivo = 'elaguacate_morse.txt'
archivo  = open(narchivo, 'r')

# PROCEDIMIENTO
s = '.- '
n = len(s)
conteo = np.zeros(shape=(n,n), dtype=int)
linea  = archivo.readline()
while not(linea ==''):
    linea = linea.strip('\n')
    m = len(linea)
    for i in range(0,m-1,1):
        simbolo = linea[i]
        simbolosigue = linea[i+1]
        f = s.find(simbolo)
        c = s.find(simbolosigue)
        conteo[f,c] = conteo[f,c] +1

    print(linea)
    linea = archivo.readline()

# SALIDA
print('matriz de conteo: ')
print('   .   -  espacio')
print(conteo)

Resultado del algoritmo

matriz de conteo: 
   .   -  espacio
[[123 116 145]
 [100  93 123]
 [156  92 102]]