|
| 1 | +""" |
| 2 | +DeepLabCut2.0 Toolbox |
| 3 | +https://github.com/AlexEMG/DeepLabCut |
| 4 | +A Mathis, alexander.mathis@bethgelab.org |
| 5 | +T Nath, nath@rowland.harvard.edu |
| 6 | +M Mathis, mackenzie@post.harvard.edu |
| 7 | +
|
| 8 | +""" |
| 9 | + |
| 10 | +""" |
| 11 | +Class to drag,annotate and remove the data points. Use left click to drag the data points |
| 12 | +around. Use right click to remove any unwanted data points. Internally the corresponding data |
| 13 | +point is set to nan. When the user hovers the mouse over any data point, each data point is annotated with the labels and its corresponding likelihood. These annotations also move with the drag! |
| 14 | +""" |
| 15 | + |
| 16 | + |
| 17 | +import numpy as np |
| 18 | +import wx |
| 19 | + |
| 20 | +class DraggablePoint: |
| 21 | + lock = None #only one can be animated at a time |
| 22 | + def __init__(self, point,individual_names,bodyParts): |
| 23 | +# def __init__(self, point,bodyParts): |
| 24 | + self.point = point |
| 25 | + self.bodyParts = bodyParts |
| 26 | + self.individual_names = individual_names |
| 27 | +# self.likelihood = likelihood |
| 28 | + self.press = None |
| 29 | + self.background = None |
| 30 | + self.final_point = (0.0, 0.0) |
| 31 | + self.annot = self.point.axes.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",bbox=dict(boxstyle="round", fc="w"),arrowprops=dict(arrowstyle="->")) |
| 32 | + self.annot.set_visible(False) |
| 33 | + self.coords = [] |
| 34 | + |
| 35 | + |
| 36 | + def connect(self): |
| 37 | + 'connect to all the events we need' |
| 38 | +# self.coords = [0,0] |
| 39 | + self.cidpress = self.point.figure.canvas.mpl_connect('button_press_event', self.on_press) |
| 40 | + self.cidrelease = self.point.figure.canvas.mpl_connect('button_release_event', self.on_release) |
| 41 | + self.cidmotion = self.point.figure.canvas.mpl_connect('motion_notify_event', self.on_motion) |
| 42 | + self.cidhover = self.point.figure.canvas.mpl_connect("motion_notify_event", self.on_hover) |
| 43 | + |
| 44 | + def on_press(self, event): |
| 45 | + """ |
| 46 | + Define the event for the button press! |
| 47 | + """ |
| 48 | + if event.inaxes != self.point.axes: return |
| 49 | + if DraggablePoint.lock is not None: return |
| 50 | + contains, attrd = self.point.contains(event) |
| 51 | + if not contains: return |
| 52 | + if event.button == 1: |
| 53 | + """ |
| 54 | + This button press corresponds to the left click |
| 55 | + """ |
| 56 | + self.press = (self.point.center), event.xdata, event.ydata |
| 57 | + DraggablePoint.lock = self |
| 58 | + canvas = self.point.figure.canvas |
| 59 | + axes = self.point.axes |
| 60 | + self.point.set_animated(True) |
| 61 | + canvas.draw() |
| 62 | + self.background = canvas.copy_from_bbox(self.point.axes.bbox) |
| 63 | + axes.draw_artist(self.point) |
| 64 | + canvas.blit(axes.bbox) |
| 65 | + elif event.button == 2: |
| 66 | + """ |
| 67 | + To remove a predicted label. Internally, the coordinates of the selected predicted label is replaced with nan. The user needs to right click for the event.After right |
| 68 | + click the data point is removed from the plot. |
| 69 | + """ |
| 70 | + msg = wx.MessageBox('Do you want to remove the label %s ?'%self.bodyParts, 'Remove!', wx.YES_NO | wx.ICON_WARNING) |
| 71 | + if msg == 2: |
| 72 | + self.press = None |
| 73 | + DraggablePoint.lock = None |
| 74 | + self.point.set_animated(False) |
| 75 | + self.background = None |
| 76 | + self.final_point = (np.nan,np.nan,self.individual_names,self.bodyParts) |
| 77 | + self.point.center = (np.nan,np.nan) |
| 78 | + self.coords.append(self.final_point) |
| 79 | + self.point.figure.canvas.draw() |
| 80 | + |
| 81 | + |
| 82 | + def on_motion(self, event): |
| 83 | + """ |
| 84 | + During the drag! |
| 85 | + """ |
| 86 | + if DraggablePoint.lock is not self: |
| 87 | + return |
| 88 | + if event.inaxes != self.point.axes: return |
| 89 | + |
| 90 | + if event.button == 1: |
| 91 | + self.point.center, xpress, ypress = self.press |
| 92 | + dx = event.xdata - xpress |
| 93 | + dy = event.ydata - ypress |
| 94 | + self.point.center = (self.point.center[0]+dx, self.point.center[1]+dy) |
| 95 | + canvas = self.point.figure.canvas |
| 96 | + axes = self.point.axes |
| 97 | + # restore the background region |
| 98 | + canvas.restore_region(self.background) |
| 99 | + axes.draw_artist(self.point) |
| 100 | + canvas.blit(axes.bbox) |
| 101 | + |
| 102 | + def on_release(self, event): |
| 103 | + 'on release we reset the press data' |
| 104 | + if DraggablePoint.lock is not self: |
| 105 | + return |
| 106 | + if event.button == 1: |
| 107 | + self.press = None |
| 108 | + DraggablePoint.lock = None |
| 109 | + self.point.set_animated(False) |
| 110 | + self.background = None |
| 111 | + self.point.figure.canvas.draw() |
| 112 | + self.final_point = (event.xdata, event.ydata,self.individual_names,self.bodyParts) |
| 113 | + self.coords.append(self.final_point) |
| 114 | + |
| 115 | + def on_hover(self,event): |
| 116 | + """ |
| 117 | + Annotate the lables and likelihood when the user hovers over the data points. |
| 118 | + """ |
| 119 | + vis = self.annot.get_visible() |
| 120 | + |
| 121 | + if event.inaxes == self.point.axes: |
| 122 | + contains, attrd = self.point.contains(event) |
| 123 | + if contains: |
| 124 | + self.annot.xy = (self.point.center[0],self.point.center[1]) |
| 125 | +# text = str(self.bodyParts) |
| 126 | + text = str(self.individual_names+','+self.bodyParts) |
| 127 | + self.annot.set_text(text) |
| 128 | + self.annot.get_bbox_patch().set_alpha(0.4) |
| 129 | + self.annot.set_visible(True) |
| 130 | + self.point.figure.canvas.draw_idle() |
| 131 | + else: |
| 132 | + if vis: |
| 133 | + self.annot.set_visible(False) |
| 134 | + |
| 135 | + |
| 136 | + def disconnect(self): |
| 137 | + 'disconnect all the stored connection ids' |
| 138 | + self.point.figure.canvas.mpl_disconnect(self.cidpress) |
| 139 | + self.point.figure.canvas.mpl_disconnect(self.cidrelease) |
| 140 | + self.point.figure.canvas.mpl_disconnect(self.cidmotion) |
| 141 | + self.point.figure.canvas.mpl_disconnect(self.cidhover) |
| 142 | + self.point.figure.canvas.mpl_disconnect(self.cidkey) |
0 commit comments