Exemplo n.º 1
0
class viewer(graphplot):
    '''
    Do:
    viewer = viewer(window)
    viewer.connect()
    To instantiate and use
    '''
    def __init__(self,
                 nodes_obj,
                 window=None,
                 figsize=None,
                 idxlist=[],
                 usekm=False):
        # window are the [xmin,xmax,ymin,ymax] dimensions of the viewer

        self.coordunits = "coords"
        if usekm: self.coordunits = "coords_km"

        # Create nodedict if nodes is a dataframe
        if "DataFrame" in str(type(nodes_obj)):
            nodedict = nodes_obj.to_dict("index")
        else:
            nodedict = nodes_obj

        self.figsize = (9, 9) if not figsize else figsize
        self.fig_main = plt.figure(figsize=self.figsize)
        self.grid = plt.GridSpec(2,
                                 2,
                                 hspace=0.1,
                                 wspace=0.1,
                                 width_ratios=[2.2, 1],
                                 height_ratios=[0.8, 1])
        self.axs = [self.fig_main.add_subplot(self.grid[:, 0])]
        self.axs.append(self.fig_main.add_subplot(self.grid[0, 1]))

        # Initialize parent graph object
        super().__init__(nodedict,
                         idxlist,
                         (self.figsize[0] * 0.75, self.figsize[1] * 0.75),
                         self.fig_main,
                         self.axs[0],
                         usekm=usekm)
        self.axs[0].set_aspect('equal', adjustable='box', anchor="NW")

        # Draw main graph
        self.drawgraph()

        # Setup viewer
        if not window:
            #    window = [self.xlims[0]+0.4*self.graphwidth,
            #              self.xlims[0]+0.6*self.graphwidth,
            #              self.ylims[0]+0.4*self.graphheight,
            #              self.ylims[0]+0.6*self.graphheight]
            dw = 1. / long2km
            if usekm: dw = 1.
            window = [
                self.xlims[0] + 0.5 * self.graphwidth - dw,
                self.xlims[0] + 0.5 * self.graphwidth + dw,
                self.ylims[0] + 0.5 * self.graphheight - dw,
                self.ylims[0] + 0.5 * self.graphheight + dw
            ]
        xmin, xmax, ymin, ymax = window[0], window[1], window[2], window[3]
        self.window = Rectangle((xmin, ymin),
                                xmax - xmin,
                                ymax - ymin,
                                fill=False,
                                linewidth=1.6,
                                edgecolor="orangered")
        self.axs[0].add_patch(self.window)

        # Create inset axis
        xmin, ymin, xmax, ymax = self.get_rect_coords(self.window)
        self.axs[1].set_ylim(ymin, ymax)
        self.axs[1].set_xlim(xmin, xmax)
        self.axs[1].set_aspect('equal', adjustable='box', anchor="NE")
        self.axs[1].set_xticks([])
        self.axs[1].set_yticks([])
        self.press = None

        self.updateinset()

    def updateinset(self):
        # Remove any artists if present
        self.axs[1].clear()

        # Collect which nodes are included
        insetnodes = {}
        xmin, ymin, xmax, ymax = self.get_rect_coords(self.window)
        for key, node in self.nodes.items():
            x, y = node[self.coordunits]
            if x > xmin and x < xmax and y > ymin and y < ymax:
                insetnodes.update({key: node})
                self.plotnode(self.axs[1], x, y)
                edges = node["nbrs"]
                for e in edges:
                    if e in self.idxlist:
                        nbr = self.nodes[e][self.coordunits]
                        self.plotLine(self.axs[1], x, y, nbr[0], nbr[1])

        self.axs[1].set_ylim(ymin, ymax)
        self.axs[1].set_xlim(xmin, xmax)
        #self.axs[1].set_aspect('equal', adjustable='box',anchor="NE")
        self.axs[1].set_xticks([])
        self.axs[1].set_yticks([])


#         pickle.dump(self., file('myplot.pickle', 'w'))

    def connect(self):
        'connect to all the events we need'
        self.cidpress = self.window.figure.canvas.mpl_connect(
            'button_press_event', self.on_press)
        self.cidrelease = self.window.figure.canvas.mpl_connect(
            'button_release_event', self.on_release)
        self.cidmotion = self.window.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

    def on_press(self, event):
        'on button press we will see if the mouse is over us and store some data'
        if event.inaxes != self.window.axes: return

        contains, attrd = self.window.contains(event)
        self.window.set_x(event.xdata - self.window.get_width() * 0.5)
        self.window.set_y(event.ydata - self.window.get_height() * 0.5)
        if True:
            # Update attributes for motion
            print('event contains', self.window.xy)
            x0, y0 = self.window.xy
            self.press = x0, y0, event.xdata, event.ydata

    def on_motion(self, event):
        'on motion we will move the window if the mouse is over us'
        if self.press is None: return
        if event.inaxes != self.window.axes: return
        x0, y0, xpress, ypress = self.press
        dx = event.xdata - xpress
        dy = event.ydata - ypress
        #print('x0=%f, xpress=%f, event.xdata=%f, dx=%f, x0+dx=%f' %
        #      (x0, xpress, event.xdata, dx, x0+dx))

        self.window.set_x(x0 + dx)
        self.window.set_y(y0 + dy)
        self.window.figure.canvas.draw()

    def on_release(self, event):
        'on release we reset the press data'
        self.press = None
        self.updateinset()
        self.window.figure.canvas.draw()

    def disconnect(self):
        'disconnect all the stored connection ids'
        self.window.figure.canvas.mpl_disconnect(self.cidpress)
        self.window.figure.canvas.mpl_disconnect(self.cidrelease)
        self.window.figure.canvas.mpl_disconnect(self.cidmotion)
class RectROI(ROI):

    def __init__(self, ax, fig, canvas, red=0.5, green=0.5, blue=0.5):

        ROI.__init__(self, ax, fig, canvas)

        self.x0 = 0
        self.y0 = 0
        self.x1 = 0
        self.y1 = 0
        self.line_color = (red, green, blue)
        self.rect = None
        return

    def button_press_callback(self, event):

        if event.inaxes:
            if event.button == 1:  # If you press the left mouse button
                if self.rect is None:
                    self.x0 = event.xdata
                    self.y0 = event.ydata
        return

    def button_release_callback(self, event):
        # When the user releases the mouse button, make sure the ROI line
        # no longer moves with the mouse.
        if event.button == 1:

            if self.rect is None:
                self.x1 = event.xdata
                self.y1 = event.ydata
                width = self.x1 - self.x0
                height = self.y1 - self.y0
                self.rect = Rectangle((self.x0, self.y0), width, height, color=self.line_color, fill=False, picker=True,
                                      visible=True, figure=self.fig)

                ax = event.inaxes
                ax.add_patch(self.rect)
                self.fig.canvas.draw()

        self.grab_line = None

        return

    def motion_notify_callback(self, event):
        '''
        This is called when the user moves the mouse over the plot.
        It will change the size or position of the ROI.
        '''

        if event.inaxes:
            if (event.button == 1) and (not (self.grab_line is None)):
                # Change the position of the bottom right corner of the ROI
                # as the mouse is dragged across the image.
                self.x1 = event.xdata
                self.y1 = event.ydata
                width = self.x1 - self.x0
                height = self.y1 - self.y0

                self.rect.set_width(width)
                self.rect.set_height(height)

                self.fig.canvas.draw()

            if (event.button == 3) and (not (self.grab_line is None)):
                # Change the position of the top left corner of the ROI
                # as the mouse is dragged across the image.
                self.x0 = event.xdata
                self.y0 = event.ydata

                self.rect.set_xy((self.x0, self.y0))

                self.fig.canvas.draw()

        return

    def object_picked_callback(self, event):
        # Set the line grabbed to the object that is clicked on.
        contains, attrd = self.rect.contains(event.mouseevent)
        if contains:
            self.grab_line = event.artist
        return

    def AddLines(self):
        if self.rect is not None:
            self.ax.add_patch(self.rect)
            self.ax.figure.canvas.draw()

        return

    def RemoveLines(self):
        try:
            self.rect.remove()
            self.fig.canvas.draw()
        except AttributeError:
            return
        return

    def GetDimensions(self):
        dim_list = []
        dim_list.append(self.x0)
        dim_list.append(self.y0)
        dim_list.append(self.x1)
        dim_list.append(self.y1)

        return dim_list

    def EditROI(self):

        if self.x0 == 0 or self.y0 == 0 or self.x1 == 0 or self.y1 == 0:
            return

        width = self.x0 - self.x1
        height = self.y0 - self.y1

        if self.rect is None:
            self.rect = Rectangle((self.x1, self.y1), width, height, color=self.line_color, fill=False, picker=True,
                                      visible=True, figure=self.fig, axes=self.fig.gca())
            ax = self.fig.gca()
            ax.add_patch(self.rect)
        else:
            self.rect.set_height(height)
            self.rect.set_width(width)
            self.rect.set_xy((self.x1, self.y1))

        self.fig.canvas.draw()

        return

    def SetXY(self, x, y, corner=1):

        if corner == 1:
            self.x0 = x
            self.y0 = y

        else:
            self.x1 = x
            self.y1 = y

        return
Exemplo n.º 3
0
class DraggableRectangle(object):
    def __init__(self, axes, rectwidth=100, lrwidth=10, recty=100):
        self.ax = axes  # plt.gca()

        self.rect_x = axes.get_xlim()[1] - rectwidth - lrwidth
        self.rect = Rectangle((self.rect_x, 0),
                              rectwidth,
                              recty,
                              facecolor='g',
                              alpha=0.2)
        self.rectl = Rectangle((self.rect_x - lrwidth, 0),
                               lrwidth,
                               recty,
                               facecolor='b',
                               alpha=0.8)
        self.rectr = Rectangle((self.rect_x + rectwidth, 0),
                               lrwidth,
                               recty,
                               facecolor='b',
                               alpha=0.8)

        self.ax.add_patch(self.rect)
        self.ax.add_patch(self.rectl)
        self.ax.add_patch(self.rectr)

        self.rect_width = rectwidth
        self.press = None  # 0,
        self.pressl = None
        self.pressr = None

        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):
        if event.inaxes != self.rect.axes: return

        contains, attrd = self.rect.contains(event)
        containsl, attrdl = self.rectl.contains(event)
        containsr, attrdr = self.rectr.contains(event)
        if contains:
            x0, y0 = self.rect.xy
            self.press = x0, y0, event.xdata, event.ydata
        elif containsl:
            xl, yl = self.rectl.xy
            self.pressl = xl, yl, event.xdata, event.ydata
        elif containsr:
            xr, yr = self.rectr.xy
            self.pressr = xr, yr, event.xdata, event.ydata
        else:
            return

    def on_release(self, event):
        # print ('release')
        self.press = None
        self.pressl = None
        self.pressr = None
        self.ax.figure.canvas.draw()

    def on_motion(self, event):
        'on motion we will move the rect if the mouse is over us'
        if self.press is None and self.pressl is None and self.pressr is None:
            return
        if event.inaxes != self.rect.axes and event.inaxes != self.rectl.axes and event.inaxes != self.rectr.axes:
            return

        rectwidth = self.rect_width
        if self.press != None:
            x0, y0, xpress, ypress = self.press
            dx = event.xdata - xpress
            rectl_x = x0 + dx - self.rectl.get_width()

            # to tell the left edge overriding
            if rectl_x < 0:
                rectl_x = 0
            # to tell the right edge overriding
            if rectl_x + self.rectl.get_width(
            ) + rectwidth + self.rectr.get_width() > self.ax.get_xlim()[1] - 1:
                rectl_x = self.ax.get_xlim(
                )[1] - rectwidth - self.rectr.get_width(
                ) - self.rectl.get_width()
                print("self.ax.get_xlim()[1]=",
                      self.ax.get_xlim()[1], " rectLx=", rectl_x)

            self.rect_x = rectl_x + self.rectl.get_width()
            self.rect.set_x(self.rect_x)
            self.rectl.set_x(rectl_x)
            self.rectr.set_x(self.rect_x + self.rect.get_width())
            # self.rect.figure.canvas.draw()
        elif self.pressl != None:
            if event.xdata >= self.rectr.get_x() - 10:
                self.rect_width = 10
                return

            xl, yl, xpress, ypress = self.pressl
            dx = event.xdata - xpress
            rectl_x = xl + dx  #- self.rectl.get_width()

            # to tell the left edge overriding
            if rectl_x < 0:
                self.rect_width = self.rectr.get_x() - self.rectl.get_width()
                rectl_x = 0

            self.rectl.set_x(rectl_x)
            # draw rect
            self.rect.set_x(rectl_x + self.rectl.get_width())
            xr = self.rectr.get_x()
            rectwidth = xr - rectl_x - self.rectl.get_width()
            # self.rectl.figure.canvas.draw()
        elif self.pressr != None:
            if event.xdata <= self.rectl.get_x() + self.rectl.get_width() + 10:
                self.rect_width = 10
                return

            xr, yr, xpress, ypress = self.pressr
            dx = event.xdata - xpress
            rectr_x = xr + dx

            # to tell the right edge overriding
            xlim = self.ax.get_xlim()[1]
            print('xlim=', xlim)
            if rectr_x + self.rectr.get_width() > xlim:
                self.rect_width = xlim - self.rectl.get_x(
                ) - self.rectl.get_width()
                rectr_x = xlim - self.rectr.get_width()

            self.rectr.set_x(rectr_x)
            # draw rect
            rectwidth = rectr_x - self.rectl.get_x() - self.rectl.get_width()
            # self.rectr.figure.canvas.draw()

        self.rect.set_width(rectwidth)
        self.rect_width = rectwidth
        self.ax.figure.canvas.draw()
        # self.rectl.figure.canvas.draw()  # why we just draw rect here, but rectl and rectr are drawed too ?

    def reset_rects(self, xl, xr):
        xlim = self.ax.get_xlim()[1]
        if xr > xlim: return
        if xl < 0: return

        self.rectl.set_x(xl)
        self.rectr.set_x(xr - self.rectr.get_width())
        self.rect_x = xl + self.rectl.get_width()
        self.rect.set_x(self.rect_x)
        self.rect_width = xr - self.rectr.get_width() - self.rect_x
        self.rect.set_width(self.rect_width)
        self.ax.figure.canvas.draw()

    def is_pressed(self):
        r = 0
        if self.press:
            r = 1
        elif self.pressl:
            r = 2
        elif self.pressr:
            r = 3
        else:
            r = 0
        return r

    def get_rect_x1(self):
        return int(self.rectl.get_x())

    def get_rect_x2(self):
        return int(self.rectr.get_x() + self.rectr.get_width() - 1)
Exemplo n.º 4
0
class ClickableRectangle:
    def __init__(self, fig, ax, colors_cube, f, i_f, j_f):
        self.f = f
        self.i_f = i_f
        self.j_f = j_f

        self.colors_cube = colors_cube
        self.x = i_f
        self.y = j_f
        self.color = self.colors_cube[f, i_f, j_f]

        self.fig = fig
        self.ax = ax

        self.rect = Rectangle(
            (self.x, self.y),
            width=1,
            height=1,
            facecolor=self.color,
            linewidth=2,
            edgecolor='k',
            picker=True
        )

        self.patch = self.ax.add_patch(self.rect)

        self.active = False
        clicker = self.fig.canvas.mpl_connect(
            'button_press_event', lambda e: self.onclick(e))
        presser = self.fig.canvas.mpl_connect(
            'key_press_event', lambda e: self.keypress(e))

    def onclick(self, event):
        # Was the click on the same axis as the rectangle?
        if event.inaxes != self.rect.axes:
            self.active = False
            return

        # Was the click inside the rectangle?
        contains, attrd = self.rect.contains(event)
        if not contains:
            self.active = False
            return

        # Only concerned with double click events
        if event.dblclick:
            # Set active
            self.active = True

    def keypress(self, event):
        if not self.active:
            return

        elif event.key in ['w', 'W']:
            self.color = 'white'
        elif event.key in ['o', 'O']:
            self.color = 'orange'
        elif event.key in ['r', 'R']:
            self.color = 'red'
        elif event.key in ['g', 'G']:
            self.color = 'green'
        elif event.key in ['b', 'B']:
            self.color = 'blue'
        elif event.key in ['y', 'Y']:
            self.color = 'yellow'
        elif event.key == 'enter':
            self.active = False

        self.colors_cube[self.f, self.i_f, self.j_f] = self.color

        self.patch.set_facecolor(self.color)
        self.fig.canvas.draw()