def init(self, parent): factory = self.factory container = OverlayPlotContainer(bgcolor='transparent', padding=0, spacing=0) window = Window(parent, component=container) interval = self.high - self.low data = ([self.low, self.high], [0.5]*2) plot = create_line_plot(data, color='black', bgcolor="sys_window") plot.x_mapper.range.low = self.low - interval*0.1 plot.x_mapper.range.high = self.high + interval*0.1 plot.y_mapper.range.high = 1.0 plot.y_mapper.range.low = 0.0 range_selection = RangeSelection(plot, left_button_selects=True) # Do not allow the user to reset the range range_selection.event_state = "selected" range_selection.deselect = lambda x: None range_selection.on_trait_change(self.update_interval, 'selection') plot.tools.append(range_selection) plot.overlays.append(RangeKnobsOverlay(plot)) self.plot = plot container.add(self.plot) # To set the low and high, we're actually going to set the # 'selection' metadata on the line plot to the tuple (low,high). plot.index.metadata["selections"] = (0, 1.0) # Tell the editor what to display self.control = window.control self.control.SetSize((factory.width, factory.height))
def _create_price_plots(self, times, prices, mini_height=75): """ Creates the two plots of prices and returns them. One of the plots can be zoomed and panned, and the other plot (smaller) always shows the full data. *dates* and *prices* are two data sources. """ # Create the price plot price_plot = FilledLinePlot(index = times, value = prices, index_mapper = LinearMapper(range=DataRange1D(times)), value_mapper = LinearMapper(range=DataRange1D(prices)), edge_color = "blue", face_color = "paleturquoise", bgcolor = "white", border_visible = True) # Add pan and zoom price_plot.tools.append(PanTool(price_plot, constrain=True, constrain_direction="x")) price_plot.overlays.append(ZoomTool(price_plot, drag_button="right", always_on=True, tool_mode="range", axis="index", max_zoom_out_factor=1.0, )) # Create the miniplot miniplot = LinePlot(index = times, value = prices, index_mapper = LinearMapper(range=DataRange1D(times)), value_mapper = LinearMapper(range=DataRange1D(prices)), color = "black", border_visible = True, bgcolor = "white", height = mini_height, resizable = "h") # Add a range overlay to the miniplot that is hooked up to the range # of the main price_plot range_tool = RangeSelection(miniplot) miniplot.tools.append(range_tool) range_overlay = RangeSelectionOverlay(miniplot, metadata_name="selections") miniplot.overlays.append(range_overlay) range_tool.on_trait_change(self._range_selection_handler, "selection") # Attach a handler that sets the tool when the plot's index range changes self.range_tool = range_tool price_plot.index_range.on_trait_change(self._plot_range_handler, "updated") return price_plot, miniplot
def create_hplot(self, key=None, mini=False): if mini: hpc = HPlotContainer(bgcolor='darkgrey', height=MINI_HEIGHT, resizable='h', padding=HPLOT_PADDING ) else: hpc = HPlotContainer(bgcolor='lightgrey', padding=HPLOT_PADDING, resizable='hv' ) # make slice plot for showing intesity profile of main plot #************************************************************ slice_plot = Plot(self.data, width=SLICE_PLOT_WIDTH, orientation="v", resizable="v", padding=MAIN_PADDING, padding_left=MAIN_PADDING_LEFT, padding_bottom=MAIN_PADDING_BOTTOM, bgcolor='beige', origin='top left' ) mini_slice = Plot(self.data, width=SLICE_PLOT_WIDTH, orientation="v", resizable="v", padding=MAIN_PADDING, padding_left=MAIN_PADDING_LEFT, padding_bottom=MAIN_PADDING_BOTTOM, bgcolor='beige', origin='top left' ) slice_plot.x_axis.visible = True slice_key = key + '_slice' ydata_key = key + '_y' slice_plot.plot((ydata_key, slice_key), name=slice_key) # make plot to show line at depth of cursor. y values constant slice_depth_key = key + '_depth' slice_plot.plot(('slice_depth_depth', 'slice_depth_y'), name=slice_depth_key, color='red') self.update_slice_depth_line_plot(slice_plot, depth=0) # make main plot for editing depth lines #************************************************************ main = Plot(self.data, border_visible=True, bgcolor='beige', origin='top left', padding=MAIN_PADDING, padding_left=MAIN_PADDING_LEFT, padding_bottom=MAIN_PADDING_BOTTOM ) if mini: #main.padding = MINI_PADDING main.padding_bottom = MINI_PADDING_BOTTOM # add intensity img to plot and get reference for line inspector #************************************************************ img_plot = main.img_plot(key, name=key, xbounds=self.model.xbounds[key], ybounds=self.model.ybounds[key], colormap=self._cmap )[0] # add line plots: use method since these may change #************************************************************ self.update_line_plots(key, main, update=True) self.plot_mask_array(key, main) # set slice plot index range to follow main plot value range #************************************************************ slice_plot.index_range = main.value_range # add vertical core lines to main plots and slices #************************************************************ # save pos and distance in session dict for view info and control for core in self.model.core_samples: # add boundarys to slice plot self.plot_core_depths(slice_plot, core, ref_depth_line=None) # add positions to main plots self.plot_core(main, core, ref_depth_line=None) # now add tools depending if it is a mini plot or not #************************************************************ if mini: # add range selection tool only # first add a reference line to attach it to reference = self.make_reference_plot() main.add(reference) main.plots['reference'] = [reference] # attache range selector to this plot range_tool = RangeSelection(reference) reference.tools.append(range_tool) range_overlay = RangeSelectionOverlay(reference, metadata_name="selections") reference.overlays.append(range_overlay) range_tool.on_trait_change(self._range_selection_handler, "selection") # add zoombox to mini plot main.plot(('zoombox_x', 'zoombox_y'), type='polygon', face_color=ZOOMBOX_COLOR, alpha=ZOOMBOX_ALPHA) # add to hplot and dict hpc.add(main, mini_slice) self.hplot_dict['mini'] = hpc else: # add zoom tools zoom = ZoomTool(main, tool_mode='box', axis='both', alpha=0.5, drag_button="left") main.tools.append(zoom) main.overlays.append(zoom) self.zoom_tools[key] = zoom main.value_mapper.on_trait_change(self.zoom_all_value, 'updated') main.index_mapper.on_trait_change(self.zoom_all_index, 'updated') # add line inspector and attach to freeze tool #********************************************* line_inspector = LineInspector(component=img_plot, axis='index_x', inspect_mode="indexed", is_interactive=True, write_metadata=True, metadata_name='x_slice', is_listener=True, color="white") img_plot.overlays.append(line_inspector) self.inspector_freeze_tool.tool_set.add(line_inspector) # add listener for changes to metadata made by line inspector #************************************************************ img_plot.on_trait_change(self.metadata_changed, 'index.metadata') # set slice plot index range to follow main plot value range #************************************************************ slice_plot.index_range = main.value_range # add clickable legend ; must update legend when depth_dict updated #****************************************************************** legend = Legend(component=main, padding=0, align="ur", font='modern 8') legend_highlighter = LegendHighlighter(legend, drag_button="right") legend.tools.append(legend_highlighter) self.legend_dict[key] = [legend, legend_highlighter] self.update_legend_plots(legend, main) legend.visible = False main.overlays.append(legend) legend_highlighter.on_trait_change(self.legend_moved, '_drag_state') # add pan tool pan_tool = PanTool(main, drag_button="right") main.tools.append(pan_tool) self.pan_tool_dict[key] = pan_tool # add main and slice plot to hplot container and dict #**************************************************** main.title = 'frequency = {} kHz'.format(key) main.title_font = TITLE_FONT hpc.add(main, slice_plot) self.hplot_dict[key] = hpc return hpc
def create_hplot(self, key=None, mini=False): if mini: hpc = HPlotContainer(bgcolor='darkgrey', height=MINI_HEIGHT, resizable='h', padding=0) else: hpc = HPlotContainer(bgcolor='lightgrey', padding=HPLOT_PADDING, resizable='hv') # make slice plot for showing intesity profile of main plot #************************************************************ slice_plot = Plot(self.data, width=SLICE_PLOT_WIDTH, orientation="v", resizable="v", padding=MAIN_PADDING, padding_left=MAIN_PADDING_LEFT, bgcolor='beige', origin='top left') slice_plot.x_axis.visible = False slice_key = key + '_slice' ydata_key = key + '_y' slice_plot.plot((ydata_key, slice_key), name=slice_key) # make main plot for editing depth lines #************************************************************ main = Plot( self.data, border_visible=True, bgcolor='beige', origin='top left', padding=MAIN_PADDING, padding_left=MAIN_PADDING_LEFT, ) if mini: main.padding = MINI_PADDING # add intensity img to plot and get reference for line inspector #************************************************************ img_plot = main.img_plot(key, name=key, xbounds=self.model.xbounds[key], ybounds=self.model.ybounds[key], colormap=self._cmap)[0] # add line plots: use method since these may change #************************************************************ self.update_line_plots(key, main, update=True) # set slice plot index range to follow main plot value range #************************************************************ slice_plot.index_range = main.value_range # add vertical core lines to main plots and slices #************************************************************ # save pos and distance in session dict for view info and control for core in self.model.core_samples: loc_index, loc, dist = self.model.core_info_dict[core.core_id] # add boundarys to slice plot ref_line = self.model.final_lake_depth self.plot_core_depths(slice_plot, core, ref_line, loc_index) # add positions to main plots self.plot_core(main, core, ref_line, loc_index, loc) # now add tools depending if it is a mini plot or not #************************************************************ if mini: # add range selection tool only # first add a reference line to attach it to reference = self.make_reference_plot() main.add(reference) # attache range selector to this plot range_tool = RangeSelection(reference) reference.tools.append(range_tool) range_overlay = RangeSelectionOverlay(reference, metadata_name="selections") reference.overlays.append(range_overlay) range_tool.on_trait_change(self._range_selection_handler, "selection") # add zoombox to mini plot main.plot(('zoombox_x', 'zoombox_y'), type='polygon', face_color=ZOOMBOX_COLOR, alpha=ZOOMBOX_ALPHA) # add to hplot and dict hpc.add(main) self.hplot_dict['mini'] = hpc else: # add zoom tools main.tools.append(PanTool(main)) zoom = ZoomTool(main, tool_mode='box', axis='both', alpha=0.5) main.tools.append(zoom) main.overlays.append(zoom) main.value_mapper.on_trait_change(self.zoom_all_value, 'updated') main.index_mapper.on_trait_change(self.zoom_all_index, 'updated') # add line inspector and attach to freeze tool #********************************************* line_inspector = LineInspector(component=img_plot, axis='index_x', inspect_mode="indexed", is_interactive=True, write_metadata=True, metadata_name='x_slice', is_listener=True, color="white") img_plot.overlays.append(line_inspector) self.inspector_freeze_tool.tool_set.add(line_inspector) # add listener for changes to metadata made by line inspector #************************************************************ img_plot.on_trait_change(self.metadata_changed, 'index.metadata') # set slice plot index range to follow main plot value range #************************************************************ slice_plot.index_range = main.value_range # add clickable legend ; must update legend when depth_dict updated #****************************************************************** legend = Legend(component=main, padding=0, align="ur", font='modern 8') legend_highlighter = LegendHighlighter(legend, drag_button="right") legend.tools.append(legend_highlighter) self.update_legend_plots(legend, main) legend.visible = False self.legend_dict[key] = [legend, legend_highlighter] main.overlays.append(legend) # add main and slice plot to hplot container and dict #**************************************************** main.title = 'frequency = {} kHz'.format(key) main.title_font = TITLE_FONT hpc.add(main, slice_plot) self.hplot_dict[key] = hpc return hpc
class PandasPlot(HasTraits): '''Plot to interface a pandas df''' ### For testing rnd_cols=Bool(False) samecols=Bool(False) transpose=Bool(False) ### Traits of the actual plot and plotdatasource handler ### _dffull=Instance(DataFrame) #Any? plot=Instance(Plot) plotdata=Instance(PandasPlotData) #Data stored at any given time in the plot df=Instance(DataFrame) ### Axis traits idxname=Str('Index') colname=Str('Column') idxorient=DefaultEnum('top', 'bottom', 'left', 'right', default='bottom') colorient=DefaultEnum('top', 'bottom', 'left', 'right', default='top') selection_axis=DefaultEnum('index','value', default='index') #Which axis does selection tool sample ### Aesthetic traits title=Str('Title') #Defaults from df name linecolor=Str('yellow') pointcolor=Str('red') linestyle=Enum('line', 'scatter', 'both') markersize=Range(low=1, high=5) sampling=Range(low=0.0, high=100., value=100.0) _spacing=Property(depends_on='sampling') ### _Event Handlers def _rnd_cols_changed(self): x=np.linspace(0, 100, 100) #Index generator y=np.linspace(0, 100, 100) #Column generator scale=randint(1,1000) self.df=DataFrame((np.random.rand(len(x),len(y))), columns=(scale/2.0)*y, index=scale*x) def _samecols_changed(self): self.df=DataFrame((np.random.rand(100,100))) def _transpose_changed(self): self.df=self.df.transpose() ### Axis Aesthetics @on_trait_change('idxname','idxcolumn', 'idxorient', 'colorient') def _axis_changed(self, trait, new): '''Change plot axis name or orientation''' setattr(self, trait, new) self._update_axis() self.plot.request_redraw() #Necessary but how do I only call axis redraw? def _title_changed(self, old, new): if old != new: self.plot.title=new self.plot.request_redraw() #HOW TO PREVENT COLLISION WITH TOP OVERLAY def _selection_axis_changed(self, old, new): if old != new: self._update_lines() def _df_changed(self, old, new): ''' Handles how updates occur when df changes. Evaluates if columns or columnlabels have been changed. Provides entry condition as well. Note: New automatically sets self.df, so when I refer to new, I am actually referring to self.df. Using "new" instead of self.df is just for readability''' ### Initialize plot first time df is passed into the class. Boolean listeners ### for df behave oddly, so uses self.plotdata for entry condition. if not self.plotdata: self.plotdata=PandasPlotData(df=new) self._dffull=new ### Try to infer plot title from df name ### try: self.title=new.name #Turn into a "transfer" method where I pass list of attributes i want look for except AttributeError: pass ### Draw barebones of plot self._plot_default() self._update_lines() ### Decide to update columns or completely redraw df. else: changed=self.plotdata.set_df(new) ### If 'event changed', don't bother updaing lines if not changed: self._update_lines() ### Plot spacing def _get__spacing(self): '''Integer spacing given % sampling''' samp=self.sampling/100.0 colsize=df.shape[0] return colsize - int(round( colsize*samp, 0)) def _sampling_changed(self, old, new): if old != new: self._update_samples() def _update_samples(self): '''Updates the list of line plots shown or hidden based on plot sampling.''' if self._spacing==0: return ### Hide all plots to_hide=self.plot.plots.keys() self.plot.hideplot(*to_hide) ### Show only plots in samples to_show=self.plot.plots.keys()[::self._spacing] self.plot.showplot(*to_show) self.plot.request_redraw() def _update_rangeselect(self): ''' Overwrites range selection tool in current plot.''' #### Remove current overlay self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)] mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary inds=range(len(self.df.index)) idx=ArrayDataSource(inds) vals=ArrayDataSource(df.index.values) index_range = DataRange1D(idx) val_range=DataRange1D(vals) imap=LinearMapper(range=index_range)#,stretch_data=self.index_mapper.stretch_data) vmap=LinearMapper(range=val_range) # mycomp.index_range.refresh() mycomp.index_mapper=imap mycomp.value_mapper=vmap self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis) self.plot.active_tool = self.rangeselect self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) self.rangeselect.on_trait_change(self.on_selection_changed, "selection") def _update_lines(self): ''' Redraws lines, plots and reapplies line selection.''' oldplots=self.plot.plots.keys() newplots=[name for name in self.plotdata.list_data(as_strings=True)] to_remove=[p for p in oldplots if p not in newplots] to_add=[p for p in newplots if p not in oldplots] if to_remove: for p in to_remove: self.plot.delplot(p) if to_add: for name in to_add: self.plot.plot(('index', name), name=name, color=self.linecolor) self._update_axis() self._update_samples() self._update_rangeselect() def on_selection_changed(self, selection): if selection != None: self.rangeXMin, self.rangeXMax = selection print selection def _update_axis(self): ''' Forces a label axis onto the plot. ''' print 'updaing axis', self.idxname indexlabels=[str(round(i,1)) for i in self.df.index] columnlabels=[str(round(i,1)) for i in self.df.columns] index_axis=LabelAxis(self.plot, orientation=self.idxorient, positions=range(int(float(indexlabels[0])), int(float(indexlabels[-1]))), labels=indexlabels,#, resizable='hv', title=self.idxname) col_axis=LabelAxis(self.plot, orientation=self.colorient, positions=range(int(float(columnlabels[0])), int(float(columnlabels[-1]))), labels=columnlabels,#, resizable='hv', title=self.colname) ### Remove underlays self.plot.underlays=[obj for obj in self.plot.underlays if not isinstance(obj, PlotAxis)] self.plot.underlays=[obj for obj in self.plot.underlays if not isinstance(obj, LabelAxis)] self.plot.underlays.append(index_axis) self.plot.underlays.append(col_axis) def _plot_default(self, toolbar=True, **pltkwds): ''' Draw bare plot, including main plotting area, toolbar, etc... either at initialization or global redo''' if toolbar: self.plot=ToolbarPlot(self.plotdata, **pltkwds) else: self.plot=Plot(self.plotdata, **pltkwds) self.plot.title = self.title self.plot.padding = 50 self.plot.legend.visible=False self.plot.tools.append(PanTool(self.plot)) zoom=BetterSelectingZoom(component=self.plot, tool_mode="box", always_on=False) self.plot.overlays.append(zoom) def _overwrite_plotdata(self): '''When a new instance of PandasPlotData is created, this overwrites the data source and updates the axis values.''' self.plotdata=PandasPlotData(df=self.df) self._plot_default() #CAN THIS JUST DRAW LINES ### Traits View main_group=Group( HGroup(Item('rnd_cols'), Item('samecols'), Item('transpose'),), Item('plot', editor=ComponentEditor(), show_label=False), Item('idxname'), Item('idxorient'), Item('selection_axis'), Item('title'), Item('sampling'), # Item('df_new'), Item('df_change'), #Include('sample_group'), #Include('axis_traits_group') ) traits_view=View( Include('main_group') , height=600, width=800)
def __init__(self, **kw): super(MLabChacoPlot, self).__init__(**kw) self.prices = get_data() x = self.prices['Date'] pd = ArrayPlotData(index = x) pd.set_data("y", self.prices["Crude Supply"]) # Create some line plots of some of the data plot = Plot(pd, bgcolor="none", padding=30, border_visible=True, overlay_border=True, use_backbuffer=False) #plot.legend.visible = True plot.plot(("index", "y"), name="Crude Price", color=(.3, .3, .8, .8)) #plot.tools.append(PanTool(plot)) plot.tools.append(PanTool(plot, constrain=True, drag_button="right", constrain_direction="x")) range_plt = plot.plots['Crude Price'][0] range_selection = RangeSelection(range_plt, left_button_selects=True) range_selection.on_trait_change(self.update_interval, 'selection') range_plt.tools.append(range_selection) range_plt.overlays.append(RangeSelectionOverlay(range_plt)) zoom = ZoomTool(component=plot, tool_mode="range", always_on=False, axis="index", max_zoom_out_factor=1.0,) plot.overlays.append(zoom) # Set the plot's bottom axis to use the Scales ticking system scale_sys = CalendarScaleSystem(fill_ratio=0.4, default_numlabels=5, default_numticks=10,) tick_gen = ScalesTickGenerator(scale=scale_sys) bottom_axis = ScalesPlotAxis(plot, orientation="bottom", tick_generator=tick_gen, label_color="white", line_color="white") # Hack to remove default axis - FIXME: how do I *replace* an axis? del(plot.underlays[-2]) plot.overlays.append(bottom_axis) # Create the mlab test mesh and get references to various parts of the # VTK pipeline f = mlab.figure(size=(700,500)) self.m = mlab.points3d(self.prices['Gasoline Supply'], self.prices['Jet Fuel Supply'], self.prices['Distillate Supply'], self.prices['Crude Supply']) # Add another glyph module to render the full set of points g2 = Glyph() g2.glyph.glyph_source.glyph_source.glyph_type = "circle" g2.glyph.glyph_source.glyph_source.filled = True g2.actor.property.opacity = 0.75 self.m.module_manager.source.add_module(g2) # Set a bunch of properties on the scene to make things look right self.m.module_manager.scalar_lut_manager.lut_mode = 'PuBuGn' self.m.glyph.mask_points.random_mode = False self.m.glyph.mask_points.on_ratio = 1 self.m.scene.isometric_view() self.m.scene.background = (.9, 0.95, 1.0) scene = mlab.gcf().scene render_window = scene.render_window renderer = scene.renderer rwi = scene.interactor plot.resizable = "" plot.bounds = [600,120] plot.padding = 25 plot.bgcolor = "white" plot.outer_position = [30,30] plot.tools.append(MoveTool(component=plot,drag_button="right")) container = OverlayPlotContainer(bgcolor = "transparent", fit_window = True) container.add(plot) # Create the Enable Window window = EnableVTKWindow(rwi, renderer, component=container, istyle_class = tvtk.InteractorStyleTrackballCamera, bgcolor = "transparent", event_passthrough = True, ) mlab.show()
def _create_price_plots(self, times, prices, mini_height=75): """ Creates the two plots of prices and returns them. One of the plots can be zoomed and panned, and the other plot (smaller) always shows the full data. *dates* and *prices* are two data sources. """ # Create the price plot price_plot = FilledLinePlot( index=times, value=prices, index_mapper=LinearMapper(range=DataRange1D(times)), value_mapper=LinearMapper(range=DataRange1D(prices)), edge_color="blue", face_color="paleturquoise", bgcolor="white", border_visible=True) # Add pan and zoom price_plot.tools.append( PanTool(price_plot, constrain=True, constrain_direction="x", restrict_to_data=True)) price_plot.overlays.append( ZoomTool(price_plot, drag_button="right", always_on=True, tool_mode="range", axis="index", max_zoom_out_factor=1.0, x_min_zoom_factor=float(1e-3))) # Create the miniplot miniplot = LinePlot( index=times, value=prices, index_mapper=LinearMapper(range=DataRange1D(times)), value_mapper=LinearMapper(range=DataRange1D(prices)), color="black", border_visible=True, bgcolor="white", height=mini_height, resizable="h") # Add a range overlay to the miniplot that is hooked up to the range # of the main price_plot range_tool = RangeSelection(miniplot) miniplot.tools.append(range_tool) range_overlay = RangeSelectionOverlay(miniplot, metadata_name="selections") miniplot.overlays.append(range_overlay) range_tool.on_trait_change(self._range_selection_handler, "selection") # Attach a handler that sets the tool when the plot's index range changes self.range_tool = range_tool price_plot.index_range.on_trait_change(self._plot_range_handler, "updated") return price_plot, miniplot
class Display(HasTraits, object): def __init__(self, queue, **kwargs): super(Display, self).__init__() self.jobqueue = queue self.add_trait('filename', Int()) def _arrow_callback(self, tool, n): if n == 1: self.jobqueue.put(['updatecache', ['right']]) else: self.jobqueue.put(['updatecache', ['left']]) def _metadata_handler(self): sel_indices = self.index_datasource.metadata.get('selections', []) hover_indices = self.index_datasource.metadata.get('hover', []) print "Selection indices:", sel_indices print "Hover indices:", hover_indices if sel_indices: self.jobqueue.put(['changendx', [sel_indices[-1]]]) print sel_indices[-1] if hover_indices: self.filename = hover_indices[0] print 'self.filename', self.filename else: self.filename = -1 return def plotImage(self, image, plot=None): '''plot one image image: Image object plot: plot instance to be update, if None, a plot instance will be created return: plot instance''' if plot == None: pd = ArrayPlotData() pd.set_data('imagedata', image.data) plot = Plot(pd, default_origin = "bottom left", padding=0) #plot.title = image.name plot.bgcolor = 'white' plot.fixed_preferred_size = (100, 100) plot.x_axis.visible = False plot.y_axis.visible = False self.imageplot = plot # TODO: mess with color maps on else block imgPlot = plot.img_plot("imagedata", colormap=jet, name='image')[0] self.imgPlot = imgPlot self._appendImageTools(imgPlot) #plot.overlays.append(MyLineDrawer(plot)) else: plot.data.set_data('imagedata', image.data) imgPlot = plot.plots['image'][0] #plot.title = image.name plot.aspect_ratio = float(image.data.shape[1]) / image.data.shape[0] plot.invalidate_draw() return plot def plotRRMap(self, rr, rrchoice, plot=None): if plot == None: pd = ArrayPlotData(y=np.array([0]), x=np.array([0])) plot = Plot(pd, padding=(70, 5, 0, 0)) self._setData(rr, plot) plot.plot(('x', 'y'), name='rrplot', type="scatter", color='green', marker="circle", marker_size=6) #plot.title = 'rrplot' plot.value_axis.title = rrchoice #plot.y_axis.visible = False plot.bgcolor = 'white' plot.aspect_ratio = 2.5 plot.fixed_preferred_size = (100, 50) #left, bottom = add_default_axes(plot) hgrid, vgrid = add_default_grids(plot) self._appendCMapTools(plot) else: self._setData(rr, plot) plot.request_redraw() return plot def _setData(self, rr, plot): if rr == None: return ydata = plot.data.get_data('y') if len(ydata) == 1 and ydata[0] == 0: ydata = np.array([rr]) else: ydata = np.append(ydata, [rr]) plot.data.set_data('x', range(len(ydata))) plot.data.set_data('y', ydata) #print rr #print plot.data.get_data('y') #print plot.data.get_data('x') return def plotHistogram(self, image, plot=None): if plot == None: pd = ArrayPlotData(y=np.array([0]), x=np.array([0])) plot = Plot(pd, padding=(70, 10, 0, 0)) plot.plot(('x', 'y'), name='Histogram', type='bar', bar_width=5.0, color='auto') #plot.title = 'Histogram' plot.line_color = 'black' plot.bgcolor = "white" plot.fixed_preferred_size = (100, 30) add_default_grids(plot) plot.value_axis.title = "Histogram" self._appendHistogramTools(plot) ''' plot.overlays.append(PlotAxis(plot, orientation='left')) plot.overlays.append(PlotAxis(plot, orientation='bottom')) ''' else: data = np.histogram(image.data, bins=10000) index = np.delete(data[1], data[1].size-1) values = data[0] plot.index_range.low= np.min(index) plot.index_range.high = np.max(index) plot.value_range.low = 0 plot.value_range.high = np.max(values) plot.data.set_data('x', index) plot.data.set_data('y', values) plot.request_redraw() return plot def _appendImageTools(self, plot): '''append xy position, zoom, pan tools to plot ''' plot.tools.append(PanTool(plot)) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False, color='transparent', zoom_factor=1.25, pointer='sizing', prev_state_key=KeySpec('n'), next_state_key=KeySpec('m'), x_min_zoom_factor = 1.0, y_min_zoom_factor = 1.0 ) plot.overlays.append(zoom) plot.zoom = zoom plot.tools.append(KBInputTool(plot, arrow_cb=self._arrow_callback)) #plot.overlays.append(MyLineDrawer(plot)) colormap = plot.color_mapper colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), color_mapper=colormap, plot=plot, orientation='v', resizable='v', width=30, padding=20) range_selection = RangeSelection(component=colorbar) colorbar.tools.append(range_selection) rangeselect = RangeSelectionOverlay(component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray") colorbar.overlays.append(rangeselect) range_selection.listeners.append(plot) self.colorbar = colorbar return def _appendHistogramTools(self, plot): plot.tools.append(PanTool(plot)) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False, color='transparent', zoom_factor=1.25, pointer='sizing', enter_zoom_key=KeySpec('p'), prev_state_key=KeySpec('n'), next_state_key=KeySpec('m'), x_min_zoom_factor = 1.0, y_min_zoom_factor = 1.0 ) plot.overlays.append(zoom) plot.zoom = zoom my_plot = plot.plots["Histogram"][0] selected = Event() self.range_selection = RangeSelection(component=my_plot, selection_completed = selected) self.range_selection.on_trait_change(self._selection_changed, 'selection_completed') my_plot.tools.append(self.range_selection) rangeselect = RangeSelectionOverlay(component=my_plot, border_color="white", alpha=0.8, fill_color="lightgray") my_plot.overlays.append(rangeselect) self.range_selection.listeners.append(self.imgPlot) return def _selection_changed(self): print 'Region highlighted' print self.range_selection._selection return def _appendCMapTools(self, plot): my_plot = plot.plots['rrplot'][0] self.index_datasource = my_plot.index self.index_datasource.on_trait_change(self._metadata_handler, "metadata_changed") my_plot.tools.append(ScatterInspector(my_plot, selection_mode="toggle", persistent_hover=False)) my_plot.overlays.append(ScatterInspectorOverlay(my_plot, hover_color = "transparent", hover_marker_size = 10, hover_outline_color = "purple", hover_line_width = 2, selection_marker_size = 8, selection_color = "lawngreen") ) zoom = ZoomTool(component=plot, tool_mode='box', always_on=False, zoom_factor=1.25, color='transparent') plot.overlays.append(zoom) plot.tools.append(PanTool(plot)) return
class Trait(HasTraits): plot = Instance(Component) #creates the container container = OverlayPlotContainer(padding = 50, fill_padding = True, bgcolor = "lightgray", use_backbuffer=True) container2 = OverlayPlotContainer(padding = 50, fill_padding = True, bgcolor = "lightgray", use_backbuffer=True) a1 = [] b1 = [] a2 = [] b2 = [] # Traits xmin = Float xmax = Float ymin = Float ymax = Float rangeXMin = Float rangeXMax = Float sl=plotData() arr,index=sl.reader("~/cyborg-t1dm/cyborg-t1dm/viztool/MYFILE104.no_gaps.csv") x,y = arr['8SkinTempAve'], arr['28SensorValue'] for i in range(len(x)): if x[i]!= float('inf'): a1.append(x[i]) b1.append(y[i]) print len(arr['8SkinTempAve']) print len(a1) timestamp = [] timestamp.extend(range(0,len(arr['8SkinTempAve']+1))) space,startpoint,maxcount=sl.bestspace(arr,index,8,90) space = 115 c,d = sl.plotter(arr,index,8,space,startpoint,90) print space mean1 = mean(a1) mean2 = mean(b1) std1 = std(a1) std2 = std(b1) for i in range(len(x)): if x[i]!= float('inf'): a2.append((x[i]-mean1)/std1) b2.append((y[i]-mean2)/std2) else: a2.append(-1) b2.append(-1) print len(a2) z = [0]*space e = z+b2 ''' mean1 = mean(x) mean2 = mean(y) print mean1 print mean2 std1 = std(x) std2 = std(y) for i in range(len(x)): a.append((x[i] - mean1)/std1) b.append((y[i] - mean2)/std2) z = [0]*space e = z+a #print e ''' # TraitsUI view traits_view = View(Group( HGroup( VGroup(Item("container", editor = ComponentEditor(), show_label = False)), VGroup(Item("container2", editor = ComponentEditor(), show_label = False))), HGroup(Item("xmin"), Item("xmax"), Item("ymin"), Item("ymax"), show_border = True, label = "Plotborders"), HGroup(Item("rangeXMin", label="x_min"), Item("rangeXMax", label="x_max"), show_border = True, label="Range of right plot")), buttons = [OKButton, CancelButton], resizable = True, width = 1000, height = 500) # Constructor def __init__(self): super(Trait, self).__init__() uebergabe = main() # initialize traits self.xmin = uebergabe["xlim"][0] self.xmax = uebergabe["xlim"][1] self.ymin = uebergabe["ylim"][0] self.ymax = uebergabe["ylim"][1] self.rangeXMin = uebergabe["ranges"][0] self.rangeXMin = uebergabe["ranges"][1] self.y3 = 0 self.y4 = 1 self._create_Container() def _create_Container(self): #creating dict of plots and the broadcaster plots = {} broadcaster = BroadcasterTool() #=====================first container=========================== #first plot #index = linspace(-2*pi,2*pi,1000) plot = create_line_plot((self.timestamp, self.e), color = "black", index_bounds=(self.xmin, self.xmax), value_bounds = (self.ymin, self.ymax)) plot.bgcolor = "white" plot.border_visible = True value_mapper = plot.value_mapper index_mapper = plot.index_mapper add_default_grids(plot) add_default_axes(plot) self.sync_trait("xmin", index_mapper.range, "_low_value") self.sync_trait("xmax", index_mapper.range, "_high_value") self.sync_trait("ymin", value_mapper.range, "_low_value") self.sync_trait("ymax", value_mapper.range, "_high_value") # range selection self.rangeselect = RangeSelection(plot, left_button_selects = False, auto_handle_event = False) plot.active_tool = self.rangeselect plot.overlays.append(RangeSelectionOverlay(component=plot)) self.rangeselect.on_trait_change(self.on_selection_changed, "selection") #adds plot to the container self.container.add(plot) # second plot index2 = linspace(-5*pi,4*pi,1000) plot = create_line_plot((self.timestamp, self.a2), color = "red", index_bounds=(self.xmin, self.xmax), value_bounds = (self.ymin, self.ymax)) print plot plot.value_mapper = value_mapper value_mapper.range.add(plot.value) plot.index_mapper = index_mapper index_mapper.range.add(plot.index) # Create a pan tool and give it a reference to the plot pan = PanTool(plot, drag_button="left") broadcaster.tools.append(pan) # allows to zoom zoom = ZoomTool(plot, tool_mode="box", always_on = False, visible = True) plot.overlays.append(zoom) #adds plot to the container self.container.add(plot) # appends broadcaster to the container self.container.tools.append(broadcaster) # title of the container self.container.overlays.append(PlotLabel("Plotting of the Normalized SkinTemp and CGM Timeseries ", component=self.container, overlay_position = "top")) #==============end of first container=========================== #====================second container=========================== #first plot2 plot2 = create_line_plot((self.c, self.d), color = "blue", index_bounds=(self.rangeXMin, self.rangeXMax), value_bounds = (self.y3, self.y4)) plot2.bgcolor = "white" plot2.border_visible = True #plot2.value_mapper = value_mapper # the plot uses the same index and #plot2.index_mapper = index_mapper # value like the plots of container1 self.sync_trait("rangeXMin", plot2.index_mapper.range, "low", False) self.sync_trait("rangeXMax", plot2.index_mapper.range, "high", False) plot2.index_mapper.range.low = 0 plot2.index_mapper.range.high = 10000 plot2.value_mapper.range.low = 0 plot2.value_mapper.range.high = 1 value_mapper.range.add(plot2.value) index_mapper.range.add(plot2.index) add_default_grids(plot2) add_default_axes(plot2) #adds plot to the container self.container2.add(plot2) # title of the container self.container2.overlays.append(PlotLabel("R-Squared Correlation", component=self.container, overlay_position = "top")) index_mapper.on_trait_change(self.on_mapper_updated, "updated") #=============end of second container=========================== def on_mapper_updated(self, mapper, name, value): if not self.rangeselect.selection: self.rangeXMin = mapper.range.low self.rangeXMax = mapper.range.high def on_selection_changed(self, selection): if selection != None: self.rangeXMin, self.rangeXMax = selection #print selection print pearsonr (self.x,self.y)
class PandasPlot(HasTraits): '''Plot to interface a pandas df''' ### For testing rnd_cols = Bool(False) samecols = Bool(False) transpose = Bool(False) ### Traits of the actual plot and plotdatasource handler ### _dffull = Instance(DataFrame) #Any? plot = Instance(Plot) plotdata = Instance( PandasPlotData) #Data stored at any given time in the plot df = Instance(DataFrame) ### Axis traits idxname = Str('Index') colname = Str('Column') idxorient = DefaultEnum('top', 'bottom', 'left', 'right', default='bottom') colorient = DefaultEnum('top', 'bottom', 'left', 'right', default='top') selection_axis = DefaultEnum( 'index', 'value', default='index') #Which axis does selection tool sample ### Aesthetic traits title = Str('Title') #Defaults from df name linecolor = Str('yellow') pointcolor = Str('red') linestyle = Enum('line', 'scatter', 'both') markersize = Range(low=1, high=5) sampling = Range(low=0.0, high=100., value=100.0) _spacing = Property(depends_on='sampling') ### _Event Handlers def _rnd_cols_changed(self): x = np.linspace(0, 100, 100) #Index generator y = np.linspace(0, 100, 100) #Column generator scale = randint(1, 1000) self.df = DataFrame((np.random.rand(len(x), len(y))), columns=(scale / 2.0) * y, index=scale * x) def _samecols_changed(self): self.df = DataFrame((np.random.rand(100, 100))) def _transpose_changed(self): self.df = self.df.transpose() ### Axis Aesthetics @on_trait_change('idxname', 'idxcolumn', 'idxorient', 'colorient') def _axis_changed(self, trait, new): '''Change plot axis name or orientation''' setattr(self, trait, new) self._update_axis() self.plot.request_redraw( ) #Necessary but how do I only call axis redraw? def _title_changed(self, old, new): if old != new: self.plot.title = new self.plot.request_redraw( ) #HOW TO PREVENT COLLISION WITH TOP OVERLAY def _selection_axis_changed(self, old, new): if old != new: self._update_lines() def _df_changed(self, old, new): ''' Handles how updates occur when df changes. Evaluates if columns or columnlabels have been changed. Provides entry condition as well. Note: New automatically sets self.df, so when I refer to new, I am actually referring to self.df. Using "new" instead of self.df is just for readability''' ### Initialize plot first time df is passed into the class. Boolean listeners ### for df behave oddly, so uses self.plotdata for entry condition. if not self.plotdata: self.plotdata = PandasPlotData(df=new) self._dffull = new ### Try to infer plot title from df name ### try: self.title = new.name #Turn into a "transfer" method where I pass list of attributes i want look for except AttributeError: pass ### Draw barebones of plot self._plot_default() self._update_lines() ### Decide to update columns or completely redraw df. else: changed = self.plotdata.set_df(new) ### If 'event changed', don't bother updaing lines if not changed: self._update_lines() ### Plot spacing def _get__spacing(self): '''Integer spacing given % sampling''' samp = self.sampling / 100.0 colsize = df.shape[0] return colsize - int(round(colsize * samp, 0)) def _sampling_changed(self, old, new): if old != new: self._update_samples() def _update_samples(self): '''Updates the list of line plots shown or hidden based on plot sampling.''' if self._spacing == 0: return ### Hide all plots to_hide = self.plot.plots.keys() self.plot.hideplot(*to_hide) ### Show only plots in samples to_show = self.plot.plots.keys()[::self._spacing] self.plot.showplot(*to_show) self.plot.request_redraw() def _update_rangeselect(self): ''' Overwrites range selection tool in current plot.''' #### Remove current overlay self.plot.overlays = [ obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay) ] mycomp = self.plot.plots.itervalues().next()[ 0] #Quick wayt to get first value in dictionary inds = range(len(self.df.index)) idx = ArrayDataSource(inds) vals = ArrayDataSource(df.index.values) index_range = DataRange1D(idx) val_range = DataRange1D(vals) imap = LinearMapper( range=index_range) #,stretch_data=self.index_mapper.stretch_data) vmap = LinearMapper(range=val_range) # mycomp.index_range.refresh() mycomp.index_mapper = imap mycomp.value_mapper = vmap self.rangeselect = RangeSelection(mycomp, axis=self.selection_axis) self.plot.active_tool = self.rangeselect self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) self.rangeselect.on_trait_change(self.on_selection_changed, "selection") def _update_lines(self): ''' Redraws lines, plots and reapplies line selection.''' oldplots = self.plot.plots.keys() newplots = [name for name in self.plotdata.list_data(as_strings=True)] to_remove = [p for p in oldplots if p not in newplots] to_add = [p for p in newplots if p not in oldplots] if to_remove: for p in to_remove: self.plot.delplot(p) if to_add: for name in to_add: self.plot.plot(('index', name), name=name, color=self.linecolor) self._update_axis() self._update_samples() self._update_rangeselect() def on_selection_changed(self, selection): if selection != None: self.rangeXMin, self.rangeXMax = selection print selection def _update_axis(self): ''' Forces a label axis onto the plot. ''' print 'updaing axis', self.idxname indexlabels = [str(round(i, 1)) for i in self.df.index] columnlabels = [str(round(i, 1)) for i in self.df.columns] index_axis = LabelAxis( self.plot, orientation=self.idxorient, positions=range(int(float(indexlabels[0])), int(float(indexlabels[-1]))), labels=indexlabels, #, resizable='hv', title=self.idxname) col_axis = LabelAxis( self.plot, orientation=self.colorient, positions=range(int(float(columnlabels[0])), int(float(columnlabels[-1]))), labels=columnlabels, #, resizable='hv', title=self.colname) ### Remove underlays self.plot.underlays = [ obj for obj in self.plot.underlays if not isinstance(obj, PlotAxis) ] self.plot.underlays = [ obj for obj in self.plot.underlays if not isinstance(obj, LabelAxis) ] self.plot.underlays.append(index_axis) self.plot.underlays.append(col_axis) def _plot_default(self, toolbar=True, **pltkwds): ''' Draw bare plot, including main plotting area, toolbar, etc... either at initialization or global redo''' if toolbar: self.plot = ToolbarPlot(self.plotdata, **pltkwds) else: self.plot = Plot(self.plotdata, **pltkwds) self.plot.title = self.title self.plot.padding = 50 self.plot.legend.visible = False self.plot.tools.append(PanTool(self.plot)) zoom = BetterSelectingZoom(component=self.plot, tool_mode="box", always_on=False) self.plot.overlays.append(zoom) def _overwrite_plotdata(self): '''When a new instance of PandasPlotData is created, this overwrites the data source and updates the axis values.''' self.plotdata = PandasPlotData(df=self.df) self._plot_default() #CAN THIS JUST DRAW LINES ### Traits View main_group = Group( HGroup( Item('rnd_cols'), Item('samecols'), Item('transpose'), ), Item('plot', editor=ComponentEditor(), show_label=False), Item('idxname'), Item('idxorient'), Item('selection_axis'), Item('title'), Item('sampling'), # Item('df_new'), Item('df_change'), #Include('sample_group'), #Include('axis_traits_group') ) traits_view = View(Include('main_group'), height=600, width=800)