class PeakSelector(_SelectorWidget): """Draw a Peak as triangle.""" # pylint: disable=too-many-arguments # pylint: disable=too-many-instance-attributes # pylint: disable=invalid-name # pylint: disable=attribute-defined-outside-init def __init__(self, ax, onselect, minfwhm=None, minamp=None, useblit=False, wedgeprops=None, onmove_callback=None, peak_stays=False, button=None, limits=None): _SelectorWidget.__init__(self, ax, onselect, useblit=useblit, button=button) if minfwhm is not None or minamp is not None: raise NotImplementedError if wedgeprops is None: wedgeprops = dict(facecolor='red', alpha=0.5, fill=True) wedgeprops['animated'] = self.useblit self.wedge = None self.pressv = None if limits is None: limits = (-np.inf, np.inf) self.limits = limits self.wedgeprops = wedgeprops self.onmove_callback = onmove_callback self.minfwhm = minfwhm self.minamp = minamp self.peak_stays = peak_stays # Needed when dragging out of axes self.prev = (0, 0) # Reset canvas so that `new_axes` connects events. self.canvas = None self.new_axes(ax) def new_axes(self, ax): """Set SpanSelector to operate on a new Axes""" self.ax = ax if self.canvas is not ax.figure.canvas: if self.canvas is not None: self.disconnect_events() self.canvas = ax.figure.canvas self.connect_default_events() self.wedge = Wedge((0, 0), 1e10, 0, 0, visible=False, **self.wedgeprops) if self.peak_stays: self.stay_wedge = Wedge((0, 0), 1e10, 0, 0, visible=False, **self.wedgeprops) self.stay_wedge.set_animated(False) self.ax.add_patch(self.stay_wedge) self.ax.add_patch(self.wedge) self.artists = [self.wedge] def set_wedgeprops(self, wedgeprops): """Custom: set new rectprops.""" self.wedgeprops = wedgeprops self.new_axes(self.ax) def set_limits(self, limits): """Sets new limits. Peak will only be drawn when press event occurs inside these x values.""" self.limits = limits def ignore(self, event): """return *True* if *event* should be ignored""" return _SelectorWidget.ignore(self, event) or not self.visible def _press(self, event): """on button press event""" x0, y0 = self._get_data(event) if not self.limits[0] <= x0 <= self.limits[1]: return True self.wedge.set_visible(self.visible) if self.peak_stays: self.stay_wedge.set_visible(False) # really force a draw so that the stay rect is not in # the blit background if self.useblit: self.canvas.draw() self.pressv = (x0, y0) self.wedge.set_center((x0, y0)) return False def _release(self, event): """on button release event""" if self.pressv is None: return True self.buttonDown = False self.wedge.set_visible(False) if self.peak_stays: self.stay_wedge.set_center(self.wedge.center) self.stay_wedge.set_radius(self.wedge.r) self.stay_wedge.set_theta1(self.wedge.theta1) self.stay_wedge.set_theta2(self.wedge.theta2) self.stay_wedge.set_visible(True) self.canvas.draw_idle() x0, y0, = self.pressv center = x0 amplitude = y0 x, y = self._get_data(event) angle = abs(np.arctan((x - x0) / (y - y0))) self.onselect(center, amplitude, angle) self.pressv = None return False def _onmove(self, event): """on motion notify event""" if self.pressv is None: return True x, y = self._get_data(event) if x is None: return True x0, y0, = self.pressv angle = abs(np.arctan((x - x0) / (y - y0))) self.wedge.set_theta1(np.rad2deg(-angle) - 90) self.wedge.set_theta2(np.rad2deg(angle) - 90) if self.onmove_callback is not None: center = x0 amplitude = y0 self.onmove_callback(center, amplitude, angle) self.update() return False