diff options
Diffstat (limited to 'debian/heatmap.py')
-rw-r--r-- | debian/heatmap.py | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/debian/heatmap.py b/debian/heatmap.py new file mode 100644 index 0000000..c3ac935 --- /dev/null +++ b/debian/heatmap.py @@ -0,0 +1,134 @@ +#! /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) + + + + + + |