#!/usr/pkg/bin/python """optimized to plot graph of function that varies with time x scale always starts at zero, y varies positive and negative with screenheight / 2 as y axis""" Copyright = """ dydtplot - show graph of any time-varying function Copyright (C) 2004 John Comeau This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ errormessage = "Not all needed libraries found, upgrade or check path" try: import sys, os import Tkinter from types import * except exception: try: sys.stderr.write("%s\n" % errormessage) except: print errormessage raise exception # get name this program was called as, minus .py extension if any self = sys.argv[0].split(os.sep)[-1].split('.')[0] # now get name we gave it when we wrote it originalself = Copyright.split()[0] # routines that should be in every program # (yes, you could import them, but that causes problems too, don't go there) def dbgprint(*whatever): sys.stderr.write("%s\n" % repr(whatever)) def setvalue(name, default, **options): if options.has_key(name): return options[name] options[name] = default return options[name] globals = {} # this can make it easier, put everything in a dictionary # other globals, specific to this program xmax = 128 # these can always be resized by user later ymax = 128 # globals derived from those above, or defined later in program tk = Tkinter.Tk(self) canvas = Tkinter.Canvas(tk, {'height': ymax, 'width': xmax}) wave = None def dydtplot(*args, **options): global self, xmax, ymax, tk, canvas, wave canvas.pack({'expand': True, 'fill': 'both'}) tk.bind('', redraw) if type(args[0]) is ListType: wave = args[0] elif type(args[0]) is TupleType: wave = args[0].tolist() else: wave = args wave = map(float, wave) # in case of command-line testing (strings) dbgprint('wave', wave) draw() tk.mainloop() def redraw(this): """set xmax and ymax after resize, then draw the graph anew do it this way, two functions, because otherwise draw() will think height and width are 1 pixel for some reason""" global canvas, xmax, ymax xmax, ymax = canvas.winfo_width(), canvas.winfo_height() draw() def draw(): """display the global array 'wave' as a graph scaling assumes that y varies between -1 and 1""" global canvas, wave, xmax, ymax if len(wave) < 1: return yscale = ymax / 2.0 ymidpoint = int(yscale) dbgprint(xmax, yscale, ymidpoint, wave) for i in range(0, xmax - 4): # tk canvas seems to be padded such that if you draw anything with x # coordinates of 0 or 1 it will not be seen... # since I don't know how to get this info programmatically I will # just kludge it by adding 2 to the x value try: canvas.create_line((i + 2, ymidpoint, i + 2, ymidpoint - (yscale * wave[i]))) except: pass if __name__ == '__main__': # if this program was imported by another, the above test will fail, # and this following code won't be used... # however, if this program was invoked directly, by whatever name, # the name used will be treated as a function call. # the simplest case would be that it was invoked as its original name, # in which case it will just call the main routine try: eval("%s(sys.argv[1:])" % self) except: sys.stderr.write("""Usage: %s [OPTIONS] INFILE[...] or for more detailed help, read source or: pydoc %s """ % (originalself, originalself)) raise