2 # -*- coding: utf-8 -*-
4 # PlotFile2 -- A tool to make quick plots from data series.
5 # Version: 0.1-alpha (see VERSION file)
6 # This program is part of PyPlotSuite <http://pyplotsuite.sourceforge.net>.
8 # Copyright (C) 2007 Antonio Ingargiola <tritemio@gmail.com>
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
18 rootdir
= os
.path
.abspath(imp
.find_module('pyplotsuite')[1]) + '/'
19 sourcedir
= rootdir
+ 'plotfile/'
22 from matplotlib
.lines
import Line2D
23 from pyplotsuite
.common
.gtk_generic_windows
import \
24 GenericMainPlotWindow
, DialogWindowWithCancel
,\
25 GenericOpenFileDialog
, GenericSecondaryWindow
26 from pyplotsuite
.common
.filedata
import xyLabelFromFile
27 from pyplotsuite
.common
.version
import read_version
28 from numpy
import arange
, array
, min
30 # XML GUI Description file
31 gladefile
= sourcedir
+ 'plotfile2.glade'
33 # Minimum default axis value in log scale when the original value was <= 0
36 # How many centimeter is an inch
40 """An object describing data series with a shared X axis."""
41 def __init__(self
, x
=None, y1
=None, name
=None):
42 # self.x is the X axis shared for all y series
47 # self.y is a list of series of data
49 if y1
!= None: self
.add(y1
)
51 # self.yline is a list of plotted lines from the current DataSet
54 # Set the plot style, maker and linestyle attributes
55 # Marker and linestyle are separate variables so we can switch them off
56 # and then recover the style information when we turn them on
61 if len(yi
) != self
.len:
62 raise IndexError, 'Y data length (%d) must be == len(x) (%d)'\
68 """Simple struct to store any properties that has different values for X
76 class PlotFileApp(GenericMainPlotWindow
):
78 This class implements an interactive plot windows with various options.
80 def __init__(self
, x
=None, y
=None, title
='Title', debug
=False):
81 GenericMainPlotWindow
.__init
__(self
, 'PlotFileWindow', gladefile
)
88 self
.setup_gui_widgets()
90 # Data: self.data is a list of DataSet() instances
92 self
.data
.append( DataSet(x
, y
, 'Plot 1') )
96 # Try to load the file passed as parameter
97 if x
== None and y
== None:
99 self
.load(sys
.argv
[1])
104 self
.open_file_dialog
= OpenFileDialog(self
)
106 def set_defaults(self
):
112 self
.xlabel
= 'X Axis'
113 self
.ylabel
= 'Y Axis'
114 self
.xscale
= 'linear'
115 self
.yscale
= 'linear'
116 self
.showPoints
= True
117 self
.showLines
= True
121 self
.xmin
, self
.xmax
, self
.ymin
, self
.ymax
= None, None, None, None
122 self
.axes_limits
= AxesProperty()
123 self
.axes_limits
.x
= dict(linear
=None, log
=None)
124 self
.axes_limits
.y
= dict(linear
=None, log
=None)
126 def reset_scale_buttons(self
):
128 if self
.xscale
== 'log':
129 self
.xscaleCheckB
.set_active(True)
131 self
.xscaleCheckB
.set_active(False)
132 if self
.yscale
== 'log':
133 self
.yscaleCheckB
.set_active(True)
135 self
.yscaleCheckB
.set_active(False)
138 def setup_gui_widgets(self
):
139 # Create the text entry handler
140 self
.xminEntry
= self
.widgetTree
.get_widget('xmin_entry')
141 self
.xmaxEntry
= self
.widgetTree
.get_widget('xmax_entry')
142 self
.yminEntry
= self
.widgetTree
.get_widget('ymin_entry')
143 self
.ymaxEntry
= self
.widgetTree
.get_widget('ymax_entry')
145 # Initialize the check buttons to the correct value
146 self
.pointsCheckB
= self
.widgetTree
.get_widget('points_chk_butt')
147 self
.linesCheckB
= self
.widgetTree
.get_widget('lines_chk_butt')
148 self
.xscaleCheckB
= self
.widgetTree
.get_widget('xlog_chk_butt')
149 self
.yscaleCheckB
= self
.widgetTree
.get_widget('ylog_chk_butt')
150 self
.reset_scale_buttons()
152 self
.cooPickerCheckB
= self
.widgetTree
.get_widget('coordinatePicker')
153 self
.moreGridCheckB
= self
.widgetTree
.get_widget('moreGrid')
155 self
.window
.show_all()
156 if self
.debug
: print 'end of setup_gui_widgets()'
158 def is_ydata_positive(self
):
161 if (yi
<= 0).any(): return False
164 def plot_data(self
, n
=0):
165 """Plot the n-th data from the self.data list of DataSet()."""
167 if self
.debug
: print 'plot_data method'
170 d
.yline
= range(len(d
.y
))
171 for i
, yi
in enumerate(d
.y
):
172 d
.yline
[i
], = self
.axis
.plot(d
.x
, yi
, ls
=d
.linestyle
,
175 self
.axis
.set_title(self
.title
)
176 self
.axis
.set_xlabel(self
.xlabel
)
177 self
.axis
.set_ylabel(self
.ylabel
)
183 #self.update_axis_limits_entry()
185 def update_axis_limits_entry(self
):
187 xmin
, xmax
= self
.axis
.get_xlim()
188 self
.xminEntry
.set_text(str(xmin
))
189 self
.xmaxEntry
.set_text(str(xmax
))
191 ymin
, ymax
= self
.axis
.get_ylim()
192 self
.yminEntry
.set_text(str(ymin
))
193 self
.ymaxEntry
.set_text(str(ymax
))
197 if self
.debug
: print 'plot method'
199 if self
.yscale
== 'log' and not self
.is_ydata_positive():
200 self
.writeStatusBar('WARNING: Negative Y values in log scale.')
204 self
.axis
.set_yscale('linear')
205 self
.axis
.set_xscale('linear')
208 d
.yline
= range(len(d
.y
))
209 for i
, yi
in enumerate(d
.y
):
210 d
.yline
[i
], = self
.axis
.plot(d
.x
, yi
, ls
=d
.linestyle
,
213 self
.axis
.set_title(self
.title
)
214 self
.axis
.set_xlabel(self
.xlabel
)
215 self
.axis
.set_ylabel(self
.ylabel
)
216 self
.axis
.grid(self
.grid
)
218 print 'x', self
.xscale
, 'y', self
.yscale
219 self
.axis
.set_yscale(self
.yscale
)
220 self
.axis
.set_xscale(self
.xscale
)
222 if len(self
.data
) > 0:
224 if len(self
.data
[0].y
) > 0:
230 if self
.axes_limits
.x
[self
.xscale
] == None:
231 if self
.debug
: print 'autoscaling...'
232 self
.axis
.autoscale_view(scalex
=True, scaley
=False)
233 self
.xmin
, self
.xmax
= self
.axis
.get_xlim()
235 if self
.debug
: print 'using old axis limit', self
.axes_limits
.x
236 self
.xmin
, self
.xmax
= self
.axes_limits
.x
[self
.xscale
]
237 if self
.xscale
== 'log':
238 if self
.xmin
<= 0: self
.xmin
= LOGMIN
239 if self
.xmax
<= self
.xmin
: self
.xmax
= self
.xmin
+1
240 self
.axis
.set_xlim(xmin
=self
.xmin
, xmax
=self
.xmax
)
242 if self
.debug
: print 'xmin:', self
.xmin
, 'xmax:', self
.xmax
243 self
.xminEntry
.set_text(str(self
.xmin
))
244 self
.xmaxEntry
.set_text(str(self
.xmax
))
247 if self
.axes_limits
.y
[self
.yscale
] == None:
248 if self
.debug
: print 'autoscaling...'
249 self
.axis
.autoscale_view(scaley
=True, scalex
=False)
250 self
.ymin
, self
.ymax
= self
.axis
.get_ylim()
252 if self
.debug
: print 'using old axis limit'
253 self
.ymin
, self
.ymax
= self
.axes_limits
.y
[self
.yscale
]
254 if self
.yscale
== 'log':
255 if self
.ymin
<= 0: self
.ymin
= LOGMIN
256 if self
.ymax
<= self
.ymin
: self
.ymax
= self
.ymin
+1
257 self
.axis
.set_ylim(ymin
=self
.ymin
, ymax
=self
.ymax
)
259 if self
.debug
: print 'ymin:', self
.ymin
, 'ymax:', self
.ymax
260 self
.yminEntry
.set_text(str(self
.ymin
))
261 self
.ymaxEntry
.set_text(str(self
.ymax
))
263 def load(self
, filename
):
265 x
, y
, xlab
, ylab
= xyLabelFromFile(filename
)
267 self
.writeStatusBar("Can't open file '%s'" % filename
)
270 self
.writeStatusBar("File '%s': file format unknown." % filename
)
273 filename
= os
.path
.basename(filename
)
274 self
.data
.append(DataSet(x
,y
, filename
))
275 self
.title
= filename
276 if xlab
is not None: self
.xlabel
= xlab
277 if ylab
is not None: self
.ylabel
= ylab
278 self
.axes_limits
.x
= dict(linear
=None, log
=None)
279 self
.axes_limits
.y
= dict(linear
=None, log
=None)
280 self
.writeStatusBar("File '%s' loaded." % filename
)
286 self
.writeStatusBar('Warning: '+msg
)
289 # The following are GUI callback methods
291 def on_xscale_toggled(self
, widget
, *args
):
293 self
.axes_limits
.x
[self
.xscale
] = self
.axis
.get_xlim()
294 if self
.xscaleCheckB
.get_active(): self
.xscale
= 'log'
295 else: self
.xscale
= 'linear'
296 if self
.debug
: print "XScale:", self
.xscale
297 self
.axis
.set_xscale(self
.xscale
)
300 self
.writeStatusBar('X Axis Scale: %s.' % self
.xscale
)
303 def on_yscale_toggled(self
, widget
, *args
):
305 self
.axes_limits
.y
[self
.yscale
] = self
.axis
.get_ylim()
306 if self
.yscaleCheckB
.get_active(): self
.yscale
= 'log'
307 else: self
.yscale
= 'linear'
308 if self
.debug
: print "YScale:", self
.yscale
309 self
.axis
.set_yscale(self
.yscale
)
313 if self
.negative
and self
.yscale
== 'log':
314 self
.warn('Negative values not displayed in log-scale, lines '+\
315 'may appear discontinuos!')
317 self
.writeStatusBar('Y Axis Scale: %s.' % self
.yscale
)
320 def on_points_toggled(self
, widget
, *args
):
321 self
.showPoints
= not self
.showPoints
322 if self
.debug
: print "Show Points:", self
.showPoints
325 # Restore the previous marker style
326 d
.yline
[0].set_marker(d
.marker
)
328 # Turn off the marker visualization
329 d
.yline
[0].set_marker('')
332 def on_lines_toggled(self
, widget
, *args
):
333 self
.showLines
= not self
.showLines
334 if self
.debug
: print "Show Lines:", self
.showLines
337 # Restore the previous linestyle
338 d
.yline
[0].set_linestyle(d
.linestyle
)
340 # Turn off the line visualization
341 d
.yline
[0].set_linestyle('')
344 def on_grid_toggled(self
, widget
, *args
):
345 self
.grid
= not self
.grid
346 if self
.debug
: print "Show Grid:", self
.grid
347 self
.axis
.grid(self
.grid
)
350 def on_xmin_entry_activate(self
, widget
, *args
):
351 if self
.debug
: print 'X Min Entry Activated'
352 s
= self
.xminEntry
.get_text()
356 self
.statusBar
.push(self
.context
, 'Wrong X axis min limit.')
357 self
.xminEntry
.set_text('')
359 if self
.xscale
== 'log' and val
<= 0:
361 self
.warn('Only values > 0 are allowed in log scale.')
362 self
.xminEntry
.set_text(str(val
))
364 self
.axis
.set_xlim(xmin
=val
)
367 def on_xmax_entry_activate(self
, widget
, *args
):
368 if self
.debug
: print 'X Max Entry Activated'
369 s
= self
.xmaxEntry
.get_text()
373 self
.statusBar
.push(self
.context
, 'Wrong X axis max limit.')
374 self
.xmaxEntry
.set_text('')
376 if self
.xscale
== 'log' and val
<= 0:
378 self
.warn('Only values > 0 are allowed in log scale.')
379 self
.xmaxEntry
.set_text(str(val
))
381 self
.axis
.set_xlim(xmax
=val
)
384 def on_ymin_entry_activate(self
, widget
, *args
):
385 if self
.debug
: print 'Y Min Entry Activated'
386 s
= self
.yminEntry
.get_text()
390 self
.statusBar
.push(self
.context
, 'Wrong Y axis min limit.')
391 self
.yminEntry
.set_text('')
393 if self
.yscale
== 'log' and val
<= 0:
395 self
.warn('Only values > 0 are allowed in log scale.')
396 self
.yminEntry
.set_text(str(val
))
398 self
.axis
.set_ylim(ymin
=val
)
401 def on_ymax_entry_activate(self
, widget
, *args
):
402 if self
.debug
: print 'Y Max Entry Activated'
403 s
= self
.ymaxEntry
.get_text()
407 self
.statusBar
.push(self
.context
, 'Wrong Y axis max limit.')
408 self
.ymaxEntry
.set_text('')
410 if self
.yscale
== 'log' and val
<= 0:
412 self
.warn('Only values > 0 are allowed in log scale.')
413 self
.ymaxEntry
.set_text(str(val
))
415 self
.axis
.set_ylim(ymax
=val
)
418 def on_apply_button_clicked(self
, widget
, *args
):
419 sxmin
= self
.xminEntry
.get_text()
420 sxmax
= self
.xmaxEntry
.get_text()
421 symin
= self
.yminEntry
.get_text()
422 symax
= self
.ymaxEntry
.get_text()
424 xmin_val
= float(sxmin
)
425 xmax_val
= float(sxmax
)
426 ymin_val
= float(symin
)
427 ymax_val
= float(symax
)
429 self
.statusBar
.push(self
.context
, 'Wrong axis limit')
431 if self
.xscale
== 'log':
432 if xmin_val
<= 0: xmin_val
= LOGMIN
433 if xmax_val
<= 0: xmax_val
= xmin_val
*10
434 if ymin_val
<= 0: ymin_val
= LOGMIN
435 if ymax_val
<= 0: ymax_val
= ymin_val
*10
436 self
.xmin
, self
.xmax
, self
.ymin
, self
.ymax
= \
437 xmin_val
, xmax_val
, ymin_val
, ymax_val
438 self
.axis
.set_xlim(xmin
=xmin_val
)
439 self
.axis
.set_xlim(xmax
=xmax_val
)
440 self
.axis
.set_ylim(ymin
=ymin_val
)
441 self
.axis
.set_ylim(ymax
=ymax_val
)
445 # The following are MENU callback methods
449 def on_addDataSet_activate(self
, widget
, *args
):
450 self
.open_file_dialog
.window
.show()
451 def on_new_activate(self
, widget
, *args
):
453 self
.reset_scale_buttons()
457 def on_autoscale_activate(self
, widget
, *args
):
458 self
.axis
.autoscale_view()
460 def on_coordinatePicker_activate(self
, widget
, *args
):
461 if self
.cooPickerCheckB
.get_active():
462 self
.cid
= self
.canvas
.mpl_connect('button_press_event',
464 self
.writeStatusBar('Click on the plot to log coordinates on '+\
466 elif self
.cid
!= None:
467 self
.canvas
.mpl_disconnect(self
.cid
)
468 self
.writeStatusBar('Coordinate picker disabled.')
470 print "Error: tried to disconnect an unexistent event."
471 def on_moreGrid_activate(self
, widget
, *args
):
472 if self
.moreGridCheckB
.get_active():
473 self
.axis
.xaxis
.grid(True, which
='minor', ls
='--', alpha
=0.5)
474 self
.axis
.yaxis
.grid(True, which
='minor', ls
='--', alpha
=0.5)
475 self
.axis
.xaxis
.grid(True, which
='major', ls
='-', alpha
=0.5)
476 self
.axis
.yaxis
.grid(True, which
='major', ls
='-', alpha
=0.5)
478 self
.axis
.xaxis
.grid(False, which
='minor')
479 self
.axis
.yaxis
.grid(False, which
='minor')
480 self
.axis
.xaxis
.grid(True, which
='major', ls
=':')
481 self
.axis
.yaxis
.grid(True, which
='major', ls
=':')
485 def on_SizeAndResolution_activate(self
, widget
, *args
):
486 DimentionAndResolution(self
)
487 def on_plot_properties_activate(self
, widget
, *args
):
488 PlotPropertiesDialog(self
)
489 def on_makeInterpolation_activate(self
, widget
, *args
):
490 InterpolationDialog(self
)
491 def on_title_and_axes_labels_activate(self
, widget
, *args
):
492 TitleAndAxesWindow(self
)
493 def on_info_activate(self
, widget
, *args
):
497 def get_coordinates_cb(event
):
499 Callback for the coordinate picker tool. This function is not a class
500 method because I don't know how to connect an MPL event to a method instead
503 if not event
.inaxes
: return
504 print "%3.4f\t%3.4f" % (event
.xdata
, event
.ydata
)
507 # Abstract dialogs classes
509 class DialogWithPlotList(DialogWindowWithCancel
):
510 """Abstract class for dialogs with a list of current plots in them."""
512 def __init__(self
, dialogName
, gladefile
, callerApp
):
513 DialogWindowWithCancel
.__init
__(self
, dialogName
, gladefile
, callerApp
)
515 self
.treeView
= self
.widgetTree
.get_widget('treeview')
516 self
.create_plotlist()
518 def create_plotlist(self
):
519 # Add a column to the treeView
520 self
.addListColumn('Plot List', 0)
522 # Create the listStore Model to use with the treeView
523 self
.plotList
= gtk
.ListStore(str)
526 self
.insertPlotList()
528 # Attatch the model to the treeView
529 self
.treeView
.set_model(self
.plotList
)
531 def addListColumn(self
, title
, columnId
):
532 """This function adds a column to the list view.
533 First it create the gtk.TreeViewColumn and then set
534 some needed properties"""
536 column
= gtk
.TreeViewColumn(title
, gtk
.CellRendererText(), text
=0)
537 column
.set_resizable(True)
538 column
.set_sort_column_id(columnId
)
539 self
.treeView
.append_column(column
)
541 def insertPlotList(self
):
542 for data
in self
.callerApp
.data
:
543 self
.plotList
.append([data
.name
])
545 def on_applyButton_clicked(self
, widget
, *args
):
546 self
.window
.destroy()
548 def on_cancelButton_clicked(self
, widget
, *args
):
549 self
.window
.destroy()
551 def on_okButton_clicked(self
, widget
, *args
):
552 self
.window
.destroy()
557 class InterpolationDialog(DialogWithPlotList
):
558 def __init__(self
, callerApp
):
559 DialogWithPlotList
.__init
__(self
, 'InterpolationDialog',
560 gladefile
, callerApp
)
561 # To be implemented ...
564 class PlotPropertiesDialog(DialogWithPlotList
):
568 line_styles
= ['-', '--', ':', '-.']
569 line_stylesd
= {'Continuous': '-', 'Dashed': '--', 'Dotted': ':',
572 markers
= 'os^v<>.+xdDhHp'
574 def __init__(self
, callerApp
):
575 DialogWithPlotList
.__init
__(self
, 'PlotPropertiesDialog',
576 gladefile
, callerApp
)
578 if not self
.callerApp
.linesCheckB
.get_active():
579 self
.callerApp
.linesCheckB
.set_active(True)
581 if not self
.callerApp
.pointsCheckB
.get_active():
582 self
.callerApp
.pointsCheckB
.set_active(True)
586 # Retrive the data list
587 self
.data
= self
.callerApp
.data
589 # Save all the lines properties in case of Cancell-button
590 self
.orig_lines
= range(len(self
.data
))
591 for i
,d
in enumerate(self
.data
):
592 self
.orig_lines
[i
] = [Line2D([0], [0]), d
.linestyle
, d
.marker
]
593 self
.orig_lines
[i
][0].update_from(d
.yline
[0])
595 self
.selected_data
= None
596 self
.selected_line
= None
597 self
.allowReplot
= False
599 def load_widgets(self
):
600 self
.lineWidthSpinButt
= \
601 self
.widgetTree
.get_widget('lineWidthSpinButton')
602 self
.lineStyleComboB
= \
603 self
.widgetTree
.get_widget('lineStyleComboBox')
605 self
.widgetTree
.get_widget('lineColorComboBox')
606 self
.markerComboB
= \
607 self
.widgetTree
.get_widget('markerTypeComboBox')
608 self
.markerSizeSpinButt
= \
609 self
.widgetTree
.get_widget('markerSizeSpinButton')
610 self
.markerEdgeColorComboB
= \
611 self
.widgetTree
.get_widget('markerEdgeColComboBox')
612 self
.markerFaceColorComboB
= \
613 self
.widgetTree
.get_widget('markerFaceColComboBox')
614 self
.markerEdgeWidthSpinButt
= \
615 self
.widgetTree
.get_widget('markerEdgeWidthSpinButton')
617 def update_properties(self
):
618 selected_line
= self
.selected_line
620 # Set the Spin Buttons with the values for the selected data
621 self
.lineWidthSpinButt
.set_value(selected_line
.get_linewidth())
622 self
.markerSizeSpinButt
.set_value(selected_line
.get_markersize())
623 mew
= selected_line
.get_markeredgewidth()
624 self
.markerEdgeWidthSpinButt
.set_value(mew
)
626 # Set the Combo Boxes with the values for the selected data
627 self
.set_combobox(self
.lineStyleComboB
, selected_line
.get_linestyle
,
629 self
.set_combobox(self
.colorComboB
, selected_line
.get_color
,
631 self
.set_combobox(self
.markerComboB
, selected_line
.get_marker
,
633 self
.set_combobox(self
.markerEdgeColorComboB
, selected_line
.get_mec
,
635 self
.set_combobox(self
.markerFaceColorComboB
, selected_line
.get_mfc
,
638 def set_combobox(self
, cbox
, retrive_fun
, choses
):
639 value
= retrive_fun()
643 i
= choses
.index(value
)
646 print "WARNING: Unsupported value '%s'." % value
649 def set_line_prop_sbut(self
, prop
):
650 value
= getattr(self
, prop
+'SpinButt').get_value()
651 self
.set_line_prop(prop
, value
)
653 def set_line_prop_cbox(self
, prop
, choses
=None):
655 text
= getattr(self
, prop
+'ComboB').get_active_text()
658 value
= text
[text
.find('(') + 1]
659 elif text
in choses
.keys():
662 print "WARNING: Unsupported value '%s'." % value
664 self
.set_line_prop(prop
, value
)
666 def set_line_prop(self
, prop
, value
):
667 if not self
.allowReplot
or self
.selected_data
is None: return
669 set_fun
= getattr(self
.selected_line
, 'set_'+prop
.lower())
671 self
.callerApp
.canvas
.draw()
677 def on_treeview_cursor_changed(self
, *args
):
678 # Retrive the current plot/line reference
679 plot_index
= self
.treeView
.get_cursor()[0][0]
680 self
.selected_line
= self
.data
[plot_index
].yline
[0]
681 self
.selected_data
= self
.callerApp
.data
[plot_index
]
683 # Update the plot with the current line/plot properties
684 self
.allowReplot
= False
685 self
.update_properties()
686 self
.allowReplot
= True
688 def on_lineWidth_value_changed(self
, *args
):
689 self
.set_line_prop_sbut('lineWidth')
691 def on_lineStyle_changed(self
, *args
):
692 self
.set_line_prop_cbox('lineStyle', choses
=self
.line_stylesd
)
694 def on_lineColor_changed(self
, *args
):
695 self
.set_line_prop_cbox('color')
697 def on_markerType_changed(self
, *args
):
698 self
.set_line_prop_cbox('marker')
700 def on_markerSize_value_changed(self
, *args
):
701 self
.set_line_prop_sbut('markerSize')
703 def on_markerEdgeWidth_value_changed(self
, *args
):
704 self
.set_line_prop_sbut('markerEdgeWidth')
706 def on_markerEdgeColor_changed(self
, *args
):
707 self
.set_line_prop_cbox('markerEdgeColor')
709 def on_markerFaceColor_changed(self
, *args
):
710 self
.set_line_prop_cbox('markerFaceColor')
713 def on_cancelButton_clicked(self
, widget
, *args
):
714 # Restore the old style
715 for orig_line
, d
in zip(self
.orig_lines
, self
.data
):
716 d
.yline
[0].update_from(orig_line
[0])
717 d
.linestyle
= orig_line
[1]
718 d
.marker
= orig_line
[2]
720 self
.callerApp
.canvas
.draw()
721 self
.window
.destroy()
723 def on_okButton_clicked(self
, widget
, *args
):
724 self
.window
.destroy()
727 class TitleAndAxesWindow(DialogWindowWithCancel
):
729 Dialog for setting Title and axes labels.
731 def __init__(self
, callerApp
):
732 DialogWindowWithCancel
.__init
__(self
, 'TitleAndAxesWindow', gladefile
,
735 self
.titleEntry
= self
.widgetTree
.get_widget('titleEntry')
736 self
.xlabelEntry
= self
.widgetTree
.get_widget('xlabelEntry')
737 self
.ylabelEntry
= self
.widgetTree
.get_widget('ylabelEntry')
739 # Update the entries with the current values
740 def sync(field
, entry
):
741 if field
!= None: entry
.set_text(field
)
743 sync(self
.callerApp
.title
, self
.titleEntry
)
744 sync(self
.callerApp
.xlabel
, self
.xlabelEntry
)
745 sync(self
.callerApp
.ylabel
, self
.ylabelEntry
)
747 def on_okButton_clicked(self
, widget
, *args
):
749 self
.callerApp
.axis
.set_title(self
.titleEntry
.get_text())
750 self
.callerApp
.axis
.set_xlabel(self
.xlabelEntry
.get_text())
751 self
.callerApp
.axis
.set_ylabel(self
.ylabelEntry
.get_text())
752 self
.callerApp
.canvas
.draw()
754 self
.callerApp
.title
= self
.titleEntry
.get_text()
755 self
.callerApp
.xlabel
= self
.ylabelEntry
.get_text()
756 self
.callerApp
.ylabel
= self
.xlabelEntry
.get_text()
758 self
.window
.destroy()
760 class DimentionAndResolution(DialogWindowWithCancel
):
762 Dialog for setting Figure dimentions and resolution.
764 def __init__(self
, callerApp
):
765 DialogWindowWithCancel
.__init
__(self
, 'DimentionsDialog', gladefile
,
767 self
.xdimSpinButton
= self
.widgetTree
.get_widget('xdimSpinButton')
768 self
.ydimSpinButton
= self
.widgetTree
.get_widget('ydimSpinButton')
769 self
.resolutionSpinButton
= self
.widgetTree
.get_widget(
770 'resolutionSpinButton')
771 self
.inchesRadioB
= self
.widgetTree
.get_widget('inRadioButton')
773 self
.xdim_o
, self
.ydim_o
= self
.callerApp
.figure
.get_size_inches()
774 self
.dpi_o
= self
.callerApp
.figure
.get_dpi()
776 self
.set_initial_values()
778 def set_values(self
, xdim
, ydim
, dpi
):
779 if not self
.inchesRadioB
.get_active():
780 xdim
*= CM_PER_INCHES
781 ydim
*= CM_PER_INCHES
782 self
.xdimSpinButton
.set_value(xdim
)
783 self
.ydimSpinButton
.set_value(ydim
)
784 self
.resolutionSpinButton
.set_value(dpi
)
786 def set_initial_values(self
):
787 self
.set_values(self
.xdim_o
, self
.ydim_o
, self
.dpi_o
)
789 def set_default_values(self
):
790 xdim
, ydim
= rcParams
['figure.figsize']
791 dpi
= rcParams
['figure.dpi']
792 self
.set_values(xdim
, ydim
, dpi
)
794 def get_values(self
):
795 self
.xdim
= self
.xdimSpinButton
.get_value()
796 self
.ydim
= self
.ydimSpinButton
.get_value()
797 self
.resolution
= self
.resolutionSpinButton
.get_value()
798 if not self
.inchesRadioB
.get_active():
799 self
.xdim
/= CM_PER_INCHES
800 self
.ydim
/= CM_PER_INCHES
802 def set_figsize(self
):
803 self
.callerApp
.figure
.set_size_inches(self
.xdim
, self
.ydim
)
804 self
.callerApp
.figure
.set_dpi(self
.resolution
)
806 def on_unity_toggled(self
, widget
, *args
):
807 xdim
= self
.xdimSpinButton
.get_value()
808 ydim
= self
.ydimSpinButton
.get_value()
809 if self
.inchesRadioB
.get_active():
810 xdim
/= CM_PER_INCHES
811 ydim
/= CM_PER_INCHES
813 xdim
*= CM_PER_INCHES
814 ydim
*= CM_PER_INCHES
815 self
.xdimSpinButton
.set_value(xdim
)
816 self
.ydimSpinButton
.set_value(ydim
)
818 def on_okButton_clicked(self
, widget
, *args
):
822 self
.callerApp
.canvas
.draw()
823 self
.window
.destroy()
825 def on_restoreButton_clicked(self
, widget
, *args
):
826 self
.set_default_values()
829 class OpenFileDialog(GenericOpenFileDialog
):
831 This class implements the "Open File" dialog.
833 def __init__(self
, callerApp
):
834 GenericOpenFileDialog
.__init
__(self
, 'OpenFileDialog', gladefile
,
838 def openSelectedFile(self
):
839 loaded
= self
.callerApp
.load( self
.filename
)
841 self
.callerApp
.plot_data(-1)
844 def on_cancelButton_clicked(self
, widget
, *args
):
850 class AboutDialog(GenericSecondaryWindow
):
852 Object for the "About Dialog".
855 GenericSecondaryWindow
.__init
__(self
, 'AboutDialog', gladefile
)
856 self
.window
.set_version(read_version(rootdir
))
857 self
.window
.connect("response", lambda d
, r
: d
.destroy())
865 p
= PlotFileApp(x
, y
, title
='Random Sequence', debug
=True)
869 p
= PlotFileApp(debug
=True)
870 # Try to open a sample file
871 if len(sys
.argv
) < 2 and os
.path
.isfile(sourcedir
+'samples/data.txt'):
872 p
.load(sourcedir
+'samples/data.txt')
876 if __name__
== '__main__': main()