mirror of
https://github.com/rtlsdrblog/rtl-sdr-blog.git
synced 2024-11-10 12:47:40 +01:00
135 lines
3.7 KiB
Python
135 lines
3.7 KiB
Python
|
#! /usr/bin/env python2
|
||
|
|
||
|
from PIL import Image, ImageDraw, ImageFont
|
||
|
import sys, gzip, math, colorsys, datetime
|
||
|
from collections import defaultdict
|
||
|
from itertools import *
|
||
|
|
||
|
# todo: matplotlib powered --interactive
|
||
|
# arbitrary freq marker spacing
|
||
|
|
||
|
path = sys.argv[1]
|
||
|
output = sys.argv[2]
|
||
|
|
||
|
raw_data = lambda: open(path)
|
||
|
if path.endswith('.gz'):
|
||
|
raw_data = lambda: gzip.open(path, 'rb')
|
||
|
|
||
|
def frange(start, stop, step):
|
||
|
i = 0
|
||
|
while (i*step + start <= stop):
|
||
|
yield i*step + start
|
||
|
i += 1
|
||
|
|
||
|
print("loading")
|
||
|
|
||
|
freqs = set()
|
||
|
f_cache = set()
|
||
|
times = set()
|
||
|
labels = set()
|
||
|
min_z = 0
|
||
|
max_z = -100
|
||
|
start, stop = None, None
|
||
|
for line in raw_data():
|
||
|
line = [s.strip() for s in line.strip().split(',')]
|
||
|
line = [line[0], line[1]] + [float(s) for s in line[2:] if s]
|
||
|
|
||
|
low = line[2]
|
||
|
high = line[3]
|
||
|
step = line[4]
|
||
|
f_key = (int(low), int(high), step)
|
||
|
if f_key not in f_cache:
|
||
|
freqs.update(list(frange(int(low), int(high), step)))
|
||
|
freqs.add(high)
|
||
|
labels.add(low)
|
||
|
f_cache.add(f_key)
|
||
|
|
||
|
t = line[0] + ' ' + line[1]
|
||
|
times.add(t)
|
||
|
|
||
|
zs = line[6:]
|
||
|
min_z = min(min_z, min(z for z in zs if not math.isinf(z)))
|
||
|
max_z = max(max_z, max(zs))
|
||
|
|
||
|
if start is None:
|
||
|
start = datetime.datetime.strptime(line[0] + ' ' + line[1], '%Y-%m-%d %H:%M:%S')
|
||
|
stop = datetime.datetime.strptime(line[0] + ' ' + line[1], '%Y-%m-%d %H:%M:%S')
|
||
|
|
||
|
freqs = list(sorted(list(freqs)))
|
||
|
times = list(sorted(list(times)))
|
||
|
labels = list(sorted(list(labels)))
|
||
|
|
||
|
if len(labels) == 1:
|
||
|
delta = (max(freqs) - min(freqs)) / (len(freqs) / 500)
|
||
|
delta = round(delta / 10**int(math.log10(delta))) * 10**int(math.log10(delta))
|
||
|
delta = int(delta)
|
||
|
lower = int(math.ceil(min(freqs) / delta) * delta)
|
||
|
labels = list(range(lower, int(max(freqs)), delta))
|
||
|
|
||
|
print("x: %i, y: %i, z: (%f, %f)" % (len(freqs), len(times), min_z, max_z))
|
||
|
|
||
|
def rgb2(z):
|
||
|
g = (z - min_z) / (max_z - min_z)
|
||
|
return (int(g*255), int(g*255), 50)
|
||
|
|
||
|
def rgb3(z):
|
||
|
g = (z - min_z) / (max_z - min_z)
|
||
|
c = colorsys.hsv_to_rgb(0.65-(g-0.08), 1, 0.2+g)
|
||
|
return (int(c[0]*256),int(c[1]*256),int(c[2]*256))
|
||
|
|
||
|
print("drawing")
|
||
|
img = Image.new("RGB", (len(freqs), len(times)))
|
||
|
pix = img.load()
|
||
|
x_size = img.size[0]
|
||
|
for line in raw_data():
|
||
|
line = [s.strip() for s in line.strip().split(',')]
|
||
|
line = [line[0], line[1]] + [float(s) for s in line[2:] if s]
|
||
|
t = line[0] + ' ' + line[1]
|
||
|
if t not in times:
|
||
|
continue # happens with live files
|
||
|
y = times.index(t)
|
||
|
low = line[2]
|
||
|
high = line[3]
|
||
|
step = line[4]
|
||
|
x_start = freqs.index(low)
|
||
|
for i in range(len(line[6:])):
|
||
|
x = x_start + i
|
||
|
if x >= x_size:
|
||
|
continue
|
||
|
z = line[6+i]
|
||
|
# fast check for nan/-inf
|
||
|
if not z >= min_z:
|
||
|
z = min_z
|
||
|
pix[x,y] = rgb2(z)
|
||
|
|
||
|
print("labeling")
|
||
|
draw = ImageDraw.Draw(img)
|
||
|
font = ImageFont.load_default()
|
||
|
pixel_width = step
|
||
|
for label in labels:
|
||
|
y = 10
|
||
|
#x = freqs.index(label)
|
||
|
x = int((label-min(freqs)) / pixel_width)
|
||
|
s = '%.3fMHz' % (label/1000000.0)
|
||
|
draw.text((x, y), s, font=font, fill='white')
|
||
|
|
||
|
duration = stop - start
|
||
|
duration = duration.seconds
|
||
|
pixel_height = duration / len(times)
|
||
|
hours = int(duration / 3600)
|
||
|
minutes = int((duration - 3600*hours) / 60)
|
||
|
draw.text((2, img.size[1] - 45), 'Duration: %i:%02i' % (hours, minutes), font=font, fill='white')
|
||
|
draw.text((2, img.size[1] - 35), 'Range: %.2fMHz - %.2fMHz' % (min(freqs)/1e6, max(freqs)/1e6), font=font, fill='white')
|
||
|
draw.text((2, img.size[1] - 25), 'Pixel: %.2fHz x %is' % (pixel_width, int(round(pixel_height))), font=font, fill='white')
|
||
|
draw.text((2, img.size[1] - 15), 'Started: {0}'.format(start), font=font, fill='white')
|
||
|
# bin size
|
||
|
|
||
|
print("saving")
|
||
|
img.save(output)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|