axi/examples/nes.py

153 lines
3.8 KiB
Python
Raw Normal View History

2018-01-21 01:11:19 +00:00
from __future__ import division
import axi
import numpy as np
2018-01-22 15:59:50 +00:00
import os
2018-01-21 01:11:19 +00:00
import sys
2018-01-29 18:44:44 +00:00
NUMBER = '19'
TITLE = 'Fifteen Seconds of The Legend of Zelda'
2018-01-22 21:23:10 +00:00
LABEL = '#%s' % NUMBER
2018-01-22 15:11:43 +00:00
2018-01-29 18:44:44 +00:00
COLUMNS = 8
SECONDS = 15
FRAME_OFFSET = 600
MIN_CHANGES = 2
UNIQUE = False
SIMPLIFY = 5
def simplify_sparkline(values, n):
if not n:
return values
result = []
previous = None
for x, y in enumerate(values):
if result:
window = result[-n:]
lo = min(window)
hi = max(window)
if y >= lo and y <= hi:
result.append(result[-1])
previous = y
continue
if previous is not None:
result[-1] = previous
result.append(y)
previous = y
return result
2018-01-21 01:11:19 +00:00
2018-01-22 00:21:08 +00:00
def stack_drawings(ds, spacing=0):
result = axi.Drawing()
y = 0
for d in ds:
d = d.origin().translate(-d.width / 2, y)
result.add(d)
y += d.height + spacing
return result
2018-01-22 15:11:43 +00:00
def title():
d = axi.Drawing(axi.text(TITLE, axi.FUTURAM))
d = d.scale_to_fit_height(0.25)
2018-01-22 00:21:08 +00:00
d = d.move(6, 8.5, 0.5, 1)
2018-01-22 15:11:43 +00:00
d = d.join_paths(0.01)
return d
def label():
d = axi.Drawing(axi.text(LABEL, axi.FUTURAL))
d = d.scale_to_fit_height(0.125)
d = d.rotate(-90)
d = d.move(12, 8.5, 1, 1)
2018-01-22 00:21:08 +00:00
d = d.join_paths(0.01)
return d
2018-01-21 01:11:19 +00:00
def main():
2018-01-22 15:56:16 +00:00
# read file
2018-01-21 01:11:19 +00:00
with open(sys.argv[1], 'r') as fp:
data = fp.read()
2018-01-22 15:56:16 +00:00
# strip and split lines
2018-01-21 01:11:19 +00:00
lines = data.split('\n')
lines = [x.strip() for x in lines]
lines = [x.strip(',') for x in lines]
lines = filter(None, lines)
2018-01-22 15:56:16 +00:00
# read values and transpose
2018-01-21 01:11:19 +00:00
data = [map(int, line.split(',')) for line in lines]
data = np.transpose(data)
2018-01-22 15:56:16 +00:00
print '%d series in file' % len(data)
2018-01-21 01:11:19 +00:00
2018-01-22 15:56:16 +00:00
# trim to SECONDS worth of data
2018-01-21 01:11:19 +00:00
n = len(data[0])
2018-01-22 21:23:10 +00:00
m = int(SECONDS * 60 / 2)
mid = int(n // 2) + FRAME_OFFSET
a = max(0, mid - m)
b = min(n, mid + m)
2018-01-21 01:11:19 +00:00
data = [x[a:b] for x in data]
2018-01-22 15:56:16 +00:00
# remove addresses with too few values
2018-01-22 21:23:10 +00:00
data = [x for x in data if len(set(x)) > MIN_CHANGES]
2018-01-22 15:56:16 +00:00
print '%d series that changed' % len(data)
2018-01-21 01:11:19 +00:00
2018-01-29 18:44:44 +00:00
# remove duplicate series
if UNIQUE:
new_data = []
seen = set()
for x in data:
k = tuple(x)
if k in seen:
continue
seen.add(k)
new_data.append(x)
data = new_data
print '%d unique series' % len(data)
2018-01-22 15:56:16 +00:00
# trim so all rows are full
2018-01-21 01:11:19 +00:00
data = data[:int((len(data) // COLUMNS) * COLUMNS)]
2018-01-22 15:56:16 +00:00
print '%d series after trimming' % len(data)
print '%d data points each' % len(data[0])
2018-01-21 01:11:19 +00:00
2018-01-22 15:56:16 +00:00
# create sparklines in a grid pattern
2018-01-21 01:11:19 +00:00
paths = []
for i, row in enumerate(data):
2018-01-29 18:44:44 +00:00
row = simplify_sparkline(row, SIMPLIFY)
2018-01-21 01:11:19 +00:00
r = i // COLUMNS
c = i % COLUMNS
lo = min(row)
hi = max(row)
if lo == hi:
row = [0 for x in row]
else:
row = [(x - lo) / float(hi - lo) for x in row]
path = []
for j, value in enumerate(row):
x = (j / len(row) + c * 1.1)
y = 1-value + r * 1.5
path.append((x, y))
paths.append(path)
d = axi.Drawing(paths)
2018-01-22 00:21:08 +00:00
2018-01-22 15:56:16 +00:00
# add title and label and fit to page
d = d.scale(8.5 / d.width, (12 - 0.5) / d.height)
2018-01-22 15:11:43 +00:00
d = stack_drawings([d, title()], 0.25)
d = d.rotate(-90)
d = d.center(12, 8.5)
d.add(label())
print d.bounds
2018-01-22 00:21:08 +00:00
2018-01-22 15:56:16 +00:00
# save outputs
2018-01-22 21:23:10 +00:00
dirname = 'nes/%s' % NUMBER
2018-01-22 15:59:50 +00:00
try:
os.makedirs(dirname)
except Exception:
pass
d.dump(os.path.join(dirname, 'out.axi'))
2018-01-22 15:43:06 +00:00
rotated = d.rotate(90).center(8.5, 12)
2018-01-22 15:59:50 +00:00
rotated.dump_svg(os.path.join(dirname, 'out.svg'))
im = rotated.render(scale=109 * 1, line_width=0.3/25.4)
im.write_to_png(os.path.join(dirname, 'out.png'))
2018-01-21 01:11:19 +00:00
if __name__ == '__main__':
main()