# ---------------------------------------------------------------------------
# 2-Dimensional Image base class
#
# This class provides basic support for 2D images. Functions to clear the
# frame buffer, create images, and do other things are provided. User
# must provide the draw() and function.
#
# This class has a bunch of parameters for controlling the look of 2D plots.
#
# self.xmin = xmin (minimum x coordinate)
# self.ymin = ymin (minimum y coordinate)
# self.xmax = xmax (maximum x coordinate)
# self.ymax = ymax (maximum y coordinate)
#
# These parameters define where the following region is inside the view region.
# They are given in pixels. For example, self.frame_left = 50 means that
# the actual data will be plotted 50 pixels from the left boundary.
#
# self.frame_left
# self.frame_right
# self.frame_top
# self.frame_bottom
# self.frame_color
# self.frame_width
#
# These parameters define properties of text on the graph
# self.title
# self.title_color
# self.xaxis_label
# self.xaxis_label_color
# self.yaxis_label
# self.yaxis_label_color
#
# These parameters define properties of tick-marks on the graph
# self.xtick_spacing
# self.xtick_length
# self.ytick_spacing
# self.ytick_length
# self.xtick_user (User defined tick mark locations)
# self.ytick_user
#
# These properties define various things about the axis
#
# self.axis_mode (ORIGIN,FRAME)
# self.axis_color
# self.axis_origin (Where do tick marks start?)
# self.xaxis_scale (LINEAR,LOG)
# self.yaxis_scale
# self.xaxis_precision
# self.yaxis_precision
#
# Status variables indicating various other things
# self.draw_axis
# self.draw_frame
# self.draw_labels
# self.draw_ranges
#
# ... and more parameters can be added later
#
# Methods : The following operations can be performed on 2D plots
#
# self.plot(x,y,color) : Plot a point
# self.line(x1,y1,x2,y2,color) : Make a line
# self.box(x1,y1,x2,y2,color) : Make a box
# self.solidbox(x1,y1,x2,y2,color) : Make a solid box
# self.circle(x,y,radius,color) : Plot a circle
# self.solidcircle(x,y,radius,color) : Make a solid circle
# self.drawsymbol(symbol,x,y,color) : Draw a pix map
# self.zoom(s) : Zoom in on an image
# self.left(s) : Move left
# self.right(s) : Move right
# self.up(s) : Move up
# self.down(s) : Move down
# self.scalex(s) : scale X axis
# self.scaley(s) : scale Y axis
# self.region(xmin,ymin,xmax,ymax) : set the viewing region
#
# General purpose, used before plotting
# self.clear()
# self.setplotview()
# self.setrange() : Sets the plotting range
#
# ---------------------------------------------------------------------------
from image import *
import gifplot
ORIGIN = 1
FRAME = 2
SQUARE = gifplot.SQUARE
CROSS = gifplot.CROSS
TRIANGLE = gifplot.TRIANGLE
class Image2D(Plot2D,Image):
# Create a new 2D Image
def __init__(self,xmin,ymin,xmax,ymax):
init_framebuffer()
Plot2D.__init__(self,Image.Default_framebuffer,xmin,ymin,xmax,ymax)
Image.__init__(self)
self.bgcolor = BLACK
self.fgcolor = WHITE
# Default values for 2D plots follow. Note : changing these changes them
# for all 2D plots.
# default values for view frame (in pixels)
self.frame_left = 60
self.frame_right = 15
self.frame_top = 15
self.frame_bottom = 50
self.frame_color = self.fgcolor
self.frame_width = 1
# default values for text and labels
self.title = "Untitled " + str(self.imageno)
self.title_color = self.fgcolor
self.xaxis_label = ""
self.xaxis_label_color = self.fgcolor
self.yaxis_label = ""
self.yaxis_label_color = self.fgcolor
# default values for tickmarks
self.xtick_spacing = (xmax - xmin)/10.0
self.xtick_length = 3
self.ytick_spacing = (ymax - ymin)/10.0
self.ytick_length = 3
self.xtick_user = []
self.ytick_user = []
# default values for axis
self.axis_mode = ORIGIN
self.axis_color = self.fgcolor
self.axis_origin = (0,0)
self.xaxis_scale = LINEAR
self.yaxis_scale = LINEAR
self.xaxis_precision = 10
self.yaxis_precision = 7
# various status variables
self.draw_axis = 1
self.draw_frame = 1
self.draw_labels = 1
self.draw_ranges = 1
self.draw_ticks = 1
# These variables set the physical location of the 2D plotting frame
self.vxmin = 0
self.vymin = 0
self.vxmax = self.frame.width
self.vymax = self.frame.height
# Set plotting region
def setplotview(self):
x1 = self.vxmin + self.frame_left
x2 = self.vxmax - self.frame_right
y1 = self.vymin + self.frame_bottom
y2 = self.vymax - self.frame_top
self.setview(x1,y1,x2,y2)
# Draw the frame around the image
def drawframe(self):
if self.draw_frame == 1:
self.frame.setclip(self.vxmin,self.vymin,self.vxmax,self.vymax)
x1 = self.vxmin + self.frame_left
x2 = self.vxmax - self.frame_right
y1 = self.vymin + self.frame_bottom
y2 = self.vymax - self.frame_top
self.frame.box(x1,y1,x2,y2,self.frame_color)
# Draw the axis on the image
def drawaxis(self):
if self.draw_axis == 1:
self.setplotview()
if self.axis_mode == ORIGIN:
# Draw axis from origin
self.xaxis(self.axis_origin[0],self.axis_origin[1],\
self.xtick_spacing, self.xtick_length,self.fgcolor)
self.yaxis(self.axis_origin[0],self.axis_origin[1],\
self.ytick_spacing, self.ytick_length,self.fgcolor)
elif self.axis_mode == FRAME:
# Draw axis as part of bounding box
self.xaxis(self.axis_origin[0],self.ymin,\
self.xtick_spacing,self.xtick_length,self.fgcolor)
self.xaxis(self.axis_origin[0],self.ymax,\
self.xtick_spacing,self.xtick_length,self.fgcolor)
self.yaxis(self.xmin,self.axis_origin[1],\
self.ytick_spacing,self.ytick_length,self.fgcolor)
self.yaxis(self.xmax,self.axis_origin[1],\
self.ytick_spacing,self.ytick_length,self.fgcolor)
# Put annotation (ie. labels) on the graph
def drawtext(self):
vxmin = self.vxmin
vymin = self.vymin
vxmax = self.vxmax
vymax = self.vymax
self.frame.setclip(vxmin,vymin,vxmax,vymax)
sxmin = str(self.xmin)
symin = str(self.ymin)
sxmax = str(self.xmax)
symax = str(self.ymax)
sxmin = sxmin[0:self.xaxis_precision]
symin = symin[0:self.yaxis_precision]
sxmax = sxmax[0:self.xaxis_precision]
symax = symax[0:self.yaxis_precision]
# Put ranges on the plot
if self.draw_ranges == 1:
self.frame.drawstring(vxmin+self.frame_left,vymin+self.frame_bottom-12,\
self.fgcolor,self.bgcolor,sxmin,HORIZONTAL)
self.frame.drawstring(vxmax-8*len(sxmax)-self.frame_right,\
vymin+self.frame_bottom-12,self.fgcolor,\
self.bgcolor,sxmax,HORIZONTAL)
self.frame.drawstring(vxmin+self.frame_left-8*len(symin),\
vymin+self.frame_bottom,self.fgcolor,\
self.bgcolor,symin,HORIZONTAL)
self.frame.drawstring(vxmin+self.frame_left-8*len(symax),\
vymax-self.frame_top-10,self.fgcolor,\
self.bgcolor,symax,HORIZONTAL)
# Put title on the plot
xc = (vxmin + self.frame_left + vxmax - self.frame_right)/2
self.frame.drawstring(xc-4*len(self.title),vymax-self.frame_top+2,\
self.fgcolor,self.bgcolor,self.title,HORIZONTAL)
# Draw axis labels
if self.draw_labels == 1:
self.frame.drawstring(xc-4*len(self.xaxis_label),vymin+self.frame_bottom-12,\
self.fgcolor,self.bgcolor,self.xaxis_label,HORIZONTAL)
yc = (vymin + self.frame_bottom + vymax - self.frame_top)/2
self.frame.drawstring(vxmin+self.frame_left-9,yc - 4*len(self.yaxis_label),\
self.fgcolor,self.bgcolor,self.yaxis_label,VERTICAL)
# start a new plot. Clears the framebuffer, draws frame, text, titles, etc...
def newplot(self):
self.setview(self.vxmin,self.vymin,self.vxmax,self.vymax)
self.clear(self.bgcolor)
self.drawframe()
self.drawaxis()
self.drawtext()
self.setplotview()
self.start()
# Image manipulation methods. Do things like zoom, translate, etc....
# scalex(s). Scales the x-axis. s is given as a scaling factor
def scalex(self,s):
dx = self.xmax - self.xmin
xc = self.xmin + dx/2.0
dx = dx*s
self.xmin = xc - dx/2.0
self.xmax = xc + dx/2.0
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
# scaley(s). Scales the y-axis. s is given as a percent with s = 100 meaning no effect
def scaley(self,s):
dy = self.ymax - self.ymin
yc = self.ymin + dy/2.0
dy = dy*s
self.ymin = yc - dy/2.0
self.ymax = yc + dy/2.0
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
# Zooms a current image. s is given as a percent with s = 100 meaning no effect
def zoom(self,s):
s = 100.0/s
self.scalex(s)
self.scaley(s)
# Move image left. s is given in range 0,100. 100 moves a full screen left
def left(self,s):
dx = self.xmax -self.xmin
dx = dx*s/100.0
self.xmin = self.xmin + dx
self.xmax = self.xmax + dx
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
# Move image right. s is given in range 0,100. 100 moves a full screen right
def right(self,s):
dx = self.xmax -self.xmin
dx = dx*s/100.0
self.xmin = self.xmin - dx
self.xmax = self.xmax - dx
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
# Move image down. s is given in range 0,100. 100 moves a full screen down
def down(self,s):
dy = self.ymax -self.ymin
dy = dy*s/100.0
self.ymin = self.ymin + dy
self.ymax = self.ymax + dy
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
# Move image up. s is given in range 0,100. 100 moves a full screen up
def up(self,s):
dy = self.ymax -self.ymin
dy = dy*s/100.0
self.ymin = self.ymin - dy
self.ymax = self.ymax - dy
self.setrange(self.xmin,self.ymin,self.xmax,self.ymax)
def plotarray(self,data,xmin,xmax,color,symbol):
if len(data) == 0: return
dx = 1.0*(xmax- xmin)/len(data)
x1 = xmin
y1 = data[0]
i = 0
npoints = len(data)
# Plot the first point
if symbol != None:
self.drawpixmap(symbol, x1,y1,color,self.bgcolor)
i = i + 1
while i < npoints:
x2 = x1 + dx
y2 = data[i]
self.line(x1,y1,x2,y2,color)
if symbol != None:
self.drawpixmap(symbol,x2,y2,color,self.bgcolor)
x1 = x2
y1 = y2
i = i + 1
def plotbar(self,data,xmin,xmax,color):
if len(data) == 0: return
dx = 1.0*(xmax- xmin)/len(data)
x1 = xmin
i = 0
npoints = len(data)
while i < npoints:
self.solidbox(x1-0.5*dx,0,x1+0.5*dx,data[i],color)
x1 = x1 + dx
i = i + 1
def plotxy(self,xdata,ydata,color,symbol):
if len(xdata) == 0: return
if len(xdata) != len(ydata) : return
x1 = xdata[0]
y1 = ydata[0]
i = 0
npoints = len(xdata)
# Plot the first point
if symbol != None:
self.drawpixmap(symbol,x1,y1,color,self.bgcolor)
i = i + 1
while i < npoints:
x2 = xdata[i]
y2 = ydata[i]
self.line(x1,y1,x2,y2,color)
if symbol != None:
self.drawpixmap(symbol,x2,y2,color,self.bgcolor)
x1 = x2
y1 = y2
i = i + 1
syntax highlighted by Code2HTML, v. 0.9.1