Mercurial > ~darius > hgwebdir.cgi > beermon
view logplot.py @ 12:87d9d862ecc4
Avoid using pylab helper functions to reduce the magic level.
author | darius |
---|---|
date | Tue, 23 Oct 2007 01:01:48 +0000 |
parents | cb03cea09bda |
children | 9264a9cacfde |
line wrap: on
line source
#!/usr/bin/env python import re, datetime, time, sys, cPickle, numpy import matplotlib import matplotlib.figure import matplotlib.backends.backend_agg import matplotlib.dates daterestr = '([0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}): ' targtre = re.compile(daterestr + 'target temperature - (-?[0-9]+\.[0-9]+)') templre = re.compile(daterestr + '(-?[0-9]+\.[0-9]+)\s+(-?[0-9]+\.[0-9]+)\s+(-?[0-9]+\.[0-9]+)\s+([a-z-]+)\s+([a-z-]+)') datefmt = '%Y/%m/%d %H:%M:%S' tz = matplotlib.pytz.timezone('Australia/Adelaide') #start = time.mktime(time.strptime("2007/09/22 14:00:00", datefmt)) start = None #end = time.mktime(time.strptime("2007/09/30 14:00:00", datefmt)) end = None def parselog(f, start, end, times, fermTemps, fridgeTemps, ambTemps, targetTemps, states): targetTemp = 18.0 # Have to guess this.. for line in f: # Log line? m = templre.match(line) if (m == None): # No, might be a target temp line m = targtre.match(line) if (m != None): # Parse date portion t = datetime.datetime(*time.strptime(m.group(1), datefmt)[0:6]) if ((start != None and t < start) or (end != None and t > end)): continue targetTemp = float(m.group(2)) continue else: # Isn't anything, next! continue # Parse date portion t = datetime.datetime(*time.strptime(m.group(1), datefmt)[0:6]) if ((start != None and t < start) or (end != None and t > end)): continue fermTemp = float(m.group(2)) fridgeTemp = float(m.group(3)) ambTemp = float(m.group(4)) state = m.group(5) # Convert to Gregorian days (float) because that is what matplotlib uses times.append(matplotlib.dates._to_ordinalf(t)) fermTemps.append(fermTemp) fridgeTemps.append(fridgeTemp) ambTemps.append(ambTemp) targetTemps.append(targetTemp) if (state == 'heat'): states.append(10) elif (state == 'idle'): states.append(8) else: states.append(6) return(times, fermTemps, fridgeTemps, ambTemps, targetTemps, states) def doplot(times, fermTemps, fridgeTemps, ambTemps, targetTemps, states, outfile): assert(len(times) == len(fermTemps)) assert(len(times) == len(fridgeTemps)) assert(len(times) == len(ambTemps)) assert(len(times) == len(targetTemps)) assert(len(times) == len(states)) nrec = len(times) print "nrec = %d" % (nrec) newsz = [1000] then = time.time() times = rebin(numpy.array(times), newsz) fermTemps = rebin(numpy.array(fermTemps), newsz) fridgeTemps = rebin(numpy.array(fridgeTemps), newsz) ambTemps = rebin(numpy.array(ambTemps), newsz) targetTemps = rebin(numpy.array(targetTemps), newsz) states = rebin(numpy.array(states, 'f'), newsz) now = time.time() print "Rebinning took %.2f msec" % ((now - then) * 1000) title = "%s to %s (%d -> %d pts)" % (matplotlib.dates._from_ordinalf(times[0]).strftime(datefmt), matplotlib.dates._from_ordinalf(times[-1]).strftime(datefmt), nrec, len(times)) print title then = time.time() # A figure fig = matplotlib.figure.Figure(figsize = (9.0, 5.0)) # Create a plot, get some axes ax = fig.add_subplot(111) # Plot the data onto the axes p = ax.plot(times, fermTemps, times, fridgeTemps, times, ambTemps, times, targetTemps, times, states, '.') ax.set_title(title, weight = 'bold') ax.set_autoscale_on(True) # Add a formatter hoursFmt = matplotlib.dates.DateFormatter('%d %b\n%H:%M') ax.xaxis.set_major_formatter(hoursFmt) # Prettify it ax.grid(True) ax.set_xlabel('Date') ax.set_ylabel('Temperature(C)') # Set the legend legend = ax.legend((p[0], p[1], p[2], p[3], p[4]), ('Fermenter', 'Fridge', 'Ambient', 'Target', 'State'), 'best') # Render the figure canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig) canvas.print_figure(outfile, dpi = 96) now = time.time() print "Plotting took %.2f msec" % ((now - then) * 1000) def main(): logf = open(sys.argv[1], 'r') outfile = sys.argv[1][:-3] + 'png' try: # Try reading the pickled data p = cPickle.Unpickler(open("data.pck", "r")) then = time.time() times, fermTemps, fridgeTemps, ambTemps, targetTemps, states, offs = p.load() now = time.time() print "Unpickle took %.2f msec" % ((now - then) * 1000) # Seek up to the last place we parsed logf.seek(offs) del p print "Parsed pickle OK" except (IOError, cPickle.UnpicklingError, ValueError): # Either the pickle doesn't exist, or it's invalid, start anew print "Can't read pickle, starting from scratch" times = [] fermTemps = [] fridgeTemps = [] ambTemps = [] states = [] targetTemps = [] then = time.time() parselog(logf, start, end, times, fermTemps, fridgeTemps, ambTemps, targetTemps, states) now = time.time() print "Parselog took %.2f msec" % ((now - then) * 1000) # Write the pickle back out p = cPickle.Pickler(open("data.pck", "w"), protocol = -1) then = time.time() p.dump((times, fermTemps, fridgeTemps, ambTemps, targetTemps, states, logf.tell())) now = time.time() print "Pickle took %.2f msec" % ((now - then) * 1000) del p # Do the plot doplot(times, fermTemps, fridgeTemps, ambTemps, targetTemps, states, outfile) def rebin(a, newshape): '''Rebin an array to a new shape. ''' assert len(a.shape) == len(newshape) slices = [slice(0, old, float(old)/new) for old,new in zip(a.shape,newshape) ] coordinates = numpy.mgrid[slices] indices = coordinates.astype('i') #choose the biggest smaller integer index return a[tuple(indices)] if __name__ == "__main__": main()