1
from wxPython import wx
4
from numpy.core.umath import *
7
from plot_utility import *
8
from plot_objects import *
9
from scipy.misc.common import lena
13
bub.SetSize((400,400))
15
#if bub.GetSizeTuple()[0] ==400: bub.SetSize((200,200))
16
#else: bub.SetSize((400,400))
17
#bub.client.layout_all()
18
bub.client.draw_graph_area()
21
# -- Fix textobject.size() for non-90 degree rotations
22
# -- Auto attributes haven't been fully thought through
23
# -- Axis titles probably should be axis properties
24
# This might save some current layout problems.
25
# -- Little attention has been paid to round off errors.
26
# Occassionly you'll see the consequences in a miss
27
# placed grid line or slightly off markers, but overall
29
# -- Could use a more sophisticated property setting scheme,
30
# perhaps like graphite???? Anyway you can do bad things
31
# such as assign a string instead of a text_object to
32
# titles, etc. This is bad. Optional typing in future
33
# Python would remove the need for fancy property type
34
# checking system (I think). Hope it comes to pass...
35
# -- This should be split up into several modules. Probably
37
# -- Printing on windows does not print out line styles.
38
# Everything is printed as solid lines. argh!
39
# Update: This seems like an issue with calling dc.SetUserScale
40
# If this isn't called, the problem is fixed - but the graph is
41
# tiny!!! Should I work out the appropriate scaling in draw()
42
# or should the SetUserScale() method maintain line types?
43
# -- Print Preview scaling is not correct. Not sure why not,
44
# but it looks lit the dc size is different the printer dc size.
46
# -- Rotated text does not print with correct font type. Is this
47
# a wxPython(windows) problem or mine?
48
# -- Plot windows do not become top window when using gui_thread.
52
# -- MouseDown support for changing fonts
53
from plot_utility import *
57
#make this a box_object?
60
aspect_ratios = ['normal', 'equal']
62
class plot_canvas(wx.wxWindow,property_object):
64
'background_color': ['light grey',colors,"Window background color" \
66
'aspect_ratio': ['normal',aspect_ratios,"Set the axis aspect ratio"],
67
'hold': ['off',['on','off'],"Used externally for adding lines to plot"],
70
__type_hack__ = "plot_canvas"
72
#background color is not working...
73
def __init__(self, parent, id = -1, pos=wx.wxPyDefaultPosition,
74
size=wx.wxPyDefaultSize, **attr):
75
wx.wxWindow.__init__(self, parent, id, pos,size)
76
wx.EVT_PAINT(self,self.on_paint)
77
property_object.__init__(self, attr)
78
background = wx.wxNamedColour(self.background_color)
79
self.SetBackgroundColour(background)
80
##self.title = text_object('')
81
##self.x_title = text_object('')
82
##self.y_title = text_object('')
83
self.title = text_window(self,'')
84
self.x_title = text_window(self,'')
85
self.y_title = text_window(self,'')
86
self.all_titles = [self.title,self.x_title,self.y_title] #handy to have
87
##self.x_axis = axis_object(graph_location='above',rotate=0)
88
##self.y_axis = axis_object(graph_location='right',rotate=90)
89
self.x_axis = axis_window(self,graph_location='above',rotate=0)
90
self.y_axis = axis_window(self,graph_location='right',rotate=90)
92
self.image_list = graphic_list()
93
self.line_list = auto_line_list() # make this the data object.
94
self.legend = legend_object()
95
self.text_list = None # list of text objects to place on screen
96
self.overlays = None # list of objects to draw on top of graph
97
# (boxes, circles, etc.)
98
##self.y2_axis = axis_object(graph_location='left',rotate=90)
99
self.client_size = (0,0)
100
# zoom selection helpers
101
self._mouse_selection = 0
102
self._mouse_selection_start = wx.wxPoint(0,0)
103
self._mouse_selection_stop = wx.wxPoint(0,0)
105
wx.EVT_RIGHT_DOWN(self,self.on_right_down)
106
wx.EVT_LEFT_DOWN(self, self.on_mouse_event)
107
wx.EVT_LEFT_UP(self, self.on_mouse_event)
108
wx.EVT_MOTION(self, self.on_mouse_event)
109
wx.EVT_MOTION(self, self.on_mouse_event)
110
wx.EVT_SIZE(self, self.update)
114
def on_mouse_event(self, event):
116
# start zoom selection
117
self._mouse_selection_start = event.GetPosition()
118
self._mouse_selection_stop = event.GetPosition()
119
self._mouse_selection = 1
120
elif event.LeftUp() and self._mouse_selection:
122
self.zoom(event.GetPosition())
123
self._mouse_selection = 0
124
elif event.LeftIsDown() and self._mouse_selection:
125
# update zoom selection
126
self.rubberband(event.GetPosition())
132
# cannot call autoscale(), since validate_active() apparently
133
# leads to a race condition:(
134
self.x_axis.bounds = ['auto','auto']
135
self.y_axis.bounds = ['auto','auto']
136
self.x_axis.tick_interval = 'auto'
137
self.y_axis.tick_interval = 'auto'
140
def on_auto_zoom(self,event):
143
def on_paint(self, event):
144
self.draw(wx.wxPaintDC(self))
146
def on_right_down(self,event):
148
pos = event.GetX(),event.GetY()
149
dc = wx.wxClientDC(self)
150
for title in self.all_titles:
151
title.set_dc(dc) # this dc stuff is a pain...
152
if title.contains(pos):
153
title.format_popup(pos)
158
if self.x_axis.contains(pos,dc):
159
self.x_axis.format_popup(pos)
160
elif self.y_axis.contains(pos,dc):
161
self.y_axis.format_popup(pos)
163
self.format_popup(pos)
165
def format_popup(self,pos):
167
menu.Append(500, 'Auto Zoom', 'Auto Zoom')
168
wx.EVT_MENU(self, 500, self.on_auto_zoom)
170
self.PopupMenuXY(menu,pos[0],pos[1])
173
def rubberband(self, new):
174
"""Delete previous selection band and paint new one."""
175
if self._mouse_selection:
176
dc = wx.wxClientDC(self)
177
dc.SetLogicalFunction(wx.wxXOR)
178
dc.SetPen(wx.wxGREY_PEN)
179
dc.SetBrush(wx.wxTRANSPARENT_BRUSH)
180
diff = self._mouse_selection_stop - self._mouse_selection_start
181
dc.DrawRectangle(self._mouse_selection_start.x,
182
self._mouse_selection_start.y, diff.x, diff.y)
183
self._mouse_selection_stop = new
184
diff = self._mouse_selection_stop - self._mouse_selection_start
185
dc.DrawRectangle(self._mouse_selection_start.x,
186
self._mouse_selection_start.y, diff.x, diff.y)
188
def save(self,path,image_type):
189
w,h = self.GetSizeTuple()
190
bitmap = wx.wxEmptyBitmap(w,h)
192
dc.SelectObject(bitmap)
194
# The background isn't drawn right without this cluge.
195
#fill_color = get_color(self.background_color)
196
fill_color = get_color('white')
197
dc.SetPen(wx.wxPen(fill_color))
198
dc.SetBrush(wx.wxBrush(fill_color)) #how to handle transparency???
199
dc.DrawRectangle(0,0,w,h)
200
dc.SetPen(wx.wxNullPen)
201
dc.SetBrush(wx.wxNullBrush)
204
image = wx.wxImageFromBitmap(bitmap)
205
wx.wxInitAllImageHandlers()
206
image.SaveFile(path,image_type_map[image_type])
208
def layout_all(self,dc=None):
209
#settingbackgroundcolors
210
#background = wx.wxNamedColour(self.background_color)
211
#if self.GetBackgroundColour() != background:
212
# self.SetBackgroundColour(background)
215
if not dc: dc = wx.wxClientDC(self)
216
self.client_size = array(self.GetClientSizeTuple())
217
# set the device context for all titles so they can
218
# calculate their size
219
for text_obj in self.all_titles:
222
graph_area = box_object((0,0),self.client_size)
223
graph_area.inflate(.95) # shrink box slightly
225
# shrink graph area to make room for titles
226
graph_area = self.layout_border_text(graph_area)
227
# layout axis and graph data
228
graph_area = self.layout_graph(graph_area,dc)
229
# center titles around graph area.
230
self.finalize_border_text(graph_area,dc)
231
self.graph_box = graph_area
232
# clear the dc for all titles
234
for text_obj in self.all_titles:
238
#self.legend.layout(self.line_list,graph_area,dc)
240
def layout_border_text(self,graph_area):
241
# Shrink graph area to make room for titles.
242
# Also, specify where the text is to live
243
# in realation to the graph. This only
244
# specifies one axis. The other can only
245
# be specified after the final graph area
248
graph_area.trim_top(self.title.height()+margin)
249
graph_area.trim_bottom(self.x_title.height()+margin)
250
self.y_title.rotate = 90 # make sure it is rotated
251
graph_area.trim_left(self.y_title.width()+margin)
252
#this is just to make so extra room for axis labels
254
graph_area.trim_right(12)
257
def layout_data(self):
258
# get scale and offset
259
axis_range = array((self.x_axis.range(),self.y_axis.range()),Float)
260
# negative y to account for positve down in window coordinates
261
scale = self.graph_box.size() / axis_range * array((1.,-1.))
262
offset = self.graph_to_window(array((0.,0.)))
263
self.image_list.scale_and_shift(scale,offset)
264
self.line_list.scale_and_shift(scale,offset)
269
def layout_graph(self,graph_area,dc):
271
#data_x_bounds,data_y_bounds = [0,6.28], [-1.1,1000]
272
#jeez this is unwieldy code...
273
smalls = []; bigs =[]
274
if len(self.line_list):
275
p1,p2 = self.line_list.bounding_box()
276
smalls.append(p1);bigs.append(p2)
277
if len(self.image_list):
278
p1,p2 = self.image_list.bounding_box()
279
smalls.append(p1);bigs.append(p2)
281
min_point = minimum.reduce(smalls)
282
max_point = maximum.reduce(bigs)
284
min_point = array((-1.,-1.),)
285
max_point = array((1.,1.))
286
data_x_bounds = array((min_point[0],max_point[0]))
287
data_y_bounds = array((min_point[1],max_point[1]))
288
self.x_axis.calculate_ticks(data_x_bounds)
289
height = self.x_axis.max_label_height(dc)
290
graph_area.trim_bottom(height)
291
self.y_axis.calculate_ticks(data_y_bounds)
292
width = self.y_axis.max_label_width(dc)
293
graph_area.trim_left(width)
294
if self.aspect_ratio == 'equal':
295
x_scale = float(graph_area.width()) / self.x_axis.range()
296
y_scale = float(graph_area.height()) / self.y_axis.range()
297
#print 'scales:', x_scale,y_scale,self.x_axis.range(),self.y_axis.range()
298
if x_scale > y_scale:
299
new_width = y_scale * self.x_axis.range()
300
remove = .5 * (graph_area.width() - new_width)
301
graph_area.trim_left(remove)
302
graph_area.trim_right(remove)
304
new_height = x_scale * self.y_axis.range()
305
remove = .5 * (graph_area.height() - new_height)
306
graph_area.trim_top(remove)
307
graph_area.trim_bottom(remove)
308
#self.y2_axis = axis_object(graph_location='left',rotate=90)
309
#self.y2_axis.label_location = 'plus'
310
#self.y2_axis.calculate_ticks(y2bounds)
311
#width = self.y2_axis.max_label_width(dc)
312
#graph_area.trim_right(width)
313
self.x_axis.layout(graph_area,dc)
314
self.x_axis.move((graph_area.left(),graph_area.bottom()))
315
self.axes.append(self.x_axis)
316
self.y_axis.layout(graph_area,dc)
317
self.y_axis.move((graph_area.left(),graph_area.bottom()))
318
self.axes.append(self.y_axis)
319
#self.y2_axis.grid_color = 'wheat'
320
#self.y2_axis.layout(graph_area,dc)
321
#self.y2_axis.move((graph_area.right(),graph_area.bottom()))
322
#self.axes.append(self.y2_axis)
323
self.border = border_object()
324
self.border.layout(graph_area,self.x_axis,self.y_axis)
327
def finalize_border_text(self,graph_area,dc):
328
# Center the titles around the graph.
329
# -- Really need to make axis object box_objects.
330
# Use this to help determine more appropriate
331
# title location. Current works fine
332
# if axis labels are beside graph. Title
333
# will be to far away if they are in center of graph
336
self.title.center_on_x_of(graph_area)
337
self.title.above(graph_area,margin)
339
offset = self.x_axis.max_label_height(dc)
340
self.x_title.center_on_x_of(graph_area)
341
self.x_title.below(graph_area,margin + offset)
343
offset = self.y_axis.max_label_width(dc)
344
self.y_title.center_on_y_of(graph_area)
345
self.y_title.left_of(graph_area,margin+offset)
346
#if self.y2_title:self.y2_title.center_on_y_of(graph_area)
348
def graph_to_window(self,pts):
349
axis_range = array((self.x_axis.range(),self.y_axis.range()))
350
# negative y to account for positve down in window coordinates
351
scale = self.graph_box.size() / axis_range * array((1.,-1.))
352
graph_min = array((self.x_axis.ticks[0],self.y_axis.ticks[0]))
353
zero_offset = (array((0.,0))- graph_min) * scale
354
graph_offset = array((self.graph_box.left(),self.graph_box.bottom()))
355
return pts * scale + zero_offset + graph_offset
357
def reset_size(self, dc = None):
358
new_size = self.GetClientSizeTuple()
359
if new_size != self.client_size:
361
self.client_size = new_size
363
def draw_graph_area(self,dc=None):
364
if not dc: dc = wx.wxClientDC(self)
365
self.layout_data() # just to check how real time plot would go...
369
# SHOULD SET PEN HERE TO FILL BACKGROUND WITH CORRECT COLOR
370
fill_color = get_color('white')
371
dc.SetPen(wx.wxPen(fill_color))
372
dc.SetBrush(wx.wxBrush(fill_color))
373
# NEEDED FOR REAL-TIME PLOTTING
374
dc.DrawRectangle(gb.left(),gb.top(),
375
gb.width()+1,gb.height()+1)
376
#needed to make sure images stay within bounds
377
##dc.SetClippingRegion(gb.left()-1,gb.top()-1,
378
## gb.width()+2,gb.height()+2) # mod by GAP 26092003
379
dc.SetClippingRegion(int(gb.left()-1),int(gb.top()-1),
380
int(gb.width()+2),int(gb.height()+2))
382
self.image_list.draw(dc)
383
dc.DestroyClippingRegion()
384
# draw axes lines and tick marks
386
for axis in self.axes:
388
#for axis in self.axes:
389
# axis.draw_grid_lines(dc)
390
#for axis in self.axes:
391
# axis.draw_ticks(dc)
393
#print 'lines:', t2 - t1
395
t1 = time.clock(); self.border.draw(dc); t2 = time.clock()
396
#print 'border:', t2 - t1
397
# slightly larger clipping area so that marks
398
# aren't clipped on edges
399
# should really clip markers and lines separately
401
self.line_list.clip_box(self.graph_box)
402
self.line_list.draw(dc)
405
# self.legend.draw(dc)
406
# draw overlay objects
408
def draw(self,dc=None):
409
#if not len(self.line_list) or len(self.image_list):
411
# resize if necessary
414
t1 = time.clock();self.reset_size(dc);t2 = time.clock()
415
#print 'resize:',t2 - t1
416
if not dc: dc = wx.wxClientDC(self)
417
# draw titles and axes labels
419
for text in self.all_titles:
421
for axis in self.axes:
424
#print 'text:',t2 - t1
425
self.draw_graph_area(dc)
427
def update(self,event=None):
428
self.client_size = (0,0) # forces the layout
431
def zoom(self, stop):
432
"""Delete selection band and zoom selection to full scale."""
434
dc = wx.wxClientDC(self)
435
dc.SetLogicalFunction(wx.wxXOR)
436
dc.SetPen(wx.wxGREY_PEN)
437
dc.SetBrush(wx.wxTRANSPARENT_BRUSH)
438
diff = self._mouse_selection_stop - self._mouse_selection_start
439
dc.DrawRectangle(self._mouse_selection_start.x,
440
self._mouse_selection_start.y, diff.x, diff.y)
441
self._mouse_selection_stop = stop
442
# get zoom-area coordinates
443
p1 = self._mouse_selection_start
444
p2 = self._mouse_selection_stop
446
if abs(p1.x-p2.x) < 3 and abs(p1.y-p2.y) < 3:
447
# zoom aborted (we assume)
449
left = float(min(p1.x, p2.x) - gb.left()) / gb.width()
450
right = float(max(p1.x, p2.x) - gb.left()) / gb.width()
451
top = float(min(p1.y, p2.y) - gb.top()) / gb.height()
452
bottom = float(max(p1.y, p2.y) - gb.top()) / gb.height()
453
# convert to real bounds
454
width = self.x_axis.ticks[-1] - self.x_axis.ticks[0]
455
height = self.y_axis.ticks[-1] - self.y_axis.ticks[0]
456
left = left * width + self.x_axis.ticks[0]
457
right = right * width + self.x_axis.ticks[0]
458
top = self.y_axis.ticks[-1] - top * height
459
bottom = self.y_axis.ticks[-1] - bottom * height
460
x_int = auto_interval([left, right])
461
y_int = auto_interval([bottom,top])
462
self.x_axis.bounds = auto_bounds([left, right],x_int)
463
self.y_axis.bounds = auto_bounds([bottom, top],y_int)
469
#------------------ tick utilities -----------------------
470
# flexible log function
471
#------------------ end tick utilities -----------------------
473
class graph_printout(wx.wxPrintout):
475
# Do not change method names in this class,
476
# we have to override wxPrintout methods here!
477
def __init__(self, graph):
478
wx.wxPrintout.__init__(self)
481
def HasPage(self, page):
487
def GetPageInfo(self):
490
def OnPrintPage(self, page):
492
# .5 inch margins are automatic
493
# on my HP. Probably not standard.
494
# Need smarter margin control.
495
w_inch,h_inch = self.GetPPIPrinter()
496
x_margin = .0* w_inch
497
y_margin = .0* h_inch
498
#-------------------------------------------
499
# One possible method of setting scaling factors...
501
#print dc.GetSizeTuple()
502
graph_box = box_object((0,0),self.graph.GetSizeTuple())
503
# Get the size of the DC in pixels
504
page_size = dc.GetSizeTuple()
505
#print 'dc size:',page_size
506
#page_size = self.GetPageSizePixels()
507
#print 'page size:',page_size
508
print_box = box_object((0,0),page_size)
509
print_box.trim_left(x_margin)
510
print_box.trim_right(x_margin)
511
print_box.trim_top(y_margin)
512
print_box.trim_bottom(y_margin)
513
# Calculate a suitable scaling factor
514
scales = array(print_box.size(), Float)/graph_box.size()
515
# Use x or y scaling factor, whichever fits on the DC
517
# resize the graph and center on the page
518
graph_box.inflate(scale)
519
graph_box.center_on(print_box)
520
# set the device scale and origin
521
dc.SetUserScale(scale, scale)
522
dc.SetDeviceOrigin(graph_box.left(),graph_box.top())
523
#-------------------------------------------
524
#print 'print dc size:', dc.GetSizeTuple()
529
class plot_window(plot_canvas):
530
"""Plot canvas window.
532
This is a complete q+d hack, but it does (somewhat) work.
534
def __init__(self, parent, id = -1, pos=wx.wxPyDefaultPosition,
535
size=wx.wxPyDefaultSize,**attr):
536
plot_canvas.__init__(self, parent, id, pos, size)
538
self.proxy_object_alive = wx.true
539
scipy.plt.figure(self)
541
scipy.plt.xaxis('fit')
542
# initial print setup
543
self.print_data = wx.wxPrintData()
544
self.print_data.SetPaperId(wx.wxPAPER_LETTER)
545
self.print_data.SetOrientation(wx.wxLANDSCAPE)
547
def add(self, x, y, **keywds):
548
"""Add data to plot."""
549
groups = scipy.plt.plot_groups([x, y, 'b-'])
552
lines.extend(scipy.plt.lines_from_group(group))
553
# check for hold here
554
for name in plot_objects.poly_marker._attributes.keys():
555
value = keywds.get(name)
556
if value is not None:
557
for k in range(len(lines)):
558
exec('lines[k].markers.%s = value' % name)
560
self.line_list.append(i)
564
"""Clear canvas, remove all plots."""
565
self.line_list = auto_line_list()
566
scipy.plt.autoscale()
568
def set_title(self, title):
569
"""Set plot title."""
570
self.title = text_window(self, title)
571
self.all_titles[0] = self.title
574
def set_xaxis_title(self, xtitle):
575
"""Set x-axis title"""
576
self.x_title = text_window(self, xtitle)
577
self.all_titles[1] = self.x_title
580
def set_yaxis_title(self, ytitle):
581
"""Set y-axis title"""
582
self.y_title = text_window(self, ytitle)
583
self.all_titles[2] = self.y_title
586
def printout(self, paper=None):
587
"""Print current plot."""
589
self.print_data.SetPaperId(paper)
590
pdd = wx.wxPrintDialogData()
591
pdd.SetPrintData(self.print_data)
592
printer = wx.wxPrinter(pdd)
593
out = graph_printout(self)
594
print_ok = printer.Print(self.parent, out)
596
self.print_data = printer.GetPrintDialogData().GetPrintData()
599
def print_preview(self):
600
"""Print-preview current plot."""
601
printout = graph_printout(self)
602
printout2 = graph_printout(self)
603
self.preview = wx.wxPrintPreview(printout, printout2, self.print_data)
604
if not self.preview.Ok():
605
wx.wxMessageDialog(self, "Print Preview failed.\n" \
606
"Check that default printer is configured\n", \
607
"Print error", wx.wxOK|wx.wxCENTRE).ShowModal()
609
frame = wx.wxPreviewFrame(self.preview, self.parent, "Preview")
611
frame.SetPosition(self.GetPosition())
612
frame.SetSize(self.GetSize())
616
class plot_frame(wx.wxFrame):
617
"""wxFrame for interactive use of plot_canvas."""
622
TITLE_TEXT,X_TEXT,Y_TEXT = 220,221,222
624
default_size = (500,400) # the default on Linux is always tiny???
626
def __init__(self, parent=wx.NULL, id = -1, title = '',
627
pos=wx.wxPyDefaultPosition,
628
size=default_size,visible=1):
629
wx.wxFrame.__init__(self, parent, id, title,pos,size)
630
# Now Create the menu bar and items
631
self.mainmenu = wx.wxMenuBar()
633
menu.Append(200, '&Save As...', 'Save plot to image file')
634
wx.EVT_MENU(self, 200, self.file_save_as)
635
menu.Append(203, '&Print...', 'Print the current plot')
636
wx.EVT_MENU(self, 203, self.file_print)
637
menu.Append(204, 'Print Pre&view', 'Preview the current plot')
638
wx.EVT_MENU(self, 204, self.file_preview)
639
menu.Append(205, 'Close', 'Close plot')
640
wx.EVT_MENU(self, 205, self.file_close)
641
self.mainmenu.Append(menu, '&File')
643
menu.Append(self.TITLE_TEXT, '&Graph Title', 'Title for plot')
644
wx.EVT_MENU(self,self.TITLE_TEXT,self.title)
645
menu.Append(self.X_TEXT, '&X Title', 'Title for X axis')
646
wx.EVT_MENU(self,self.X_TEXT,self.title)
647
menu.Append(self.Y_TEXT, '&Y Title', 'Title for Y axis')
648
wx.EVT_MENU(self,self.Y_TEXT,self.title)
649
self.mainmenu.Append(menu, '&Titles')
651
#menu.Append(300, '&Profile', 'Check the hot spots in the program')
652
#wx.EVT_MENU(self,300,self.OnProfile)
653
#self.mainmenu.Append(menu, '&Utility')
654
self.SetMenuBar(self.mainmenu)
655
# A status bar to tell people what's happening
656
self.CreateStatusBar(1)
657
self.print_data = wx.wxPrintData()
658
self.print_data.SetPaperId(wx.wxPAPER_LETTER)
659
self.client = plot_canvas(self)
660
if visible: self.Show(1)
664
def plot_draw(self, event):
665
#self.client.graphics = _InitObjects()
666
self.client.title.text = 'Bubba'
667
self.client.x_title.text = 'x title'
668
self.client.y_title.text = 'y title'
669
#self.client.y2_title.text = 'y2 title'
670
for i in _InitObjects():
671
self.client.line_list.append(i)
672
#self.client.image_list.append(lena_obj())
676
def profile(self, event):
678
#self.client.graphics = _InitObjects()
679
self.client.title.text = 'Bubba'
680
self.client.x_title.text = 'x title'
681
self.client.y_title.text = 'y title'
682
#self.client.y2_title.text = 'y2 title'
683
#for i in _InitObjects():
684
# self.client.line_list.append(i)
685
#self.client.image_list.append(lena_obj())
688
profile.run('from plt import loop;loop()','profile')
690
def file_print(self, event):
691
self.print_data.SetPaperId(wx.wxPAPER_LETTER)
692
pdd = wx.wxPrintDialogData()
693
pdd.SetPrintData(self.print_data)
694
printer = wx.wxPrinter(pdd)
695
printout = graph_printout(self.client)
696
print_ok = printer.Print(self, printout)
697
#Is Abort() not wrapped?
698
#if not printer.Abort() and not print_ok:
699
# wx.wxMessageBox("There was a problem printing.\n" \
700
# "Perhaps your current printer is not set correctly?",
701
# "Printing", wx.wxOK)
703
# self.print_data = printer.GetPrintDialogData().GetPrintData()
705
self.print_data = printer.GetPrintDialogData().GetPrintData()
708
def file_preview(self, event):
709
printout = graph_printout(self.client)
710
printout2 = graph_printout(self.client)
711
self.preview = wx.wxPrintPreview(printout, printout2, self.print_data)
712
if not self.preview.Ok():
713
#self.log.WriteText("Print Preview failed." \
714
# "Check that default printer is configured\n")
715
print "Print Preview failed." \
716
"Check that default printer is configured\n"
718
frame = wx.wxPreviewFrame(self.preview, self, "Preview")
720
frame.SetPosition(self.GetPosition())
721
frame.SetSize(self.GetSize())
724
def file_save_as(self, event):
726
wildcard = "PNG files (*.png)|*.png|" \
727
"BMP files (*.bmp)|*.bmp|" \
728
"JPEG files (*.jpg)|*.jpg|" \
729
"PCX files (*.pcx)|*.pcx|" \
730
"TIFF files (*.tif)|*.tif|" \
732
dlg = wx.wxFileDialog(self, "Save As", ".", "", wildcard, wx.wxSAVE)
733
if dlg.ShowModal() == wx.wxID_OK:
735
dummy, ftype = os.path.splitext(f)
738
if ftype in image_type_map.keys():
739
self.client.save(dlg.GetPath(),ftype)
741
msg = "Extension is currently used to determine file type." \
742
"'%s' is not a valid extension." \
743
"You may use one of the following extensions. %s" \
744
% (ftype,image_type_map.keys())
745
d = wx.wxMessageDialog(self,msg,style=wx.wxOK)
750
def file_close(self, event):
753
def format_font(self,event):
754
font_attr,color_attr = 'font','color'
755
if event.GetId() == self.TITLE_FONT:
756
texts = [self.client.title]
757
elif event.GetId() == self.AXIS_FONT:
758
texts = [self.client.x_title,self.client.y_title]
759
#texts = [self.client.y_title]
760
elif event.GetId() == self.LABEL_FONT:
761
texts = [self.client.x_axis,self.client.y_axis]
762
font_attr,color_attr = 'label_font','label_color'
763
data = wx.wxFontData()
764
current_color = get_color(getattr(texts[0],color_attr))
765
current_font = getattr(texts[0],font_attr)
766
data.SetColour(current_color)
767
data.SetInitialFont(current_font)
768
dlg = wx.wxFontDialog(self, data)
769
if dlg.ShowModal() == wx.wxID_OK:
770
data = dlg.GetFontData()
771
font = data.GetChosenFont()
772
color = data.GetColour()
773
rgb = color.Red(),color.Green(),color.Blue()
775
setattr(text,color_attr,rgb)
776
setattr(text,font_attr,font)
780
def title(self,event):
781
if event.GetId() == self.TITLE_TEXT:
782
title = self.client.title
783
prompt = 'Enter graph title'
784
elif event.GetId() == self.X_TEXT:
785
title = self.client.x_title
786
prompt = 'Enter x axis title'
787
elif event.GetId() == self.Y_TEXT:
788
title = self.client.y_title
789
prompt = 'Enter y axis title'
790
dlg = wx.wxTextEntryDialog(self, prompt,'', title.text)
791
if dlg.ShowModal() == wx.wxID_OK:
792
title.text = dlg.GetValue()
799
def __getattr__(self,key):
801
return self.__dict__[key]
803
return getattr(self.__dict__['client'],key)
805
def __setattr__(self,key,val):
807
#if plot_canvas._attributes.has_key(key):
808
# self.__dict__['client'].__dict__[key] = val
810
self.__dict__[key] = val
817
return image_object(lena(),colormap='grey')
820
# 100 points sin function, plotted as green circles
821
data1 = 2.*pi*arange(200)/200.
822
data1.shape = (100, 2)
823
data1[:,1] = sin(data1[:,0])
824
#markers1 = poly_marker(data1, color='green', marker='circle',size=1)
825
markers1 = line_object(data1)
827
# 50 points cos function, plotted as red line
828
data1 = 2.*pi*arange(100)/100.
830
data1[:,1] = cos(data1[:,0])
831
#lines = poly_line(data1, color='red')
832
lines = line_object(data1)
833
# A few more points...
834
#markers2 = poly_marker([(0., 0.), (pi/4., 1.), (pi/2, 0.),
835
# (3.*pi/4., -1)], color='blue',
836
# fillcolor='green', marker='cross')
837
markers2 = line_object([(0., 0.), (pi/4., 1.), (pi/2, 0.),(3.*pi/4., -1)])
839
return [markers1]#, lines, markers2]
843
a = axis_object(rotate = 0)
844
graph_area = box_object((10,10),(100,100))
846
a.calculate_ticks(bounds)
848
a.layout(graph_area,dummy_dc)
852
a.calculate_ticks(bounds)
853
a.layout(graph_area,dummy_dc)
860
if __name__ == '__main__':
862
class MyApp(wx.wxApp):
864
frame = plot_frame(wx.NULL, -1, "Graph",size=(400,400))
866
self.SetTopWindow(frame)
867
#frame.OnPlotDraw(None)