Esempio n. 1
1
class ImagePanel(tk.Frame):
    """ This is a wrapper class for matplotlib figure canvas.
    It implements the mediator pattern for communication with collegues.
    """

    def __init__(self, parent, name, figsize=(2,2), dpi=100, title='', wl=False, info=False, toolbar=False, cb=False):
        self.name = name
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.img_is_set = False
        self.figsize = figsize
        self.dpi = dpi
        self.title = title
        self.toolbar = toolbar
        self.wl = wl
        self.make_canvas()
        if info: self.make_info()
        self.images = None
        self.original_img = None
        self.nZoom = 0
        self.indexOfImg = 0
        self.level_is_set = False
        self.window_is_set = False
        self.initial_level = None
        self.initial_window = None
        self.img = None
        self.cb = cb
        self.cbar = None
        self.metadata = {}
        self.collegues = []

    def register(self, collegue):
        self.collegues.append(collegue)

    def inform(self, event):
        for collegue in self.collegues:
            collegue.update_(self.name, event)

    def doubleclick(self, event):
        if event.dblclick:
            self.inform('<Double-Button-1>')
            print('DoubleClick')

    def make_canvas(self):
        self.canvas_frame = tk.Frame(self, padx=5, pady=5, cursor='crosshair')
        self.canvas_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        if self.toolbar:
            self.toolbar_frame = self.make_toolbar()
            self.toolbar_frame.pack(side=tk.TOP, fill=tk.X, expand=0)

        self.f = Figure(figsize=self.figsize, dpi=self.dpi)
        self.subplot = self.f.add_subplot(111)
        self.subplot.set_title(self.title, fontsize=10)
        plt.setp(self.subplot.get_xticklabels(), fontsize=4)
        plt.setp(self.subplot.get_yticklabels(), fontsize=4)
        self.canvas = FigureCanvasTkAgg(self.f, master=self.canvas_frame)
        self.img = self.canvas.show()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas.mpl_connect('scroll_event', self.mouseWheel)
        self.canvas.mpl_connect('button_press_event', self.doubleclick)

        if self.wl:
            self.wl_scale = self.make_wl()
            self.wl_scale.pack(side=tk.TOP, fill=tk.X, expand=0)

    def make_wl(self):
        f = font.Font(size=6)
        wl_frame = tk.Frame(self.canvas_frame)
        self.levelScale = tk.Scale(wl_frame, orient=tk.HORIZONTAL, from_=0.0, to=256.0, width=8, font=f, command=self.set_level)
        self.levelScale.pack(side=tk.TOP, fill=tk.X, expand=0)
        self.windowScale = tk.Scale(wl_frame, orient=tk.HORIZONTAL, from_=0.0, to=256.0, width=8, font=f, command=self.set_window)
        self.windowScale.pack(side=tk.TOP, fill=tk.X, expand=0)

        return wl_frame

    def make_info(self):
        self.info = tk.LabelFrame(self.parent, text='Image Info', padx=5, pady=5, width=400)
        self.info.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)

    def make_toolbar(self):
        toolbar_frame = tk.Frame(self.canvas_frame)

        set = ('DrawRectangle$icons/Rectangle$tk.FLAT$self.drawRectangle$tk.LEFT',
               'Delete$icons/Delete$tk.FLAT$self.deleteRectangle$tk.LEFT',
               'ZoomIn$icons/ZoomIn$tk.FLAT$self.zoomIn$tk.LEFT',
               'ZoomOut$icons/ZoomOut$tk.FLAT$self.zoomOut$tk.LEFT',
               'Reset$icons/ResetZoom$tk.FLAT$self.resetZoom$tk.LEFT',
               'Move$icons/Move$tk.FLAT$self.move$tk.LEFT',
               'Ruler$icons/Ruler$tk.FLAT$self.ruler$tk.LEFT',
               'Histogram$icons/Histogram$tk.FLAT$self.histogram$tk.LEFT',
               'Info$icons/Info$tk.FLAT$self.info$tk.LEFT',
               'Save$icons/Save18$tk.FLAT$self.savePicture$tk.LEFT'
               )
        self.imgToolbar= []
        for v in set:
            text, image, relief, command, side = v.split('$')
            self.imgToolbar.append(tk.PhotoImage(file=image+'.gif'))
            button = tk.Button(toolbar_frame, image=self.imgToolbar[-1], text=text, relief=eval(relief), command=eval(command))
            button.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
        return toolbar_frame

    def drawRectangle(self):
        print('Draw rectangle!')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.xp0 = None
        self.yp0 = None
        self.xp1 = None
        self.yp1 = None
        self.rectangle = Rectangle((0,0), 1, 1, facecolor='None', edgecolor='green')
        self.subplot.add_patch(self.rectangle)
        self.ispressed = False
        self.bpe = self.canvas.mpl_connect('button_press_event', self.drawRectangle_onPress)
        self.bre = self.canvas.mpl_connect('button_release_event', self.drawRectangle_onRelease)
        self.mne = self.canvas.mpl_connect('motion_notify_event', self.drawRectangle_onMotion)

    def drawRectangle_onPress(self, event):
        self.xp0 = event.x
        self.yp0 = event.y
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rectangle.set_width(self.x1-self.x0)
        self.rectangle.set_xy((self.x0, self.y0))
        self.rectangle.set_linestyle('dashed')
        self.canvas.draw()
        self.ispressed = True


    def drawRectangle_onRelease(self, event):
        self.xp1 = event.x
        self.yp1 = event.y
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rectangle.set_width(self.x1-self.x0)
        self.rectangle.set_height(self.y1-self.y0)
        self.rectangle.set_xy((self.x0, self.y0))
        self.rectangle.set_linestyle('solid')
        self.canvas.draw()
        self.ispressed = False
        self.canvas.mpl_disconnect(self.bpe)
        self.canvas.mpl_disconnect(self.bre)
        self.canvas.mpl_disconnect(self.mne)
        print(self.xp0, self.yp0, self.xp1, self.yp1)
        self.inform('<DrawRectangle>')
        return (self.xp0, self.yp0, self.xp1, self.yp1)

    def getRectanglePoints(self):
        return (self.xp0, self.yp0, self.xp1, self.yp1)

    def drawRectangle_onMotion(self, event):
        if self.ispressed is True:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.rectangle.set_width(self.x1-self.x0)
            self.rectangle.set_height(self.y1-self.y0)
            self.rectangle.set_xy((self.x0, self.y0))
            self.rectangle.set_linestyle('dashed')
            self.canvas.draw()

    def deleteRectangle(self):
        print('Delete rectangle!')
        self.rectangle.remove()
        self.canvas.draw()
        self.inform('<DeleteRectangle>')

    def zoomIn(self):
        print('Zoom in!')
        print(np.shape(self.images))
        self.images = self.images[:,10:-10, 10:-10]
        self.show_images()
        self.nZoom = self.nZoom+1


    def zoomOut(self):
        print('ZoomOut!')
        if np.shape(self.images) != np.shape(self.original_img):
            if self.nZoom>1:
                self.images = self.original_img[:,(self.nZoom-1)*10:-(self.nZoom-1)*10, (self.nZoom-1)*10:-(self.nZoom-1)*10]
                self.show_images()
                self.nZoom = self.nZoom-1
            else:
                self.images = self.original_img
                self.nZoom = 0



    def resetZoom(self):
        print('Reset zoom!')
        self.images = self.original_img
        self.show_images()
        self.nZoom = 0

    def histogram(self):
        print('Histogram!')
        histo = tk.Toplevel()
        f = Figure(figsize=(4,4), dpi=100)
        subplot = f.add_subplot(111)
        subplot.set_title('Histogram', fontsize=10)
        plt.setp(subplot.get_xticklabels(), fontsize=8)
        plt.setp(subplot.get_yticklabels(), fontsize=8)
        canvas = FigureCanvasTkAgg(f, master=histo)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        subplot.hist(self.images.flatten(), 100, normed=True, histtype='step', fc='k', ec='k')
        canvas.draw()
        close_button = tk.Button(histo, text='Close', command = histo.destroy)
        close_button.pack(side=tk.TOP)

    def savePicture(self):
        print('Save!')
        savefile = tk.filedialog.asksaveasfilename(title='Save image as ...', defaultextension='png',
                                                  filetypes=[('all files', '.*'), ('png files', '.png')])
        if savefile:
            self.f.savefig(savefile, dpi=1200, format='png', )

    def mouseWheel(self, event):
        print('Test mouseWheel.')
        if event.button == 'down':
            self.indexOfImg = self.indexOfImg+1
            self.show_images()
            self.inform('<MouseWheelDown')
        if event.button == 'up':
            self.indexOfImg = self.indexOfImg-1
            self.show_images()
            self.inform('<MouseWheelUp')

    def change_wl(self, arg):
        print('Button press event test')

    def set_images(self, images):
        self.images = images
        if self.img_is_set == False:
            self.original_img = images
        self.show_images()
        self.img_is_set = True

    def set_metadata(self, data):
        self.metadata = data

    def show_images(self):
        plt.clf()
        if (self.indexOfImg < np.size(self.images, 0))and (self.indexOfImg >= 0):
            self.img = self.subplot.imshow(self.images[self.indexOfImg])
            if self.level_is_set == False:
                self.level = (np.max(self.images[self.indexOfImg])-np.min(self.images[self.indexOfImg]))/2
                self.window = 2*self.level
                self.levelScale.config(from_=np.min(self.images[self.indexOfImg]))
                self.levelScale.config(to=np.max(self.images[self.indexOfImg]))
                self.levelScale.set(self.level)
                self.windowScale.config(from_=0)
                self.windowScale.config(to=self.window)
                self.windowScale.set(self.window)
                if self.window < 1:
                    self.levelScale.config(resolution=0.0001)
                    self.windowScale.config(resolution=0.0001)
                self.img.set_clim(self.level-self.window/2, self.level+self.window/2)
        else:
            self.indexOfImg = 0
            self.img = self.subplot.imshow(self.images[self.indexOfImg])

            if self.level_is_set == False:
                self.level = (np.max(self.images[self.indexOfImg])-np.min(self.images[self.indexOfImg]))/2
                self.window = 2*self.level
                self.levelScale.config(from_=np.min(self.images[self.indexOfImg]))
                self.levelScale.config(to=np.max(self.images[self.indexOfImg]))
                self.levelScale.set(self.level)
                self.windowScale.config(from_=0)
                self.windowScale.config(to=self.window)
                self.windowScale.set(self.window)
                if self.window < 1:
                    self.levelScale.config(resolution=0.0001)
                    self.windowScale.config(resolution=0.0001)
                self.img.set_clim(self.level-self.window/2, self.level+self.window/2)

        if self.cb:
                if self.cbar:
                    self.cbar.set_clim(np.min(self.images[self.indexOfImg]), np.max(self.images[self.indexOfImg]))
                else:
                    self.cbar = self.f.colorbar(self.img)
        self.canvas.draw()

    def set_level(self, event):
        self.level = self.levelScale.get()
        if self.level >= (np.max(self.images[self.indexOfImg])-np.min(self.images[self.indexOfImg]))/2:
             self.window = 2*(np.max(self.images[self.indexOfImg])-self.level)
        elif self.level < (np.max(self.images[self.indexOfImg])-np.min(self.images[self.indexOfImg]))/2:
             self.window = 2*(self.level-np.min(self.images[self.indexOfImg]))
        print(self.level, self.window)
        if self.windowScale.get() <= self.window:
             self.img.set_clim(float(self.level-self.windowScale.get()/2), float(self.level+self.windowScale.get()/2))
        else:
             self.img.set_clim(float(self.level-self.window/2), float(self.level+self.window/2))
        #self.level_is_set = True
        self.windowScale.config(to = self.window)
        self.canvas.draw()

    def set_window(self, event):
        self.window = self.windowScale.get()
        self.img.set_clim(float(self.level-self.window/2), float(self.level+self.window/2))
        #self.level_is_set = True
        self.canvas.draw()



    def set_indexOfImg(self, index):
        self.indexOfImg = index

    def ruler(self):
        print('Measure!')

    def move(self):
        print('Move!')

    def info(self):
        info = tk.Toplevel()
        tk.Button(info, text='Close', command = info.destroy).pack(side=tk.TOP)
Esempio n. 2
0
class click_yrange:
   '''An interactive yrange selector.  Given an axis and a starting
   y0 location, draw a full-width rectange that follows the mouise.
   Similar to click_window, but more appropriate for selecting out
   a y-range.'''

   def __init__(self, ax, y0):
      self.ax = ax
      self.y0 = y0
      x0,x1 = ax.get_xbound()
      self.rect = Rectangle((x0,y0), width=(x1-x0), height=0, alpha=0.1)
      ax.add_artist(self.rect)

   def connect(self):
      self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

   def on_motion(self, event):
      # Have we left the axes?
      if event.inaxes != self.rect.axes:  return

      self.rect.set_height(event.ydata - self.y0)
      self.ax.figure.canvas.draw()

   def close(self):
      self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
      self.rect.remove()
      self.ax.figure.canvas.draw()
      return(self.y0, self.rect.get_y()+self.rect.get_height())
class Annotate(object):
    def __init__(self, ax):
        self.ax = ax
        self.rect = Rectangle((0,0), 1, 1, fill=False)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)

    def on_press(self, event):
        print 'press'
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_release(self, event):
        print 'release'
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()
        self.get_graph_bound()
        #self.bounds = ColorBounds(Cb_min=self.x0, Cr_min=self.y0, Cb_max=self.x1, Cr_max=self.y1)
        self.bounds = ColorBounds(Cr_min=self.x0, Yp_min=self.y0, Cr_max=self.x1, Yp_max=self.y1)
        
    def get_graph_bound(self):
        print(self.x0, self.y0, self.x1, self.y1)
Esempio n. 4
0
class LaneSelector(object):
    def __init__(self, cb):
        self.ax = gca()
        self.rect = Rectangle((0,0), 1, 1, alpha=0.2, color='red')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.pressed = False
        self.cb = cb
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.pressed = True

    def on_release(self, event):
        self.pressed = False
        if self.x0 != self.x1 and self.y0 != self.y1:
            self.cb(self.x0, self.y0, self.x1, self.y1)

    def on_motion(self, event):
        if self.pressed:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.ax.figure.canvas.draw()
Esempio n. 5
0
class Annotate(object):
    def __init__(self, ax, areas, rects):
        self.ax = ax
        self.areas = areas
        self.rects = rects
        self.rect = Rectangle((0, 0), 0, 0, color='orange', alpha=0.5)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)

    def on_press(self, event):
        if event.inaxes == self.ax:
            self.x0 = event.xdata
            self.y0 = event.ydata

    def on_release(self, event):
        if event.inaxes == self.ax:
            self.x1 = event.xdata
            self.y1 = event.ydata
            if event.button == 1:
                self.areas.append(
                    [self.x0, self.y0, self.x1, self.y1, "appended", "a"])
            elif event.button == 3:
                self.areas.append(
                    [self.x0, self.y0, self.x1, self.y1, "appended", "d"])
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.rect.set_visible(False)
Esempio n. 6
0
class Annotate(object):
  def __init__(self):
    self.ax = plt.gca()
    self.rect = Rectangle((0,0), 0, 0)
    self.x0 = 0
    self.y0 = 0
    self.x1 = 0
    self.y1 = 0
    self.ax.add_patch(self.rect)
    self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
    self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)

  def on_press(self, event):
    self.x0 = event.xdata
    self.y0 = event.ydata

  def on_release(self, event):
    try:
      self.x1 = event.xdata
      self.y1 = event.ydata
      self.rect.set_width(self.x1 - self.x0)
      self.rect.set_height(self.y1 - self.y0)
      self.rect.set_xy((self.x0, self.y0))
      self.ax.figure.canvas.draw()
    except TypeError:
      print("Can't select outside the plot! Try again!")
Esempio n. 7
0
class click_window:
    '''An interactive window.  Given an axis instance and a start point
   (x0,y0), draw a dynamic rectangle that follows the mouse until
   the close() function is called (which returns the coordinates of
   the final rectangle.  Useful or selecting out square regions.'''
    def __init__(self, ax, x0, y0):
        self.ax = ax
        self.x0 = x0
        self.y0 = y0
        self.rect = Rectangle((x0, y0), width=0, height=0, alpha=0.1)
        ax.add_artist(self.rect)

    def connect(self):
        self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

    def on_motion(self, event):
        # Have we left the axes?
        if event.inaxes != self.rect.axes: return

        self.rect.set_width(event.xdata - self.x0)
        self.rect.set_height(event.ydata - self.y0)
        self.ax.figure.canvas.draw()

    def close(self):
        self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
        extent = self.rect.get_bbox().get_points()
        self.rect.remove()
        self.ax.figure.canvas.draw()
        return (list(ravel(extent)))
Esempio n. 8
0
class Selector(object):
    def __init__(self, ax):
        self.ax = ax

        self.x0 = None
        self.y0 = None

        self.rect = Rectangle((0, 0), 1, 1, fill=False)
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_release(self, event):
        x1 = event.xdata
        y1 = event.ydata

        self.rect.set_width(x1 - self.x0)
        self.rect.set_height(y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()

        x_min = min(self.x0, x1)
        x_max = max(self.x0, x1)
        y_min = min(self.y0, y1)
        y_max = max(self.y0, y1)

        self.xybounds = (x_min, x_max, y_min, y_max)
Esempio n. 9
0
class click_yrange:
    '''An interactive yrange selector.  Given an axis and a starting
   y0 location, draw a full-width rectange that follows the mouise.
   Similar to click_window, but more appropriate for selecting out
   a y-range.'''
    def __init__(self, ax, y0):
        self.ax = ax
        self.y0 = y0
        x0, x1 = ax.get_xbound()
        self.rect = Rectangle((x0, y0), width=(x1 - x0), height=0, alpha=0.1)
        ax.add_artist(self.rect)

    def connect(self):
        self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

    def on_motion(self, event):
        # Have we left the axes?
        if event.inaxes != self.rect.axes: return

        self.rect.set_height(event.ydata - self.y0)
        self.ax.figure.canvas.draw()

    def close(self):
        self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
        self.rect.remove()
        self.ax.figure.canvas.draw()
        return (self.y0, self.rect.get_y() + self.rect.get_height())
Esempio n. 10
0
    def resizeGraphics(self, width, height):
        """ It is time to set a magnitude to our currently normalized
            lines, and send them to the figure. Here we assume that
            __normLines & __normPatches are already fully populated. """
        self.__fig.lines = []  # clear all old lines from figure
        self.__fig.patches = []  # clear all old patches from figure
        self.__xsz = width
        self.__ysz = height

        # scale each text item
        for t in self.__fig.texts:
            t.set_size(self.getTextPointSize(t.gkiTextSzFactor, width, height))

        # scale each line, then apply it to the figure
        for nrln in self.__normLines:
            ll = Line2D([], [])
            ll.update_from(nrln)
            ll.set_data(
                nrln.get_xdata(True) * self.__xsz,
                nrln.get_ydata(True) * self.__ysz)
            self.__fig.lines.append(ll)

        # scale each patch, then apply it to the figure
        for nrpa in self.__normPatches:
            rr = Rectangle((0, 0), 0, 0)
            rr.update_from(nrpa)
            rr.set_x(nrpa.get_x() * self.__xsz)
            rr.set_y(nrpa.get_y() * self.__ysz)
            rr.set_width(nrpa.get_width() * self.__xsz)
            rr.set_height(nrpa.get_height() * self.__ysz)
            self.__fig.patches.append(rr)
Esempio n. 11
0
class Annotate(object):
    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0,0), 1, 1)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)

    def on_press(self, event):
        print 'press'
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_release(self, event):
        print 'release'
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()
Esempio n. 12
0
class Annotate(object):
    def __init__(self, uploaded_image):
        self.uploaded_image = uploaded_image
        plt.imshow(uploaded_image, zorder=0)
        self.ax = plt.gca()
        axcut = plt.axes([0.9, 0.0, 0.1, 0.075])
        self.bsubmit = Button(axcut, "Submit", color='red', hovercolor="green")
        self.rect = Rectangle((0, 0),
                              1,
                              1,
                              fc=(1, 0, 0, .5),
                              ec=(0, 0, 0, 1),
                              lw=2)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.boundedboxes = []
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.bsubmit.on_clicked(self.submit)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata

    # For drawing the boxes. When release it saves the coordinates in list of list datastructure
    def on_release(self, event):
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.boundedboxes.append([self.x0, self.y0, self.x1, self.y1])
        self.ax.figure.canvas.draw()

    # On click of submit button
    # Needs to be updated to send these values to the function which will
    # recognize the objects
    # Then closes all the matplotlib objects that are open
    def submit(self, event):

        word = ""
        count = 0
        n = len(self.boundedboxes)
        n = n - 1
        cropped_images = np.empty(shape=(n, 32, 32, 3))
        for i in self.boundedboxes:
            if i[1] > 1:
                cropped_images[count, :, :, :] = crop_image(
                    self.uploaded_image, i)
                count += 1

        guesses = predict_char(cropped_images)
        for i in guesses:
            word += get_label_name(i)

        Translate(word)
Esempio n. 13
0
File: roi.py Progetto: hayd/glue
class MplYRangeROI(AbstractMplRoi):

    def __init__(self, ax):
        """
        :param ax: A matplotlib Axes object to attach the graphical ROI to
        """

        AbstractMplRoi.__init__(self, ax)
        self._xi = None

        self.plot_opts = {'edgecolor': PATCH_COLOR, 'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        trans = blended_transform_factory(self._ax.transAxes,
                                          self._ax.transData)
        self._patch = Rectangle((0., 0.), 1., 1., transform=trans)
        self._patch.set_zorder(100)
        self._setup_patch()

    def _setup_patch(self):
        self._ax.add_patch(self._patch)
        self._patch.set_visible(False)
        self._sync_patch()

    def _roi_factory(self):
        return YRangeROI()

    def start_selection(self, event):
        if event.inaxes != self._ax:
            return

        self._roi.reset()
        self._roi.set_range(event.ydata, event.ydata)
        self._xi = event.ydata
        self._mid_selection = True
        self._sync_patch()

    def update_selection(self, event):
        if not self._mid_selection or event.inaxes != self._ax:
            return
        self._roi.set_range(min(event.ydata, self._xi),
                            max(event.ydata, self._xi))
        self._sync_patch()

    def finalize_selection(self, event):
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            rng = self._roi.range()
            self._patch.set_xy((0, rng[0]))
            self._patch.set_height(rng[1] - rng[0])
            self._patch.set_width(1)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)
        self._draw()
class Selector(object):
    def __init__(self, ax):
        self.ax = ax
        
        self.x0 = None
        self.y0 = None
        
        self.rect = Rectangle((0,0), 1, 1, fill=False)
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_release(self, event):
        x1 = event.xdata
        y1 = event.ydata

        self.rect.set_width(x1 - self.x0)
        self.rect.set_height(y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()
        
        x_min = min(self.x0, x1)
        x_max = max(self.x0, x1)
        y_min = min(self.y0, y1)
        y_max = max(self.y0, y1)

        self.xybounds = (x_min, x_max, y_min, y_max)
Esempio n. 15
0
class Annotate(object):
    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0,0), 1, 1)
        self.x0 = None         
        self.y0 = None         
        self.x1 = None         
        self.y1 = None         
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
       
   
    def on_press(self, event):
        print 'press'         
        self.x0 = event.xdata         
        self.y0 = event.ydata      
       
       
    def on_release(self, event):         
        print 'release'         
        self.x1 = event.xdata         
        self.y1 = event.ydata         
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)         
        self.rect.set_xy((self.x0, self.y0))         
        self.ax.figure.canvas.draw()  
Esempio n. 16
0
class click_window:
   '''An interactive window.  Given an axis instance and a start point
   (x0,y0), draw a dynamic rectangle that follows the mouse until
   the close() function is called (which returns the coordinates of
   the final rectangle.  Useful or selecting out square regions.'''

   def __init__(self, ax, x0, y0):
      self.ax = ax
      self.x0 = x0
      self.y0 = y0
      self.rect = Rectangle((x0,y0), width=0, height=0, alpha=0.1)
      ax.add_artist(self.rect)

   def connect(self):
      self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

   def on_motion(self, event):
      # Have we left the axes?
      if event.inaxes != self.rect.axes:  return

      self.rect.set_width(event.xdata - self.x0)
      self.rect.set_height(event.ydata - self.y0)
      self.ax.figure.canvas.draw()

   def close(self):
      self.rect.figure.canvas.mpl_disconnect(self.cidmotion)
      extent = self.rect.get_bbox().get_points()
      self.rect.remove()
      self.ax.figure.canvas.draw()
      return(list(ravel(extent)))
Esempio n. 17
0
    def resizeGraphics(self, width, height):

        """ It is time to set a magnitude to our currently normalized
            lines, and send them to the figure. Here we assume that
            __normLines & __normPatches are already fully populated. """
        self.__fig.lines   = [] # clear all old lines from figure
        self.__fig.patches = [] # clear all old patches from figure
        self.__xsz = width
        self.__ysz = height

        # scale each text item
        for t in self.__fig.texts:
            t.set_size(self.getTextPointSize(t.gkiTextSzFactor, width, height))

        # scale each line, then apply it to the figure
        for nrln in self.__normLines:
            ll = Line2D([], [])
            ll.update_from(nrln)
            ll.set_data(nrln.get_xdata(True)*self.__xsz,
                        nrln.get_ydata(True)*self.__ysz)
            self.__fig.lines.append(ll)

        # scale each patch, then apply it to the figure
        for nrpa in self.__normPatches:
            rr = Rectangle((0,0),0,0)
            rr.update_from(nrpa)
            rr.set_x(nrpa.get_x()*self.__xsz)
            rr.set_y(nrpa.get_y()*self.__ysz)
            rr.set_width(nrpa.get_width()*self.__xsz)
            rr.set_height(nrpa.get_height()*self.__ysz)
            self.__fig.patches.append(rr)
Esempio n. 18
0
class Annotate(object):
    def __init__(self):
        self.ax = plt.gca()
        #self.ax = ax
        #self.fig = fig
        self.rect = Rectangle((0,0), 1, 1, facecolor='None', edgecolor='green')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.is_pressed = False
        self.ax.add_patch(self.rect)
        #self.fig.canvas.mpl_connect('button_press_event',self.on_press)
        #self.fig.canvas.mpl_connect('button_release_event', self.on_release)
        #self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)
        
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
        self.ax.figure.canvas.draw()
    def on_press(self, event):
        print 'press'
        self.is_pressed = True
        self.x0 = event.xdata
        self.y0 = event.ydata
        print self.x0, self.y0
        #self.rect.set_width(self.x1 - self.x0)
        #self.rect.set_height(self.y1 - self.y0)
        #self.rect.set_xy((self.x0, self.y0))
        #self.rect.set_linestyle('dashed')
        #self.fig.canvas.draw()
        #self.ax.figure.canvas.draw()
    def on_motion(self,event):
        print 'motion'
        if self.is_pressed is True:
            return
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.rect.set_linestyle('dashed')
        #self.fig.canvas.draw()
        self.ax.figure.canvas.draw()
    def on_release(self, event):
        print 'release'
        self.is_pressed = False
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.rect.set_linestyle('solid')
        #self.fig.canvas.draw()
        self.ax.figure.canvas.draw()
        #time.sleep(3)
        #plt.close()
        print self.x0,self.y0,self.x1,self.y1
Esempio n. 19
0
class MplYRangeROI(AbstractMplRoi):
    def __init__(self, ax):
        """
        :param ax: A matplotlib Axes object to attach the graphical ROI to
        """

        AbstractMplRoi.__init__(self, ax)
        self._xi = None

        self.plot_opts = {
            'edgecolor': PATCH_COLOR,
            'facecolor': PATCH_COLOR,
            'alpha': 0.3
        }

        trans = blended_transform_factory(self._ax.transAxes,
                                          self._ax.transData)
        self._patch = Rectangle((0., 0.), 1., 1., transform=trans)
        self._patch.set_zorder(100)
        self._ax.add_patch(self._patch)
        self._sync_patch()

    def _roi_factory(self):
        return YRangeROI()

    def start_selection(self, event):
        if event.inaxes != self._ax:
            return

        self._roi.reset()
        self._roi.set_range(event.ydata, event.ydata)
        self._xi = event.ydata
        self._mid_selection = True
        self._sync_patch()

    def update_selection(self, event):
        if not self._mid_selection or event.inaxes != self._ax:
            return
        self._roi.set_range(min(event.ydata, self._xi),
                            max(event.ydata, self._xi))
        self._sync_patch()

    def finalize_selection(self, event):
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            rng = self._roi.range()
            self._patch.set_xy((0, rng[0]))
            self._patch.set_height(rng[1] - rng[0])
            self._patch.set_width(1)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)
        self._draw()
Esempio n. 20
0
class Annotate(object):
    def __init__(self):
        self.ax = plt.gca()
        self.img = cv2.imread('./img/11.jpg')
        self.rect = Rectangle((0, 0), 1, 1, edgecolor='red')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.range = self.img.shape[0:2]
        self.rect_coor = []
        self.press = False
        self.ax.add_patch(self.rect)
        self.ax.imshow(self.img)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event',
                                          self.on_motion)

    def on_press(self, event):
        self.x0 = event.xdata if event.xdata else 0
        self.y0 = event.ydata if event.ydata else 0
        self.press = True

    def on_release(self, event):
        self.x1 = event.xdata if event.xdata else 0
        self.y1 = event.ydata if event.ydata else 0
        self.press = False
        # self.rect.set_width(self.x1 - self.x0)
        # self.rect.set_height(self.y1 - self.y0)
        # self.rect.set_xy((self.x0, self.y0))
        self.rect_coor.append((self.x0, self.y0, self.x1, self.y1))
        self.draw_rect(self.rect_coor)
        print(self.rect_coor)

    def on_motion(self, event):
        if self.press == True:
            x0, y0, x1, y1 = self.x0, self.y0, self.x1, self.y1
            x_now = event.xdata if event.xdata else 0
            y_now = event.ydata if event.ydata else 0
            dx = x_now - x0
            dy = y_now - y0
            self.rect.set_width(dx)
            self.rect.set_height(dy)
            self.rect.set_xy((self.x0, self.y0))
            self.ax.figure.canvas.draw()

    def draw_rect(self, coor_arrs):
        '''draw rect, and rect's arr from coor_arrs
            '''
        for coor in coor_arrs:
            rect = Rectangle((0, 0), 1, 1, edgecolor='red', fill=False)
            self.ax.add_patch(rect)
            rect.set_width(coor[2] - coor[0])
            rect.set_height(coor[3] - coor[1])
            rect.set_xy((coor[0], coor[1]))
            self.ax.figure.canvas.draw()
Esempio n. 21
0
 def draw_rect(self, coor):
     rect = Rectangle((0, 0), 1, 1, edgecolor='red', fill=False)
     self.ax.add_patch(rect)
     rect.set_width(coor[2] - coor[0])
     rect.set_height(coor[3] - coor[1])
     rect.set_xy((coor[0], coor[1]))
     # self.ax.annotate(1, (coor[0], coor[1]), color='w', weight='bold',
     #         fontsize=16, horizontalalignment='left', verticalalignment='top')
     self.ax.figure.canvas.draw()
Esempio n. 22
0
class ImageAreaSelect(object):
    def __init__(self, img, out, fit=False):
        self.img = img
        self.out = out
        self.fit = fit

        plt.figure()
        plt.title("Testing Image")
        plt.xlabel(r'M')
        plt.ylabel(r'N')
        self.ax = plt.gca()
        self.rect = Rectangle((0, 0), 1, 1, antialiased=True, color='b',
                              linestyle='solid', lw=1.2)
        self.rect.set_fill(False)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None

        self.draw_rect = False

        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

        plt.imshow(self.img, cmap="gray")
        plt.show()

    def on_press(self, event):
        self.draw_rect = True
        self.x0 = int(event.xdata)
        self.y0 = int(event.ydata)

    def on_motion(self, event):
        if self.draw_rect:
            if self.x1 != int(event.xdata) or self.y1 != int(event.ydata):
                self.x1 = int(event.xdata)
                self.y1 = int(event.ydata)
                self.rect.set_width(self.x1 - self.x0)
                self.rect.set_height(self.y1 - self.y0)
                self.rect.set_xy((self.x0, self.y0))
                self.ax.figure.canvas.draw()

    def on_release(self, event):
        self.draw_rect = False
        self.x1 = int(event.xdata)
        self.y1 = int(event.ydata)
        self.calc()

    def calc(self):
        if self.x1 == self.x0 or self.y1 == self.y0:
            return
        print('crop(x,y):', self.x0, self.x1, self.y0, self.y1)
        img = self.img[self.y0:self.y1, self.x0:self.x1]
        mtf_from_img(img, self.out + "/" + str(self.x0) + "_" + str(self.x1) + "_" + str(self.y0) + "_" + str(self.y1), True)
Esempio n. 23
0
 def draw_rect(self, coor_arrs):
     '''draw rect, and rect's arr from coor_arrs
         '''
     for coor in coor_arrs:
         rect = Rectangle((0, 0), 1, 1, edgecolor='red', fill=False)
         self.ax.add_patch(rect)
         rect.set_width(coor[2] - coor[0])
         rect.set_height(coor[3] - coor[1])
         rect.set_xy((coor[0], coor[1]))
         self.ax.figure.canvas.draw()
Esempio n. 24
0
class Annotate(object):
    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0, 0), 1, 1, facecolor='None', edgecolor='red')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.x2 = None
        self.y2 = None
        self.is_pressed = False
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event',
                                          self.on_motion)

    def on_press(self, event):
        self.is_pressed = True
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_motion(self, event):
        self.x1, self.y1 = event.xdata, event.ydata
        if (self.is_pressed is True and self.x1 is not None
                and self.y1 is not None):
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.rect.set_linestyle('dashed')
            self.ax.figure.canvas.draw()

    def on_release(self, event):
        self.is_pressed = False
        self.x1, self.y1 = event.xdata, event.ydata
        try:
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
        except TypeError:
            if (self.x1 is None or self.y1 is None):
                return
            else:
                raise
        self.rect.set_linestyle('solid')
        self.ax.figure.canvas.draw()
        print self.x0, self.x1, self.y0, self.y1
        self.x2 = self.x1
        self.y2 = self.y1

    def __call__(self):
        return [self.x0, self.x2, self.y0, self.y2]
Esempio n. 25
0
class RoiRect(object):
    ''' Class for getting a mouse drawn rectangle
    Based on the example from:
    http://matplotlib.org/users/event_handling.html#draggable-rectangle-exercise
    Note that:
    
    * It makes only one roi
    
    '''
    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0,0), 1, 1,fc='none', ec='r')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_press(self, event):
        print 'press'
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.rect.set_linestyle('dashed')
        self.set = False

    def on_release(self, event):
        print 'release'
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.rect.set_linestyle('solid')
        self.ax.figure.canvas.draw()
        self.set = True
        self.ax.figure.canvas.mpl_disconnect(self.on_press)
        self.ax.figure.canvas.mpl_disconnect(self.on_release)
        self.ax.figure.canvas.mpl_disconnect(self.on_motion)
        
    def on_motion(self, event):
        # on motion will move the rect if the mouse
        if self.x0 is None: return
        if self.set: return
        # if event.inaxes != self.rect.axes: return
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()
Esempio n. 26
0
class ROI(object):
    def __init__(self, fig, ax_tran, ax_fron, ax_sagi):
        self.fig = fig
        self.ax_tran = ax_tran
        self.ax_fron = ax_fron
        self.ax_sagi = ax_sagi

        self.rect = Rectangle((0, 0), 1, 1, facecolor='None', edgecolor='red')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.is_pressed = False

        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def check_axes(self, event):
        if self.ax_tran.in_axes(event):
            self.ax_tran.add_patch(self.rect)

    def on_press(self, event):
        self.is_pressed = True
        print('press')
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_motion(self, event):
        if self.is_pressed == True:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.rect.set_linestyle('dashed')
            self.fig.canvas.draw()
            # self.ax.figure.canvas.draw()

    def on_release(self, event):
        self.is_pressed = False
        print('release')
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.rect.set_linestyle('solid')
        self.fig.canvas.draw()
        # self.ax.figure.canvas.draw()
        print(self.x0, self.x1, self.y0, self.y1)
        return [self.x0, self.x1, self.y0, self.y1]
Esempio n. 27
0
class rectSelection(GuiSelection):
    """Interactive selection of a rectangular region on the axis.

    Used by hist2d_alex().
    """
    def on_press_draw(self):
        if 'r' in self.__dict__:
            self.r.set_height(0)
            self.r.set_width(0)
            self.r.set_xy((self.xs, self.ys))
            self.e.height = 0
            self.e.width = 0
            self.e.center = (self.xs, self.ys)
        else:
            self.r = Rectangle(xy=(self.xs, self.ys),
                               height=0,
                               width=0,
                               fill=False,
                               lw=2,
                               alpha=0.5,
                               color='blue')
            self.e = Ellipse(xy=(self.xs, self.ys),
                             height=0,
                             width=0,
                             fill=False,
                             lw=2,
                             alpha=0.6,
                             color='blue')
            self.ax.add_artist(self.r)
            self.ax.add_artist(self.e)
            self.r.set_clip_box(self.ax.bbox)
            self.r.set_zorder(10)
            self.e.set_clip_box(self.ax.bbox)
            self.e.set_zorder(10)

    def on_motion_draw(self):
        self.r.set_height(self.ye - self.ys)
        self.r.set_width(self.xe - self.xs)
        self.e.height = (self.ye - self.ys)
        self.e.width = (self.xe - self.xs)
        self.e.center = (np.mean([self.xs,
                                  self.xe]), np.mean([self.ys, self.ye]))
        self.fig.canvas.draw()

    def on_release_print(self):
        # This is the only custom method for hist2d_alex()
        E1, E2 = min((self.xs, self.xe)), max((self.xs, self.xe))
        S1, S2 = min((self.ys, self.ye)), max((self.ys, self.ye))
        self.selection = dict(E1=E1, E2=E2, S1=S1, S2=S2)
        pprint("Selection: \nE1=%.2f, E2=%.2f, S1=%.2f, S2=%.2f\n" %\
                (E1,E2,S1,S2))
Esempio n. 28
0
class Selector():
    def __init__(self, ax, canvas, x0=0, y0=0, x1=1, y1=1):
        self.Rect = Rectangle((x0, y0), x1-x0, y1-y0, color="blue", alpha=0.2, visible=False)
        self.cHandles = Line2D([x0, x1, x1, x0], [y0, y0, y1, y1], marker='o', markersize=7, mfc='w', markeredgecolor='mediumblue', ls='none', alpha=0.8, visible=False, label='_nolegend_')
        self.eHandles = Line2D([(x0+x1)/2, x1, (x0+x1)/2, x0], [y0, (y0+y1)/2, y1, (y0+y1)/2], marker='s', markersize=5, mfc='w', markeredgecolor='dodgerblue', ls='none', alpha=0.8, visible=False, label='_nolegend_')
        self.artist = [self.Rect, self.cHandles, self.eHandles]
        self.region = (x0, y0, x1, y1)
        self.active_handle = 0
        self.visible = False
        self.ax = ax
        self.canvas = canvas
        self.moveing_state = "draw"
        self.origin = (0, 0)
        self.ax.add_patch(self.Rect)
        self.ax.add_line(self.cHandles)
        self.ax.add_line(self.eHandles)

    def resize(self, x0, y0, x1, y1):
        xmin, xmax = sorted((x0, x1))
        ymin, ymax = sorted((y0, y1))
        self.region = (xmin, ymin, xmax, ymax)
        self.Rect.set_xy((xmin, ymin))
        self.Rect.set_width(xmax-xmin)
        self.Rect.set_height(ymax-ymin)
        self.cHandles.set_data([xmin, xmax, xmax, xmin], [ymin, ymin, ymax, ymax])
        self.eHandles.set_data([(xmin+xmax)/2, xmax, (xmin+xmax)/2, xmin], [ymin, (ymin+ymax)/2, ymax, (ymin+ymax)/2])

    def set_visible(self, visible):
        self.Rect.set_visible(visible)
        self.cHandles.set_visible(visible)
        self.eHandles.set_visible(visible)
        self.visible = visible

    def isinRegion(self, x, y):
        if ((self.region[0] < x < self.region[2]) and (self.region[1] < y < self.region[3])):
            return True
        else:
            return False

    def nearestCorner(self, x, y):
        x0, y0, x1, y1 = self.region
        array = np.array([[x0,y0], [(x0+x1)/2, y0], [x1,y0], [x1, (y0+y1)/2], [x1,y1], [(x0+x1)/2, y1], [x0,y1], [x0, (y0+y1)/2]])
        pts = self.ax.transData.transform(array)
        diff = pts - ((x, y))
        distance = np.sqrt(np.sum(diff ** 2, axis=1))
        self.active_handle = distance.argmin()
        return distance.min()
class ROI(object):
    def __init__(self, ax, roi_data, pat_id, ax_name, ax_index):
        self.ax = ax
        self.roi_data = roi_data
        self.pat_id = pat_id
        self.ax_name = ax_name
        self.ax_index = ax_index
        
        self.rect = Rectangle((0, 0), 1, 1, facecolor='None', edgecolor='red')
        self.x1 = None
        self.y1 = None
        self.x2 = None
        self.y2 = None
        self.is_pressed = False
        self.ax.add_patch(self.rect)
        
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
        
    def on_press(self, event):
        self.is_pressed = True
        self.x1 = event.xdata
        self.y1 = event.ydata

    def on_motion(self, event):
        if self.is_pressed == True:
            self.x2 = event.xdata
            self.y2 = event.ydata
            self.rect.set_width(self.x2 - self.x1)
            self.rect.set_height(self.y2 - self.y1)
            self.rect.set_xy((self.x1, self.y1))
            self.rect.set_linestyle('dashed')
            self.ax.figure.canvas.draw()
            
    def on_release(self, event):
        self.is_pressed = False
        self.x2 = event.xdata
        self.y2 = event.ydata
        self.rect.set_width(self.x2 - self.x1)
        self.rect.set_height(self.y2 - self.y1)
        self.rect.set_xy((self.x1, self.y1))
        self.rect.set_linestyle('solid')
        self.ax.figure.canvas.draw()
        
        # Append axes name and two rectangluar coordinates
        self.roi_data.append([self.pat_id, self.ax_name, self.ax_index[-1], int(self.x1), int(self.y1), int(self.x2), int(self.y2)])
Esempio n. 30
0
 def draw_rects(self, coor_arrs):
     '''draw rect, and rect's arr from coor_arrs
         '''
     for index, coor in enumerate(coor_arrs):
         rect = Rectangle((0, 0), 1, 1, edgecolor='red', fill=False)
         self.ax.add_patch(rect)
         rect.set_width(coor[2] - coor[0])
         rect.set_height(coor[3] - coor[1])
         rect.set_xy((coor[0], coor[1]))
         ann = self.ax.annotate((index, int(coor[0]), int(
             coor[1]), int(coor[2]), int(coor[3])), (coor[0], coor[1]),
                                color='w',
                                fontsize=10,
                                horizontalalignment='left',
                                verticalalignment='top')
         self.anns.append(ann)
     self.ax.figure.canvas.draw()
Esempio n. 31
0
class RectangleRegionSelector(object):
    isPressed = False

    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0, 0), 1, 1, color='b', fill=False)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event',
                                          self.on_motion)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.isPressed = True

    def on_motion(self, event):
        if self.isPressed:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.draw_rect()

    def on_release(self, event):
        self.isPressed = False
        if event.xdata is not None and event.ydata is not None:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.draw_rect()
        else:
            print "Mouse must be released within the axes, try again."

    def draw_rect(self):
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()

    def asXYWH(self):
        return (min(self.x0, self.x1), min(self.y0, self.y1),
                abs(self.x1 - self.x0), abs(self.y1 - self.y0))
Esempio n. 32
0
class Plotcanvas_with_rect(FigureCanvas):
    def __init__(self,
                 parent=None,
                 width=8,
                 height=8,
                 dpi=100,
                 topo=[],
                 cmap='binary'):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.fig.set_tight_layout({'pad': 0, 'w_pad': 0, 'h_pad': 0})
        self.fig.set_constrained_layout_pads(w_pad=0,
                                             h_pad=0,
                                             wspace=0,
                                             hspace=0)
        self.cmap = cmap
        self.topo = topo
        self.axs = self.fig.add_subplot(111)
        FigureCanvas.__init__(self, self.fig)
        self.axs.pcolormesh(self.topo, cmap=plt.get_cmap(cmap))
        self.rect = Rectangle((0, 0), 0.2, 0.2, color='k', fill=None, alpha=1)
        self.axs.add_patch(self.rect)
        self.rect.set_visible(False)
        self.fig.canvas.draw()
        self.show()

        self.fig.canvas.mpl_connect('button_press_event', self.on_click)
        self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_click(self, event):
        if event.button == 1 or event.button == 3:
            if event.inaxes is not None:
                self.xclick = event.xdata
                self.yclick = event.ydata
                self.onpress = True

    def on_motion(self, event):
        if event.button == 1 or event.button == 3 and self.on_press == True:
            if (self.xclick is not None and self.yclick is not None):
                x0, y0 = self.xclick, self.yclick
                x1, y1 = event.xdata, event.ydata
                if (x1 is not None or y1 is not None):
                    self.rect.set_width(x1 - x0)
                    self.rect.set_height(y1 - y0)
                    self.rect.set_xy((x0, y0))
                    self.rect.set_visible(True)
                    self.draw()  # self.canvas.drawRectangle(self.rect)
Esempio n. 33
0
class RectangleRegionSelector(object):
    isPressed = False

    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0, 0), 1, 1, color='b', fill=False)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event',
                                          self.on_motion)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.isPressed = True

    def on_motion(self, event):
        if self.isPressed:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.draw_rect()

    def on_release(self, event):
        self.isPressed = False
        if event.xdata is not None and event.ydata is not None:
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.draw_rect()
        else:
            print "Mouse must be released within the axes, try again."

    def draw_rect(self):
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()

    def asXYWH(self):
        return (min(self.x0, self.x1), min(self.y0, self.y1),
                abs(self.x1-self.x0), abs(self.y1-self.y0))
Esempio n. 34
0
def UpdateZoomGizmo(scale, xrange, yrange):
    global axis, zoom_factor, img_offset, z_container, z_box

    aspect = yrange / xrange

    # Change the size of the Gizmo
    size = 320

    if zoom_factor > 1:
        gizmo_w = size * scale
        gizmo_h = size * scale * aspect
        gizmo_pos = img_offset[0] - xrange * scale, img_offset[
            1] + yrange * scale - gizmo_h

        if z_container is None:
            z_container = Rectangle(gizmo_pos,
                                    gizmo_w,
                                    gizmo_h,
                                    edgecolor="w",
                                    facecolor='none')
            z_container.label = "zoom_container"

            z_box = Rectangle(gizmo_pos, gizmo_w, gizmo_h, alpha=0.5)
            z_box.label = "zoom_box"

            axis.add_artist(z_container)
            axis.add_artist(z_box)
        else:
            z_container.set_xy(gizmo_pos)
            z_container.set_width(gizmo_w)
            z_container.set_height(gizmo_h)

            z_box.set_x(gizmo_pos[0] + 0.5 *
                        (img_offset[0] * gizmo_w / xrange - gizmo_w * scale))
            z_box.set_y(gizmo_pos[1] + 0.5 *
                        (img_offset[1] * gizmo_h / yrange - gizmo_h * scale))
            z_box.set_width(gizmo_w * scale)
            z_box.set_height(gizmo_h * scale)
    else:
        if z_container is not None:
            z_container.remove()
            z_container = None

            z_box.remove()
            z_box = None
Esempio n. 35
0
class AxesSelectBlobImage(BoardFreeHand):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.binary_image = []
        self.rectangle = Rectangle((np.nan, np.nan),
                                   np.nan,
                                   np.nan,
                                   linewidth=1,
                                   edgecolor='g',
                                   facecolor='none')
        self.ax.add_patch(self.rectangle)
        # protected
        self._command = []

    @property
    def command(self):
        return self.__command

    def command(self, command):
        # check if the command is lambda expression
        if callable(command):

            self._command = command

    def set_binary_image(self, binary_image: np.array):
        self.binary_image = binary_image
        self.ax.imshow(binary_image)
        pass

    def draw_on(self, x0: int, y0: int, drawcolor='black', size=1):

        if callable(self.command):
            self.command(x0, y0, self.binary_image)
        else:

            blob = blob_select(self.binary_image, x0, y0)
            ROI = blob['ROI']
            self.rectangle.set_x(ROI['x'])
            self.rectangle.set_y(ROI['y'])
            self.rectangle.set_width(ROI['width'])
            self.rectangle.set_height(ROI['height'])
        # Add the patch to the Axes

        pass
Esempio n. 36
0
class selectRect(object):
    """
    Draws a rectangle on a figure and keeps track of the rectangle's size and
    location.  Used to select the target image data.

    Attributes
    ----------
    x0 : float64
        X coordinate (row) of start of rectangle.
    y0 : float 64
        Y coordinate (column) of start of rectangle.
    x1 : float64
        X coordinate (row) of end of rectangle.
    y1 : float 64
        Y coordinate (column) of end of rectangle.
    """
    def __init__(self):
        self.ax = plt.gca()
        self.rect = Rectangle((0, 0),
                              1,
                              1,
                              facecolor='none',
                              edgecolor='#6CFF33',
                              linewidth=3)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata

    def on_release(self, event):
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.draw()
Esempio n. 37
0
    def visualize_generation(self, generation):
        """
        Draw each ab combination color and size coded
        :param generation:
        :param ax:
        :return:
        """

        fig, ax = plt.subplots()

        # ax.clear()
        for ind in range(len(self.ga_solver.population[generation])):

            child = self.ga_solver.population[generation][ind]

            xy = self._ab_to_xy(child)
            rect = Rectangle(xy=xy, width=0.5, height=0.5, angle=90)
            ax.add_artist(rect)

            rect.set_clip_box(ax.bbox)
            # alpha = float(child[3]) / ANTIBODY_CNT
            # rgb = [float(child[0])/ANTIBODY_CNT, float(child[1])/ANTIBODY_CNT, float(child[2])/ANTIBODY_CNT/ ANTIBODY_CNT]
            #
            # rect.set_alpha(alpha)
            # rect.set_facecolor(rgb)

            fitness = self.ga_solver.get_fitness_value(child)

            if fitness > 0.5:
                rect.set_facecolor('r')
            else:
                rect.set_facecolor('b')

            rect.set_width(fitness * 100)
            rect.set_height(fitness * 100)

        ax.set_xlim(
            0, self.ga_solver.antibody_cnt * self.ga_solver.antibody_cnt + 10)
        ax.set_ylim(
            0, self.ga_solver.antibody_cnt * self.ga_solver.antibody_cnt + 10)

        plt.show()
        plt.pause(1)
        plt.close()
Esempio n. 38
0
 def get_score(self,event):
     # if self.handle==None:
     #     self.handle = get_handle()
     # im = prtsc(self.handle)
     if isinstance(self.origin_img,np.ndarray) and isinstance(self.cut_img,np.ndarray):
         pass
     else:
         wx.MessageBox("请先载入并裁剪相应图像")
         return
     im = self.origin_img
     #changed to BGR aligned to the cv2
     #im = im [:,:,::-1]
     window_resolution = globalvar.get_window_resolution()
     max_resolution = self.origin_res
     match_im = config_ark.pic_resize(self.cut_img,window_resolution,max_resolution)
     results = pic_locate(match_im,im,0.8,True,True)
     if results:
         for i in results:
             pos = i['rectangle'][0]
             width = i['rectangle'][2][0] - i['rectangle'][0][0]
             height = i['rectangle'][1][1] - i['rectangle'][0][1]
     # Draw the bounding rectangle
             #self.rect = Rectangle((0, 0), 0, 0, facecolor='None', edgecolor='red')
             #self.axes.add_patch(self.rect)
             tmp_rect = Rectangle((0, 0), 0, 0, facecolor='None', edgecolor='red')
             tmp_rect.set_width(width)
             tmp_rect.set_height(height)
             tmp_rect.set_xy(pos)
             self.axes.add_patch(tmp_rect)
             #tmp_rect.remove()
             self.draws.append(tmp_rect)
             #self.text = plt.text(pos[0],pos[1],"{0:.4f}".format(i['confidence']))
             tmp_text = self.axes.text(pos[0],pos[1],"{0:.3f}".format(i['confidence']),fontdict={'color':'red','size':12},
                                       bbox=dict(facecolor='white', alpha=0.8))
             #tmp_text.remove()
             self.draws.append(tmp_text)
         self.canvas.draw()
         for j in self.draws:
             j.remove()
         self.draws = []
     else:
         wx.MessageBox("模拟器中没有包含所选图像")
Esempio n. 39
0
class RectSelect(object):
    '''
    region = RectSelect()
    plt.show()
    '''
    def __init__(self, ax=None):
        self.ax = ax or plt.gca()
        self.rect = Rectangle((0, 0), 0, 0, color='orange', alpha=0.5)
        self.ax.add_patch(self.rect)
        self.blc = np.zeros(2)
        self.brc = np.zeros(2)
        self.tlc = np.zeros(2)
        self.trc = np.zeros(2)

        def selector(event):
            if event.key in ['Q', 'q'] and selector.RS.active:
                print('RectangleSelector deactivated.')
                selector.RS.set_active(False)
            if event.key in ['A', 'a'] and not selector.RS.active:
                print('RectangleSelector activated.')
                selector.RS.set_active(True)

        selector.RS = RectangleSelector(self.ax, self.callback)
        self.ax.figure.canvas.mpl_connect('key_press_event', selector)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.release)

    def callback(self, eclick, erelease):
        x0, x1 = eclick.xdata, erelease.xdata
        y0, y1 = eclick.ydata, erelease.ydata
        self.blc = min(x0, x1), min(y0, y1)
        self.brc = max(x0, x1), min(y0, y1)
        self.tlc = min(x0, x1), max(y0, y1)
        self.trc = max(x0, x1), max(y0, y1)
        blc_print = '({:0.4},{:0.4})'.format(*self.blc)
        trc_print = '({:0.4},{:0.4})'.format(*self.trc)
        print('blc={}, trc={}'.format(blc_print, trc_print))

    def release(self, event):
        self.rect.set_width(self.trc[0] - self.blc[0])
        self.rect.set_height(self.trc[1] - self.blc[1])
        self.rect.set_xy(self.blc)
        self.ax.figure.canvas.draw()
Esempio n. 40
0
class rectSelection(GuiSelection):
    """Interactive selection of a rectangular region on the axis.

    Used by hist2d_alex().
    """
    def on_press_draw(self):
        if 'r' in self.__dict__:
            self.r.set_height(0)
            self.r.set_width(0)
            self.r.set_xy((self.xs, self.ys))
            self.e.height = 0
            self.e.width = 0
            self.e.center = (self.xs, self.ys)
        else:
            self.r = Rectangle(xy=(self.xs, self.ys), height=0, width=0,
                               fill=False, lw=2, alpha=0.5, color='blue')
            self.e = Ellipse(xy=(self.xs, self.ys), height=0, width=0,
                    fill=False, lw=2, alpha=0.6, color='blue')
            self.ax.add_artist(self.r)
            self.ax.add_artist(self.e)
            self.r.set_clip_box(self.ax.bbox)
            self.r.set_zorder(10)
            self.e.set_clip_box(self.ax.bbox)
            self.e.set_zorder(10)

    def on_motion_draw(self):
        self.r.set_height(self.ye - self.ys)
        self.r.set_width(self.xe - self.xs)
        self.e.height = (self.ye - self.ys)
        self.e.width = (self.xe - self.xs)
        self.e.center = (np.mean([self.xs, self.xe]),
                         np.mean([self.ys, self.ye]))
        self.fig.canvas.draw()

    def on_release_print(self):
        # This is the only custom method for hist2d_alex()
        E1, E2 = min((self.xs, self.xe)), max((self.xs, self.xe))
        S1, S2 = min((self.ys, self.ye)), max((self.ys, self.ye))
        self.selection = dict(E1=E1, E2=E2, S1=S1, S2=S2)
        pprint("Selection: \nE1=%.2f, E2=%.2f, S1=%.2f, S2=%.2f\n" %\
                (E1,E2,S1,S2))
class Annotate(object):
    def __init__(self, image):
        self.ax = plt.gca()
        self.ax.imshow(image)
        self.rect = Rectangle((0, 0), 1, 1)
        self.rect.fill = False
        self.x0 = self.y0 = self.x1 = self.y1 = None
        self.pressing = False
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.motion)
        self.ax.figure.canvas.mpl_connect('button_release_event',
                                          self.on_release)
        self.ax.figure.canvas.mpl_connect('key_press_event', self.on_key)

    def run(self):
        plt.show()

    def on_press(self, event):
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.pressing = True

    def motion(self, event):
        if self.pressing:
            x1 = event.xdata
            y1 = event.ydata
            self.rect.set_width(x1 - self.x0)
            self.rect.set_height(y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.ax.figure.canvas.draw()

    def on_release(self, event):
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.pressing = False

    def on_key(self, event):
        if event.key == 'enter' and a.x1:
            plt.close()
Esempio n. 42
0
class Annotate(object):
    def __init__(self,ax=None):
        if ax==None:
            self.ax = plt.gca()
        else:
            self.ax = ax
        self.rect = Rectangle((0,0), 0, 0, facecolor='yellow', edgecolor='yellow', alpha=.5, \
                                  zorder=10, clip_on=False)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.is_pressed = False
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
    def on_press(self, event):
        self.is_pressed = True
        print 'press'
        self.x0 = event.xdata
        self.y0 = event.ydata    
        self.x1 = event.xdata
        self.y1 = event.ydata
        if not np.any( [c==None for c in [self.x0,self.y0,self.x1,self.y1]] ):
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.rect.set_linestyle('dashed')
        self.ax.figure.canvas.draw()
    def on_motion(self,event):
        if self.is_pressed is True:
            self.x1 = event.xdata
            self.y1 = event.ydata
            if not np.any( [c==None for c in [self.x0,self.y0,self.x1,self.y1]] ):
                self.rect.set_width(self.x1 - self.x0)
                self.rect.set_height(self.y1 - self.y0)
                self.rect.set_xy((self.x0, self.y0))
                self.rect.set_linestyle('dashed')
                self.ax.figure.canvas.draw()
    def on_release(self, event):
        self.is_pressed = False
        print 'release'
        self.x1 = event.xdata
        self.y1 = event.ydata
        if not np.any( [c==None for c in [self.x0,self.y0,self.x1,self.y1]] ):
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.rect.set_linestyle('solid')
            self.ax.figure.canvas.draw()
        print self.x0,self.y0,self.x1,self.y1
        
        if self.x0==self.x1 and self.y0==self.y1:
            print type(self.__bases__)
Esempio n. 43
0
class GaussianSelector:
    """
    GaussianSelector is a class for hand-fitting Gaussian components.

    Taken and tweaked from SMR's pygaussfit.py
    """

    def __init__(self, ax, profile, errs, tau=0.0, fixscat=True,
            auto_gauss=0.0, profile_fit_flags=None, minspanx=None,
            minspany=None, useblit=True):
        """
        Initialize the input parameters and open the interactive window.

        ax is a pyplot axis.
        profile is an array of pulse profile data values.
        errs specifies the uncertainty on the profile values.
        tau is a scattering timescale [bin].
        fixscat=True does not fit for the scattering timescale.
        auto_gauss != 0.0 specifies the initial guess at a width [rot] of a
            single Gaussian component to be fit automatically.
        profile_fit_flags is an array specifying which of the non-scattering
            parameters to fit; defaults to fitting all.
        minspanx, minspany are vestigial.
        useblit should be True.
        """
        if not auto_gauss:
            print ""
            print "============================================="
            print "Left mouse click to draw a Gaussian component"
            print "Middle mouse click to fit components to data"
            print "Right mouse click to remove last component"
        print "============================================="
        print "Press 'q' or close window when done fitting"
        print "============================================="
        self.ax = ax.axes
        self.profile = profile
        self.proflen = len(profile)
        self.phases = np.arange(self.proflen, dtype='d') / self.proflen
        self.errs = errs
        self.tauguess = tau #in bins
        self.fit_scattering = not fixscat
        if self.fit_scattering and self.tauguess == 0.0:
            self.tauguess = 0.1 #seems to break otherwise
        self.profile_fit_flags = profile_fit_flags
        self.visible = True
        self.DCguess = sorted(profile)[len(profile)/10 + 1]
        self.init_params = [self.DCguess, self.tauguess]
        self.ngauss = 0
        self.canvas = ax.figure.canvas
        self.canvas.mpl_connect('motion_notify_event', self.onmove)
        self.canvas.mpl_connect('button_press_event', self.press)
        self.canvas.mpl_connect('button_release_event', self.release)
        self.canvas.mpl_connect('draw_event', self.update_background)
        self.canvas.mpl_connect('key_press_event', self.keypress)
        self.background = None
        self.rectprops = dict(facecolor='white', edgecolor = 'black',
                              alpha=0.5, fill=False)
        self.to_draw = Rectangle((0,0), 0, 1, visible=False, **self.rectprops)
        self.ax.add_patch(self.to_draw)
        self.useblit = useblit
        self.minspanx = minspanx
        self.minspany = minspany
        # will save the data (position at mouseclick)
        self.eventpress = None
        # will save the data (pos. at mouserelease)
        self.eventrelease = None
        self.plot_gaussians(self.init_params)
        self.auto_gauss = auto_gauss
        if self.auto_gauss:
            amp = self.profile.max()
            wid = self.auto_gauss
            first_gauss = amp*gaussian_profile(self.proflen, 0.5, wid)
            loc = 0.5 + fit_phase_shift(self.profile, first_gauss,
                    self.errs).phase
            self.init_params += [loc, wid, amp]
            self.ngauss += 1
            self.plot_gaussians(self.init_params)
            print "Auto-fitting a single Gaussian component..."
            fgp = fit_gaussian_profile(self.profile, self.init_params,
                    np.zeros(self.proflen) + self.errs, self.profile_fit_flags,
                    self.fit_scattering, quiet=True)
            self.fitted_params = fgp.fitted_params
            self.fit_errs = fgp.fit_errs
            self.chi2 = fgp.chi2
            self.dof = fgp.dof
            self.residuals = fgp.residuals
            # scaled uncertainties
            #scaled_fit_errs = fit_errs * np.sqrt(chi_sq / dof)

            # Plot the best-fit profile
            self.plot_gaussians(self.fitted_params)
            fitprof = gen_gaussian_profile(self.fitted_params, self.proflen)
            plt.plot(self.phases, fitprof, c='black', lw=1)
            plt.draw()

            # Plot the residuals
            plt.subplot(212)
            plt.cla()
            residuals = self.profile - fitprof
            plt.plot(self.phases, residuals, 'k')
            plt.xlabel('Pulse Phase')
            plt.ylabel('Data-Fit Residuals')
            plt.draw()
            self.eventpress = None
            # will save the data (pos. at mouserelease)
            self.eventrelease = None

    def update_background(self, event):
        """force an update of the background"""
        if self.useblit:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)

    def ignore(self, event):
        """return True if event should be ignored"""
        # If no button was pressed yet ignore the event if it was out
        # of the axes
        if self.eventpress == None:
            return event.inaxes != self.ax
        # If a button was pressed, check if the release-button is the
        # same.
        return (event.inaxes != self.ax or
                event.button != self.eventpress.button)

    def press(self, event):
        """on button press event"""
        # Is the correct button pressed within the correct axes?
        if self.ignore(event): return
        # make the drawed box/line visible get the click-coordinates,
        # button, ...
        self.eventpress = event
        if event.button == 1:
            self.to_draw.set_visible(self.visible)
            self.eventpress.ydata = self.DCguess

    def release(self, event):
        """on button release event"""
        if self.eventpress is None or self.ignore(event): return
        # release coordinates, button, ...
        self.eventrelease = event
        if event.button == 1:
            # make the box/line invisible again
            self.to_draw.set_visible(False)
            self.canvas.draw()
            xmin, ymin = self.eventpress.xdata, self.eventpress.ydata
            xmax, ymax = self.eventrelease.xdata, self.eventrelease.ydata
            # calculate dimensions of box 
            if xmin > xmax: xmin, xmax = xmax, xmin
            if ymin > ymax: ymin, ymax = ymax, ymin
            spanx = xmax - xmin
            spany = ymax - ymin
            xproblems = self.minspanx is not None and spanx < self.minspanx
            yproblems = self.minspany is not None and spany < self.minspany
        # call desired function
        self.onselect()
        self.eventpress = None                # reset the variables to their
        self.eventrelease = None              #   inital values

    def update(self):
        """draw using blit or old draw depending on useblit"""
        if self.useblit:
            if self.background is not None:
                self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.to_draw)
            self.canvas.blit(self.ax.bbox)
        else:
            self.canvas.draw_idle()

    def onmove(self, event):
        """on move event"""
        if self.eventpress is None or self.ignore(event): return
        x, y = event.xdata, event.ydata         # actual position 
                                                # with button still pressed
        minx, maxx = self.eventpress.xdata, x   # click-x and actual mouse-x
        miny, maxy = self.eventpress.ydata, y   # click-y and actual mouse-y
        if minx > maxx: minx, maxx = maxx, minx # get them in the right order
        if miny > maxy: miny, maxy = maxy, miny
        self.to_draw.set_x(minx)                # set lower left of box
        self.to_draw.set_y(miny)
        self.to_draw.set_width(maxx - minx)     # set width and height of box
        self.to_draw.set_height(maxy - miny)
        self.update()

    def keypress(self, event):
        """on key press event"""
        if self.ignore(event): return
        self.eventpress = event
        if event.key == 'q':
            self.eventpress = None
            self.close()

    def plot_gaussians(self, params):
        """plot Gaussian components and profile"""
        plt.subplot(211)
        plt.cla()
        # Re-plot the original profile
        plt.hlines(0, 0.0, 1.0, color='black', lw=1, alpha=0.3, linestyle=':')
        plt.plot(self.phases, self.profile, c='black', lw=3, alpha=0.3)
        plt.xlabel('Pulse Phase')
        plt.ylabel('Pulse Amplitude')
        prefit_buff = 0.1
        postfit_buff = 0.1
        if self.fit_scattering: prefit_buff = 1.0
        ymin,ymax = plt.ylim()
        ymin = params[0] - prefit_buff*(self.profile.max()-self.profile.min())
        ymax = self.profile.max() + prefit_buff * \
                (self.profile.max()-self.profile.min())
        plt.ylim(ymin, ymax)
        DC = params[0]
        tau = params[1]
        # Plot the individual Gaussians
        max_amp = 0.0
        for igauss in range(self.ngauss):
            loc, wid, amp = params[(2 + igauss*3):(5 + igauss*3)]
            if amp >= max_amp:
                max_amp = amp
            plt.plot(self.phases, DC + amp*gaussian_profile(self.proflen, loc,
                wid), '%s'%cols[igauss])
            if max_amp > ymax:
                plt.ylim(ymin, max_amp + postfit_buff * \
                        (max_amp - self.profile.min()))

    def onselect(self):
        """on select event"""
        event1 = self.eventpress
        event2 = self.eventrelease
        # Left mouse button = add a Gaussian
        if event1.button == event2.button == 1:
            x1, y1 = event1.xdata, event1.ydata
            x2, y2 = event2.xdata, event2.ydata
            loc = 0.5 * (x1 + x2)
            wid = np.fabs(x2 - x1)
            #amp = np.fabs(1.05 * (y2 - self.init_params[0]) * (x2 - x1))
            amp = np.fabs(1.05 * (y2 - self.init_params[0]))
            self.init_params += [loc, wid, amp]
            self.ngauss += 1
            self.plot_gaussians(self.init_params)
            plt.draw()
        # Middle mouse button = fit the Gaussians
        elif event1.button == event2.button == 2:
            print "Fitting reference Gaussian profile..."
            fgp = fit_gaussian_profile(self.profile, self.init_params,
                    np.zeros(self.proflen) + self.errs, self.profile_fit_flags,
                    self.fit_scattering, quiet=True)
            self.fitted_params = fgp.fitted_params
            self.fit_errs = fgp.fit_errs
            self.chi2 = fgp.chi2
            self.dof = fgp.dof
            self.residuals = fgp.residuals
            # scaled uncertainties
            #scaled_fit_errs = fit_errs * np.sqrt(chi_sq / dof)

            # Plot the best-fit profile
            self.plot_gaussians(self.fitted_params)
            fitprof = gen_gaussian_profile(self.fitted_params, self.proflen)
            plt.plot(self.phases, fitprof, c='black', lw=1)
            plt.draw()

            # Plot the residuals
            plt.subplot(212)
            plt.cla()
            residuals = self.profile - fitprof
            plt.plot(self.phases, residuals, 'k')
            plt.xlabel('Pulse Phase')
            plt.ylabel('Data-Fit Residuals')
            plt.draw()
        # Right mouse button = remove last Gaussian
        elif event1.button == event2.button == 3:
            if self.ngauss:
                self.init_params = self.init_params[:-3]
                self.ngauss -= 1
                self.plot_gaussians(self.init_params)
                plt.draw()
                plt.subplot(212)
                plt.cla()
                plt.xlabel('Pulse Phase')
                plt.ylabel('Data-Fit Residuals')
                plt.draw()

    def close(self):
        """close"""
        plt.close(1)
        plt.close(2)
Esempio n. 44
0
class GaussianSelector:
    def __init__(self, ax, profile, errs, profnm, minspanx=None,
                 minspany=None, useblit=True):
        self.ax = ax.axes
        self.profile = profile
        self.proflen = len(profile)
        self.profnm = profnm
        self.phases = Num.arange(self.proflen, dtype='d')/self.proflen
        self.errs = errs
        self.visible = True
        self.DCguess = sorted(profile)[len(profile)/10+1]
        self.init_params = [self.DCguess]
        self.numgaussians = 0
        self.canvas = ax.figure.canvas
        self.canvas.mpl_connect('motion_notify_event', self.onmove)
        self.canvas.mpl_connect('button_press_event', self.press)
        self.canvas.mpl_connect('button_release_event', self.release)
        self.canvas.mpl_connect('draw_event', self.update_background)
        self.background = None
        self.rectprops = dict(facecolor='white', edgecolor = 'black',
                              alpha=0.5, fill=False)
        self.to_draw = Rectangle((0,0), 0, 1, visible=False, **self.rectprops)
        self.ax.add_patch(self.to_draw)
        self.useblit = useblit
        self.minspanx = minspanx
        self.minspany = minspany
        # will save the data (position at mouseclick)
        self.eventpress = None            
        # will save the data (pos. at mouserelease)
        self.eventrelease = None          
        self.plot_gaussians(self.init_params)

    def update_background(self, event):
        'force an update of the background'
        if self.useblit:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        
    def ignore(self, event):
        'return True if event should be ignored'
        # If no button was pressed yet ignore the event if it was out
        # of the axes
        if self.eventpress == None:
            return event.inaxes!= self.ax       
        # If a button was pressed, check if the release-button is the
        # same.
        return (event.inaxes!=self.ax or
                event.button != self.eventpress.button)
      
    def press(self, event):
        'on button press event'
        # Is the correct button pressed within the correct axes?
        if self.ignore(event): return         
        # make the drawed box/line visible get the click-coordinates,
        # button, ...
        self.eventpress = event               
        if event.button==1:
            self.to_draw.set_visible(self.visible)
            self.eventpress.ydata = self.DCguess

    def release(self, event):
        'on button release event'
        if self.eventpress is None or self.ignore(event): return
        # release coordinates, button, ...
        self.eventrelease = event             
        if event.button==1:
            # make the box/line invisible again
            self.to_draw.set_visible(False)       
            self.canvas.draw()
            xmin, ymin = self.eventpress.xdata, self.eventpress.ydata
            xmax, ymax = self.eventrelease.xdata, self.eventrelease.ydata
            # calculate dimensions of box 
            if xmin>xmax: xmin, xmax = xmax, xmin        
            if ymin>ymax: ymin, ymax = ymax, ymin
            spanx = xmax - xmin                  
            spany = ymax - ymin
            xproblems = self.minspanx is not None and spanx<self.minspanx
            yproblems = self.minspany is not None and spany<self.minspany
        # call desired function
        self.onselect()
        self.eventpress = None                # reset the variables to their
        self.eventrelease = None              #   inital values

    def update(self):
        'draw using newfangled blit or oldfangled draw depending on useblit'
        if self.useblit:
            if self.background is not None:
                self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.to_draw)
            self.canvas.blit(self.ax.bbox)
        else:
            self.canvas.draw_idle()

    def onmove(self, event):
        if self.eventpress is None or self.ignore(event): return
        x,y = event.xdata, event.ydata # actual position with button still pressed
        minx, maxx = self.eventpress.xdata, x # click-x and actual mouse-x
        miny, maxy = self.eventpress.ydata, y # click-y and actual mouse-y
        if minx>maxx: minx, maxx = maxx, minx # get them in the right order
        if miny>maxy: miny, maxy = maxy, miny
        self.to_draw.set_x(minx)             # set lower left of box
        self.to_draw.set_y(miny)
        self.to_draw.set_width(maxx-minx)     # set width and height of box
        self.to_draw.set_height(maxy-miny)
        self.update()
    
    def plot_gaussians(self, params):
        plt.subplot(211)
        plt.cla()
        # Re-plot the original profile
        plt.plot(self.phases, self.profile, c='black', lw=3, alpha=0.3)
        plt.xlabel('Pulse Phase')
        plt.ylabel('Pulse Amplitude')
        DC = params[0]
        # Plot the individual gaussians
        for ii in range(self.numgaussians):
            phase, FWHM, amp = params[1+ii*3:4+ii*3]
            plt.plot(self.phases, DC + amp*gaussian_profile(self.proflen, phase, FWHM))

    def onselect(self):
        event1 = self.eventpress
        event2 = self.eventrelease
        # Left mouse button = add a gaussian
        if event1.button == event2.button == 1:
            x1, y1 = event1.xdata, event1.ydata
            x2, y2 = event2.xdata, event2.ydata
            phase = 0.5*(x1+x2)
            FWHM = Num.fabs(x2-x1)
            amp = Num.fabs(1.05*(y2-self.init_params[0])*(x2-x1))
            self.init_params += [phase, FWHM, amp]
            self.numgaussians += 1
            self.plot_gaussians(self.init_params)
            plt.draw()
        # Middle mouse button = fit the gaussians
        elif event1.button == event2.button == 2:
            fit_params, fit_errs, chi_sq, dof = \
                        fit_gaussians(self.profile, self.init_params,
                                      Num.zeros(self.proflen)+self.errs,
                                      self.profnm)
            # scaled uncertainties
            #scaled_fit_errs = fit_errs * Num.sqrt(chi_sq / dof)

            # Plot the best-fit profile
            self.plot_gaussians(fit_params)
            fitprof = gen_gaussians(fit_params, self.proflen)
            plt.plot(self.phases, fitprof, c='black', lw=1)
            plt.draw()
            
            # Plot the residuals
            plt.subplot(212)
            plt.cla()
            residuals = prof - fitprof
            plt.plot(self.phases, residuals)
            plt.xlabel('Pulse Phase')
            plt.ylabel('Data-Fit Residuals')
            plt.draw()
        # Right mouse button = remove last gaussian
        elif event1.button == event2.button == 3:
            if self.numgaussians:
                self.init_params = self.init_params[:-3]
                self.numgaussians -= 1
                self.plot_gaussians(self.init_params)
                plt.draw()
                plt.subplot(212)
                plt.cla()
                plt.xlabel('Pulse Phase')
                plt.ylabel('Data-Fit Residuals')
                plt.draw()
Esempio n. 45
0
class RectangleSelectImagePanel(wx.Panel):
    ''' Panel that contains an image that allows the users to select an area of the image with the mouse. The user clicks and
    holds the mouse to create a dotted rectangle, and when the mouse is released the rectangles origin, width and height can be
    read. The dimensions of these readings are always relative to the original image, so even if the image is scaled up larger
    to fit the panel the measurements will always refer to the original image.'''

    def __init__(self, parent, pathToImage=None):
        ''' Initialise the panel. Setting an initial image is optional.'''
        
        # Initialise the parent
        wx.Panel.__init__(self, parent)

        # Intitialise the matplotlib figure
        self.figure = plt.figure()

        # Create an axes, turn off the labels and add them to the figure
        self.axes = plt.Axes(self.figure,[0,0,1,1])      
        self.axes.set_axis_off() 
        self.figure.add_axes(self.axes) 

        # Add the figure to the wxFigureCanvas
        self.canvas = FigureCanvas(self, -1, self.figure)

        # Initialise the rectangle
        self.rect = Rectangle((0,0), 1, 1, facecolor='None', edgecolor='green')
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.axes.add_patch(self.rect)
        
        # Sizer to contain the canvas
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 3, wx.ALL)
        self.SetSizer(self.sizer)
        self.Fit()
        
        # Connect the mouse events to their relevant callbacks
        self.canvas.mpl_connect('button_press_event', self._onPress)
        self.canvas.mpl_connect('button_release_event', self._onRelease)
        self.canvas.mpl_connect('motion_notify_event', self._onMotion)
        
        # Lock to stop the motion event from behaving badly when the mouse isn't pressed
        self.pressed = False

        # If there is an initial image, display it on the figure
        if pathToImage is not None:
            self.setImage(pathToImage)


    def _onPress(self, event):
        ''' Callback to handle the mouse being clicked and held over the canvas'''

        # Check the mouse press was actually on the canvas
        if event.xdata is not None and event.ydata is not None:

            # Upon initial press of the mouse record the origin and record the mouse as pressed
            self.pressed = True
            self.rect.set_linestyle('dashed')
            self.x0 = event.xdata
            self.y0 = event.ydata


    def _onRelease(self, event):
        '''Callback to handle the mouse being released over the canvas'''

        # Check that the mouse was actually pressed on the canvas to begin with and this isn't a rouge mouse 
        # release event that started somewhere else
        if self.pressed:

            # Upon release draw the rectangle as a solid rectangle
            self.pressed = False
            self.rect.set_linestyle('solid')

            # Check the mouse was released on the canvas, and if it wasn't then just leave the width and 
            # height as the last values set by the motion event
            if event.xdata is not None and event.ydata is not None:
                self.x1 = event.xdata
                self.y1 = event.ydata

            # Set the width and height and origin of the bounding rectangle
            self.boundingRectWidth =  self.x1 - self.x0
            self.boundingRectHeight =  self.y1 - self.y0
            self.bouningRectOrigin = (self.x0, self.y0)

            # Draw the bounding rectangle
            self.rect.set_width(self.boundingRectWidth)
            self.rect.set_height(self.boundingRectHeight)
            self.rect.set_xy((self.x0, self.y0))
            self.canvas.draw()


    def _onMotion(self, event):
        '''Callback to handle the motion event created by the mouse moving over the canvas'''

        # If the mouse has been pressed draw an updated rectangle when the mouse is moved so 
        # the user can see what the current selection is
        if self.pressed:

            # Check the mouse was released on the canvas, and if it wasn't then just leave the width and 
            # height as the last values set by the motion event
            if event.xdata is not None and event.ydata is not None:
                self.x1 = event.xdata
                self.y1 = event.ydata
            
            # Set the width and height and draw the rectangle
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
            self.canvas.draw()


    def setImage(self, pathToImage):
        '''Sets the background image of the canvas'''
        
        # Load the image into matplotlib and PIL
        image = matplotlib.image.imread(pathToImage) 
        imPIL = Image.open(pathToImage) 

        # Save the image's dimensions from PIL
        self.imageSize = imPIL.size
        
        # Add the image to the figure and redraw the canvas. Also ensure the aspect ratio of the image is retained.
        self.axes.imshow(image,aspect='equal') 
        self.canvas.draw()
Esempio n. 46
0
File: roi.py Progetto: saimn/glue
class MplRectangularROI(AbstractMplRoi):

    """
    A subclass of RectangularROI that also renders the ROI to a plot

    *Attributes*:

        plot_opts:

                   Dictionary instance
                   A dictionary of plot keywords that are passed to
                   the patch representing the ROI. These control
                   the visual properties of the ROI
    """

    def __init__(self, axes):
        """
        :param axes: A matplotlib Axes object to attach the graphical ROI to
        """

        AbstractMplRoi.__init__(self, axes)

        self._xi = None
        self._yi = None

        self.plot_opts = {'edgecolor': PATCH_COLOR, 'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        self._patch = Rectangle((0., 0.), 1., 1.)
        self._patch.set_zorder(100)
        self._setup_patch()

    def _setup_patch(self):
        self._axes.add_patch(self._patch)
        self._patch.set_visible(False)

        self._sync_patch()

    def _roi_factory(self):
        return RectangularROI()

    def start_selection(self, event):

        if event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False
            elif not self._roi.contains(event.xdata, event.ydata):
                return False

        self._roi_store()
        self._xi = event.xdata
        self._yi = event.ydata

        if event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._cx, self._cy = self._roi.center()
        else:
            self.reset()
            self._roi.update_limits(event.xdata, event.ydata,
                                    event.xdata, event.ydata)

        self._mid_selection = True
        self._sync_patch()

    def update_selection(self, event):

        if not self._mid_selection or event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False

        if self._scrubbing:
            self._roi.move_to(self._cx + event.xdata - self._xi,
                              self._cy + event.ydata - self._yi)
        else:
            self._roi.update_limits(min(event.xdata, self._xi),
                                    min(event.ydata, self._yi),
                                    max(event.xdata, self._xi),
                                    max(event.ydata, self._yi))
        self._sync_patch()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            corner = self._roi.corner()
            width = self._roi.width()
            height = self._roi.height()
            self._patch.set_xy(corner)
            self._patch.set_width(width)
            self._patch.set_height(height)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)
        self._draw()

    def __str__(self):
        return "MPL Rectangle: %s" % self._patch
Esempio n. 47
0
File: roi.py Progetto: saimn/glue
class MplXRangeROI(AbstractMplRoi):

    def __init__(self, axes):
        """
        :param axes: A matplotlib Axes object to attach the graphical ROI to
        """

        AbstractMplRoi.__init__(self, axes)
        self._xi = None

        self.plot_opts = {'edgecolor': PATCH_COLOR, 'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        trans = blended_transform_factory(self._axes.transData,
                                          self._axes.transAxes)
        self._patch = Rectangle((0., 0.), 1., 1., transform=trans)
        self._patch.set_zorder(100)
        self._setup_patch()

    def _setup_patch(self):
        self._axes.add_patch(self._patch)
        self._patch.set_visible(False)
        self._sync_patch()

    def _roi_factory(self):
        return XRangeROI()

    def start_selection(self, event):

        if event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False
            elif not self._roi.contains(event.xdata, event.ydata):
                return False

        self._roi_store()

        if event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._dx = event.xdata - self._roi.center()
        else:
            self.reset()
            self._roi.set_range(event.xdata, event.xdata)
            self._xi = event.xdata
        self._mid_selection = True
        self._sync_patch()

    def update_selection(self, event):

        if not self._mid_selection or event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False

        if self._scrubbing:
            self._roi.move_to(event.xdata + self._dx)
        else:
            self._roi.set_range(min(event.xdata, self._xi),
                                max(event.xdata, self._xi))
        self._sync_patch()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            rng = self._roi.range()
            self._patch.set_xy((rng[0], 0))
            self._patch.set_width(rng[1] - rng[0])
            self._patch.set_height(1)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)
        self._draw()
Esempio n. 48
0
class PlotInterface(object):
    def __init__(self, df, EvT_color_set, EvT_size_set):
        self.df = df
        self.ax = plt.gca()
        self.rect = Rectangle((0.1,0.1), 0, 0, fill=False)
        self.rect.set_visible(False)
        self.ax.add_patch(self.rect)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.press = False
        self.sub_df = None
        self.EvT_color_set = EvT_color_set
        self.EvT_size_set = EvT_size_set
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
        self.ax.figure.canvas.mpl_connect('motion_notify_event',self.on_motion)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
        
    def on_press(self, event):
        if event.inaxes:
            
            self.press = True
            self.x0 = event.xdata
            self.y0 = event.ydata
            self.rect.set_width(0)
            self.rect.set_height(0)
            self.rect.set_xy((self.x0,self.y0))
            self.rect.set_visible(True)
            #Save the plot background
            self.background = self.ax.figure.canvas.copy_from_bbox(self.ax.bbox)
            


    def on_release(self, event):
        if event.inaxes:
            self.press = False
            self.x1 = event.xdata
            self.y1 = event.ydata
            self.rect.set_visible(False)
            self.ax.figure.canvas.draw()
            self.min_x = min(self.x0,self.x1)
            self.max_x = max(self.x0,self.x1)
            self.min_y = min(self.y0,self.y1)
            self.max_y = max(self.y0,self.y1)
            
            if self.sub_df is not None:
                self.sub_df = self.sub_df.append(self.df[ (self.df['timestamp'] > self.min_x) & (self.df['timestamp'] < self.max_x) & \
                                 (self.df['amplitude'] > self.min_y) & (self.df['amplitude'] < self.max_y)])
            else:
                self.sub_df = self.df[ (self.df['timestamp'] > self.min_x) & (self.df['timestamp'] < self.max_x) & \
                                 (self.df['amplitude'] > self.min_y) & (self.df['amplitude'] < self.max_y)]            
            
            plt.scatter(self.sub_df['timestamp'],self.sub_df['amplitude'],color='blue',s=self.EvT_size_set)  
            self.ax.figure.canvas.draw()

            print('Selected (%d < timestamp < %d) and (%d < amplitude < %d)' % (self.min_x, self.max_x, self.min_y, self.max_y))
            
    def on_motion(self, event):
        if self.press is False: return
        if event.inaxes != self.rect.axes: return
        self.x1 = event.xdata
        self.y1 = event.ydata
        self.rect.set_width(self.x1 - self.x0)
        self.rect.set_height(self.y1 - self.y0)
        self.rect.set_xy((self.x0, self.y0))
        self.ax.figure.canvas.restore_region(self.background)
        self.ax.draw_artist(self.rect)
        self.ax.figure.canvas.blit(self.rect.clipbox)
Esempio n. 49
0
class Annotate(object):
    def __init__(self, cloud, selection_shape, z_color=False, unlabeled_color = (1,0,0), labeled_color = (0,0,1)):
        self.selection_shape = selection_shape
        self.unlabeled_color = np.array(unlabeled_color)
        self.labeled_color = np.array(labeled_color)
        assert not np.all(unlabeled_color == labeled_color)
        
        self.fig = plt.figure('label rope ends', figsize=(24,12))
        self.fig.clear()
        self.ax = self.fig.add_subplot(111, aspect='equal')
        
        if cloud.shape[1] == 6:
            self.cloud = cloud
        else:
            self.cloud = np.c_[cloud[:,:3], np.tile(self.unlabeled_color, (cloud.shape[0],1))]
        
        if z_color:
            z_min = self.cloud[:,2].min()
            z_max = self.cloud[:,2].max()
            self.z_color = np.empty((len(self.cloud),3))
            for i in range(len(self.cloud)):
                f = (self.cloud[i,2] - z_min) / (z_max - z_min)
                self.z_color[i,:] = np.array(colorsys.hsv_to_rgb(f,1,1))
        else:
            self.z_color = None
        self.scatters = []
        self.rescatter_cloud()
        self.ax.autoscale(False)
        
        if self.selection_shape == 'rectangle' or self.selection_shape == 'square':
            self.rect = Rectangle((0,0), 0, 0, facecolor='None', edgecolor='green', linestyle='dashed')
            self.ax.add_patch(self.rect)
        elif self.selection_shape == 'circle':
            self.circle = Circle((0,0), 0, facecolor='None', edgecolor='green', linestyle='dashed')
            self.ax.add_patch(self.circle)
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None

        self.fig.canvas.mpl_connect('button_press_event', self.on_press)
        self.fig.canvas.mpl_connect('button_release_event', self.on_release)
        self.motion_notify_cid = None
        self.fig.canvas.mpl_connect('key_press_event', self.on_key)

        plt.show()
    
    def rescatter_cloud(self):
        for scatter in self.scatters:
            scatter.remove()
        self.scatters = []
        if self.z_color is not None:
            ul_inds = np.absolute((self.cloud[:,3:] - self.unlabeled_color)).sum(axis=1) == 0 # unlabeled inds
            self.scatters.append(plt.scatter(self.cloud[ul_inds,0], self.cloud[ul_inds,1], c=self.z_color[ul_inds,:], edgecolors=self.z_color[ul_inds,:], marker=',', s=5))
            self.scatters.append(plt.scatter(self.cloud[~ul_inds,0], self.cloud[~ul_inds,1], c=self.cloud[~ul_inds,3:], edgecolors=self.cloud[~ul_inds,3:], marker='o', s=20))
        else:
            self.scatters.append(plt.scatter(self.cloud[:,0], self.cloud[:,1], c=self.cloud[:,3:], edgecolors=self.cloud[:,3:], marker=',', s=5))
    
    def on_press(self, event):
        if event.xdata < self.ax.get_xlim()[0] or event.xdata > self.ax.get_xlim()[1] or \
            event.ydata < self.ax.get_ylim()[0] or event.ydata > self.ax.get_ylim()[1]:
            return
        self.x0 = event.xdata
        self.y0 = event.ydata
        self.motion_notify_cid = self.fig.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_release(self, event):
        if self.motion_notify_cid:
            self.fig.canvas.mpl_disconnect(self.motion_notify_cid)
            self.motion_notify_cid = None
            if self.selection_shape == 'rectangle' or self.selection_shape == 'square':
                x0 = min(self.x0, self.x1)
                x1 = max(self.x0, self.x1)
                y0 = min(self.y0, self.y1)
                y1 = max(self.y0, self.y1)
                inside_rect_inds = (x0 <= self.cloud[:,0]) * (self.cloud[:,0] <= x1) * (y0 <= self.cloud[:,1]) * (self.cloud[:,1] <= y1)
                num_pts_inside_rect = inside_rect_inds.sum()
                self.cloud[inside_rect_inds,3:] = np.tile(self.labeled_color, (num_pts_inside_rect,1))
            elif self.selection_shape == 'circle':
                inside_circle_inds = np.apply_along_axis(np.linalg.norm, 1, self.cloud[:,:2] - np.array(self.circle.center)) <= self.circle.get_radius()
                num_pts_inside_circle = inside_circle_inds.sum()
                self.cloud[inside_circle_inds,3:] = np.tile(self.labeled_color, (num_pts_inside_circle,1))
            self.rescatter_cloud()
            plt.draw()
    
    def on_motion(self, event):
        if event.xdata < self.ax.get_xlim()[0] or event.xdata > self.ax.get_xlim()[1] or \
            event.ydata < self.ax.get_ylim()[0] or event.ydata > self.ax.get_ylim()[1]:
            return
        if self.selection_shape == 'rectangle':
            self.x1 = event.xdata
            self.y1 = event.ydata
        elif self.selection_shape == 'circle' or self.selection_shape == 'square':
            side = max(abs(event.xdata - self.x0), abs(event.ydata - self.y0))
            self.x1 = self.x0 + np.sign(event.xdata - self.x0) * side
            self.y1 = self.y0 + np.sign(event.ydata - self.y0) * side
        if self.selection_shape == 'rectangle' or self.selection_shape == 'square':
            self.rect.set_width(self.x1 - self.x0)
            self.rect.set_height(self.y1 - self.y0)
            self.rect.set_xy((self.x0, self.y0))
        elif self.selection_shape == 'circle':
            self.circle.center = ((self.x1 + self.x0)/2.0, (self.y0 + self.y1)/2.0)
            self.circle.set_radius(side/2.0)
        plt.draw()
    
    def on_key(self, event):
        if event.key == 'q':
            sys.exit(0)
        if event.key == 'd':
            plt.close(self.fig)
Esempio n. 50
0
  def display_bx():
      bx[0].cla()
      bx[1].cla()
      bx[3].cla()
      bx[4].cla()
      bx[5].cla()
      bx[0].text(20, 0.0, r'g-r', fontsize=15)
      bx[1].text(20, 0.0, r'g-i', fontsize=15)
      bx[3].text(20, 2, r'r-i', fontsize=15)
      bx[4].text(20, 2, r'i-z', fontsize=15)
      bx[5].text(20, 2, r'r-z', fontsize=15)
      bx[0].scatter(self.gr_mag_all, self.gr_color_all,color="black", marker='.',s=1)
      bx[1].scatter(self.gi_mag_all, self.gi_color_all,color="black", marker='.',s=1)
      bx[3].scatter(self.ri_mag_all, self.ri_color_all,color="black", marker='.',s=1)
 	    bx[4].scatter(self.iz_mag_all, self.iz_color_all,color="black", marker='.',s=1)
      bx[5].scatter(self.rz_mag_all, self.rz_color_all,color="black", marker='.',s=1)
 	    if len(self.ra) > 1:
         bx[0].scatter(self.r_mag,self.gr_color,marker='o',s=40,color="blue")
         bx[1].scatter(self.i_mag,self.gi_color,marker='o',s=40,color="green")
         bx[3].scatter(self.r_mag,self.ri_color,marker='o',s=40,color="orange")
         bx[4].scatter(self.i_mag,self.iz_color,marker='o',s=40,color="red")
         bx[5].scatter(self.i_mag,self.rz_color,marker='o',s=40,color="magenta")    
      if len(self.zra) > 1:
         bx[0].scatter(self.z_gr_mag,self.z_gr_color,color="cyan",marker='s',s=5)
         bx[1].scatter(self.z_gi_mag,self.z_gi_color,color="cyan",marker='s',s=5)
         bx[3].scatter(self.z_ri_mag,self.z_ri_color,color="cyan",marker='s',s=5)
         bx[4].scatter(self.z_iz_mag,self.z_iz_color,color="cyan",marker='s',s=5)
         bx[5].scatter(self.z_rz_mag,self.z_rz_color,color="cyan",marker='s',s=5)
      if len(self.bcg_ra>1):
         bx[0].scatter(self.bcg_r_mag,self.bcg_gr_color,color="red",marker=(5, 0),s=250, alpha=0.2)
         bx[1].scatter(self.bcg_i_mag,self.bcg_gi_color,color="red",marker=(5, 0),s=250, alpha=0.2)
         bx[3].scatter(self.bcg_r_mag,self.bcg_ri_color,color="red",marker=(5, 0),s=250, alpha=0.2)
         bx[4].scatter(self.bcg_i_mag,self.bcg_iz_color,color="red",marker=(5, 0),s=250, alpha=0.2)
         bx[5].scatter(self.bcg_i_mag,self.bcg_rz_color,color="red",marker=(5, 0),s=250, alpha=0.2)
      if self.temp_gr_color !=-100:
         bx[0].scatter(self.temp_r_mag, self.temp_gr_color, color="black", marker=(5, 2), s=250, alpha=0.4)
         bx[1].scatter(self.temp_i_mag, self.temp_gi_color, color="black", marker=(5, 2), s=250, alpha=0.4)
         bx[3].scatter(self.temp_r_mag, self.temp_ri_color, color="black", marker=(5, 2), s=250, alpha=0.4)
         bx[4].scatter(self.temp_i_mag, self.temp_iz_color, color="black", marker=(5, 2), s=250, alpha=0.4)
         bx[5].scatter(self.temp_i_mag, self.temp_rz_color, color="black", marker=(5, 2), s=250, alpha=0.4)
      if (self.gr_xbot != 0):
         rect = Rectangle( ( 0,0 ), 1, 1, alpha = 0.2, ec = "gray", fc = "CornflowerBlue", visible = True, axes=bx[0])
         rect.set_width(self.gr_xtop - self.gr_xbot)
         rect.set_height(self.gr_ytop - self.gr_ybot)
         rect.set_xy((self.gr_xbot, self.gr_ybot))
         bx[0].add_patch(rect)
      if (self.gi_xbot != 0):
         rect = Rectangle( ( 0,0 ), 1, 1, alpha = 0.2, ec = "gray", fc = "CornflowerBlue", visible = True, axes=bx[1])
         rect.set_width(self.gi_xtop - self.gi_xbot)
         rect.set_height(self.gi_ytop - self.gi_ybot)
         rect.set_xy((self.gi_xbot, self.gi_ybot))
         bx[1].add_patch(rect)
      if (self.ri_xbot != 0):
         rect = Rectangle( ( 0,0 ), 1, 1, alpha = 0.2, ec = "gray", fc = "CornflowerBlue", visible = True, axes=bx[3])
         rect.set_width(self.ri_xtop - self.ri_xbot)
         rect.set_height(self.ri_ytop - self.ri_ybot)
         rect.set_xy((self.ri_xbot, self.ri_ybot))
         bx[3].add_patch(rect)
      if (self.iz_xbot != 0):
         rect = Rectangle( ( 0,0 ), 1, 1, alpha = 0.2, ec = "gray", fc = "CornflowerBlue", visible = True, axes=bx[4])
         rect.set_width(self.iz_xtop - self.iz_xbot)
         rect.set_height(self.iz_ytop - self.iz_ybot)
         rect.set_xy((self.iz_xbot, self.iz_ybot))
         bx[4].add_patch(rect)
      if (self.rz_xbot != 0):
         rect = Rectangle( ( 0,0 ), 1, 1, alpha = 0.2, ec = "gray", fc = "CornflowerBlue", visible = True, axes=bx[5])
         rect.set_width(self.rz_xtop - self.rz_xbot)
         rect.set_height(self.rz_ytop - self.rz_ybot)
         rect.set_xy((self.rz_xbot, self.rz_ybot))
         bx[5].add_patch(rect)  
      bx.set_xlim(16, 24)
      bx.set_ylim(-0.2, 3.5)
      bx.axes_llc.set_xlabel("magnitude")
      bx.axes_llc.set_ylabel("color")
      fig2.suptitle('Measured Redshift = '+'{: .3f}'.format(xcs_z), fontsize=20)
      fig2.canvas.draw()  
Esempio n. 51
0
def handle_event():
    global command
    global command_meta
    global main_pic
    global history
    global patch
    global patches
    global click_handlers
    global G


    if command=="horizontal_line" or command=="vertical_line":
        h,w = main_pic.shape[:2]
        if patch is not None:
            w1,h1 = patch.get_xy()
            if command=="horizontal_line":
                line = Line(0,int(h1),w,int(h1), int(patch.get_height()), magenta)
            else:
                line = Line(int(w1),0,int(w1),h, int(patch.get_width()), magenta)
            main_pic = draw_line_on_picture(main_pic, line)
            patch=None
        else:
            if command=="horizontal_line":
                patch = Rectangle((0,0), w, 1, edgecolor='magenta', alpha=1)
            else:
                patch = Rectangle((0,0), 1, h, edgecolor='magenta', alpha=1)

    if command=="needle" or command=="angle_needle":
        G["needle"]["active"] = True
        just_added_patch = False
        if "pt1" in G["needle"] and "pt2" in G["needle"]: 
            if patch is None:
                print "Drawing needle patch"
                pt1 = G["needle"]["pt1"]
                pt2 = G["needle"]["pt2"]
                if command=="needle":
                    patch = Rectangle((pt1[0], pt1[1]), abs(pt2[0]-pt1[0]), abs(pt2[1]-pt1[1]), edgecolor='magenta', alpha=1, facecolor='magenta')
                else:
                    patch = Polygon(np.array([pt1, pt2, p(pt1), p(pt2)]), closed=False,
                            edgecolor='magenta', alpha=1, facecolor='magenta')
                    angle = get_angle(pt1, pt2)
                    print ("Angle :{}".format(angle)) 
                    # how to add text?
                just_added_patch = True

        if patch is not None and not just_added_patch:
            if isinstance(patch, Polygon):
                patches.append(patch)
                patch=None
            else:
                print "finalize"
                w1,h1 = patch.get_xy()
                w = patch.get_width()
                h = patch.get_height()

                if w>h:
                    print("horizontal patch")
                    line = Line(int(w1),int(h1),int(w1+w),int(h1), 3, magenta)
                else:
                    line = Line(int(w1),int(h1),int(w1),int(h1+h), 3, magenta)

                main_pic = draw_line_on_picture(main_pic, line)
            G["needle"] = {}

    if command == "divide":
        divide(command_meta.xdata, command_meta.ydata)
    if command == "brighten":
        main_pic = do_brighten(main_pic)
    if command == "mirror":
	main_pic = np.fliplr(main_pic)
    if command == "zoom":
        click_handlers = not click_handlers
    if command == "darken":
        main_pic = do_darken(main_pic)
    if command == "edge":
        main_pic = edge_detect(main_pic)
    if command == "resize_patch":
        if patch is not None:
            h = patch.get_height()
            w = patch.get_width()
            patch.set_width(int(w * 0.9))
            patch.set_height(int(h * 0.9))

    if command == "crop":
        if patch is not None:
            # apply patch
            # crop main_pic
            h = patch.get_height()
            w = patch.get_width()
            w1,h1 = patch.get_xy()
            main_pic = main_pic[slice(h1,h1+h),slice(w1,w1+w),slice(None)]
            patch=None

        else:
            # create patch
            # TODO: can read this from settings :))
            portrait_ratio = 14.8/20.8
            if orientation=="portrait":
                w_to_h = portrait_ratio
            else:
                w_to_h = 1.0/portrait_ratio
            shape = main_pic.shape
            border = 15
            hp = shape[0] - border
            wp = shape[1] - border

            if w_to_h * hp >wp:
                tw = wp
                th = wp / w_to_h 
            else:
                th = hp
                tw = w_to_h * hp
            print th,tw
            patch = Rectangle((0,0), tw, th, edgecolor='magenta', alpha=1, facecolor='none')
    if command == "undo":
        print "Undoing"
        print len(history)
        if len(history)>=2:
            main_pic,cmd = history[-2]
            print cmd
            history = history[:-1]

    if command!="undo":
        history.append((np.copy(main_pic),command))
    if command not in ["crop","horizontal_line","vertical_line","needle","angle_needle","resize_patch"]:
        patch = None
    command = None
    command_meta = None
    plot(patch=patch, click_handlers=click_handlers)
    if command is not None:
        handle_event()
Esempio n. 52
0
File: roi.py Progetto: glue-viz/glue
class MplYRangeROI(AbstractMplRoi):
    """
    Matplotlib ROI for y range selections

    Parameters
    ----------
    axes : `~matplotlib.axes.Axes`
        The Matplotlib axes to draw to.
    """

    _roi_cls = YRangeROI

    def __init__(self, axes):

        super(MplYRangeROI, self).__init__(axes)

        self._xi = None

        self.plot_opts = {'edgecolor': PATCH_COLOR,
                          'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        trans = blended_transform_factory(self._axes.transAxes,
                                          self._axes.transData)
        self._patch = Rectangle((0., 0.), 1., 1., transform=trans, zorder=100)
        self._patch.set_visible(False)
        self._axes.add_patch(self._patch)

    def start_selection(self, event):

        if event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False
            elif not self._roi.contains(event.xdata, event.ydata):
                return False

        self._store_previous_roi()
        self._store_background()

        if event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._dy = event.ydata - self._roi.center()
        else:
            self.reset()
            self._roi.set_range(event.ydata, event.ydata)
            self._xi = event.ydata

        self._mid_selection = True

        self._sync_patch()
        self._draw()

    def update_selection(self, event):

        if not self._mid_selection or event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False

        if self._scrubbing:
            self._roi.move_to(event.ydata + self._dy)
        else:
            self._roi.set_range(min(event.ydata, self._xi),
                                max(event.ydata, self._xi))

        self._sync_patch()
        self._draw()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            rng = self._roi.range()
            self._patch.set_xy((0, rng[0]))
            self._patch.set_height(rng[1] - rng[0])
            self._patch.set_width(1)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)
Esempio n. 53
0
class set_line(object):
    """
    Class to set a line to cross in an image
    Saves either an X coordinate for a vertical line or a Y coordinate for a horizontal one
    
    line will have a bit of thickness as it is essentially a very thin rectangular ROI
    """    
    def __init__(self, line_color, background_img, line_width=3, line_mode = 'vertical', roi_selection_msg = "Press the 'n' key on your keyboard when you are happy with the ROI"):        
        self.fig, self.ax = plt.subplots()
        self.fig.set_size_inches((11, 8.5), forward=True)
        self.ax.imshow(background_img)
        self.fig.suptitle(roi_selection_msg, size=16)

        self.type = 'line'        
        self.line_width=line_width
        self.color = line_color
        self.ax_height, self.ax_width = background_img.shape[:2]
                
        self.line_mode = line_mode
        self.click_pos = None    
        self.start_pos = None
        self.end_pos = None
        self.roi = None
        self.roi_finalized = False        
        self.line = Rectangle((0,0), 0, 0, color=self.color, alpha=0.4)        
        
        self.ax.add_patch(self.line)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_mouse_press)
        self.ax.figure.canvas.mpl_connect('key_press_event', self.on_key_press)
        
    def on_mouse_press(self, event):
        if self.roi_finalized is False:
            self.click_pos = np.array([event.xdata, event.ydata])
            
            if self.line_mode is 'vertical':
                self.center_offset = event.xdata - self.line_width/2.        
                self.line.set_width(self.line_width)
                self.line.set_height(self.ax_height)
                self.line.set_xy((self.center_offset, 0))
                
                self.start_pos = np.array([self.center_offset, 0])
                self.end_pos = np.array([self.center_offset + self.line_width, self.ax_height])
                               
            if self.line_mode is 'horizontal':
                self.center_offset = event.ydata - self.line_width/2.        
                self.line.set_width(self.ax_width)
                self.line.set_height(self.line_width)
                self.line.set_xy((0, self.center_offset))
                
                self.start_pos = np.array([0, self.center_offset])   
                self.end_pos = np.array([self.ax_width, self.center_offset + self.line_width])
            
            self.ax.figure.canvas.draw()
        
    def on_key_press(self, event):
        if event.key=='n':
            self.roi = (self.start_pos.astype('int'), self.end_pos.astype('int'))
            #print "test"
            self.roi_finalized = True
            plt.close(self.fig)
            
    def wait_for_roi(self):
        """
        Function that allows scripts that invoke roi classes to wait for user to set ROI
        """
        while True:
            plt.pause(0.0001)
            if self.roi_finalized is True:
                print("ROI is finalized")
                break
Esempio n. 54
0
class set_roi(object):
    """
    Class to set an roi in an image.
    Saves start of ROI on mouse button press and saves end of ROI on mouse button release
    Need to specify an roi_color to use as well as a background_img to draw the roi on
    """
    def __init__(self, roi_color, background_img, roi_selection_msg = "Press the 'n' key on your keyboard when you are happy with the ROI"):        
        self.fig, self.ax = plt.subplots()
        self.fig.set_size_inches((11, 8.5), forward=True)
        self.ax.imshow(background_img)
        self.fig.suptitle(roi_selection_msg, size=16)

        self.type = 'roi'        
        self.color = roi_color
        self.bg_img = background_img
        self.rect = Rectangle((0,0), 0, 0, color=self.color, alpha=0.4)
        
        self.start_pos = None
        self.end_pos = None   
        self.current_pos = None        
        self.released = True
        self.roi_finalized = False
        
        self.ax.add_patch(self.rect)
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_mouse_press)
        self.ax.figure.canvas.mpl_connect('button_release_event', self.on_mouse_release)
        self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_mouse_motion)
        self.ax.figure.canvas.mpl_connect('key_press_event', self.on_key_press) 

    def on_mouse_press(self, event):
        self.released = False
        if self.roi_finalized is False:
            self.start_pos = np.array([event.xdata, event.ydata])

    def on_mouse_release(self, event):
        self.released = True
        if self.roi_finalized is False:
            self.end_pos = np.array([event.xdata, event.ydata]) 
            try:
                self.diff = (self.end_pos - self.start_pos)
                self.rect.set_width(self.diff[0])
                self.rect.set_height(self.diff[1])
                self.rect.set_xy(self.start_pos)
                self.ax.figure.canvas.draw()
            except:
                print("The mouse cursor went out of the canvas area! Please retry drawing the ROI!")
                  
    def on_mouse_motion(self, event):
        if self.roi_finalized is False:
            if self.released is False:
                self.current_pos = np.array([event.xdata, event.ydata])
                try:
                    self.diff = (self.current_pos - self.start_pos)
                    self.rect.set_width(self.diff[0])
                    self.rect.set_height(self.diff[1])
                    self.rect.set_xy(self.start_pos)
                    self.ax.figure.canvas.draw()
                except:
                    print("The mouse cursor went out of the canvas area! Please retry drawing the ROI!")
                    
    def standardize_coords(self):
        """
        This function take the start and end coordinates selected by the user
        and standardizes them so that the start is always the upper left corner
        and the end is always the lower right corner
        """
        x_coords, y_coords = zip(*(self.start_pos, self.end_pos))
        
        #0,0 is top left and max, max is bottom right
        standardized_start = np.array([min(x_coords), min(y_coords)])
        standardized_end = np.array([max(x_coords), max(y_coords)])
        
        return standardized_start.astype('int'), standardized_end.astype('int')
    
    def on_key_press(self, event):
        if event.key=='n':
            self.roi = self.standardize_coords()
            #print "test"
            self.roi_finalized = True
            plt.close(self.fig)
            
    def wait_for_roi(self):
        """
        Function that allows scripts that invoke roi classes to wait for user to set ROI
        """
        while True:
            plt.pause(0.0001)
            if self.roi_finalized is True:
                print("ROI is finalized")
                break
Esempio n. 55
0
class Annotate(object):
    def __init__(self, image,name):
        self.img = image
        self.imgname = name
        self.i = 1
        self.col = 'b' # deafult color for true positive label
        self.ax = plt.gca()
        # Initialize the Reactangle patch object with properties 
        self.rect = Rectangle((0,0), 1, 1, alpha = 1,ls = 'solid',fill = False, clip_on = True,color = self.col)
        # Initialize two diagonally opposite co-ordinates of reactangle as None
        self.xc = None
        self.yc = None
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.sizeModifier = 2
        
        self.w = 30.0
        self.h = 40.0
        self.qkey = None
        self.objList = []

        #self.centers
        # The list that will store value of those two co-ordinates of 
        # all the patches for storing into the file later
        self.xy = []
        self.ax.add_patch(self.rect)
        # Initialize mpl connect object 
        connect = self.ax.figure.canvas.mpl_connect
        # Create objects that will handle user initiated events 
        # We are using three events 
        # First event is button press event (on left key click)- 
        # on which on_click function is called
        self.ax.figure.canvas.mpl_connect('button_press_event', self.on_click)
        self.ax.figure.canvas.mpl_connect('close_event', self.handle_close)
        
        
        # Second event to draw, in case a mistake in labelling is made, 
        # deleting the patch requires redrawing the original canvas
        self.draw_cid = connect('draw_event', self.grab_background)
        
        # Third event - key press event
        # To change color of the patches when you want to switch between 
        # true postive and false postive labels
        self.ax.figure.canvas.mpl_connect('key_press_event',self.colorChange)
 



    def objCreation(self):
        # The new reactangle object to use after blit function (clearing 
        # the canvas and removing rectangle objects)
        
        self.rect = Rectangle((0,0), 1, 1, alpha = 1,ls = 'solid',fill = False, clip_on = True)
        self.xc = None # x co-ordinate of patch center
        self.yc = None # y co-ordinate of patch center
        self.x0 = None # top left x co-ordinate of patch center
        self.y0 = None # top left y co-ordinate of patch center
        self.x1 = None # lower right y co-ordinate of patch center
        self.y1 = None # lower right y co-ordinate of patch center
        self.sizeModifier = 2 # The amount by which width/height will increase/decrease
        self.w = 30.0 # Initial width
        self.h = 40.0 # Initial height
        # Aspect Ratio of 3/4
        # Add the patch on the axes object of figure
        self.ax.add_patch(self.rect)  


    def deletePrevious(self):
        '''
        Deletes the latest patch that was drawn
        '''
        # Clear the screen by calling blit function
        self.blit()
        # Remove the last patch co-ordinates from the list
        self.xy = self.xy[:-1]


        # Redraw all the rects except the previous ones
        for coords in self.xy:
            self.rect.set_width(coords[2] - coords[0])
            self.rect.set_height(coords[3] - coords[1])
            self.rect.set_xy((coords[0], coords[1]))
            self.rect.set_color(coords[4])
            self.ax.draw_artist(self.rect)
            self.ax.figure.canvas.blit(self.ax.bbox)

    def resize(self,det):
        '''
        Resizing at the same center, maintaing the same aspect ratio
        and using key only (without dragging)
        '''

        # Resizing without dragging requires deleting previous patch
        # Saving the center, width, height of the patch before deleting it
        # As it will be used for reconstructing with increased/decreased size
       
        last_obj = self.xy[-1]
        # print last_obj
        xc = last_obj[-2]
        yc = last_obj[-1]
        col = last_obj[-3]
        w = last_obj[2] - last_obj[0]
        h = last_obj[3] - last_obj[1]

        self.deletePrevious()
        self.xc = xc
        self.yc = yc
        self.col = col
        
        self.w = w*det 
        print self.w
        
        self.h =  h*det
        
        self.drawRect()

    def handle_close(self,event):
        '''
        if you ended up closing the plot using the plot's X button instead of 'q' key
        '''
        if self.qkey != 'q':
            self.close_plot()
    
    def close_plot(self):
        '''
        saving numpy patches and co-ordinates of the patches 
        '''
        b = 0
        r = 0
        print os.getcwd()
        print 'close'
        header = open('header.txt','a')
        
        
        ##print self.xy

        #self.xy = filter(lambda x: 0 not in np.shape(x) , self.xy)
        blue_patches = filter(lambda x: x[4]=='b',self.xy)
        for blue_patch_list in blue_patches:
            xy = blue_patch_list
            name = str('NumpyPatches\\')+str(self.imgname)+'_blue'+str(b)+'.npy'
            patch_array = self.img[xy[1]:xy[3],xy[0]:xy[2]]
            if 0 not in np.shape(patch_array):
                header.write("%s" % self.imgname+',')
                print os.getcwd()
                np.save(name, patch_array)
                b = b+1
                for item in xy[:5]:
                    
                    header.write("%s" % item+',')
                header.write('\n')


        red_patches = filter(lambda x: x[4]=='r',self.xy)
        for red_patch_list in red_patches:
            xy = red_patch_list
            name = self.imgname+'_red'+str(r)+'.npy'
            patch_array = self.img[xy[1]:xy[3],xy[0]:xy[2]]
            if 0 not in np.shape(patch_array):
                header.write("%s" % self.imgname+',')
                np.save(name, patch_array)
                r = r+1
                for item in xy[:5]:
                    
                    header.write("%s" % item+',')
                header.write('\n')
        
        # xy = self.xy[0]
        # patch = img[xy[1]:xy[3],xy[0]:xy[2]]
        
        # imgplot = plt.imshow(patch)
        # plt.show()

        plt.close()


        
    def colorChange(self,event):
        '''
        To change color to take  false positves into consideration - the default is color blue for true postive
        '''
        
        print('press', event.key)
        sys.stdout.flush()
        if event.key == 'r': # red color
            # When 'r' key is pressed, the color of the next patch will be red
            self.col = 'r'
           

        elif event.key == 'b': # blue color
            # When 'b' key is pressed, the color of the next patch will be blue
            self.col = 'b' 

        # Optional setting for drawing patched using spacebar
        # elif event.key == ' ':
        #     self.on_click(event)    
            

        elif event.key == 'd': # delete
            # When 'd' key is pressed, the latest patch drawn is deleted
            #self.deletePrevious()
            nr = self.objList[-1]
            nr.set_visible(False)


        elif event.key == 'c': # clear 
            # When 'c' key is pressed, all the patches are cleared, only orignal background is present
            self.blit()    
            self.xy = []
            # Flush out the list as we don't want to consider any patch co-ordinates

        elif event.key == 'tab':
            # use tab to increase the aspect ratio of the patch 

            self.resize(1.2)

        elif event.key == 'control':
            # use control key to decrease the aspect ratio of the patch
            self.resize(0.95)

        elif event.key == '2':
            # use control key to decrease the aspect ratio of the patch
            self.resize(0.85)

        elif event.key == '3':
            # use control key to decrease the aspect ratio of the patch
            self.resize(0.50)  

        
        elif event.key == 'q': # quit plot, show up the next
            # save necessary labels and close the plot
            self.qkey = 'q'
            self.close_plot()
                
        elif event.key == '0':
            sys.exit()
            

    

    
    def on_click(self, event):
        '''
        Using one click on the center of the human, make a patch of fixed aspect ratio
        '''
       
    
        # The first click to mark center point of the rectangle and save the coordinates

        print 'click1'
        self.xc = event.xdata
        self.yc = event.ydata
        # Chosing Aspect Ratio of 3/4
        self.w = 30.0
        self.h = 40.0
        self.drawRect()

       

    def drawRect(self):
            
        
        # Set the two diagonally opposite co-ordinates of the patch  by width and height
       
    
        self.x0 = self.xc-self.w/2
        self.y0 = self.yc-self.h/2
        self.x1 = self.xc+self.w/2
        self.y1 = self.yc+self.h/2
        # set the stated width
        self.rect.set_width(self.w)
        # set the stated height 
        self.rect.set_height(self.h)
        # set the top left corner
        self.rect.set_xy((self.x0, self.y0 )) 

        # append to the list of patch co-ordinates
        self.xy.append([self.x0,self.y0,self.x1,self.y1,self.col,self.xc,self.yc])
        #print self.xy
        self.objList.append(self.rect)
        
        
        # Set the color of the reactangle - can be blue/red depending on postive/negative label respectively
        self.rect.set_color(self.col)
        self.ax.draw_artist(self.rect)
        self.ax.figure.canvas.update()

        # Blit is used to successively retain and display patches on the screen 
        # Else Successively drawing one patch will remove the last drawn patch 
        #self.ax.figure.canvas.blit(self.ax.bbox)


    # The following three functions taken from 
    # http://stackoverflow.com/questions/29277080/efficient-matplotlib-redrawing

    def safe_draw(self):
        """Temporarily disconnect the draw_event callback to avoid recursion"""
        canvas = self.ax.figure.canvas
        canvas.mpl_disconnect(self.draw_cid)
        canvas.draw()
        self.draw_cid = canvas.mpl_connect('draw_event', self.grab_background)


    def grab_background(self, event=None):
        """
        When the figure is resized, hide the rect, draw everything,
        and update the background.
        """
        self.rect.set_visible(False)
        self.safe_draw()

        # With most backends (e.g. TkAgg), we could grab (and refresh, in
        # self.blit) self.ax.bbox instead of self.fig.bbox, but Qt4Agg, and
        # some others, requires us to update the _full_ canvas, instead.
        self.background = self.ax.figure.canvas.copy_from_bbox(self.ax.figure.bbox)
        self.rect.set_visible(True)
        self.blit()

    

    def blit(self):
        """
        Efficiently update the figure, without needing to redraw the
        "background" artists.
        """
        self.objCreation()
        self.ax.figure.canvas.restore_region(self.background)
        self.ax.draw_artist(self.rect)
        self.ax.figure.canvas.blit(self.ax.figure.bbox)
Esempio n. 56
0
class RangeSelector:
    def __init__(self, axes, callbackPre, callbackPost):
        self.axes = axes
        self.callbackPre = callbackPre
        self.callbackPost = callbackPost

        self.eventPressed = None
        self.eventReleased = None

        props = dict(facecolor="red", edgecolor="white", alpha=0.25, fill=True, zorder=100, gid="range")
        self.rect = Rectangle((0, 0), 0, 0, **props)
        self.axes.add_patch(self.rect)

        figure = self.axes.get_figure()
        figure.canvas.mpl_connect("motion_notify_event", self.__on_move)
        figure.canvas.mpl_connect("button_press_event", self.__on_press)
        figure.canvas.mpl_connect("button_release_event", self.__on_release)

    def __on_press(self, event):
        if self.__skip_event(event):
            return

        self.eventPressed = event
        self.callbackPre()
        self.rect.set_visible(True)
        return

    def __on_move(self, event):
        if self.eventPressed is None or self.__skip_event(event):
            return

        xMin = self.eventPressed.xdata
        xMax = event.xdata
        if xMin > xMax:
            xMin, xMax = xMax, xMin
        self.callbackPost(xMin, xMax)

        return

    def __on_release(self, event):
        if self.eventPressed is None or self.__skip_event(event):
            return

        self.eventReleased = event
        xMin, xMax = self.eventPressed.xdata, self.eventReleased.xdata
        if xMin > xMax:
            xMin, xMax = xMax, xMin
        self.callbackPost(xMin, xMax)
        self.eventPressed = None
        self.eventReleased = None
        return

    def __skip_event(self, event):
        if event.button != 2:
            return True

        if self.eventPressed is None:
            return event.inaxes != self.axes

        if event.button == self.eventPressed.button and event.inaxes != self.axes:
            transform = self.axes.transData.inverted()
            (x, _y) = transform.transform_point((event.x, event.y))
            x0, x1 = self.axes.get_xbound()
            x = max(x0, x)
            x = min(x1, x)
            event.xdata = x
            return False

        return event.inaxes != self.axes or event.button != self.eventPressed.button

    def draw(self, xMin, xMax):
        self.rect.set_visible(True)
        yMin, yMax = self.axes.get_ylim()
        height = yMax - yMin
        yMin -= height * 100.0
        yMax += height * 100.0
        self.rect.set_x(xMin)
        self.rect.set_y(yMin)
        self.rect.set_width(xMax - xMin)
        self.rect.set_height(yMax - yMin)

        if self.axes._cachedRenderer is not None:
            self.axes.draw_artist(self.rect)

    def hide(self):
        self.rect.set_visible(False)

    def clear(self):
        self.rect.set_visible(False)
        canvas = self.axes.get_figure().canvas
        canvas.draw()
Esempio n. 57
0
class CustomToolbar(NavToolbar):

    toolitems = NavToolbar.toolitems + (
        (None, None, None, None),
        ("ROI", "Select ROI", "selection", "_on_custom_select"),
    )

    def __init__(self, plotCanvas):
        # create the default toolbar
        NavToolbar.__init__(self, plotCanvas)
        self.selector = RectSelector(
            self.canvas.figure.axes[0], self.onSelect, button=[1, 3], minspanx=5, minspany=5  # don't use middle button
        )
        self.selector.set_active(True)
        self.ax = self.canvas.figure.axes[0]
        self.roi = None
        self.fixedSize = False
        if wx.Platform == "__WXMAC__":
            self.to_draw = Rectangle(
                (0, 0), 0, 1, visible=False, facecolor="yellow", edgecolor="black", alpha=0.5, fill=True
            )
            self.ax.add_patch(self.to_draw)
            self.background = None

    def _init_toolbar(self):
        self._parent = self.canvas.GetParent()

        self.wx_ids = {}
        for text, tooltip_text, image_file, callback in self.toolitems:
            if text is None:
                self.AddSeparator()
                continue
            self.wx_ids[text] = wx.NewId()
            try:
                bitmap = _load_bitmap(image_file + ".png")
            except IOError:
                bitmap = wx.Bitmap(image_file + ".png")
            if text in ["Pan", "Zoom", "ROI"]:
                self.AddCheckTool(self.wx_ids[text], bitmap, shortHelp=text, longHelp=tooltip_text)
            else:
                self.AddSimpleTool(self.wx_ids[text], bitmap, text, tooltip_text)
            bind(self, wx.EVT_TOOL, getattr(self, callback), id=self.wx_ids[text])

        self.ToggleTool(self.wx_ids["ROI"], True)
        self.Realize()

    def _set_markers(self):
        self.canvas.parentFrame.set_markers()

    def _update_view(self):
        NavToolbar._update_view(self)
        self._set_markers()
        # MacOS needs a forced draw to update plot
        if wx.Platform == "__WXMAC__":
            self.canvas.draw()

    def draw(self):
        self._set_markers()
        NavToolbar.draw(self)
        # MacOS needs a forced draw to update plot
        if wx.Platform == "__WXMAC__":
            self.canvas.draw()

    def zoom(self, ev):
        if wx.Platform == "__WXMAC__":
            self.ToggleTool(self.wx_ids["Zoom"], self.GetToolState(self.wx_ids["Zoom"]))
        NavToolbar.zoom(self, ev)

    def pan(self, ev):
        if wx.Platform == "__WXMAC__":
            self.ToggleTool(self.wx_ids["Pan"], self.GetToolState(self.wx_ids["Pan"]))
        NavToolbar.pan(self, ev)

    def press_zoom(self, ev):
        if wx.Platform == "__WXMAC__":
            self.update_background()
            self.to_draw.set_visible(True)
        NavToolbar.press_zoom(self, ev)

    def release_zoom(self, ev):
        if wx.Platform == "__WXMAC__":
            self.to_draw.set_visible(False)
        NavToolbar.release_zoom(self, ev)

    def draw_rubberband(self, event, x0, y0, x1, y1):
        # XOR does not work on MacOS ...
        if wx.Platform != "__WXMAC__":
            NavToolbar.draw_rubberband(self, event, x0, y0, x1, y1)
        else:
            if self.background is not None:
                self.canvas.restore_region(self.background)
            c0, c1 = self.ax.transData.inverted().transform([[x0, y0], [x1, y1]])
            l, b = c0
            r, t = c1
            self.to_draw.set_bounds(l, b, r - l, t - b)
            self.ax.draw_artist(self.to_draw)
            self.canvas.blit(self.ax.bbox)

    def update_background(self):
        """force an update of the background"""
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

    # Turn on selection
    # TODO: Proper handling of states, actual functionality.
    def _on_custom_select(self, evt):
        #        for id in ['Zoom','Pan']:
        #            self.ToggleTool(self.wx_ids[id], False)
        #        print('Select ROI: %s' % (self.GetToolState(self.wx_ids['ROI'])))
        #        self.ToggleTool(self.wx_ids['ROI'],
        #                self.GetToolState(self.wx_ids['ROI']) )
        self.toggle_selector()

    #        print('Select ROI: %s' % (self.GetToolState(self.wx_ids['ROI'])))

    def onSelect(self, eclick, erelease):
        "eclick and erelease are matplotlib events at press and release"
        #        print(' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata))
        #        print(' endposition   : (%f, %f)' % (erelease.xdata, erelease.ydata))
        #        print(' used button   : ', eclick.button)
        self.updateROI(
            min(eclick.xdata, erelease.xdata),
            min(eclick.ydata, erelease.ydata),
            abs(eclick.xdata - erelease.xdata),
            abs(eclick.ydata - erelease.ydata),
        )
        if self.canvas.parentFrame.fixedNumberCB.IsChecked():
            # We are working in the fixed-number mode
            # We need to find new roi for this center point
            # The handler will call the update ROI function for us.
            self.canvas.parentFrame.handleROIforN()

    def updateROI(self, x, y, w, h):
        if self.roi is None:
            # print('upd ROI:', x, y, w, h)
            self.roi = Rectangle((x, y), w, h, ls="solid", lw=2, color="r", fill=False, zorder=5)
            self.canvas.figure.axes[0].add_patch(self.roi)
        else:
            self.roi.set_bounds(x, y, w, h)
        self.updateCanvas()

    def toggle_selector(self):
        self.selector.set_active(not self.selector.active)

    def onFixedSize(self, ev):
        self.fixedSize = ev.IsChecked()
        self.updateCanvas()

    def onWidthChange(self, ev):
        if self.roi:
            x = self.roi.get_x()
            w = self.roi.get_width()
            nw = ev.GetValue()
            dw = {"C": (w - nw) / 2, "L": 0, "R": w - nw}[self.canvas.parentFrame.anchorRB.GetStringSelection()[0]]
            self.roi.set_x(x + dw)
            self.roi.set_width(nw)
            self.updateCanvas()

    def onHeightChange(self, ev):
        if self.roi:
            y = self.roi.get_y()
            h = self.roi.get_height()
            nh = ev.GetValue()
            dh = {"C": (h - nh) / 2, "B": 0, "T": h - nh}[self.canvas.parentFrame.anchorRB.GetStringSelection()[-1]]
            self.roi.set_y(y + dh)
            self.roi.set_height(nh)
            self.updateCanvas()

    def updateCanvas(self, redraw=True):
        if self.roi:
            self.canvas.parentFrame.showROI(
                self.roi.get_x(), self.roi.get_y(), self.roi.get_width(), self.roi.get_height()
            )
            self.canvas.parentFrame.setWH(self.roi.get_width(), self.roi.get_height())
            if self.fixedSize:
                self.selector.setSize(self.roi.get_width(), self.roi.get_height())
            else:
                self.selector.setSize()
        if redraw:
            self.draw()
Esempio n. 58
0
File: roi.py Progetto: glue-viz/glue
class MplRectangularROI(AbstractMplRoi):
    """
    Matplotlib ROI for rectangular selections

    Parameters
    ----------
    axes : `~matplotlib.axes.Axes`
        The Matplotlib axes to draw to.
    """

    _roi_cls = RectangularROI

    def __init__(self, axes):

        super(MplRectangularROI, self).__init__(axes)

        self._xi = None
        self._yi = None

        self.plot_opts = {'edgecolor': PATCH_COLOR,
                          'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        self._patch = Rectangle((0., 0.), 1., 1., zorder=100)
        self._patch.set_visible(False)
        self._axes.add_patch(self._patch)

    def start_selection(self, event):

        if event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False
            elif not self._roi.contains(event.xdata, event.ydata):
                return False

        self._store_previous_roi()
        self._store_background()

        self._xi = event.xdata
        self._yi = event.ydata

        if event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._cx, self._cy = self._roi.center()
        else:
            self.reset()
            self._roi.update_limits(event.xdata, event.ydata,
                                    event.xdata, event.ydata)

        self._mid_selection = True

        self._sync_patch()
        self._draw()

    def update_selection(self, event):

        if not self._mid_selection or event.inaxes != self._axes:
            return False

        if event.key == SCRUBBING_KEY:
            if not self._roi.defined():
                return False

        if self._scrubbing:
            self._roi.move_to(self._cx + event.xdata - self._xi,
                              self._cy + event.ydata - self._yi)
        else:
            self._roi.update_limits(min(event.xdata, self._xi),
                                    min(event.ydata, self._yi),
                                    max(event.xdata, self._xi),
                                    max(event.ydata, self._yi))

        self._sync_patch()
        self._draw()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()

    def _sync_patch(self):
        if self._roi.defined():
            corner = self._roi.corner()
            width = self._roi.width()
            height = self._roi.height()
            self._patch.set_xy(corner)
            self._patch.set_width(width)
            self._patch.set_height(height)
            self._patch.set(**self.plot_opts)
            self._patch.set_visible(True)
        else:
            self._patch.set_visible(False)

    def __str__(self):
        return "MPL Rectangle: %s" % self._patch