#!/usr/bin/python
# from ~/Desktop/downloads/PythonWeb.org/web/image/graph.py:
# self.image=PIL.Image.new("RGB", size, bgColor)
# self.draw=PIL.ImageDraw.Draw(self.image)
# self.font = PIL.ImageFont.truetype(font,12)
# look at ~/Desktop/downloads/schoolbell-m7.1/src/schooltool/rest/infofacets.py
# just to see why it is called that, even though it only mucks with images
# what does sysinfo.displaypixels() return?
# portrun python
import sys
sys.path.append("/opt/local/lib/python2.4/site-packages/")
import PIL
import PIL.Image
import PIL.ImageDraw
import os
imgbase = os.path.expanduser("~/symbian/BACKUP/current/Images/")
# lifted from bcpathtrace.py:
def old_to_new(val):
if str(val)[-1] not in "NSEW":
return float(val)
newval = float(val[:-1])/100.0
if val[-1] in "SW":
newval = -newval
return newval
def scan_where():
fields = {}
for f in os.listdir(imgbase):
if not f.endswith(".where"): continue
imgpath = os.path.join(imgbase, f)
if os.path.exists(imgpath.replace(".where",".bad")): continue
bits = open(imgpath,"r").read()
if bits.startswith("("): words=eval(bits)
else: words=bits.split(" ")
lat, lon = map(old_to_new,words[:2])
when, discard = os.path.splitext(f)
fields[when] = (lat, lon)
return fields
class scaler:
def __init__(self, insamp):
self.inmin = insamp
self.inmax = insamp
self.outmin = None
self.outmax = None
def addval(self, v):
self.inmin = min(self.inmin, v)
self.inmax = max(self.inmax, v)
def scale(self, v):
inrange = self.inmax - self.inmin
outrange = self.outmax - self.outmin
return self.outmin + outrange *(v - self.inmin)/inrange
def center(self):
inrange = self.inmax - self.inmin
return self.inmin + inrange/2
# modified from original to take the PIL.Image
def make_scalers(points, c):
order = points.keys()
order.sort()
samplat, samplon = points[order[0]]
latscale = scaler(samplat)
lonscale = scaler(samplon)
for lat, lon in points.values():
latscale.addval(lat)
lonscale.addval(lon)
max_x,max_y = c.size
latscale.outmin = 0
latscale.outmax = max_y
lonscale.outmin = 0
lonscale.outmax = max_x
return latscale, lonscale, order
# unified aspect-preserving scalers are harder, because we *don't*
# just want 1:1, we need full generality:
# >>> math.cos(math.radians(57.417))
# 0.539 for Gothenburg,
# 0.740 for Boston (42.3)
# 0.511 for Stockholm (59.243)
def find_days(points):
days = {}
for k in points.keys():
d,t = k.split("t")
days[d] = days.get(d,0) + 1
daylist = days.keys()
daylist.sort()
# require 2 points for a day to count
return [day for day in daylist if days[day] > 2]
def points_of_day(points, day):
subpoints = {}
for k,v in points.items():
d,t = k.split("t")
if d == day: # or say d.startswith(day) to handle prefix hours?
subpoints[k] = v
return subpoints
def bothscale(point, latscale, lonscale):
lat, lon = point
return (latscale.scale(lat), lonscale.scale(lon))
def latlon_to_xy(point, latscale, lonscale):
neglat, lon = bothscale(point, latscale, lonscale)
return lon, latscale.outmax - neglat
blue = (0,0,255)
green = (0,255,0)
red = (255,0,0)
yellow = (255,255,0)
if __name__ == "__main__":
allpoints = scan_where()
days = find_days(allpoints)
# enumerate isn't in 2.2, but the mac side starts with 2.3...
for dayno, thisday in enumerate(days):
target_size = (192,204) # copy value from sysinfo.displaypixels()
image = PIL.Image.new("RGB", target_size, 0)
draw = PIL.ImageDraw.Draw(image)
# what follows is lifted from bcpathtrace.render()
max_x,max_y = target_size # or image.size...
points = points_of_day(allpoints, thisday)
latscale, lonscale, order = make_scalers(points, image)
label = u"Day %s/%s: c %.4s,%.4s" % (dayno+1, len(days),
latscale.center(),lonscale.center())
# ds.text( (0,max_y), label, yellow)
draw.setink(yellow)
textwidth, textheight = draw.textsize(label)
draw.text( (0,max_y - textheight), label )
lastpoint = points[order.pop(0)]
draw.setink(blue)
draw.point(latlon_to_xy(lastpoint, latscale, lonscale) ) # width=4)
# turns out that there's no equivalent to point(width) other than manually drawing a chord...
# and PIL includes no docs on the args to chord, though guesses work ok...
# lastd, lastt = order[0].split("t")
for k in order:
# sleep makes the rendering order visible, but we don't need that with a cursor
# e32.ao_sleep(0.1)
thispoint = points[k]
# plot from lastpoint to thispoint, scaled by size
draw.setink(green)
draw.line( (latlon_to_xy(lastpoint, latscale, lonscale), latlon_to_xy(thispoint, latscale, lonscale)) )
lastpoint = thispoint
image.save(open("/tmp/uda%s.jpg" % thisday, "w"), format="JPEG")