http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_wx2.html
"""
+import logging
+
import matplotlib
matplotlib.use('WXAgg') # use wxpython with antigrain (agg) rendering
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from ....util.callback import callback, in_callback
from ....util.si import ppSI, split_data_label
+from ..dialog.selection import Selection
from . import Panel
self.style = 'line'
self._curve = None
self._x_column = None
- self._y_column = None # TODO: _y_columns (allow multiple, simultaneous y axes (rescaled?))
+ self._y_columns = [] # TODO: select right/left scales?
super(PlotPanel, self).__init__(
name='plot', callbacks=callbacks, **kwargs)
self._c = {}
self._c['x column'].SetToolTip(wx.ToolTip('x column'))
self._c['toolbar'].AddControl(self._c['x column'])
self._c['x column'].Bind(wx.EVT_CHOICE, self._on_x_column)
- self._c['y column'] = wx.Choice(
- parent=self._c['toolbar'], choices=[])
+ self._c['y column'] = wx.Button(
+ parent=self._c['toolbar'], label='y column(s)')
self._c['y column'].SetToolTip(wx.ToolTip('y column'))
self._c['toolbar'].AddControl(self._c['y column'])
- self._c['y column'].Bind(wx.EVT_CHOICE, self._on_y_column)
+ self._c['y column'].Bind(wx.EVT_BUTTON, self._on_y_column)
self._c['toolbar'].Realize() # call after putting items in the toolbar
if wx.Platform == '__WXMAC__':
self.update()
def _on_y_column(self, event):
- self._y_column = self._c['y column'].GetStringSelection()
+ if not hasattr(self, '_columns') or len(self._columns) == 0:
+ self._y_columns = []
+ return
+ s = Selection(
+ options=self._columns,
+ message='Select visible y column(s).',
+ button_id=wx.ID_OK,
+ selection_style='multiple',
+ parent=self,
+ title='Select y column(s)',
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+ s.CenterOnScreen()
+ s.ShowModal()
+ self._y_columns = [self._columns[i] for i in s.selected]
+ s.Destroy()
+ if len(self._y_columns) == 0:
+ self._y_columns = self._columns[-1:]
self.update()
def _resize_canvas(self):
self._columns = sorted(columns)
if self._x_column not in self._columns:
self._x_column = self._columns[0]
- if self._y_column not in self._columns:
- self._y_column = self._columns[-1]
+ self._y_columns = [y for y in self._y_columns if y in self._columns]
+ if len(self._y_columns) == 0:
+ self._y_columns = self._columns[-1:]
if 'x column' in self._c:
for i in range(self._c['x column'].GetCount()):
self._c['x column'].Delete(0)
self._c['x column'].AppendItems(self._columns)
self._c['x column'].SetStringSelection(self._x_column)
- if 'y column' in self._c:
- for i in range(self._c['y column'].GetCount()):
- self._c['y column'].Delete(0)
- self._c['y column'].AppendItems(self._columns)
- self._c['y column'].SetStringSelection(self._y_column)
self.update(config=config)
def update(self, config=None):
if config['plot SI format'] == True:
d = config['plot decimals']
x_n, x_unit = split_data_label(self._x_column)
- y_n, y_unit = split_data_label(self._y_column)
+ y_n, y_unit = split_data_label(self._y_columns[0])
+ for y_column in self._y_columns[1:]:
+ y_n2, y_unit2 = split_data_label(y_column)
+ if y_unit2 != y_unit:
+ log = logging.getLogger('hooke')
+ log.warn('y-axes unit mismatch: %s != %s, using %s.'
+ % (y_unit, y_unit2, y_unit))
fx = HookeFormatter(decimals=d, unit=x_unit)
axes.xaxis.set_major_formatter(fx)
fy = HookeFormatter(decimals=d, unit=y_unit)
axes.yaxis.set_major_formatter(fy)
axes.set_xlabel(x_n)
- axes.set_ylabel(y_n)
+ if len(self._y_columns) == 1:
+ axes.set_ylabel(y_n)
else:
axes.set_xlabel(self._x_column)
- axes.set_ylabel(self._y_column)
+ if len(self._y_columns) == 1:
+ axes.set_ylabel(self._y_columns[0])
self._c['figure'].hold(True)
for i,data in enumerate(self._curve.data):
- try:
- x_col = data.info['columns'].index(self._x_column)
- y_col = data.info['columns'].index(self._y_column)
- except ValueError:
- continue # data is missing a required column
- axes.plot(data[:,x_col], data[:,y_col],
- '.',
- label=data.info['name'])
- if config['plot legend'] == 'True': # HACK: config should convert
+ for y_column in self._y_columns:
+ try:
+ x_col = data.info['columns'].index(self._x_column)
+ y_col = data.info['columns'].index(y_column)
+ except ValueError:
+ continue # data is missing a required column
+ axes.plot(data[:,x_col], data[:,y_col],
+ '.',
+ label=('%s, %s' % (data.info['name'], y_column)))
+ if config['plot legend'] == True:
axes.legend(loc='best')
self._c['canvas'].draw()