Das Motiv für diesen Artikel ist in der Tat ein trauriger Anlass. Das weltberühmte Radioteleskop des Arecibo-Observatoriums in Puerto Rico ist zusammengebrochen und irreparabel. Es war viele Jahre lang das größte Radioteleskop der Welt mit voller Apertur (Durchmesser 304 m, Frequenzbereich bis 10 GHz), mit dessen Hilfe viele Entdeckungen gemacht wurden. Hier auf dem Foto von Wikipedia funktioniert es immer noch:
Quelle: en.wikipedia.org/wiki/Arecibo_Observatory
Aber der Text handelt tatsächlich von einem anderen Ereignis. 1974 wurde von diesem Teleskop aus eine Nachricht an außerirdische Zivilisationen in den Weltraum geschickt. Was und wie wurde darin verschlüsselt, Details unter dem Schnitt.
Codierung
Zunächst ist es interessant zu verstehen, wie die Nachricht übermittelt wurde. Wie Sie wissen, betrug die Nachrichtengröße nur 1679 Bit (ungefähr 210 Byte) und wurde mit einer Frequenz von 2,38 GHz mit einer Leistung von 450 kW übertragen. Zur Übertragung wurde eine Frequenzmodulation mit einer Rate von 10 Bit / s verwendet. Die Zahl 1679 wurde nicht zufällig gewählt - sie ist das Produkt zweier Primzahlen 23 und 73, daher gibt es nur eine Möglichkeit, das Bild in Form eines Rechtecks zu erweitern.
Ich konnte keine fertige Funknachricht im WAV-Format finden, aber sie ist in binärer Form und mit Python ist es einfach, selbst Sound zu erzeugen. Diejenigen, die hören möchten, was die Außerirdischen hören, können den folgenden Code herunterladen und ausführen, wodurch eine WAV-Datei generiert wird. Zur Erhöhung der Glaubwürdigkeit wurde der Nachricht auch Rauschen hinzugefügt.
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")
Um das Hören zu vereinfachen, habe ich den Frequenzabstand erhöht, in der ursprünglichen Nachricht waren es nur 10 Hz. Leider erlaubt habr das Anhängen von Audiodateien nicht. Wer dies wünscht, kann die Datei entweder selbst generieren oder einen temporären Link verwenden .
Die Nachricht wurde übrigens 1974 verschickt. Genau dort:
Quelle: en.wikipedia.org/wiki/Messier_13 Der
wunderschöne Sternhaufen M13 im Sternbild Herkules, der allen Astronomieliebhabern bekannt ist und auch mit kleinen Teleskopen beobachtet werden kann. Der Cluster befindet sich 22.000 Lichtjahre entfernt, sodass die Nachricht noch lange anhält ...
Wir haben die Codierung herausgefunden und stellen uns nun vor, wir haben eine solche Nachricht erhalten - mal sehen, wie sie decodiert werden kann.
Dekodierung
Das Prinzip der Frequenzmodulation selbst ist einfach - unterschiedliche Frequenzen entsprechen Null und Eins. Im Spektrum sieht es ungefähr so aus:
Es gibt verschiedene Möglichkeiten, FSK zu dekodieren. Als einfachste Methode filtern Sie einfach eine der Frequenzen heraus:
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()
Das Ergebnis passt ganz gut zu uns:
Natürlich wird das Signal, das 22.000 Jahre im Weltraum vergangen ist, wahrscheinlich leicht geschwächt, aber der Einfachheit halber nehmen wir an, dass die Außerirdischen gute
Sie können die Breite eines Bits leicht aus dem Bild bestimmen. Wir müssen die Bits als Bild ausgeben. weil Die Nachricht wurde an eine außerirdische Zivilisation gesendet - diejenigen, die per Definition die "terrestrischen" Codierungssysteme nicht kennen - die Übertragung eines Rasterbildes war die einzig logische Entscheidung. In der Konstellation Hercules wissen sie höchstwahrscheinlich nicht, was ASCII ist, oder Gott bewahre Unicode, aber es ist höchstwahrscheinlich möglich, das Raster irgendwo in der Galaxie auf dem Bildschirm anzuzeigen. Zumindest eine Zivilisation, die in der Lage ist, ein digitales Signal zu empfangen, verfügt wahrscheinlich über eine Art Monitor zur Anzeige.
Wir kennen die Größe des Bildes nicht, aber wir kennen die Größe eines Bits und wir kennen die Größe der gesamten Nachricht. Sie können einfach alle möglichen Optionen aussortieren, da es nicht so viele davon gibt:
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)
Aus Gründen der Klarheit musste das Bild gestreckt werden, da 23 Pixel Breite nach heutigen Maßstäben, gelinde gesagt, nicht ausreichen. Das Endergebnis ist gut sichtbar:
Final Cut:
Im Gegensatz zu den Bildern auf Wikipedia ist das Originalbild natürlich monochrom, das Signal enthält keine Farbcodierung.
Viele Dinge sind im Bild kodiert (natürlich bedingt), zum Beispiel ist eine vertikale Linie, die 2 Pixel über dem Kopf einer Person liegt, eine DNA-Spirale (schließlich ist es offensichtlich, nicht wahr?). Die Dekodierung der restlichen Piktogramme kann unter dem obigen Link auf Wikipedia eingesehen werden.
Fazit
Wie Sie sehen können, können ziemlich viele Informationen in 210 Bytes codiert werden. Im Allgemeinen ist die Aufgabe, ein Signal in den Weltraum zu senden, alles andere als einfach, weil man kann nur auf die einfachsten Modulationsmethoden hoffen. Wird die Nachricht den Adressaten erreichen? Natürlich höchstwahrscheinlich unwahrscheinlich. Ich weiß nicht, ob die Energie einer solchen "Kommunikationsleitung" und die ungefähre Empfindlichkeit des Empfängers, die zum Empfangen eines Signals benötigt wird, beim Senden bewertet wurden. Ja, das ist eigentlich nicht so wichtig - wenn solche Aktionen jemanden dazu inspirieren, den Weltraum zu erkunden, war es nicht umsonst. Nun, wir werden in 44.000 Jahren die genaue Antwort erhalten können, und ich werde versuchen, den Text zu aktualisieren, sobald neue Daten verfügbar werden;)