class ScatterPlot2(Template): #-- Template Traits -------------------------------------------------------- # The title of the plot: title = TStr('Dual Scatter Plots') # The type of marker to use. This is a mapped trait using strings as the # keys: marker = marker_trait(template='copy', event='update') # The pixel size of the marker (doesn't include the thickness of the # outline): marker_size = TRange(1, 5, 1, event='update') # The thickness, in pixels, of the outline to draw around the marker. If # this is 0, no outline will be drawn. line_width = TRange(0.0, 5.0, 1.0) # The fill color of the marker: color = TColor('red', event='update') # The color of the outline to draw around the marker outline_color = TColor('black', event='update') # The amount of space between plots: spacing = TRange(0.0, 20.0, 0.0) # The contained scatter plots: scatter_plot_1 = TInstance(ScatterPlot, ()) scatter_plot_2 = TInstance(ScatterPlot, ()) #-- Derived Traits --------------------------------------------------------- plot = TDerived #-- Traits UI Views -------------------------------------------------------- # The scatter plot view: template_view = View(VGroup( Item('title', show_label=False, style='readonly', editor=ThemedTextEditor(theme=Theme('@GBB', alignment='center'))), Item('plot', show_label=False, resizable=True, editor=EnableEditor(), item_theme=Theme('@GF5', margins=0))), resizable=True) # The scatter plot options view: options_view = View( VGroup( VGroup(Label('Scatter Plot Options', item_theme=Theme('@GBB', alignment='center')), show_labels=False), VGroup(Item('title', editor=TextEditor()), Item('marker'), Item('marker_size', editor=ThemedSliderEditor()), Item('line_width', label='Line Width', editor=ThemedSliderEditor()), Item('spacing', editor=ThemedSliderEditor()), Item('color', label='Fill Color'), Item('outline_color', label='Outline Color'), group_theme=Theme('@GF5', margins=(-5, -1)), item_theme=Theme('@G0B', margins=0)))) #-- ITemplate Interface Implementation ------------------------------------- def activate_template(self): """ Converts all contained 'TDerived' objects to real objects using the template traits of the object. This method must be overridden in subclasses. Returns ------- None """ plots = [ p for p in [self.scatter_plot_1.plot, self.scatter_plot_2.plot] if p is not None ] if len(plots) == 2: self.plot = HPlotContainer(spacing=self.spacing) self.plot.add(*plots) elif len(plots) == 1: self.plot = plots[0] #-- Default Values --------------------------------------------------------- def _scatter_plot_1_default(self): """ Returns the default value for the first scatter plot. """ result = ScatterPlot() result.index.description = 'Shared Plot Index' result.value.description += ' 1' return result def _scatter_plot_2_default(self): """ Returns the default value for the second scatter plot. """ result = ScatterPlot(index=self.scatter_plot_1.index) result.value.description += ' 2' result.value.optional = True return result #-- Trait Event Handlers --------------------------------------------------- def _update_changed(self, name, old, new): """ Handles a plot option being changed. """ setattr(self.scatter_plot_1, name, new) setattr(self.scatter_plot_2, name, new) self.plot = Undefined def _spacing_changed(self, spacing): """ Handles the spacing between plots being changed. """ self.plot = Undefined
class ScatterPlotNM(MutableTemplate): #-- Template Traits -------------------------------------------------------- # The title of the plot: title = TStr('NxM Scatter Plots') # The type of marker to use. This is a mapped trait using strings as the # keys: marker = marker_trait(template='copy', event='update') # The pixel size of the marker (doesn't include the thickness of the # outline): marker_size = TRange(1, 5, 1, event='update') # The thickness, in pixels, of the outline to draw around the marker. If # this is 0, no outline will be drawn. line_width = TRange(0.0, 5.0, 1.0) # The fill color of the marker: color = TColor('red', event='update') # The color of the outline to draw around the marker outline_color = TColor('black', event='update') # The number of rows of plots: rows = TRange(1, 3, 1, event='grid') # The number of columns of plots: columns = TRange(1, 5, 1, event='grid') # The contained scatter plots: scatter_plots = TList(ScatterPlot) #-- Derived Traits --------------------------------------------------------- plot = TDerived #-- Traits UI Views -------------------------------------------------------- # The scatter plot view: template_view = View(VGroup( Item('title', show_label=False, style='readonly', editor=ThemedTextEditor(theme=Theme('@GBB', alignment='center'))), Item('plot', show_label=False, resizable=True, editor=EnableEditor(), item_theme=Theme('@GF5', margins=0))), resizable=True) # The scatter plot options view: options_view = View( VGroup( VGroup(Label('Scatter Plot Options', item_theme=Theme('@GBB', alignment='center')), show_labels=False), VGroup(Item('title', editor=TextEditor()), Item('marker'), Item('marker_size', editor=ThemedSliderEditor()), Item('line_width', label='Line Width', editor=ThemedSliderEditor()), Item('color', label='Fill Color'), Item('outline_color', label='Outline Color'), Item('rows', editor=ThemedSliderEditor()), Item('columns', editor=ThemedSliderEditor()), group_theme=Theme('@GF5', margins=(-5, -1)), item_theme=Theme('@G0B', margins=0)))) #-- ITemplate Interface Implementation ------------------------------------- def activate_template(self): """ Converts all contained 'TDerived' objects to real objects using the template traits of the object. This method must be overridden in subclasses. Returns ------- None """ plots = [] i = 0 for r in range(self.rows): row = [] for c in range(self.columns): plot = self.scatter_plots[i].plot if plot is None: plot = PlotComponent() row.append(plot) i += 1 plots.append(row) self.plot = GridPlotContainer(shape=(self.rows, self.columns)) self.plot.component_grid = plots #-- Default Values --------------------------------------------------------- def _scatter_plots_default(self): """ Returns the default value for the scatter plots list. """ plots = [] for i in range(self.rows * self.columns): plots.append(ScatterPlot()) self._update_plots(plots) return plots #-- Trait Event Handlers --------------------------------------------------- def _update_changed(self, name, old, new): """ Handles a plot option being changed. """ for sp in self.scatter_plots: setattr(sp, name, new) self.plot = Undefined def _grid_changed(self): """ Handles the grid size being changed. """ n = self.rows * self.columns plots = self.scatter_plots if n < len(plots): self.scatter_plots = plots[:n] else: for j in range(len(plots), n): plots.append(ScatterPlot()) self._update_plots(plots) self.template_mutated = True #-- Private Methods -------------------------------------------------------- def _update_plots(self, plots): """ Update the data sources for all of the current plots. """ index = None i = 0 for r in range(self.rows): for c in range(self.columns): sp = plots[i] i += 1 desc = sp.value.description col = desc.rfind('[') if col >= 0: desc = desc[:col] sp.value.description = '%s[%d,%d]' % (desc, r, c) sp.value.optional = True if index is None: index = sp.index index.description = 'Shared Plot Index' index.optional = True else: sp.index = index
class ScatterPlot(Template): #-- Template Traits -------------------------------------------------------- # The plot index data source: index = TDataSource # The plot value data source: value = TDataSource # The title of the plot: title = TStr('Scatter Plot') # The type of marker to use. This is a mapped trait using strings as the # keys: marker = marker_trait(template='copy', event='update') # The pixel size of the marker (doesn't include the thickness of the # outline): marker_size = TRange(1, 5, 1, event='update') # The thickness, in pixels, of the outline to draw around the marker. If # this is 0, no outline will be drawn. line_width = TRange(0.0, 5.0, 1.0) # The fill color of the marker: color = TColor('red', event='update') # The color of the outline to draw around the marker outline_color = TColor('black', event='update') #-- Derived Traits --------------------------------------------------------- plot = TDerived # Instance( ScatterPlot ) #-- Traits UI Views -------------------------------------------------------- # The scatter plot view: template_view = View(VGroup( Item('title', show_label=False, style='readonly', editor=ThemedTextEditor(theme=Theme('@GBB', alignment='center'))), Item('plot', show_label=False, resizable=True, editor=EnableEditor(), item_theme=Theme('@GF5', margins=0))), resizable=True) # The scatter plot options view: options_view = View( VGroup( VGroup(Label('Scatter Plot Options', item_theme=Theme('@GBB', alignment='center')), show_labels=False), VGroup(Item('title', editor=TextEditor()), Item('marker'), Item('marker_size', editor=ThemedSliderEditor()), Item('line_width', label='Line Width', editor=ThemedSliderEditor()), Item('color', label='Fill Color'), Item('outline_color', label='Outline Color'), group_theme=Theme('@GF5', margins=(-5, -1)), item_theme=Theme('@G0B', margins=0)))) #-- Default Values --------------------------------------------------------- def _index_default(self): """ Returns the default value for the 'index' trait. """ return TemplateDataSource( items=[ValueDataNameItem(name='index', flatten=True)], description='Scatter Plot Index') def _value_default(self): """ Returns the default value for the 'value' trait. """ return TemplateDataSource( items=[ValueDataNameItem(name='value', flatten=True)], description='Scatter Plot Value') #-- ITemplate Interface Implementation ------------------------------------- def activate_template(self): """ Converts all contained 'TDerived' objects to real objects using the template traits of the object. This method must be overridden in subclasses. Returns ------- None """ # If our data sources are still unbound, then just exit; someone must # have marked them as optional: if ((self.index.context_data is Undefined) or (self.value.context_data is Undefined)): return # Create a plot data object and give it this data: pd = ArrayPlotData() pd.set_data('index', self.index.context_data) pd.set_data('value', self.value.context_data) # Create the plot: self.plot = plot = Plot(pd) plot.plot(('index', 'value'), type='scatter', index_sort='ascending', marker=self.marker, color=self.color, outline_color=self.outline_color, marker_size=self.marker_size, line_width=self.line_width, bgcolor='white') plot.set(padding_left=50, padding_right=0, padding_top=0, padding_bottom=20) # Attach some tools to the plot: plot.tools.append(PanTool(plot, constrain_key='shift')) zoom = SimpleZoom(component=plot, tool_mode='box', always_on=False) plot.overlays.append(zoom) #-- Trait Event Handlers --------------------------------------------------- def _update_changed(self): """ Handles a plot option being changed. """ self.plot = Undefined