def __init__(self, windows=None, name=None, category=None, icon=None, description=None): super(SelectionTool, self).__init__(windows) self.widget2d_r = RectangleWidget(None) self.widget2d_r.set_on(False) self.widget1d_r = RangeWidget(None) self.widget1d_r.set_on(False) self.widget2d = SquareWidget(None) self.widget2d.set_on(False) self.widget1d = VerticalLineWidget(None) self.widget1d.set_on(False) self._widgets = [ self.widget2d_r, self.widget1d_r, self.widget2d, self.widget1d ] self.valid_dimensions = [1, 2] self.ranged = True self.name = name or "Selection tool" self.category = category or 'Signal' self.description = description self.icon = icon self.cancel_on_accept = False
def _make_position_adjuster(self, component, fix_it, show_label): if (component._position is None or component._position.twin): return axis = self.axes_manager.signal_axes[0] # Create the vertical line and labels widgets = [VerticalLineWidget(self.axes_manager)] if show_label: label = LabelWidget(self.axes_manager) label.string = component._get_short_description().replace( ' component', '') widgets.append(label) self._position_widgets[component._position] = widgets for w in widgets: # Setup widget w.axes = (axis, ) w.snap_position = False w.position = (component._position.value, ) w.set_mpl_ax(self._plot.signal_plot.ax) # Create widget -> parameter connection w.events.moved.connect(self._on_widget_moved, {'obj': 'widget'}) # Create parameter -> widget connection component._position.events.value_changed.connect( w._set_position, dict(value='position')) # Map relation for close event w.events.closed.connect(self._on_position_widget_close, {'obj': 'widget'})
def switch_on_off(self, obj, trait_name, old, new): if not self.signal._plot.is_active(): return if new is True and old is False: self._line = VerticalLineWidget(self.axes_manager) self._line.set_mpl_ax(self.signal._plot.signal_plot.ax) self._line.patch.set_linewidth(2) self._color_changed("black", "black") # There is not need to call draw because setting the # color calls it. elif new is False and old is True: self._line.close() self._line = None self.draw()
def _add_widget(self, signal): if signal is None: return None if self.ndim(signal) == 1: if self.ranged: w = RangeWidget(None) else: w = VerticalLineWidget(None) else: if self.ranged: w = RectangleWidget(None) else: w = SquareWidget(None) if signal in self.widgets: self.widgets[signal].append(w) else: self.widgets[signal] = [w] w.set_on(False) return w
def __init__(self, windows=None, name=None, category=None, icon=None, description=None): super(SelectionTool, self).__init__(windows) self.widget2d_r = RectangleWidget(None) self.widget2d_r.set_on(False) self.widget1d_r = RangeWidget(None) self.widget1d_r.set_on(False) self.widget2d = SquareWidget(None) self.widget2d.set_on(False) self.widget1d = VerticalLineWidget(None) self.widget1d.set_on(False) self._widgets = [self.widget2d_r, self.widget1d_r, self.widget2d, self.widget1d] self.valid_dimensions = [1, 2] self.ranged = True self.name = name or "Selection tool" self.category = category or 'Signal' self.description = description self.icon = icon self.cancel_on_accept = False
class SelectionTool(SignalFigureTool): """ Tool to select a ROI on a signal interactively. Simply click and drag in a figure to create an ROI, and then press enter to indicate that the selection is complete, or ESC to cancel. The selection can also be aborted by simply selecting a different tool. """ accepted = QtCore.Signal([BaseInteractiveROI], [BaseInteractiveROI, SignalFigureTool]) updated = QtCore.Signal([BaseInteractiveROI], [BaseInteractiveROI, SignalFigureTool]) # TODO: Use cancelled = QtCore.Signal() def __init__(self, windows=None, name=None, category=None, icon=None, description=None): super(SelectionTool, self).__init__(windows) self.widget2d_r = RectangleWidget(None) self.widget2d_r.set_on(False) self.widget1d_r = RangeWidget(None) self.widget1d_r.set_on(False) self.widget2d = SquareWidget(None) self.widget2d.set_on(False) self.widget1d = VerticalLineWidget(None) self.widget1d.set_on(False) self._widgets = [self.widget2d_r, self.widget1d_r, self.widget2d, self.widget1d] self.valid_dimensions = [1, 2] self.ranged = True self.name = name or "Selection tool" self.category = category or 'Signal' self.description = description self.icon = icon self.cancel_on_accept = False @property def widget(self): if self.ndim == 1: if self.ranged: return self.widget1d_r else: return self.widget1d else: if self.ranged: return self.widget2d_r else: return self.widget2d @property def ndim(self): if self.axes is None: return 0 return len(self.axes) def is_on(self): return self.widget.is_on() def in_ax(self, ax): return ax == self.widget.ax def get_name(self): return self.name def get_category(self): return self.category def get_icon(self): return self.icon def make_cursor(self): return crosshair_cursor() def is_selectable(self): return True def on_mousedown(self, event): # Only accept mouse down inside axes if event.inaxes is None: return axes = self._get_axes(event) # Make sure we have a figure with valid dimensions if len(axes) not in self.valid_dimensions: return self.axes = axes # If we already have a widget, make sure dragging is passed through if self.is_on(): if any([p.contains(event)[0] == True for p in self.widget.patch]): return # Moving, handle in widget # Clicked outside existing widget, check for resize handles if self.ndim > 1 and self.widget.resizers: for r in self.widget._resizer_handles: if r.contains(event)[0] == True: return # Leave the event to widget # Cancel previous and start new self.cancel() # Cancel reset axes, so set again self.axes = axes # Find out which axes of Signal are plotted in figure s = self._get_signal(event.inaxes.figure) if s is None: return am = s.axes_manager self.widget.axes = axes if self.ndim > 0: self.widget.axes_manager = am # Have what we need, create widget x, y = event.xdata, event.ydata self.widget.set_mpl_ax(event.inaxes) # connects if self.ndim == 1: self.widget.position = (x,) self.widget.size = axes[0].scale self.widget.set_on(True) if self.ranged: span = self.widget.span span.buttonDown = True span.on_move_cid = \ span.canvas.mpl_connect('motion_notify_event', span.move_right) else: self.widget.picked = True else: self.widget.position = (x, y) self.widget.size = [ax.scale for ax in axes] if self.ranged: self.widget.resizer_picked = 3 self.widget.picked = True self.widget.set_on(True) def on_keyup(self, event): if event.key == 'enter': self.accept() elif event.key == 'escape': self.cancel() def accept(self): if self.is_on(): if self.ndim == 1: if self.ranged: roi = SpanROI(0, 1) else: roi = Point1DROI(0) elif self.ndim > 1: if self.ranged: roi = RectangularROI(0, 0, 1, 1) else: roi = Point2DROI(0, 0) else: raise RuntimeWarning("No figure could be found.") return roi._on_widget_change(self.widget) # ROI gets coords from widget self.accepted[BaseInteractiveROI].emit(roi) self.accepted[BaseInteractiveROI, SignalFigureTool].emit(roi, self) if self.cancel_on_accept: self.cancel() def cancel(self): for w in self._widgets: if w.is_on(): w.set_on(False) self.axes = None self.cancelled.emit() def disconnect_windows(self, windows): super(SelectionTool, self).disconnect_windows(windows) self.cancel()
class LineInSignal1D(t.HasTraits): """Adds a vertical draggable line to a spectrum that reports its position to the position attribute of the class. Attributes: ----------- position : float The position of the vertical line in the one dimensional signal. Moving the line changes the position but the reverse is not true. on : bool Turns on and off the line color : wx.Colour The color of the line. It automatically redraws the line. """ position = t.Float() is_ok = t.Bool(False) on = t.Bool(False) color = t.Color("black") def __init__(self, signal): if signal.axes_manager.signal_dimension != 1: raise SignalDimensionError(signal.axes_manager.signal_dimension, 1) self.signal = signal self.signal.plot() axis_dict = signal.axes_manager.signal_axes[0].get_axis_dictionary() am = AxesManager([ axis_dict, ]) am._axes[0].navigate = True # Set the position of the line in the middle of the spectral # range by default am._axes[0].index = int(round(am._axes[0].size / 2)) self.axes_manager = am self.axes_manager.events.indices_changed.connect( self.update_position, []) self.on_trait_change(self.switch_on_off, 'on') def draw(self): self.signal._plot.signal_plot.figure.canvas.draw() def switch_on_off(self, obj, trait_name, old, new): if not self.signal._plot.is_active(): return if new is True and old is False: self._line = VerticalLineWidget(self.axes_manager) self._line.set_mpl_ax(self.signal._plot.signal_plot.ax) self._line.patch.set_linewidth(2) self._color_changed("black", "black") # There is not need to call draw because setting the # color calls it. elif new is False and old is True: self._line.close() self._line = None self.draw() def update_position(self, *args, **kwargs): if not self.signal._plot.is_active(): return self.position = self.axes_manager.coordinates[0] def _color_changed(self, old, new): if self.on is False: return self._line.patch.set_color(( self.color.Red() / 255., self.color.Green() / 255., self.color.Blue() / 255., )) self.draw()
class LineInSpectrum(t.HasTraits): """Adds a vertical draggable line to a spectrum that reports its position to the position attribute of the class. Attributes: ----------- position : float The position of the vertical line in the spectrum. Moving the line changes the position but the reverse is not true. on : bool Turns on and off the line color : wx.Colour The color of the line. It automatically redraws the line. """ position = t.Float() is_ok = t.Bool(False) on = t.Bool(False) color = t.Color("black") def __init__(self, signal): if signal.axes_manager.signal_dimension != 1: raise SignalDimensionError( signal.axes_manager.signal_dimension, 1) self.signal = signal self.signal.plot() axis_dict = signal.axes_manager.signal_axes[0].get_axis_dictionary() am = AxesManager([axis_dict, ]) am._axes[0].navigate = True # Set the position of the line in the middle of the spectral # range by default am._axes[0].index = int(round(am._axes[0].size / 2)) self.axes_manager = am self.axes_manager.events.indices_changed.connect( self.update_position, []) self.on_trait_change(self.switch_on_off, 'on') def draw(self): self.signal._plot.signal_plot.figure.canvas.draw() def switch_on_off(self, obj, trait_name, old, new): if not self.signal._plot.is_active(): return if new is True and old is False: self._line = VerticalLineWidget(self.axes_manager) self._line.set_mpl_ax(self.signal._plot.signal_plot.ax) self._line.patch.set_linewidth(2) self._color_changed("black", "black") # There is not need to call draw because setting the # color calls it. elif new is False and old is True: self._line.close() self._line = None self.draw() def update_position(self, *args, **kwargs): if not self.signal._plot.is_active(): return self.position = self.axes_manager.coordinates[0] def _color_changed(self, old, new): if self.on is False: return self._line.patch.set_color((self.color.Red() / 255., self.color.Green() / 255., self.color.Blue() / 255.,)) self.draw()
class SelectionTool(SignalFigureTool): """ Tool to select a ROI on a signal interactively. Simply click and drag in a figure to create an ROI, and then press enter to indicate that the selection is complete, or ESC to cancel. The selection can also be aborted by simply selecting a different tool. """ accepted = QtCore.Signal([BaseInteractiveROI], [BaseInteractiveROI, SignalFigureTool]) updated = QtCore.Signal( [BaseInteractiveROI], [BaseInteractiveROI, SignalFigureTool]) # TODO: Use cancelled = QtCore.Signal() def __init__(self, windows=None, name=None, category=None, icon=None, description=None): super(SelectionTool, self).__init__(windows) self.widget2d_r = RectangleWidget(None) self.widget2d_r.set_on(False) self.widget1d_r = RangeWidget(None) self.widget1d_r.set_on(False) self.widget2d = SquareWidget(None) self.widget2d.set_on(False) self.widget1d = VerticalLineWidget(None) self.widget1d.set_on(False) self._widgets = [ self.widget2d_r, self.widget1d_r, self.widget2d, self.widget1d ] self.valid_dimensions = [1, 2] self.ranged = True self.name = name or "Selection tool" self.category = category or 'Signal' self.description = description self.icon = icon self.cancel_on_accept = False @property def widget(self): if self.ndim == 1: if self.ranged: return self.widget1d_r else: return self.widget1d else: if self.ranged: return self.widget2d_r else: return self.widget2d @property def ndim(self): if self.axes is None: return 0 return len(self.axes) def is_on(self): return self.widget.is_on() def in_ax(self, ax): return ax == self.widget.ax def get_name(self): return self.name def get_category(self): return self.category def get_icon(self): return self.icon def make_cursor(self): return crosshair_cursor() def is_selectable(self): return True def on_mousedown(self, event): # Only accept mouse down inside axes if event.inaxes is None: return axes = self._get_axes(event) # Make sure we have a figure with valid dimensions if len(axes) not in self.valid_dimensions: return self.axes = axes # If we already have a widget, make sure dragging is passed through if self.is_on(): if any([p.contains(event)[0] == True for p in self.widget.patch]): return # Moving, handle in widget # Clicked outside existing widget, check for resize handles if self.ndim > 1 and self.widget.resizers: for r in self.widget._resizer_handles: if r.contains(event)[0] == True: return # Leave the event to widget # Cancel previous and start new self.cancel() # Cancel reset axes, so set again self.axes = axes # Find out which axes of Signal are plotted in figure s = self._get_signal(event.inaxes.figure) if s is None: return am = s.axes_manager self.widget.axes = axes if self.ndim > 0: self.widget.axes_manager = am # Have what we need, create widget x, y = event.xdata, event.ydata self.widget.set_mpl_ax(event.inaxes) # connects if self.ndim == 1: self.widget.position = (x, ) self.widget.size = axes[0].scale self.widget.set_on(True) if self.ranged: span = self.widget.span span.buttonDown = True span.on_move_cid = \ span.canvas.mpl_connect('motion_notify_event', span.move_right) else: self.widget.picked = True else: self.widget.position = (x, y) self.widget.size = [ax.scale for ax in axes] if self.ranged: self.widget.resizer_picked = 3 self.widget.picked = True self.widget.set_on(True) def on_keyup(self, event): if event.key == 'enter': self.accept() elif event.key == 'escape': self.cancel() def accept(self): if self.is_on(): if self.ndim == 1: if self.ranged: roi = SpanROI(0, 1) else: roi = Point1DROI(0) elif self.ndim > 1: if self.ranged: roi = RectangularROI(0, 0, 1, 1) else: roi = Point2DROI(0, 0) else: raise RuntimeWarning("No figure could be found.") return roi._on_widget_change(self.widget) # ROI gets coords from widget self.accepted[BaseInteractiveROI].emit(roi) self.accepted[BaseInteractiveROI, SignalFigureTool].emit(roi, self) if self.cancel_on_accept: self.cancel() def cancel(self): for w in self._widgets: if w.is_on(): w.set_on(False) self.axes = None self.cancelled.emit() def disconnect_windows(self, windows): super(SelectionTool, self).disconnect_windows(windows) self.cancel()