78 lines
2.2 KiB
Python
78 lines
2.2 KiB
Python
import axi
|
|
import csv
|
|
import math
|
|
|
|
MIN_SIZE = 0.01
|
|
MAX_SIZE = 0.8
|
|
|
|
def circle(cx, cy, r, n):
|
|
points = []
|
|
for i in range(n + 1):
|
|
a = 2 * math.pi * i / n
|
|
x = cx + math.cos(a) * r
|
|
y = cy + math.sin(a) * r
|
|
points.append((x, y))
|
|
return points
|
|
|
|
def fill_circle(cx, cy, cr, n):
|
|
result = []
|
|
r = cr
|
|
while r > 0:
|
|
result.append(circle(cx, cy, r, n))
|
|
r -= 0.05
|
|
result[-1].append((cx, cy))
|
|
return result
|
|
|
|
def punchcard_from_csv(csv_path):
|
|
with open(csv_path, 'rb') as fp:
|
|
reader = csv.reader(fp)
|
|
csv_rows = list(reader)
|
|
row_labels = [x[0] for x in csv_rows[1:]]
|
|
col_labels = csv_rows[0][1:]
|
|
data = []
|
|
for csv_row in csv_rows[1:]:
|
|
row = []
|
|
for value in csv_row[1:]:
|
|
try:
|
|
value = float(value)
|
|
except ValueError:
|
|
value = None
|
|
row.append(value)
|
|
data.append(row)
|
|
lo = min(x for row in data for x in row if x)
|
|
hi = max(x for row in data for x in row if x)
|
|
min_area = math.pi * (MIN_SIZE / 2.0) ** 2
|
|
max_area = math.pi * (MAX_SIZE / 2.0) ** 2
|
|
paths = []
|
|
for r, row in enumerate(data):
|
|
for c, value in enumerate(row):
|
|
if not value:
|
|
continue
|
|
pct = 1.0 * (value - lo) / (hi - lo)
|
|
pct = pct ** 0.5
|
|
area = pct * (max_area - min_area) + min_area
|
|
radius = (area / math.pi) ** 0.5
|
|
paths.extend(fill_circle(c, r, radius, 90))
|
|
for r, label in enumerate(row_labels):
|
|
d = axi.Drawing(axi.text(label.upper(), axi.TIMESR))
|
|
d = d.scale(0.02, 0.02).move(-1, r, 0.5, 0.5)
|
|
paths.extend(d.paths)
|
|
for c, label in enumerate(col_labels):
|
|
d = axi.Drawing(axi.text(label.upper(), axi.TIMESR))
|
|
d = d.scale(0.02, 0.02).move(c, -1, 0.5, 0.5)
|
|
paths.extend(d.paths)
|
|
d = axi.Drawing(paths)
|
|
d = d.scale_to_fit(12, 8.5)
|
|
|
|
print 'joining paths'
|
|
d = d.join_paths(0.02)
|
|
print 'simplifying paths'
|
|
d = d.simplify_paths(0.001)
|
|
|
|
d.render().write_to_png('out.png')
|
|
axi.draw(d)
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
punchcard_from_csv(sys.argv[1])
|