#!/usr/bin/env python # -*- coding: utf-8 -*- import datetime import math import cairo from dbsettings import * cursor = db_conn.cursor() # name, test # Test gets dictionary d = {'min': float, 'max': float, 'avg': float} daytests = [ ('helle', lambda d: d['max'] >= 25.1), ('kovapakkas', lambda d: d['min'] <= -15.0), ('pakkas', lambda d: d['max'] < 0.0), ('suoja', lambda d: d['max'] <= 1.0 and d['max'] >= 0.0), ('yopakkas', lambda d: d['min'] < 0.0), ('lammin', lambda d: d['avg'] > 15.0), ('kylma', lambda d: d['avg'] < 10.0) ] # name, description, color daytypes = { 'helle': ("Hellepäivä", "s", (255, 69, 0)), 'pakkas': ("Pakkaspäivä", "w", (129, 145, 210)), 'kovapakkas': ("Kova pakkanen", "w", (240, 255, 255)), 'yopakkas': ("Yöpakkanen", "w", (147, 196, 171)), 'suoja': ("Suojakeli", "w", (0, 255, 255)), 'lammin': ("Lämmin päivä", "s", (255, 165, 0)), 'kylma': ("Kylmä päivä", "s", (0, 255, 127)), 'perus': ("Peruspäivä", "s", (127, 255, 0)), 'kuukausi': (None, None, (0, 0, 0)), 'tyhja': ("Ei tietoa", "w", (127, 127, 127)) } typeorder = ['helle', 'lammin', 'perus', 'kylma', 'yopakkas', 'suoja', 'pakkas', 'kovapakkas', 'tyhja'] def makebase(year): # Construct base array of empty days days = [] day = datetime.date(year, 1, 1) delta = datetime.timedelta(1) while day.year == year: if day.day == 1: days.append('kuukausi') days.append('tyhja') day += delta return days def getdays(year): # Make base days array days = makebase(year) cursor.execute("SELECT time, u_min, u_max, u_avg FROM longtime WHERE " + "YEAR(time) = %d ORDER BY time ASC" % year) # Replace to days array where data is known for day, u_min, u_max, u_avg in cursor.fetchall(): # Index to days array index = day.month + (day - datetime.date(year, 1, 1)).days d = {'min': u_min, 'max': u_max, 'avg': u_avg} for name, test in daytests: if test(d): days[index] = name break else: days[index] = 'perus' return days def drawdays(ctx, x, y, rad, thick, days, strip): delta = - math.pi * 2. / len(days) angle = - math.pi / 2. - math.pi / 12. daycount = len(days) if strip == 'end': while days[-1] in ['tyhja', 'kuukausi']: days = days[:-1] count = 0 for day in days: if strip == 'start': if day in ['tyhja', 'kuukausi']: angle += delta rad += float(thick) / daycount continue else: strip = None r, g, b = daytypes[day][2] ctx.set_line_width(thick) ctx.set_source_rgba(r / 256., g / 256., b / 256., 1.0) ctx.arc(x, y, rad, angle + delta, angle) ctx.stroke() # Draw separator ctx.set_line_width(1) ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) ctx.arc(x, y, rad - thick / 2., angle + delta, angle) ctx.stroke() ctx.arc(x, y, rad + thick / 2., angle + delta, angle) ctx.stroke() count += 1 angle += delta rad += float(thick) / daycount return count def drawmonthlabels(ctx, x, y, rad, thick, minyear): '''Draw month labels''' months = ["tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu"] # Make current month the first curmonth = datetime.date.today().month - 2 months = months[curmonth::-1] + months[:curmonth:-1] orig = ctx.get_matrix() delta = math.pi / 6. angle = - delta * (curmonth + 1) rad = rad - thick / 12. * (curmonth + 1) ctx.translate(x, y) ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) ctx.set_font_size(0.6 * thick) # Get font sizing font_baseheight = ctx.text_extents('x')[3] for i, month in enumerate(months): xb, yb, w, h, xa, ya = ctx.text_extents(month) angle = angle % (math.pi * 2) temp = ctx.get_matrix() if angle >= math.pi / 2. and angle <= 3 * math.pi / 2.: ctx.rotate(angle + math.pi) ctx.move_to(- w / 2., rad + font_baseheight) else: ctx.rotate(angle) ctx.move_to(- w / 2., -rad) ctx.show_text(month) if month == 'tammi': # Draw year labels yearrad = rad - thick for year in range(datetime.date.today().year - 1, minyear, -1): year = str(year) xb, yb, w, h, xa, ya = ctx.text_extents(year) ctx.move_to(- w / 2., -yearrad) ctx.show_text(year) yearrad -= thick ctx.stroke() ctx.set_matrix(temp) angle += delta rad -= thick / 12. ctx.set_matrix(orig) def drawyears(ctx, x, y, maxrad, thick, minyear): yearnow = datetime.date.today().year # Loop from last year to first for year in range(yearnow, minyear - 1, -1): if year == minyear: strip = 'start' elif year == yearnow: strip = 'end' else: strip = None drawdays(ctx, x, y, maxrad - thick / 2., thick, getdays(year), strip) maxrad -= thick def drawlegend(ctx, daytypes, maxwidth): ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) ctx.set_font_size(15.0) x = 0. y = 0. for desc, pos, (r,g,b) in daytypes: ctx.rectangle(x + 2.0, y + 2.0, 11.0, 11.0) ctx.set_source_rgba(r / 256., g / 256., b / 256., 1.0) ctx.fill() ctx.set_line_width(1.5) ctx.rectangle(x + 1., y + 1., 13., 13.) ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) ctx.stroke() xb, yb, w, h, xa, ya = ctx.text_extents(desc) ctx.move_to(x + 18., y + h) ctx.show_text(desc) ctx.stroke() x += 30. + xa if x >= maxwidth: x = 0. y += 20. if __name__ == '__main__': surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 600, 625) ctx = cairo.Context(surface) drawyears(ctx, 300, 312, 250, 30, 2004) drawmonthlabels(ctx, 300, 312, 250, 30, 2004) summertypes = [daytypes[t] for t in typeorder if daytypes[t][1] == 's'] orig = ctx.get_matrix() ctx.translate(20, 600) drawlegend(ctx, summertypes, 500) ctx.set_matrix(orig) wintertypes = [daytypes[t] for t in typeorder if daytypes[t][1] == 'w'] orig = ctx.get_matrix() ctx.translate(20, 10) drawlegend(ctx, wintertypes, 500) ctx.set_matrix(orig) surface.write_to_png("daypie.png")