Projects/laydi
Projects
/
laydi
Archived
7
0
Fork 0
This repository has been archived on 2024-07-04. You can view files and clone it, but cannot push or open issues or pull requests.
laydi/system/plots.py

1186 lines
40 KiB
Python

import os,sys
from itertools import izip
import pygtk
import gobject
import gtk
import fluents
from system import logger
import matplotlib
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
from matplotlib.backend_bases import NavigationToolbar2,cursors
from matplotlib.backends.backend_gtk import FileChooserDialog,cursord
from matplotlib.widgets import SubplotTool,RectangleSelector
from matplotlib.axes import Subplot
from matplotlib.figure import Figure
from matplotlib import cm,cbook
from pylab import Polygon
from matplotlib.collections import LineCollection
from matplotlib.mlab import prctile
import networkx
import scipy
# global active mode. Used by toolbars to communicate correct mode
active_mode = 'default'
class ObjectTable:
"""A 2D table of elements."""
def __init__(self, xsize=0, ysize=0, creator=None):
self._elements = []
self._creator = creator or (lambda : None)
self.xsize = xsize
self.ysize = ysize
self.resize(xsize, ysize)
def resize(self, xsize, ysize):
"""Resizes the table by removing and creating elements as required."""
# Delete or append new rows
del self._elements[ysize:]
new_rows = ysize - len(self._elements)
self._elements.extend([list() for i in range(new_rows)])
# Delete or append new columns
for row in self._elements:
del row[xsize:]
new_elems = xsize - len(row)
row.extend([self._creator() for i in range(new_elems)])
def __getitem__(self, index):
x, y = index
return self._elements[y][x]
def __setitem__(self, index, value):
x, y = index
self._elements[y][x] = value
class ViewFrame (gtk.Frame):
"""
A ViewFrame is a gtk bin that contains a view.
The ViewFrame is either active or inactive, and belongs to a group of
VeiwFrames of which only one can be active at any time.
"""
def __init__(self, view_frames):
gtk.Frame.__init__(self)
self.focused = False
self.view_frames = view_frames
self.empty_view = EmptyView()
self._button_event = None
view_frames.append(self)
if len(view_frames) == 1:
self.focus()
else:
self.focused = True
self.unfocus()
# Get dropped views
self.drag_dest_set(gtk.DEST_DEFAULT_ALL,
[("GTK_TREE_MODEL_ROW", gtk.TARGET_SAME_APP, 7)],
gtk.gdk.ACTION_LINK)
self.connect("drag-data-received", self.on_drag_data_received)
# Set view
self._view = self.empty_view
self._view.connect("button-press-event", self.on_button_press_event)
self.add(self._view)
self._view.show()
self.show()
def focus(self):
"""Gets focus and ensures that no other window is in focus."""
if self.focused:
self.emit('focus-changed', self, True)
return self
for frame in self.view_frames:
frame.unfocus()
self.set_shadow_type(gtk.SHADOW_IN)
self.focused = True
self.emit('focus-changed', self, True)
return self
def unfocus(self):
"""Removes focus from the ViewFrame. Does nothing if unfocused."""
if not self.focused:
return
self.set_shadow_type(gtk.SHADOW_OUT)
self.focused = False
self.emit('focus-changed', self, False)
def set_view(self, view):
"""Set view to view or to empty view if parameter is None"""
# if None is passed, use empty view
if view == None:
view = self.empty_view
# do nothing if the view is already there
if view == self._view:
return
# detach view from current parent
view_parent = view.get_parent()
if view_parent:
view_parent.set_view(None)
# switch which widget we are listening to
if self._button_event:
self._view.disconnect(self._button_event)
self._button_event = view.connect("button-press-event",
self.on_button_press_event)
# remove old view, set new view
self._view.hide()
self.remove(self._view)
self.add(view)
view.show()
self._view = view
def get_view(self):
"""Returns current view, or None if the empty view is set."""
if self._view == self.empty_view:
return None
return self._view
def on_button_press_event(self, widget, event):
if not self.focused:
self.focus()
def on_drag_data_received(self, widget, drag_context, x, y,
selection, info, timestamp):
treestore, path = selection.tree_get_row_drag_data()
iter = treestore.get_iter(path)
obj = treestore.get_value(iter, 2)
if isinstance(obj, Plot):
self.set_view(obj)
self.focus()
class MainView (gtk.Notebook):
def __init__(self):
gtk.Notebook.__init__(self)
self.set_show_tabs(False)
self.set_show_border(False)
self._view_frames = []
self._views = ObjectTable(2, 2, lambda : ViewFrame(self._view_frames))
self._small_views = gtk.Table(2, 2, True)
self._small_views.set_col_spacings(4)
self._small_views.set_row_spacings(4)
self._large_view = ViewFrame(list())
self.update_small_views()
for vf in self._view_frames:
vf.connect('focus-changed', self.on_view_focus_changed)
self.append_page(self._small_views)
self.append_page(self._large_view)
self.show()
self.set_current_page(0)
def __getitem__(self, x, y):
return self._views[x, y]
def update_small_views(self):
for x in range(self._views.xsize):
for y in range(self._views.ysize):
child = self._views[x,y]
self._small_views.attach(child, x, x+1, y, y+1)
def get_active_small_view(self):
for vf in self._view_frames:
if vf.focused:
return vf
return None
def goto_large(self):
if self.get_current_page() == 1:
return
vf = self.get_active_small_view()
view = vf.get_view()
vf.set_view(None)
self._large_view.set_view(view)
self.set_current_page(1)
def goto_small(self):
if self.get_current_page() == 0:
return
vf = self.get_active_small_view()
view = self._large_view.get_view()
self._large_view.set_view(None)
vf.set_view(view)
self.set_current_page(0)
def insert_view(self, view):
if self.get_current_page() == 0:
vf = self.get_active_small_view()
else:
vf = self._large_view
vf.set_view(view)
def set_all_plots(self, plots):
for vf in self._view_frames:
if plots:
vf.set_view(plots.pop())
else:
vf.set_view(None)
def show(self):
for vf in self._view_frames:
vf.show()
self._small_views.show()
gtk.Notebook.show(self)
def on_view_focus_changed(self, widget, vf, focused):
if focused:
self.emit('view-changed', vf)
class View (gtk.Frame):
"""The base class of everything that is shown in the center view of fluents.
Most views should rather subclass Plot, which automatically handles freezing and
toolbars, and sets up matplotlib Figure and Canvas objects.
"""
def __init__(self, title):
gtk.Frame.__init__(self)
self.title = title
self.set_shadow_type(gtk.SHADOW_NONE)
def get_toolbar(self):
return None
class EmptyView (View):
"""EmptyView is shown in ViewFrames that are unused."""
def __init__(self):
View.__init__(self, 'Empty view')
label = gtk.Label('No view')
ebox = gtk.EventBox()
ebox.add(label)
self.add(ebox)
label.show()
ebox.show()
self.show()
class Plot (View):
def __init__(self, title):
View.__init__(self, title)
self.selection_listener = None
self.fig = Figure()
self.canvas = FigureCanvas(self.fig)
self._background = None
self._frozen = False
self._toolbar = PlotToolbar(self)
self.canvas.add_events(gtk.gdk.ENTER_NOTIFY_MASK)
self.current_dim = None
def set_frozen(self, frozen):
"""A frozen plot will not be updated when the current selection is changed."""
self._frozen = frozen
def get_title(self):
return self.title
def get_toolbar(self):
return self._toolbar
def selection_changed(self, dim_name, selection):
""" Selection observer handle.
A selection change in a plot is only drawn if:
1.) plot is sensitive to selections (not freezed)
2.) plot is visible (has a view)
3.) the selections dim_name is the plot's dimension.
"""
if self._frozen \
or not self.get_property('visible') \
or self.current_dim != dim_name:
print "Ignored a selection changed call in plot: %s" %self.get_title()
return
print "Setting current selection in: %s " %self.get_title()
self.set_current_selection(selection)
def set_selection_listener(self, listener):
"""Allow project to listen to selections.
The selection will propagate back to all plots through the
selection_changed() method. The listener will be called as
listener(dimension_name, ids).
"""
self.selection_listener = listener
class LineViewPlot(Plot):
"""Line view of current selection, no interaction
Only works on 2d-arrays
input:
-- major_axis : dim_number for line dim (see scipy.ndarray for axis def.)
-- minor_axis : needs definition only for higher order arrays
ps: slow (cant get linecollection and blit to work)
"""
def __init__(self, dataset, major_axis=1, minor_axis=None, name="Line view"):
self.use_blit = False
self._last_index = []
self._data = dataset.asarray()
self.dataset = dataset
Plot.__init__(self, name)
self.ax = self.fig.add_subplot(111)
self.ax.set_title(self.get_title())
self.current_dim = self.dataset.get_dim_name(major_axis)
if len(self._data.shape)==2 and not minor_axis:
minor_axis = major_axis-1
#initial draw
x_axis = scipy.arange(self._data.shape[minor_axis])
self.line_segs=[]
for xi in range(self._data.shape[major_axis]):
yi = self._data.take([xi], major_axis)
self.line_segs.append([(xx,yy) for xx,yy in izip(x_axis,yi)])
#background
xax = scipy.arange(self._data.shape[0])
verts_0 = [] #100,0
verts_1 = [] # 90,10
verts_2 = [] # 75,25
med = []
for i in xax:
pp = prctile(self._data[i,:], [0.,5.,25,50.,75.,95.,100])
verts_0.append((i,pp[0]))
verts_1.append((i,pp[1]))
verts_2.append((i,pp[2]))
for i in xax[::-1]:
pp = prctile(self._data[i,:], [0.,5.,25,50.,75.,95.,100])
verts_0.append((i, pp[-1]))
verts_1.append((i, pp[-2]))
verts_2.append((i, pp[-3]))
med.append(pp[3])
bck0 = Polygon(verts_0, alpha=.15, lw=0)
bck1 = Polygon(verts_1, alpha=.15, lw=0)
bck2 = Polygon(verts_2, alpha=.15, lw=0)
self.ax.add_patch(bck0)
self.ax.add_patch(bck1)
self.ax.add_patch(bck2)
self.ax.plot(xax,med, 'b')
self.ax.autoscale_view()
self.add(self.canvas)
self.canvas.show()
#FIXME: Lineview plot cannot do selections -> disable in toolbar
self._toolbar = PlotToolbar(self)
self.canvas.mpl_connect('resize_event', self.clear_background)
def clear_background(self, event):
self._background = None
def set_current_selection(self, selection):
ids = selection[self.current_dim] # current identifiers
index = self.dataset.get_indices(self.current_dim, ids)
if self.use_blit:
if self._background is None:
self._bbox = self.ax.bbox.deepcopy()
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
self.canvas.restore_region(self._background)
if len(index)>0: # do we have a selection
if len(self.ax.collections)>0:
self.ax.collections = []
segs = [self.line_segs[i] for i in index]
line_coll = LineCollection(segs, colors=(1,0,0,1))
line_coll.set_clip_box(self.ax.bbox)
self.ax.update_datalim(line_coll.get_verts(self.ax.transData))
if self.use_blit:
self.ax.draw_artist(line_coll)
line_coll.get_clip_box().get_bounds()
self.canvas.blit()
else:
self.ax.add_collection(line_coll)
self.canvas.draw()
class ScatterMarkerPlot(Plot):
"""The ScatterMarkerPlot is faster than regular scatterplot, but
has no color and size options."""
def __init__(self, dataset_1, dataset_2, id_dim, sel_dim,
id_1, id_2, s=6, name="Scatter plot"):
Plot.__init__(self, name)
self.use_blit = False
self._background = None
self.ax = self.fig.add_subplot(111)
self.ax.axhline(0, color='k', lw=1., zorder=1)
self.ax.axvline(0, color='k', lw=1., zorder=1)
self.current_dim = id_dim
self.dataset_1 = dataset_1
self.ms = s
self._selection_line = None
x_index = dataset_1[sel_dim][id_1]
y_index = dataset_2[sel_dim][id_2]
self.xaxis_data = dataset_1._array[:, x_index]
self.yaxis_data = dataset_2._array[:, y_index]
self.ax.plot(self.xaxis_data, self.yaxis_data, 'o', markeredgewidth=0, markersize=s)
self.ax.set_title(self.get_title())
self.add(self.canvas)
self.canvas.show()
def rectangle_select_callback(self, x1, y1, x2, y2):
print "Rectangle select happened in: %s" %self.get_title()
ydata = self.yaxis_data
xdata = self.xaxis_data
# find indices of selected area
if x1>x2:
x1, x2 = x2, x1
if y1>y2:
y1, y2 = y2, y1
assert x1<=x2
assert y1<=y2
index = scipy.nonzero((xdata>x1) & (xdata<x2) & (ydata>y1) & (ydata<y2))[0]
ids = self.dataset_1.get_identifiers(self.current_dim, index)
self.selection_listener(self.current_dim, ids)
def set_current_selection(self, selection):
ids = selection[self.current_dim] # current identifiers
index = self.dataset_1.get_indices(self.current_dim, ids)
if self.use_blit:
if self._background is None:
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
self.canvas.restore_region(self._background)
if not len(index)>0:
return
xdata_new = self.xaxis_data.take(index) #take data
ydata_new = self.yaxis_data.take(index)
#remove old selection
if self._selection_line:
self.ax.lines.remove(self._selection_line)
self._selection_line, = self.ax.plot(xdata_new, ydata_new,marker='o', markersize=self.ms, linestyle=None, markerfacecolor='r')
# self._toolbar.forward() #update data lims before draw
if self.use_blit:
self.ax.draw_artist(self._selection_line)
self.canvas.blit()
else:
print "A draw happened in: %s" %self.get_title()
self.canvas.draw()
class ScatterPlot(Plot):
"""The ScatterPlot is slower than scattermarker, but has size option."""
def __init__(self, dataset_1, dataset_2, id_dim, sel_dim, id_1, id_2,c='b',s=30,sel_dim_2=None, name="Scatter plot"):
Plot.__init__(self, name)
self.use_blit = False
self.ax = self.fig.add_subplot(111)
self.current_dim = id_dim
self.dataset_1 = dataset_1
x_index = dataset_1[sel_dim][id_1]
if sel_dim_2:
y_index = dataset_2[sel_dim_2][id_2]
else:
y_index = dataset_2[sel_dim][id_2]
self.xaxis_data = dataset_1._array[:, x_index]
self.yaxis_data = dataset_2._array[:, y_index]
lw = scipy.zeros(self.xaxis_data.shape)
sc = self.ax.scatter(self.xaxis_data, self.yaxis_data, s=s, c=c, linewidth=lw, edgecolor='k', alpha=.6, cmap = cm.jet)
if len(c)>1:
self.fig.colorbar(sc,ticks=[], fraction=.05)
self.ax.axhline(0, color='k', lw=1., zorder=1)
self.ax.axvline(0, color='k', lw=1., zorder=1)
self.ax.set_title(self.get_title())
# collection
self.coll = self.ax.collections[0]
# add canvas to widget
self.add(self.canvas)
self.canvas.show()
def rectangle_select_callback(self, x1, y1, x2, y2):
print "Rectangle select happened in: %s" %self.get_title()
ydata = self.yaxis_data
xdata = self.xaxis_data
# find indices of selected area
if x1>x2:
x1, x2 = x2, x1
if y1>y2:
y1, y2 = y2, y1
assert x1<=x2
assert y1<=y2
index = scipy.nonzero((xdata>x1) & (xdata<x2) & (ydata>y1) & (ydata<y2))[0]
ids = self.dataset_1.get_identifiers(self.current_dim, index)
self.selection_listener(self.current_dim, ids)
def set_current_selection(self, selection):
ids = selection[self.current_dim] # current identifiers
if len(ids)==0:
print "nothing selected"
return
#self._toolbar.forward() #update data lims before draw
index = self.dataset_1.get_indices(self.current_dim, ids)
if self.use_blit:
if self._background is None:
self._background = self.canvas.copy_from_bbox(self.ax.bbox)
self.canvas.restore_region(self._background)
lw = scipy.zeros(self.xaxis_data.shape)
if len(index)>0:
lw.put(2.,index)
self.coll.set_linewidth(lw)
if self.use_blit:
print "A blit happened in : %s " %self.get_title()
self.canvas.blit()
self.ax.draw_artist(self.coll)
else:
print "A draw happened in : %s " %self.get_title()
self.canvas.draw()
class NetworkPlot(Plot):
def __init__(self, dataset, **kw):
# Set member variables and call superclass' constructor
self.graph = dataset.asnetworkx()
self.dataset = dataset
self.keywords = kw
self.dim_name = self.dataset.get_dim_name(0)
self.current_dim = self.dim_name
if not kw.has_key('name'):
kw['name'] = self.dataset.get_name()
if not kw.has_key('prog'):
kw['prog'] = 'neato'
if not kw.has_key('pos') or kw['pos']:
kw['pos'] = networkx.pygraphviz_layout(self.graph, kw['prog'])
Plot.__init__(self, kw['name'])
# Keep node size and color as dicts for fast lookup
self.node_size = {}
if kw.has_key('node_size') and cb.iterable(kw['node_size']):
kw.remove('node_size')
for id, size in zip(self.dataset[self.dim_name], kw['node_size']):
self.node_size[id] = size
else:
for id in dataset[self.dim_name]:
self.node_size[id] = 40
self.node_color = {}
if kw.has_key('node_color') and cb.iterable(kw['node_color']):
kw.remove('node_color')
for id, color in zip(self.dataset[self.dim_name], kw['node_color']):
self.node_color[id] = color
else:
self.node_color = None
# for id in self.dataset[self.dim_name]:
# self.node_color[id] = 'red'
if kw.has_key('node_color'):
kw.pop('node_color')
self.ax = self.fig.add_subplot(111)
self.ax.set_position([0.01,0.01,.99,.99])
self.ax.set_xticks([])
self.ax.set_yticks([])
# FIXME: ax shouldn't be in kw at all
if kw.has_key('ax'):
kw.pop('ax')
# Add canvas and show
self.add(self.canvas)
self.canvas.show()
# Initial draw
networkx.draw_networkx(self.graph, ax=self.ax, **kw)
def get_toolbar(self):
return self._toolbar
def rectangle_select_callback(self, x1, y1, x2, y2):
pos = self.keywords['pos']
ydata = scipy.zeros((len(pos),), 'l')
xdata = scipy.zeros((len(pos),), 'l')
node_ids = []
c = 0
for name,(x,y) in pos.items():
node_ids.append(name)
xdata[c] = x
ydata[c] = y
c+=1
# find indices of selected area
if x1 > x2:
x1, x2 = x2, x1
if y1 > y2:
y1, y2 = y2, y1
index = scipy.nonzero((xdata>x1) & (xdata<x2) & (ydata>y1) & (ydata<y2))[0]
ids = [node_ids[i] for i in index]
self.selection_listener(self.current_dim, ids)
def set_current_selection(self, selection):
ids = selection[self.current_dim] # current identifiers
node_set = set(self.graph.nodes())
selected_nodes = list(ids.intersection(node_set))
unselected_nodes = list(node_set.difference(ids))
if self.node_color:
unselected_colors = [self.node_color[x] for x in unselected_nodes]
else:
unselected_colors = 'red'
if self.node_size:
unselected_sizes = [self.node_size[x] for x in unselected_nodes]
selected_sizes = [self.node_size[x] for x in selected_nodes]
self.ax.clear()
networkx.draw_networkx_edges(self.graph, edge_list=self.graph.edges(), \
ax=self.ax, **self.keywords)
networkx.draw_networkx_labels(self.graph,**self.keywords)
if unselected_nodes:
networkx.draw_networkx_nodes(self.graph, nodelist=unselected_nodes, \
node_color='r', node_size=unselected_sizes, ax=self.ax, **self.keywords)
if selected_nodes:
networkx.draw_networkx_nodes(self.graph, nodelist=selected_nodes, \
node_color='k', node_size=selected_sizes, ax=self.ax, **self.keywords)
self.canvas.draw()
class PlotMode:
"""A PlotMode object corresponds to a mouse mode in a plot.
When a mode is selected in the toolbar, the PlotMode corresponding
to the toolbar button is activated by calling setup(ax) for the axis
system ax.
"""
def __init__(self, plot, name, tooltip, image_file):
self.name = name
self.tooltip = tooltip
self.image_file = image_file
self.plot = plot
self.canvas = plot.canvas
def get_icon(self):
"""Returns the icon for the PlotMode"""
fname = os.path.join(fluents.ICONDIR, self.image_file)
image = gtk.Image()
image.set_from_file(fname)
return image
def activate(self):
pass
def deactivate(self):
pass
class DefaultPlotMode (PlotMode):
def __init__(self, plot):
PlotMode.__init__(self, plot, 'default', 'Default mode', 'cursor.png')
class PanPlotMode (PlotMode):
def __init__(self, plot):
PlotMode.__init__(self, plot, 'pan',
'Pan axes with left mouse, zoom with right',
'move.png')
self._button_press = None
self._button_release = None
def activate(self):
self._button_press = self.canvas.mpl_connect(
'button_press_event', self._on_button_press)
self._button_relese = self.canvas.mpl_connect(
'button_release_event', self._on_button_release)
self.mode = 'pan/zoom mode'
def deactivate(self):
if self._button_press:
self.canvas.mpl_disconnect(self._button_press)
if self._button_release:
self.canvas.mpl_disconnect(self._button_release)
def _on_button_press(self, event):
pass
def _on_button_release(self, event):
pass
class ZoomPlotMode (PlotMode):
def __init__(self, plot):
PlotMode.__init__(self, plot, 'zoom',
'Zoom to rectangle','zoom_to_rect.png')
self._selectors = {}
def activate(self):
for ax in self.canvas.figure.get_axes():
props = dict(facecolor = 'blue',
edgecolor = 'black',
alpha = 0.3,
fill = True)
rs = RectangleSelector(ax, self._on_select, drawtype='box',
useblit=True, rectprops = props)
self.canvas.draw()
self._selectors[rs] = ax
def deactivate(self):
for sel in self.selectors:
self.canvas.mpl_disconnect(sel.onmove)
self.canvas.mpl_disconnect(sel.press)
self.canvas.mpl_disconnect(sel.release)
self.canvas.mpl_disconnect(sel.update_background)
self._selectors = {}
def _on_select(self, start, end):
min_x = min(start.xdata, end.xdata)
min_y = min(start.ydata, end.ydata)
max_x = max(start.xdata, end.xdata)
max_y = max(start.ydata, end.ydata)
class SelectPlotMode (PlotMode):
def __init__(self, plot):
PlotMode.__init__(self, plot, 'select',
'Select within rectangle', 'select.png')
self._selectors = {}
def activate(self):
for ax in self.canvas.figure.get_axes():
props = dict(facecolor = 'blue',
edgecolor = 'black',
alpha = 0.3,
fill = True)
rs = RectangleSelector(ax, self._on_select, drawtype='box',
useblit=True, rectprops = props)
self.canvas.draw()
self._selectors[rs] = ax
def deactivate(self):
for sel in self.selectors:
self.canvas.mpl_disconnect(sel.onmove)
self.canvas.mpl_disconnect(sel.press)
self.canvas.mpl_disconnect(sel.release)
self.canvas.mpl_disconnect(sel.update_background)
self._selectors = {}
def _on_select(self, start, end):
self.plot.rectangle_select_callback(start.xdata, start.ydata,
end.xdata, end.ydata)
class PlotToolbar(gtk.Toolbar):
def __init__(self, plot):
gtk.Toolbar.__init__(self)
self.plot = plot
self.canvas = plot.canvas
self._current_mode = None
self.tooltips = gtk.Tooltips()
## Maps toolbar buttons to PlotMode objects.
self._mode_buttons = {}
self.set_property('show-arrow', False)
#canvas.connect('enter-notify-event', self.on_enter_notify)
self.show()
self.add_mode(DefaultPlotMode(self.plot))
self.add_mode(PanPlotMode(self.plot))
self.add_mode(ZoomPlotMode(self.plot))
self.add_mode(SelectPlotMode(self.plot))
self.show_all()
def add_mode(self, mode):
"""Adds a new mode to the toolbar."""
if len(self._mode_buttons) > 0:
other = self._mode_buttons.keys()[0]
else:
other = None
btn = gtk.RadioToolButton(other)
btn.set_icon_widget(mode.get_icon())
btn.set_tooltip(self.tooltips, mode.tooltip, 'Private')
btn.connect('toggled', self._on_mode_toggle)
self._mode_buttons[btn] = mode
self.insert(btn, -1)
if self._current_mode == None:
self._current_mode = mode
def get_mode(self):
"""Returns the active mode name."""
if self._current_mode:
return self._current_mode.name
return None
def get_mode_by_name(self, mode_name):
"""Returns the mode with the given name or None."""
for m in self._mode_buttons.values():
if m.name == mode_name:
return m
return None
def get_button(self, mode_name):
"""Returns the button that corresponds to a mode name."""
for b, m in self._mode_buttons.items():
if m.name == mode_name:
print "Found button for mode: %s" % mode_name
return b
print "Couldn't find button for mode: %s" % mode_name
return None
def set_mode(self, mode_name):
"""Sets a mode by name. Returns the mode or None"""
if mode_name == self._current_mode.name:
return None
if self._current_mode:
self._current_mode.deactivate()
new_mode = self.get_mode_by_name(mode_name)
if new_mode:
new_mode.activate()
self._current_mode = self.get_mode_by_name(mode_name)
else:
logger.log('warning', 'No such mode: %s' % mode_name)
if self.get_button(mode_name) and not self.get_button(mode_name).get_active():
self.get_button(mode_name).set_active(True)
return self._current_mode
def _on_mode_toggle(self, button):
if button.get_active():
self.set_mode(self._mode_buttons[button].name)
# def show(self):
# for b in self._mode_buttons.keys():
# b.show()
# gtk.Toolbar.show(self)
# class PlotToolbar(NavigationToolbar2,gtk.Toolbar):
# # list of toolitems to add to the toolbar, format is:
# # text, tooltip_text, image_file, callback(str)
# toolitems = (
# ('Home', 'Reset original view', 'home.png', 'home'),
# #('Back', 'Back to previous view','back.png', 'back'),
# #('Forward', 'Forward to next view','forward.png', 'forward'),
# #('Subplots', 'Configure subplots','subplots.png', 'configure_subplots'),
# ('Save', 'Save the figure','filesave.png', 'save_figure'),
# )
# def __init__(self, canvas, plot):
# self.win = None
# self.plot = plot
# gtk.Toolbar.__init__(self)
# NavigationToolbar2.__init__(self, canvas)
# self._idleId = 0
# self._select_callback = None
# canvas.connect('enter-notify-event', self.on_enter_notify)
# def _init_toolbar(self):
# self.set_style(gtk.TOOLBAR_ICONS)
# self.tooltips = gtk.Tooltips()
# self._modes = {}
# self._selector = None
# self.set_property('show-arrow', False)
# basedir = fluents.ICONDIR
# # setup base buttons
# for text, tooltip_text, image_file, callback in self.toolitems:
# if text is None:
# self.insert(gtk.SeparatorToolItem(), -1 )
# continue
# fname = os.path.join(basedir, image_file)
# image = gtk.Image()
# image.set_from_file(fname)
# tbutton = gtk.ToolButton(image, text)
# self.insert(tbutton, -1)
# tbutton.connect('clicked', getattr(self, callback))
# tbutton.set_tooltip(self.tooltips, tooltip_text, 'Private')
# self.insert(gtk.SeparatorToolItem(), -1)
# # mode/state buttons
# rbutton = None
# for text,tooltip_text,image_file,callback in self.radiobuttons:
# if text is None:
# self.insert(gtk.SeparatorToolItem(), -1 )
# continue
# fname = os.path.join(basedir, image_file)
# image = gtk.Image()
# image.set_from_file(fname)
# rbutton = gtk.RadioToolButton(rbutton)
# rbutton.set_icon_widget(image)
# rbutton.connect('toggled', getattr(self, callback))
# rbutton.set_tooltip(self.tooltips, tooltip_text, 'Private')
# self._modes[text] = rbutton
# a self.insert(rbutton, -1)
# self.insert(gtk.SeparatorToolItem(), -1)
# toolitem = gtk.ToolItem()
# self.insert(toolitem, -1)
# self.message = gtk.Label()
# toolitem.add(self.message)
# self.tb_freeze = gtk.ToolItem()
# self.chk = gtk.CheckButton ()
# self.chk.set_label ('Freeze')
# self.tb_freeze.add (self.chk)
# self.tb_freeze.set_tooltip(self.tooltips, 'Freeze current selection')
# self.insert(self.tb_freeze,-1)
# toolitem = gtk.SeparatorToolItem()
# self.insert(toolitem, -1)
# self.show_all()
# self.fileselect = FileChooserDialog(title='Save the figure', parent=self.win,)
# def on_enter_notify(self, widget, event):
# if self._active != active_mode:
# self.set_mode(active_mode)
# self.set_mode(active_mode)
# def set_mode(self, mode):
# ## Do nothing if this mode is already active
# if self.mode == mode:
# print "set_mode: already in mode '%s': returning" % mode
# return mode
# ## Remove current Selector if set.
# if self._selector != None:
# self.canvas.mpl_disconnect(self._selector.onmove)
# self.canvas.mpl_disconnect(self._selector.press)
# self.canvas.mpl_disconnect(self._selector.release)
# self.canvas.mpl_disconnect(self._selector.update_background)
# print "set_mode: Removing selector in: %s" %self.plot.get_title()
# self._selector = None
# ## Remove current mouse button bindings
# if self._idPress != None:
# self._idPress = self.canvas.mpl_disconnect(self._idPress)
# self.mode = ''
# if self._idRelease != None:
# self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
# self.mode = ''
# ## Set state, and do state initialization
# self.mode = mode
# def set_mode(self, active):
# print "Set mode called in toolbar from: %s" %self.plot.get_title()
# # if state is unkown or not set, set to default
# if active == None or active not in self._modes.keys():
# active = 'DEFAULT'
# # remove current Selector:
# if self._selector != None:
# # problem is ... i have mutliple selectors still connected
# # trying to remove old selectors connections
# #
# # blah
# # Her Einar ...
# #
# self.canvas.mpl_disconnect(self._selector.onmove)
# self.canvas.mpl_disconnect(self._selector.press)
# self.canvas.mpl_disconnect(self._selector.release)
# self.canvas.mpl_disconnect(self._selector.update_background)
# print "Removing selector in: %s" %self.plot.get_title()
# self._selector = None
# # remove current button bindings
# if self._idPress != None:
# self._idPress = self.canvas.mpl_disconnect(self._idPress)
# self.mode = ''
# if self._idRelease != None:
# self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
# self.mode = ''
# self._modes[active]
# for state, button in self._modes.items():
# if state != active:
# continue
# if state == 'SELECT':
# for ax in self.canvas.figure.get_axes():
# props = dict(facecolor='blue', edgecolor = 'black',
# alpha=0.3, fill=True)
# print "creating a selector"
# self._selector = RectangleSelector(ax, self.on_select,
# drawtype='box', useblit=True,
# rectprops=props)
# self.mode = 'Select rectangle mode'
# elif state == 'PAN':
# self._idPress = self.canvas.mpl_connect(
# 'button_press_event', self.press_pan)
# self._idRelease = self.canvas.mpl_connect(
# 'button_release_event', self.release_pan)
# self.mode = 'pan/zoom mode'
# elif state == 'ZOOM':
# self._idPress = self.canvas.mpl_connect('button_press_event', self.press_zoom)
# self._idRelease = self.canvas.mpl_connect('button_release_event', self.release_zoom)
# self.mode = 'Zoom to rect mode'
# elif state == 'DEFAULT':
# pass
# else:
# pass
# if not button.get_active():
# button.set_active(True)
# for a in self.canvas.figure.get_axes():
# a.set_navigate_mode(self._active)
# self.set_message(self.mode)
# self._active = active
# # update global active_mode (for all toolbar)
# globals()['active_mode'] = active
# def get_mode(self):
# if self._active == None:
# return 'DEFAULT'
# return self._active
# def default(self, button):
# """Activates default mode"""
# if not button.get_active():
# return
# self.set_mode('DEFAULT')
# def select(self, button):
# """Activate select mode"""
# if not button.get_active():
# return
# self.set_mode('SELECT')
# def on_select(self, eclick, erelease, selector):
# 'eclick and erelease are matplotlib events at press and release'
# if self._select_callback:
# print "Onselect called:"
# print " %s" % selector
# self._select_callback(eclick.xdata, eclick.ydata, erelease.xdata, erelease.ydata)
# def pan(self, button):
# """Activate the pan/zoom tool. pan with left button, zoom with right"""
# if not button.get_active():
# return
# self.set_mode('PAN')
# def zoom(self, button):
# """Activate zoom to rect mode"""
# if not button.get_active():
# return
# self.set_mode('ZOOM')
# def mouse_move(self, event):
# """Extend NavigationToolbar2.mouse_move to provide selection support."""
# # Only update the rubberband for selection mode when mouse is
# # within the plotting area.
# #if event.inaxes and self._active=='SELECT':
# # if self._lastCursor != cursors.SELECT_REGION:
# # self.set_cursor(cursors.SELECT_REGION)
# # self._lastCursor = cursors.SELECT_REGION
# # if self._xypress is not None:
# # x, y = event.x, event.y
# # lastx, lasty, a, ind, lim, trans= self._xypress
# # self.draw_rubberband(event, x, y, lastx, lasty)
# NavigationToolbar2.mouse_move(self, event)
# def set_select_callback(self, listener):
# """Allow plots to register a callback for selection events.
# The callback will be called as listener(x1, y1, x2, y2). All
# coordinates are in the plot coordinate system, not pixels or
# widget coordinates.
# """
# self._select_callback = listener
# def set_cursor(self, cursor):
# self.canvas.window.set_cursor(cursord[cursor])
# def dynamic_update(self):
# # legacy method; new method is canvas.draw_idle
# self.canvas.draw_idle()
# def save_figure(self, button):
# fname = self.fileselect.get_filename_from_user()
# if fname:
# self.canvas.print_figure(fname)
# def configure_subplots(self, button):
# toolfig = Figure(figsize=(6,3))
# canvas = self._get_canvas(toolfig)
# toolfig.subplots_adjust(top=0.9)
# tool = SubplotTool(self.canvas.figure, toolfig)
# w = int (toolfig.bbox.width())
# h = int (toolfig.bbox.height())
# window = gtk.Window()
# window.set_title("Subplot Configuration Tool")
# window.set_default_size(w, h)
# vbox = gtk.VBox()
# window.add(vbox)
# vbox.show()
# canvas.show()
# vbox.pack_start(canvas, True, True)
# window.show()
# def _get_canvas(self, fig):
# return FigureCanvas(fig)
# Create a view-changed signal that should be emitted every time
# the active view changes.
gobject.signal_new('view-changed', MainView, gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,))
# Create focus-changed signal
gobject.signal_new('focus-changed', ViewFrame, gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN,))