diff --git a/system/plots.py b/system/plots.py index c1f6a72..2fbec64 100644 --- a/system/plots.py +++ b/system/plots.py @@ -398,96 +398,128 @@ class Plot (View): class LineViewPlot(Plot): - """Line view of current selection, no interaction - Only works on 2d-arrays + """Line view plot with percentiles. + + A line view of vectors across a specified dimension of input dataset. + No selection interaction is defined. + Only support for 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) + + fixme: 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) + self._data = dataset.asarray() if len(self._data.shape)==2 and not minor_axis: minor_axis = major_axis-1 + self.major_axis = major_axis + self.minor_axis = minor_axis + Plot.__init__(self, name) + self.use_blit = False #fixme: blitting does work + self.current_dim = self.dataset.get_dim_name(major_axis) + # make axes + self.ax = self.fig.add_subplot(111) + #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)]) + yi = self._data.take([xi], major_axis).ravel() + self.line_segs.append([(xx,yy) for xx,yy in izip(x_axis, yi)]) - #background - xax = scipy.arange(self._data.shape[0]) + # draw background + self._set_background(self.ax) + + # add canvas + self.add(self.canvas) + self.canvas.show() + + # add toolbar + #FIXME: Lineview plot cannot do selections -> disable in toolbar + #self._toolbar = PlotToolbar(self) + self.canvas.mpl_connect('resize_event', self.clear_background) + + def _set_background(self,ax): + """Add three patches representing [min max],[5,95] and [25,75] percentiles, and a line at the median. + """ + # settings + patch_color = 'b' #blue + patch_lw = 0 #no edges + patch_alpha = .15 # transparancy + median_color = 'b' #blue + median_width = 1.5 #linewidth + percentiles = [0, 5, 25, 50, 75, 100] + + # ordinate + xax = scipy.arange(self._data.shape[self.minor_axis]) + + #vertices verts_0 = [] #100,0 verts_1 = [] # 90,10 verts_2 = [] # 75,25 med = [] + # add top vertices the low vertices (do i need an order?)#background 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])) + prct = prctile(self._data.take([i], self.minor_axis), percentiles) + verts_0.append((i, prct[0])) + verts_1.append((i, prct[1])) + verts_2.append((i, prct[2])) + med.append(prct[3]) 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]) + prct = prctile(self._data.take([i], self.minor_axis), percentiles) + verts_0.append((i, prct[-1])) + verts_1.append((i, prct[-2])) + verts_2.append((i, prct[-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) + # make polygons from vertices + bck0 = Polygon(verts_0, alpha=patch_alpha, lw=patch_lw, + facecolor=patch_color) + bck1 = Polygon(verts_1, alpha=patch_alpha, lw=patch_lw, + facecolor=patch_color) + bck2 = Polygon(verts_2, alpha=patch_alpha, lw=patch_lw, + facecolor=patch_color) + + # add polygons to axes + ax.add_patch(bck0) + ax.add_patch(bck1) + ax.add_patch(bck2) + # median line + ax.plot(xax, med, median_color, linewidth=median_width) def clear_background(self, event): + """Callback on resize event. Clears the background. + """ self._background = None def set_current_selection(self, selection): + """Draws the current selection. + """ ids = selection[self.current_dim] # current identifiers index = self.dataset.get_indices(self.current_dim, ids) + if len(index)==0: # do we have a selection + return 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() - + if len(self.ax.collections)>0: # remove old linecollection + 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)) + #draw + if self.use_blit: + self.ax.draw_artist(line_coll) + self.canvas.blit() + else: + self.ax.add_collection(line_coll) + self.canvas.draw() class ScatterMarkerPlot(Plot): """The ScatterMarkerPlot is faster than regular scatterplot, but @@ -596,6 +628,7 @@ class ScatterPlot(Plot): assert y1<=y2 index = scipy.nonzero((xdata>x1) & (xdatay1) & (ydata0: lw.put(2.,index) self.coll.set_linewidth(lw)