O motivo deste artigo é, de fato, uma ocasião triste. O mundialmente famoso rádio telescópio do Observatório de Arecibo em Porto Rico entrou em colapso e não pode ser restaurado. Por muitos anos foi o maior radiotelescópio do mundo com abertura total (diâmetro 304 m, faixa de frequência de até 10 GHz), com a ajuda do qual muitas descobertas foram feitas. Aqui na foto da Wikipedia, ainda está funcionando:

Fonte: en.wikipedia.org/wiki/Arecibo_Observatory
Mas o texto é na verdade sobre outro evento. Em 1974, uma mensagem para civilizações extraterrestres foi enviada ao espaço a partir deste telescópio. O que e como estava codificado nele, detalhes sob o corte.
Codificação
Para começar, é interessante entender como a mensagem foi transmitida. Como você sabe, o tamanho da mensagem era de apenas 1679 bits (aproximadamente 210 bytes) e era transmitida a uma frequência de 2,38 GHz com uma potência de 450 kW. A modulação de frequência a uma taxa de 10 bits / s foi usada para a transmissão. O número 1679 não foi escolhido por acaso - é o produto de dois números primos 23 e 73, portanto, só há uma maneira de expandir a imagem na forma de um retângulo.
Não consegui encontrar uma mensagem de rádio pronta no formato WAV, mas está em formato binário e, usando Python, é fácil gerar som sozinho. Quem quiser ouvir o que os alienígenas vão ouvir podem baixar e rodar o código abaixo, que vai gerar um arquivo WAV. O ruído também foi adicionado à mensagem para aumentar a credibilidade.
generate.py
import scipy.io.wavfile as wav
import scipy.signal as signal
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import os
message = """0000001010101000000000000101000001010000000100100010001000100
1011001010101010101010100100100000000000000000000000000000000
0000011000000000000000000011010000000000000000000110100000000
0000000000101010000000000000000001111100000000000000000000000
0000000001100001110001100001100010000000000000110010000110100
0110001100001101011111011111011111011111000000000000000000000
0000010000000000000000010000000000000000000000000000100000000
0000000001111110000000000000111110000000000000000000000011000
0110000111000110001000000010000000001000011010000110001110011
0101111101111101111101111100000000000000000000000000100000011
0000000001000000000001100000000000000010000011000000000011111
1000001100000011111000000000011000000000000010000000010000000
0100000100000011000000010000000110000110000001000000000011000
1000011000000000000000110011000000000000011000100001100000000
0110000110000001000000010000001000000001000001000000011000000
0010001000000001100000000100010000000001000000010000010000000
1000000010000000100000000000011000000000110000000011000000000
1000111010110000000000010000000100000000000000100000111110000
0000000010000101110100101101100000010011100100111111101110000
1110000011011100000000010100000111011001000000101000001111110
0100000010100000110000001000001101100000000000000000000000000
0000000001110000010000000000000011101010001010101010100111000
0000001010101000000000000000010100000000000000111110000000000
0000001111111110000000000001110000000111000000000110000000000
0110000000110100000000010110000011001100000001100110000100010
1000001010001000010001001000100100010000000010001010001000000
0000001000010000100000000000010000000001000000000000001001010
00000000001111001111101001111000"""
def fftnoise(f):
f = np.array(f, dtype='complex')
n_p = (len(f) - 1) // 2
phases = np.random.rand(n_p) * 2 * np.pi
phases = np.cos(phases) + 1j * np.sin(phases)
f[1:n_p+1] *= phases
f[-1:-1-n_p:-1] = np.conj(f[1:n_p+1])
return np.fft.ifft(f).real
def band_limited_noise(min_freq, max_freq, samples, samplerate=1):
freqs = np.abs(np.fft.fftfreq(samples, 1/samplerate))
f = np.zeros(samples)
idx = np.where(np.logical_and(freqs>=min_freq, freqs<=max_freq))[0]
f[idx] = 1
return fftnoise(f)
message = ''.join(i for i in message if i.isdigit())
print("Original message:")
print(message)
print()
# Generate message
fs = 11025
f1, f2 = 3000, 4000
t_sym = 0.1
data = np.zeros(int(fs * t_sym * len(message)))
for p in range(len(message)):
samples = np.linspace(0, t_sym, int(fs * t_sym), endpoint=False)
freq = f2 if message[p] == '1' else f1
data[int(fs * t_sym)*p:int(fs * t_sym)*(p + 1)] = 10000*(0.25*np.sin(2 * np.pi * freq * samples) + band_limited_noise(50, 5000, len(samples), fs))
wav.write('arecibo.wav', fs, np.int16(data))
print("WAV file saved")
Para maior comodidade de ouvir, aumentei a separação de frequência, na mensagem original era de apenas 10 Hz. Infelizmente, o habr não permite anexar arquivos de som; quem quiser pode gerar o arquivo por conta própria ou usar um link temporário .
A propósito, a mensagem foi enviada em 1974. Bem aqui:

Fonte: en.wikipedia.org/wiki/Messier_13 O
belo aglomerado de estrelas M13 na constelação de Hércules, bem conhecido por todos os amantes da astronomia e acessível para observação mesmo com pequenos telescópios. O aglomerado está localizado a 22 mil anos-luz de distância, então a mensagem vai durar muito tempo ...
Nós descobrimos a codificação, agora imagine que recebemos essa mensagem - vamos ver como ela pode ser decodificada.
Decodificação
O princípio da modulação de frequência em si é simples - frequências diferentes correspondem a zero e um. No espectro, é mais ou menos assim:

Existem diferentes maneiras de decodificar FSK, como o método mais simples, basta filtrar uma das frequências:
fs, data = wav.read('arecibo.wav')
def butter_bandpass(lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = signal.butter(order, [low, high], btype='band')
return b, a
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = signal.lfilter(b, a, data)
return y
f1, f2 = 3000, 4000
data_f2 = butter_bandpass_filter(data, f2 - 200, f2 + 200, fs, order=3)
plt.plot(data)
plt.plot(data_f2)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.title("Signal")
plt.show()
O resultado nos convém muito bem:

é claro, o sinal que passou 22 mil anos no espaço provavelmente ficará um pouco enfraquecido, mas para simplificar vamos supor que os alienígenas têm rádios bons
Você pode determinar facilmente a largura de um bit da imagem. Precisamos produzir os bits como uma imagem. Porque a mensagem foi enviada a uma civilização extraterrestre - aqueles que, por definição, não conhecem os sistemas de codificação "terrestres" - transmitir uma imagem raster foi a única decisão lógica. Na constelação de Hércules, provavelmente eles não sabem o que é ASCII, ou Deus nos livre, Unicode, mas é mais provável que seja possível exibir a imagem na tela em qualquer lugar da Galáxia. Pelo menos uma civilização capaz de receber um sinal digital provavelmente terá algum tipo de monitor para exibi-lo.
Não sabemos o tamanho da imagem, mas sabemos o tamanho de um bit e sabemos o tamanho da mensagem inteira. Você pode simplesmente classificar todas as opções possíveis, uma vez que não há tantas delas:
ss = 1102 # Width of one symbol in samples
for iw in range(12*ss, 25*ss, ss):
w, h = iw, 80
image = Image.new('RGB', (w, h))
px, py = 0, 0
for p in range(data_f2.shape[0]):
image.putpixel((px, py), (0, int(data_f2[p]//32), 0))
px += 1
if px >= w:
px = 0
py += 1
if py >= h:
break
image = image.resize((w//10, 100*h))
image.save("1/image-%d.png" % iw)
Para maior clareza, a imagem teve que ser esticada, porque 23 pixels de largura pelos padrões atuais não é, para dizer o mínimo, suficiente. O resultado final é bastante visível:

Corte Final:

Ao contrário das imagens da Wikipedia , a imagem original é monocromática, não há codificação de cores no sinal.
Muitas coisas são codificadas na imagem (convencionalmente, é claro), por exemplo, uma linha vertical de 2 pixels de largura acima da cabeça de uma pessoa é uma espiral de DNA (afinal, é óbvio, não é?). A decodificação dos pictogramas restantes pode ser visualizada no link acima na Wikipedia.
Conclusão
Como você pode ver, muitas informações podem ser codificadas em 210 bytes. Em geral, a tarefa de enviar um sinal para o espaço profundo está longe de ser simples, porque só podemos esperar os métodos de modulação mais simples. A mensagem chegará ao destinatário? Claro, provavelmente improvável. Não sei se a energia de tal "linha de comunicação" e a sensibilidade aproximada do receptor necessária para receber um sinal foram avaliadas ao enviá-lo. Sim, na verdade isso não é tão importante - se essas ações inspiram alguém a explorar o espaço, então não foi em vão. Bem, poderemos obter a resposta exata em 44 mil anos, e tentarei atualizar o texto à medida que novos dados forem disponibilizados;)