| MATLAB Demo: alien_message | Open alien_message in editor. |
Overview
We are sending this message to potential intergalactic neighbors. If you received this message, how would you decode it? More information about this is available at http://www.newscientist.com/news/news.jsp?id=ns99991757 If you want to know exactly what the message codes for, look at http://www3.sympatico.ca/stephane_dumas/CETI/Lexique_1999.pdf
Here are the first few lines of the message. Noise has been added to this message to simulate lossy interstellar transmission.
str = urlread('http://www3.sympatico.ca/stephane_dumas/CETI/output_stream.txt');
disp(str(1:(43*20)))00000000000000000000000000000000000000000 00000000000000000000000000011000000000000 00000000000000000000000000000000000000000 00000000000000000000000000000000000000000 00000000000000000000000000000000100000000 00000000000010000000100010001000100010001 00001000000000000000000000000000001000100 01000100000010100100010001010000000110000 00000000000000000000000101000100010101001 00000000000000000000000000000000000100100 00000010101010100000010000000100000000011 00000000000000000000010110001000000010001 00000011000010000000000000000000000000000 00101100010001000100101000101100010100000 00110000000000000000000000000000000000000 00000001000000000100000000000000000000000 00000100000000000000000000000100000011110 00000001000000000000000000000010000000000 00000000000001000010110000000000000000000 00000000000100000000000000000000000100000
Now let's turn this string into a single long MATLAB vector. Get rid of returns, EOLs, and convert the ASCII code to numbers. Also chop off the initial zeros.
msg = double(str); msg = (msg(find(msg~= 10 & msg ~= 13))-48); onesIdx = find(msg); msg = msg(onesIdx(1)+1:end); msgLen = length(msg); size(msg)
ans =
1 272912
Let's make a guess that this long message is actually some kind of encoded picture. What statistics might we want to run to figure out where the frames are? Use fft to find the frame width
Y = fft(msg); n = length(Y); Y(1) = []; power = abs(Y(1:n/2)).^2; nyquist = 1/2; freq = (1:n/2)/(n/2)*nyquist; set(gcf,'Color','white') semilogx(freq,power) xlabel('cycles/bit')

There is a prominent peak at around 10e-2. Express this information in terms of period rather than frequency and zoom in on the peak in question.
period=1./freq; plot(period,power); ylabel('Power'); xlabel('Period (bits/cycle)'); axis([100 150 0 2e7]) index=find(power==max(power)); mainPeriod = period(index); line(period(index),power(index),'Color','red','Marker','.','MarkerSize',25); text(period(index)+2,power(index),['Period = ',num2str(period(index))]);

Shape the message into frames with 127 as the frame length. Summing down the columns indicates that we're on to something here. There appear to be registration lines running down both sides of the picture.
colWid = round(mainPeriod); msg = [msg zeros(1,colWid-rem(msgLen,colWid))]; msgRect = reshape(msg,colWid,length(msg)/colWid)'; plot(sum(msgRect))

Displaying the complete message
Here is the complete message laid out like a very long scroll.
imgH = image('CData',msgRect+1); colormap([1 1 1;0 0 0]); axis ij; axis equal set(gcf,'Double','on') set(gca,'Units','normalized','Position',[0 0 1 1]); axis off axdrag

That's the whole image, and it's clearly to small to see clearly like this. Let's zoom in on a few of the good bits. Help the aliens learn a little basic math...
set(gca,'XLim',[-12 150]) set(gca,'YLim',350 + [0 200])

Some local astronomy...
set(gca,'XLim',[-12 150]) set(gca,'YLim',1150 + [0 200])

chemistry, biology
set(gca,'XLim',[-12 150]) set(gca,'YLim',1550 + [0 200])

geography
set(gca,'XLim',[-12 150]) set(gca,'YLim',1820 + [0 200])

... and anatomy.
set(gca,'XLim',[-12 150]) set(gca,'YLim',1350 + [0 200])

I think I've seen these two before somewhere. Here's the plaque that's currently traveling with the Voyager spacecraft.
fname = tempname; urlwrite('http://www.aspsky.org/mercury/mercury/9902/photo5.gif',fname); [img, cmap] = imread(fname,'gif'); image(img) colormap(cmap) axis off

Here's another striking resemblance...
subplot(1,2,1) image(msgRect+1) colormap([1 1 1;0 0 0]); axis([7 121 468 638]) box on set(gca,'XTick',[],'YTick',[]) subplot(1,2,2) [img, cmap] = imread('space-invaders.gif'); cmap = cmap([2 1 3 4],:) image(img) colormap(cmap) axis([43 207 15 235]) set(gca,'XTick',[],'YTick',[]) box on
cmap =
1.0000 1.0000 1.0000
0 0 0
0.6471 0.1294 0.1294
0.1922 0 0.6118
