Source code for analysis_modules.plot_module.matplotlib_annotation_objects

# draggable rectangle with the animation blit techniques; see
# http://www.scipy.org/Cookbook/Matplotlib/Animations
# import numpy as np
# import matplotlib.pyplot as plt

[docs]class DraggableRectangle: lock = None # only one can be animated at a time def __init__(self, rect): self.rect = rect self.press = None self.background = None
[docs] def connect(self): """connect to all the events we need""" self.cidpress = self.rect.figure.canvas.mpl_connect( 'button_press_event', self.on_press) self.cidrelease = self.rect.figure.canvas.mpl_connect( 'button_release_event', self.on_release) self.cidmotion = self.rect.figure.canvas.mpl_connect( 'motion_notify_event', self.on_motion)
[docs] def on_press(self, event): """on button press we will see if the mouse is over us and store some data""" if event.inaxes != self.rect.axes: return if DraggableRectangle.lock is not None: return contains, attrd = self.rect.contains(event) if not contains: return print('event contains', self.rect.xy) x0, y0 = self.rect.xy self.press = x0, y0, event.xdata, event.ydata DraggableRectangle.lock = self # draw everything but the selected rectangle and store the pixel buffer canvas = self.rect.figure.canvas axes = self.rect.axes self.rect.set_animated(True) canvas.draw() self.background = canvas.copy_from_bbox(self.rect.axes.bbox) # now redraw just the rectangle axes.draw_artist(self.rect) # and blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_motion(self, event): """on motion we will move the rect if the mouse is over us""" if DraggableRectangle.lock is not self: return if event.inaxes != self.rect.axes: return x0, y0, xpress, ypress = self.press dx = event.xdata - xpress dy = event.ydata - ypress self.rect.set_x(x0 + dx) self.rect.set_y(y0 + dy) canvas = self.rect.figure.canvas axes = self.rect.axes # restore the background region canvas.restore_region(self.background) # redraw just the current rectangle axes.draw_artist(self.rect) # blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_release(self, event): """on release we reset the press data""" if DraggableRectangle.lock is not self: return self.press = None DraggableRectangle.lock = None # turn off the rect animation property and reset the background self.rect.set_animated(False) self.background = None # redraw the full figure self.rect.figure.canvas.draw()
[docs] def disconnect(self): """disconnect all the stored connection ids""" self.rect.figure.canvas.mpl_disconnect(self.cidpress) self.rect.figure.canvas.mpl_disconnect(self.cidrelease) self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
[docs]class DraggableText: lock = None # only one can be animated at a time def __init__(self, text): self.text = text self.press = None self.background = None self.prev_text = None self.text.set_picker(True) self.x = 0.5 self.y = 0.5 self.cid_press = None self.cid_release = None self.cid_motion = None
[docs] def connect(self): """connect to all the events we need""" self.cid_press = self.text.figure.canvas.mpl_connect('button_press_event', self.on_press) self.cid_release = self.text.figure.canvas.mpl_connect('button_release_event', self.on_release) self.cid_motion = self.text.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
[docs] def on_press(self, event): """on button press we will see if the mouse is over us and store some data""" if event.inaxes != self.text.axes: return if DraggableText.lock is not None: return contains, attrd = self.text.contains(event) if not contains: return x0, y0 = self.text.xy # save location details at press self.press = x0, y0, event.xdata, event.ydata DraggableText.lock = self # draw everything but the selected text and store the pixel buffer canvas = self.text.figure.canvas axes = self.text.axes self.text.set_animated(True) canvas.draw() self.background = canvas.copy_from_bbox(self.text.axes.bbox) # now redraw just the Text axes.draw_artist(self.text) # and blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_motion(self, event): """on motion, we will move the text if the mouse is over us""" if DraggableText.lock is not self: return if event.inaxes != self.text.axes: return # get text canvas and axes fig = self.text.figure canvas = self.text.figure.canvas axes = self.text.axes if self.text.xycoords == 'data': # get size of figure bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) width, height = bbox.width * fig.dpi, bbox.height * fig.dpi # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height # self.x, self.y = fig.transFigure.inversed().transform() self.x, self.y = axes.transData.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) elif self.text.xycoords == 'axes fraction': # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height self.x, self.y = axes.transAxes.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) elif self.text.xycoords == 'figure': # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height self.x, self.y = fig.transFigure.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) # restore the background region canvas.restore_region(self.background) # redraw just the current text axes.draw_artist(self.text) # blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_release(self, event): """on release, we reset the press data""" if DraggableText.lock is not self: return # reset press data self.press = None DraggableText.lock = None # turn off the text animation property and reset the background self.text.set_animated(False) self.background = None # redraw the full figure self.text.figure.canvas.draw()
[docs] def disconnect(self): """disconnect all the stored connection ids""" self.text.figure.canvas.mpl_disconnect(self.cid_press) self.text.figure.canvas.mpl_disconnect(self.cid_release) self.text.figure.canvas.mpl_disconnect(self.cid_motion)
[docs] def remove(self): self.text.remove()
[docs]class DraggableSquare: lock = None # only one can be animated at a time def __init__(self, text): self.text = text self.press = None self.background = None self.prev_text = None self.text.set_picker(True) self.x = 0.5 self.y = 0.5 self.cid_press = None self.cid_release = None self.cid_motion = None
[docs] def connect(self): """connect to all the events we need""" self.cid_press = self.text.figure.canvas.mpl_connect('button_press_event', self.on_press) self.cid_release = self.text.figure.canvas.mpl_connect('button_release_event', self.on_release) self.cid_motion = self.text.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
[docs] def on_press(self, event): """on button press we will see if the mouse is over us and store some data""" if event.inaxes != self.text.axes: return if DraggableText.lock is not None: return contains, attrd = self.text.contains(event) if not contains: return x0, y0 = self.text.xy # save location details at press self.press = x0, y0, event.xdata, event.ydata DraggableText.lock = self # draw everything but the selected text and store the pixel buffer canvas = self.text.figure.canvas axes = self.text.axes self.text.set_animated(True) canvas.draw() self.background = canvas.copy_from_bbox(self.text.axes.bbox) # now redraw just the Text axes.draw_artist(self.text) # and blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_motion(self, event): """on motion, we will move the text if the mouse is over us""" if DraggableText.lock is not self: return if event.inaxes != self.text.axes: return # get text canvas and axes fig = self.text.figure canvas = self.text.figure.canvas axes = self.text.axes if self.text.xycoords == 'data': # get size of figure bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) width, height = bbox.width * fig.dpi, bbox.height * fig.dpi # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height # self.x, self.y = fig.transFigure.inversed().transform() self.x, self.y = axes.transData.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) elif self.text.xycoords == 'axes fraction': # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height self.x, self.y = axes.transAxes.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) elif self.text.xycoords == 'figure': # calculate relative position as fraction of figure self.x = event.x # / width self.y = event.y # / height self.x, self.y = fig.transFigure.inverted().transform((self.x, self.y)) self.text.set_position((self.x, self.y)) # restore the background region canvas.restore_region(self.background) # redraw just the current text axes.draw_artist(self.text) # blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_release(self, event): """on release, we reset the press data""" if DraggableText.lock is not self: return # reset press data self.press = None DraggableText.lock = None # turn off the text animation property and reset the background self.text.set_animated(False) self.background = None # redraw the full figure self.text.figure.canvas.draw()
[docs] def disconnect(self): """disconnect all the stored connection ids""" self.text.figure.canvas.mpl_disconnect(self.cid_press) self.text.figure.canvas.mpl_disconnect(self.cid_release) self.text.figure.canvas.mpl_disconnect(self.cid_motion)
[docs] def remove(self): self.text.remove()
[docs]class DraggableArrow: lock = None # only one can be animated at a time def __init__(self, rect): self.cidrelease = None self.cidmotion = None self.cidpress = None self.rect = rect self.press = None self.background = None
[docs] def connect(self): """connect to all the events we need""" self.cidpress = self.rect.figure.canvas.mpl_connect( 'button_press_event', self.on_press) self.cidrelease = self.rect.figure.canvas.mpl_connect( 'button_release_event', self.on_release) self.cidmotion = self.rect.figure.canvas.mpl_connect( 'motion_notify_event', self.on_motion)
[docs] def on_press(self, event): """on button press we will see if the mouse is over us and store some data""" if event.inaxes != self.rect.axes: return if DraggableRectangle.lock is not None: return contains, attrd = self.rect.contains(event) if not contains: return x0, y0 = self.rect.xy self.press = x0, y0, event.xdata, event.ydata DraggableRectangle.lock = self # draw everything but the selected rectangle and store the pixel buffer canvas = self.rect.figure.canvas axes = self.rect.axes self.rect.set_animated(True) canvas.draw() self.background = canvas.copy_from_bbox(self.rect.axes.bbox) # now redraw just the rectangle axes.draw_artist(self.rect) # and blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_motion(self, event): """on motion we will move the rect if the mouse is over us""" if DraggableRectangle.lock is not self: return if event.inaxes != self.rect.axes: return x0, y0, xpress, ypress = self.press dx = event.xdata - xpress dy = event.ydata - ypress self.rect.set_x(x0 + dx) self.rect.set_y(y0 + dy) canvas = self.rect.figure.canvas axes = self.rect.axes # restore the background region canvas.restore_region(self.background) # redraw just the current rectangle axes.draw_artist(self.rect) # blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_release(self, event): """on release we reset the press data""" if DraggableRectangle.lock is not self: return self.press = None DraggableRectangle.lock = None # turn off the rect animation property and reset the background self.rect.set_animated(False) self.background = None # redraw the full figure self.rect.figure.canvas.draw()
[docs] def disconnect(self): """disconnect all the stored connection ids""" self.rect.figure.canvas.mpl_disconnect(self.cidpress) self.rect.figure.canvas.mpl_disconnect(self.cidrelease) self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
[docs]class DraggableAxvline: lock = None # only one can be animated at a time def __init__(self, axvline): self.cidmotion = None self.cidrelease = None self.cidpress = None self.axvline = axvline self.press = None self.background = None
[docs] def connect(self): """connect to all the events we need""" self.cidpress = self.axvline.figure.canvas.mpl_connect( 'button_press_event', self.on_press) self.cidrelease = self.axvline.figure.canvas.mpl_connect( 'button_release_event', self.on_release) self.cidmotion = self.axvline.figure.canvas.mpl_connect( 'motion_notify_event', self.on_motion)
[docs] def on_press(self, event): """on button press we will see if the mouse is over us and store some data""" if event.inaxes != self.axvline.axes: return if DraggableAxvline.lock is not None: return contains, attrd = self.axvline.contains(event) if not contains: return x0 = self.axvline.get_xdata() self.press = x0, event.xdata DraggableAxvline.lock = self # draw everything but the selected rectangle and store the pixel buffer canvas = self.axvline.figure.canvas axes = self.axvline.axes self.axvline.set_animated(True) canvas.draw() self.background = canvas.copy_from_bbox(self.axvline.axes.bbox) # now redraw just the rectangle axes.draw_artist(self.axvline) # and blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_motion(self, event): """on motion, we will move the axvline if the mouse is over us""" if DraggableAxvline.lock is not self: return if event.inaxes != self.axvline.axes: return x0, xpress = self.press dx = event.xdata - xpress self.axvline.set_xdata([x+dx for x in x0]) canvas = self.axvline.figure.canvas axes = self.axvline.axes # restore the background region canvas.restore_region(self.background) # redraw just the current rectangle axes.draw_artist(self.axvline) # blit just the redrawn area canvas.blit(axes.bbox)
[docs] def on_release(self, event): """on release, we reset the press data""" if DraggableAxvline.lock is not self: return self.press = None DraggableAxvline.lock = None # turn off the axvline animation property and reset the background self.axvline.set_animated(False) self.background = None # redraw the full figure self.axvline.figure.canvas.draw()
[docs] def disconnect(self): """disconnect all the stored connection ids""" self.axvline.figure.canvas.mpl_disconnect(self.cidpress) self.axvline.figure.canvas.mpl_disconnect(self.cidrelease) self.axvline.figure.canvas.mpl_disconnect(self.cidmotion)
[docs] def remove(self): self.axvline.remove()
# fig = plt.figure() # ax = fig.add_subplot(111) # rects = ax.bar(range(10), 20*np.random.rand(10)) # drs = [] # # for rect in rects: # dr = DraggableRectangle(rect) # dr.connect() # drs.append(dr) # # # add text # bbox_props = dict(boxstyle='round', fc='r', ec='k') # text = ax.annotate('local max', xy=(3, 17), bbox=bbox_props) # # dts = [] # dt = DraggableText(text) # dt.connect() # dts.append(dt) # # plt.show()