Ejemplo n.º 1
0
def test_Polygon_close():
    #: Github issue #1018 identified a bug in the Polygon handling
    #: of the closed attribute; the path was not getting closed
    #: when set_xy was used to set the vertices.

    # open set of vertices:
    xy = [[0, 0], [0, 1], [1, 1]]
    # closed set:
    xyclosed = xy + [[0, 0]]

    # start with open path and close it:
    p = Polygon(xy, closed=True)
    assert_array_equal(p.get_xy(), xyclosed)
    p.set_xy(xy)
    assert_array_equal(p.get_xy(), xyclosed)

    # start with closed path and open it:
    p = Polygon(xyclosed, closed=False)
    assert_array_equal(p.get_xy(), xy)
    p.set_xy(xyclosed)
    assert_array_equal(p.get_xy(), xy)

    # start with open path and leave it open:
    p = Polygon(xy, closed=False)
    assert_array_equal(p.get_xy(), xy)
    p.set_xy(xy)
    assert_array_equal(p.get_xy(), xy)

    # start with closed path and leave it closed:
    p = Polygon(xyclosed, closed=True)
    assert_array_equal(p.get_xy(), xyclosed)
    p.set_xy(xyclosed)
    assert_array_equal(p.get_xy(), xyclosed)
Ejemplo n.º 2
0
def test_Polygon_close():
    #: Github issue #1018 identified a bug in the Polygon handling
    #: of the closed attribute; the path was not getting closed
    #: when set_xy was used to set the vertices.

    # open set of vertices:
    xy = [[0, 0], [0, 1], [1, 1]]
    # closed set:
    xyclosed = xy + [[0, 0]]

    # start with open path and close it:
    p = Polygon(xy, closed=True)
    assert_array_equal(p.get_xy(), xyclosed)
    p.set_xy(xy)
    assert_array_equal(p.get_xy(), xyclosed)

    # start with closed path and open it:
    p = Polygon(xyclosed, closed=False)
    assert_array_equal(p.get_xy(), xy)
    p.set_xy(xyclosed)
    assert_array_equal(p.get_xy(), xy)

    # start with open path and leave it open:
    p = Polygon(xy, closed=False)
    assert_array_equal(p.get_xy(), xy)
    p.set_xy(xy)
    assert_array_equal(p.get_xy(), xy)

    # start with closed path and leave it closed:
    p = Polygon(xyclosed, closed=True)
    assert_array_equal(p.get_xy(), xyclosed)
    p.set_xy(xyclosed)
    assert_array_equal(p.get_xy(), xyclosed)
Ejemplo n.º 3
0
class HighLight():
    def __init__(self):
        self.polygon = Polygon([[0, 0], [0, 0]],
                               facecolor='lightyellow',
                               edgecolor='green',
                               linewidth=2)  # dummy data for xs,ys

    def update_polygon(self, tri):
        if tri == -1:
            points = [(0, 0), (0, 0)]
        else:
            points = draggablePolygon.List[tri].sq.vertices
            # dps[tri].poly.set_edgecolor('green')
            # dps[tri].poly.set_color('red')
        self.polygon.set_xy(zip(*points))
        self.polygon.set_zorder(tri + 1e6)
Ejemplo n.º 4
0
class WidthPolygon(object):
    def __init__(self, ax, x, y, *args, **kwargs):

        self.ax, self.x, self.y = ax, x, y
        self.data = list(zip(x,
                             y))  # [(x[0],y[0])] + zip(x,y) + [(x[-1],y[-1])]

        self.polygon = Polygon(self.data, *args, **kwargs)
        self.ax.add_patch(self.polygon)
        self.continuum, = self.ax.plot([x[0], x[-1]], [y[0], y[-1]],
                                       color='black',
                                       lw=1)

    def set_data(self, x, y):

        self.data = list(zip(x, y))
        self.polygon.set_xy(self.data)
        self.continuum.set_data([[x[0], x[-1]], [y[0], y[-1]]])

    def set_color(self, color):

        self.polygon.set_facecolor(color)

    def set_visible(self, visible):

        self.polygon.set_visible(visible)
        self.continuum.set_visible(visible)

    def __setattr__(self, name, value):

        if name == 'zoom_ignore':

            self.polygon.zoom_ignore = value
            self.continuum.zoom_ignore = value

        else:

            object.__setattr__(self, name, value)

    def delete(self):

        self.ax.patches.remove(self.polygon)
        self.ax.lines.remove(self.continuum)
Ejemplo n.º 5
0
class Polygon(object):

    def __init__(self, ax, xy, **kwargs):
        self._pol = MplPol(xy, kwargs)
        ax.add_patch(self._pol)

    @property
    def xy(self):
        return self._pol.get_xy()

    @xy.setter
    def xy(self, xy):
        self._pol.set_xy(xy)

    def remove(self):
        self._pol.remove()

    def anim_update(self, *args):
        pass
Ejemplo n.º 6
0
class Part:
    def __init__(self, cont, color, parent, alpha=0.8):
        self.parent = parent
        self.pts = cont
        self.poly = Polygon(cont, True, zorder=3, alpha=alpha, color=color)
        self.x = 0.0
        self.y = 0.0
        self.a = 0.0

    @property
    def alpha(self):
        return self.poly.alpha

    @alpha.setter
    def alpha(self, value):
        self.poly.alpha = value

    def move(self, x=0, y=0, a=0):
        R'''
            move part to the pose (x,y,angle) wrt parent
        '''
        self.x = x
        self.y = y
        self.a = a
        self.update()

    def update(self):
        px = self.parent.x
        py = self.parent.y
        pa = self.parent.a
        pR = rotmat(pa)

        wa = pa + self.a
        wx, wy = [px, py] + pR @ [self.x, self.y]

        pts = affine(self.pts, wx, wy, wa)
        self.poly.set_xy(pts)

    def patch():
        return self.poly
Ejemplo n.º 7
0
class Roi(object):
    def __init__(self, xy, name, colour, linewidth=None):
        '''
        A ROI is defined by its vertices (xy coords), a name,
        and a colour.

        Input:

          xy       Coordinates of the ROI as a numpy array of
                   shape (2, N).
          name     Name of the ROI, string.
          colour   Colour definition in any format acceptable
                   to matplotlib, ie named (e.g. 'white') or
                   RGBA format (e,g. (1.0, 1.0, 1.0, 1.0)).
        '''
        super(Roi, self).__init__()
        self.polygon = Polygon(xy, lw=linewidth)
        self.polygon.set_facecolor('none')
        self.name = name
        self.set_colour(colour)

    def set_colour(self, colour):
        self.polygon.set_edgecolor(colour)

    def get_colour(self):
        return self.polygon.get_edgecolor()

    def set_name(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def set_xy(self):
        return self.polygon.set_xy()

    def get_xy(self):
        return self.polygon.get_xy()

    def get_polygon(self):
        return self.polygon
Ejemplo n.º 8
0
Archivo: roi.py Proyecto: glue-viz/glue
class MplPolygonalROI(AbstractMplRoi):
    """
    Matplotlib ROI for polygon selections

    Parameters
    ----------
    axes : `~matplotlib.axes.Axes`
        The Matplotlib axes to draw to.
    roi : `~glue.core.roi.Roi`, optional
        If specified, this ROI will be used and updated, otherwise a new one
        will be created.
    """

    _roi_cls = PolygonalROI

    def __init__(self, axes, roi=None):

        super(MplPolygonalROI, self).__init__(axes, roi=roi)

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

        self._patch = Polygon(np.array(list(zip([0, 1], [0, 1]))), zorder=100)
        self._patch.set_visible(False)
        self._axes.add_patch(self._patch)

    def _sync_patch(self):
        if self._roi.defined():
            x, y = self._roi.to_polygon()
            self._patch.set_xy(list(zip(x + [x[0]],
                                        y + [y[0]])))
            self._patch.set_visible(True)
            self._patch.set(**self.plot_opts)
        else:
            self._patch.set_visible(False)

    def start_selection(self, event, scrubbing=False):

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

        if scrubbing or 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 scrubbing or event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self.reset()
            self._roi.add_point(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(event.xdata - self._cx,
                              event.ydata - self._cy)
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self._roi.add_point(event.xdata, event.ydata)

        self._sync_patch()
        self._draw()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()
Ejemplo n.º 9
0
class BranchMaskCreator(MaskCreator):
    default_radius = 5.

    @MaskCreator.enabled.setter
    def enabled(self, e):
        """Extend the active setter of MaskCreator to also remove any artists if deactivated"""
        # call base class property setter
        MaskCreator.enabled.fset(self, e)
        # handle own derived stuff
        if self.artist is not None:
            self.artist.remove()
            self.artist = None
            self.x, self.y, self.r = [], [], []
            self.update()

    def __init__(self, axes, canvas, update, notify, enabled=False):
        """
            Arguments:
                axes, the axes where the interactive creation takes place
                canvas, the figure canvas, required to connec to signals
                update, a callable which will be called after adding a pixel to the current mask.
                notify, a callable that will get evoked with the coordinates of all pixels of a finished mask.
                enabled, should mask creation be enabled from the begininig (default False)
        """
        self.artist = None
        # container for x,y and radius values
        self.x, self.y, self.r = [], [], []
        super(BranchMaskCreator, self).__init__(axes=axes,
                                                canvas=canvas,
                                                update=update,
                                                notify=notify,
                                                enabled=enabled)

    def onclick(self, event):
        self.x.append(event.xdata)
        self.y.append(event.ydata)
        # reuse last radius for consecutive segments
        if len(self.r) > 0:
            self.r.append(self.r[-1])
        else:
            self.r.append(BranchMaskCreator.default_radius)

        self.__update_artist()

        self.update()

    def __update_artist(self):
        # check if this is the first point of a branch
        if self.artist is None:
            self.artist = Circle([self.x[0], self.y[0]],
                                 radius=self.r[0],
                                 fill=False,
                                 lw=2,
                                 color='red')
            self.axes.add_artist(self.artist)
        elif len(self.x) == 0:
            self.artist.remove()
            self.artist = None
        elif len(self.x) == 1:
            self.artist.remove()
            self.artist = Circle([self.x[0], self.y[0]],
                                 radius=self.r[0],
                                 fill=False,
                                 lw=2,
                                 color='red')
            self.axes.add_artist(self.artist)
        # change from circle to polygon if more than 1 points are available
        elif len(self.x) == 2:
            self.artist.remove()
            branch = Branch(x=self.x,
                            y=self.y,
                            z=[0 for i in self.x],
                            r=self.r)
            self.artist = Polygon(branch.outline,
                                  fill=False,
                                  color='red',
                                  lw=2)
            self.axes.add_artist(self.artist)
        else:
            assert (len(self.x) > 2)
            branch = Branch(x=self.x,
                            y=self.y,
                            z=[0 for i in self.x],
                            r=self.r)
            self.artist.set_xy(branch.outline)

    def onkey(self, event):
        if self.artist is not None:
            if event.key == '+':
                self.r[-1] = self.r[-1] + 1
                self.__update_artist()
                self.update()
            elif event.key == '-':
                self.r[-1] = self.r[-1] - 1
                self.__update_artist()
                self.update()
            elif event.key == 'z':
                print event
                print dir(event)
                self.r = self.r[:-1]
                self.x = self.x[:-1]
                self.y = self.y[:-1]
                self.__update_artist()
                self.update()
            elif event.key == 'enter':
                self.artist.remove()
                self.update()
                self.artist = None
                if len(self.x) == 1:
                    # shift by 0.5 to compensate for pixel offset in imshow
                    mask = CircleMask(
                        center=[self.x[0] + 0.5, self.y[0] + 0.5],
                        radius=self.r[0])
                else:
                    import numpy
                    dtype = [('x', float), ('y', float), ('z', float),
                             ('radius', float)]
                    x = numpy.array(self.x) + 0.5
                    y = numpy.array(self.y) + 0.5
                    z = [0 for i in self.x]
                    r = self.r
                    data = numpy.rec.fromarrays([x, y, z, r], dtype=dtype)
                    # shift by 0.5 to compensate for pixel offset in imshow
                    mask = BranchMask(data=data)
                self.x, self.y, self.r = [], [], []
                self.notify(mask)
                self.enabled = False
Ejemplo n.º 10
0
class MplPolygonalROI(AbstractMplRoi):
    """
    Matplotlib ROI for polygon selections

    Parameters
    ----------
    axes : `~matplotlib.axes.Axes`
        The Matplotlib axes to draw to.
    roi : `~glue.core.roi.Roi`, optional
        If specified, this ROI will be used and updated, otherwise a new one
        will be created.
    """

    _roi_cls = PolygonalROI

    def __init__(self, axes, roi=None):

        super(MplPolygonalROI, self).__init__(axes, roi=roi)

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

        self._patch = Polygon(np.array(list(zip([0, 1], [0, 1]))), zorder=100)
        self._patch.set_visible(False)
        self._axes.add_patch(self._patch)

    def _sync_patch(self):
        if self._roi.defined():
            x, y = self._roi.to_polygon()
            self._patch.set_xy(list(zip(x + [x[0]],
                                        y + [y[0]])))
            self._patch.set_visible(True)
            self._patch.set(**self.plot_opts)
        else:
            self._patch.set_visible(False)

    def start_selection(self, event, scrubbing=False):

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

        if scrubbing or 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 scrubbing or event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self.reset()
            self._roi.add_point(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(event.xdata - self._cx,
                              event.ydata - self._cy)
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self._roi.add_point(event.xdata, event.ydata)

        self._sync_patch()
        self._draw()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._draw()
Ejemplo n.º 11
0
class MplPolygonalROI(AbstractMplRoi):
    """
    Defines and displays polygonal ROIs on matplotlib plots

    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, roi=None):
        """
        :param axes: A matplotlib Axes object to attach the graphical ROI to
        """
        AbstractMplRoi.__init__(self, axes, roi=roi)
        self.plot_opts = {
            'edgecolor': PATCH_COLOR,
            'facecolor': PATCH_COLOR,
            'alpha': 0.3
        }

        self._setup_patch()

    def _setup_patch(self):
        self._patch = Polygon(np.array(list(zip([0, 1], [0, 1]))))
        self._patch.set_zorder(100)
        self._patch.set(**self.plot_opts)
        self._axes.add_patch(self._patch)
        self._patch.set_visible(False)
        self._sync_patch()

    def _roi_factory(self):
        return PolygonalROI()

    def _sync_patch(self):
        # Update geometry
        if not self._roi.defined():
            self._patch.set_visible(False)
        else:
            x, y = self._roi.to_polygon()
            self._patch.set_xy(list(zip(x + [x[0]], y + [y[0]])))
            self._patch.set_visible(True)

        # Update appearance
        self._patch.set(**self.plot_opts)

        # Refresh
        self._axes.figure.canvas.draw()

    def start_selection(self, event, scrubbing=False):

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

        if scrubbing or 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 scrubbing or event.key == SCRUBBING_KEY:
            self._scrubbing = True
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self.reset()
            self._roi.add_point(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(event.xdata - self._cx, event.ydata - self._cy)
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self._roi.add_point(event.xdata, event.ydata)

        self._sync_patch()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._axes.figure.canvas.draw()
Ejemplo n.º 12
0
class PolygonInteractor(QtCore.QObject):
    """
    Polygon Interactor

    Parameters
    ----------
    axtmp : matplotlib axis
        matplotlib axis
    pntxy :

    """
    showverts = True
    epsilon = 5  # max pixel distance to count as a vertex hit
    polyi_changed = QtCore.pyqtSignal(list)

    def __init__(self, axtmp, pntxy):
        QtCore.QObject.__init__(self)
        self.ax = axtmp
        self.poly = Polygon([(1, 1)], animated=True)
        self.ax.add_patch(self.poly)
        self.canvas = self.poly.figure.canvas
        self.poly.set_alpha(0.5)
        self.pntxy = pntxy
        self.ishist = True
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        xtmp, ytmp = list(zip(*self.poly.xy))

        self.line = Line2D(xtmp, ytmp, marker='o', markerfacecolor='r',
                           color='y', animated=True)
        self.ax.add_line(self.line)

        self.poly.add_callback(self.poly_changed)
        self._ind = None  # the active vert

        self.canvas.mpl_connect('button_press_event',
                                self.button_press_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)

    def draw_callback(self):
        """ Draw callback """
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        QtWidgets.QApplication.processEvents()

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.update()

    def new_poly(self, npoly):
        """ New Polygon """
        self.poly.set_xy(npoly)
        self.line.set_data(list(zip(*self.poly.xy)))

        self.canvas.draw()
        self.update_plots()

    def poly_changed(self, poly):
        """ Changed Polygon """
        # this method is called whenever the polygon object is called
        # only copy the artist props to the line (except visibility)
        vis = self.line.get_visible()
        Artist.update_from(self.line, poly)
        self.line.set_visible(vis)  # don't use the poly visibility state

    def get_ind_under_point(self, event):
        """get the index of vertex under point if within epsilon tolerance"""

        # display coords
        xytmp = np.asarray(self.poly.xy)
        xyt = self.poly.get_transform().transform(xytmp)
        xtt, ytt = xyt[:, 0], xyt[:, 1]
        dtt = np.sqrt((xtt - event.x) ** 2 + (ytt - event.y) ** 2)
        indseq = np.nonzero(np.equal(dtt, np.amin(dtt)))[0]
        ind = indseq[0]

        if dtt[ind] >= self.epsilon:
            ind = None

        return ind

    def button_press_callback(self, event):
        """whenever a mouse button is pressed"""
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        self._ind = self.get_ind_under_point(event)

        if self._ind is None:
            xys = self.poly.get_transform().transform(self.poly.xy)
            ptmp = event.x, event.y  # display coords

            if len(xys) == 1:
                self.poly.xy = np.array(
                    [(event.xdata, event.ydata)] +
                    [(event.xdata, event.ydata)])
                self.line.set_data(list(zip(*self.poly.xy)))

                self.canvas.restore_region(self.background)
                self.ax.draw_artist(self.poly)
                self.ax.draw_artist(self.line)
                self.canvas.update()
                return
            dmin = -1
            imin = -1
            for i in range(len(xys) - 1):
                s0tmp = xys[i]
                s1tmp = xys[i + 1]
                dtmp = dist_point_to_segment(ptmp, s0tmp, s1tmp)
                if dmin == -1:
                    dmin = dtmp
                    imin = i
                elif dtmp < dmin:
                    dmin = dtmp
                    imin = i
            i = imin
            self.poly.xy = np.array(list(self.poly.xy[:i + 1]) +
                                    [(event.xdata, event.ydata)] +
                                    list(self.poly.xy[i + 1:]))
            self.line.set_data(list(zip(*self.poly.xy)))

            self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.poly)
            self.ax.draw_artist(self.line)
            self.canvas.update()

    def button_release_callback(self, event):
        """Whenever a mouse button is released"""
        if event.button != 1:
            return
        self._ind = None
        self.update_plots()

    def update_plots(self):
        """ Update Plots """
        polymask = Path(self.poly.xy).contains_points(self.pntxy)
        self.polyi_changed.emit(polymask.tolist())

    def motion_notify_callback(self, event):
        """on mouse movement"""
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        xtmp, ytmp = event.xdata, event.ydata

        self.poly.xy[self._ind] = xtmp, ytmp
        if self._ind == 0:
            self.poly.xy[-1] = xtmp, ytmp

        self.line.set_data(list(zip(*self.poly.xy)))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.update()
Ejemplo n.º 13
0
class Gate(object):
    """Gate class implements gating using Matplotlib animation and events.

    Right click to add vertex.
    Left click and drag vertex to move.
    When vertices >= 3, polygonal gate will display.
    Double click within gate to extract gated events and zoom to gated region.
    """
    def __init__(self, fcm, idxs, ax):
        self.fcm = fcm
        self.idxs = idxs
        ax.scatter(fcm[:, idxs[0]],
                   fcm[:, idxs[1]],
                   s=1,
                   c='b',
                   edgecolors='none')

        self.gate = None
        self.canvas = ax.figure.canvas
        self.ax = ax
        self.vertices = []
        self.poly = None
        self.background = None
        self.t = time.time()
        self.double_click_t = 1.0

        self.cid_press = self.canvas.mpl_connect('button_press_event',
                                                 self.onclick)
        self.cid_draw = self.canvas.mpl_connect('draw_event',
                                                self.update_background)

    def add_vertex(self, vertex):
        # print vertex.center
        self.ax.add_patch(vertex)
        dv = DraggableVertex(vertex, self)
        dv.connect()
        self.vertices.append(dv)
        self.update()

    def update_background(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

    def update(self):
        # print "updating"

        if len(self.vertices) >= 3:
            xy = numpy.array([v.circle.center for v in self.vertices])
            # bug in matplotlib? patch is not closed without this
            xy = numpy.concatenate([xy, [xy[0]]])
            if self.poly is None:
                self.poly = Polygon(xy,
                                    closed=True,
                                    alpha=0.5,
                                    facecolor='pink')
                self.ax.add_patch(self.poly)
            else:
                self.poly.set_xy(xy)

        if self.background is not None:
            self.canvas.restore_region(self.background)
        if self.poly is not None:
            self.ax.draw_artist(self.poly)
        for vertex in self.vertices:
            self.ax.draw_artist(vertex.circle)

        # print ">>>", self.ax.bbox

        self.canvas.blit(self.ax.bbox)

    def onclick(self, event):
        xmin, xmax, unused_ymin, unused_ymax = self.ax.axis()
        w = xmax - xmin

        if event.button == 3:
            vertex = Circle((event.xdata, event.ydata), radius=0.01 * w)
            self.add_vertex(vertex)

        # double left click triggers gating
        xy = numpy.array([v.circle.center for v in self.vertices])
        xypoints = numpy.array([[event.xdata, event.ydata]])

        if self.poly:
            if (event.button == 1 and points_inside_poly(xypoints, xy)):
                if (time.time() - self.t < self.double_click_t):
                    self.zoom_to_gate(event)
                self.t = time.time()

    def zoom_to_gate(self, event):
        xy = numpy.array([v.circle.center for v in self.vertices])
        gate = g(xy, self.idxs)
        gate.gate(self.fcm)
        self.gate = gate
        self.vertices = []
        self.poly = None
        self.ax.patches = []

        # get rid of old points
        del self.ax.collections[0]
        plt.close()

    def disconnect(self):
        'disconnect all the stored connection ids'
        self.canvas.mpl_disconnect(self.cid_press)
        self.canvas.mpl_disconnect(self.cid_draw)
Ejemplo n.º 14
0
Archivo: roi.py Proyecto: saimn/glue
class MplPolygonalROI(AbstractMplRoi):

    """
    Defines and displays polygonal ROIs on matplotlib plots

    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.plot_opts = {'edgecolor': PATCH_COLOR, 'facecolor': PATCH_COLOR,
                          'alpha': 0.3}

        self._setup_patch()

    def _setup_patch(self):
        self._patch = Polygon(np.array(list(zip([0, 1], [0, 1]))))
        self._patch.set_zorder(100)
        self._patch.set(**self.plot_opts)
        self._axes.add_patch(self._patch)
        self._patch.set_visible(False)
        self._sync_patch()

    def _roi_factory(self):
        return PolygonalROI()

    def _sync_patch(self):
        # Update geometry
        if not self._roi.defined():
            self._patch.set_visible(False)
        else:
            x, y = self._roi.to_polygon()
            self._patch.set_xy(list(zip(x + [x[0]],
                                        y + [y[0]])))
            self._patch.set_visible(True)

        # Update appearance
        self._patch.set(**self.plot_opts)

        # Refresh
        self._axes.figure.canvas.draw()

    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._cx = event.xdata
            self._cy = event.ydata
        else:
            self.reset()
            self._roi.add_point(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(event.xdata - self._cx,
                              event.ydata - self._cy)
            self._cx = event.xdata
            self._cy = event.ydata
        else:
            self._roi.add_point(event.xdata, event.ydata)

        self._sync_patch()

    def finalize_selection(self, event):
        self._scrubbing = False
        self._mid_selection = False
        self._patch.set_visible(False)
        self._axes.figure.canvas.draw()
Ejemplo n.º 15
0
class Blaschke3 :
    
    #Metodo para inicializar las variables 
    def __init__(self,ax,fig) :
        self.polygon = []
        self.cont = 0
        self.polygon_exist = False
        self.num_points = 20
        self.touched_circle = False
        self.list_circles = []
        self.ax = ax
        self.fig = fig
        self.cid_press = fig.canvas.mpl_connect('button_press_event', self.on_press)
        self.cid_move = fig.canvas.mpl_connect('motion_notify_event', self.on_move)
        self.cid_release = fig.canvas.mpl_connect('button_release_event', self.on_release)

    #Metodo que se activa cuando se pulsa un punto
    def on_press(self, event):
        #Comprobamos si hemos pulsado en un punto antiguo para moverlo
        for circle in self.list_circles:
            contains, attr = circle.contains(event)
            if contains:
                self.touched_circle = circle
                self.exists_touched_circle = True
                self.pressed_event = event
                self.touched_x0, self.touched_y0 = circle.center
                return
                
        #Limpiamos los ejes y pintamos todos los puntos  
        plt.cla()        
        if self.cont==2:
            self.list_circles.remove(self.list_circles[0])
        c = Circle((event.xdata,event.ydata),0.02)
        ax.add_patch(Circle((0,0),1,color='blue', fill = False))
        self.list_circles.append(c)
        for circle in self.list_circles :
            self.ax.add_patch(circle)
        
        #Guardamos el nuevo punto (borrando el primero si ya habia dos)
        new_point = [event.xdata,event.ydata]
        if not(self.polygon_exist) :
            self.polygon.append(new_point)
            self.P = Polygon(self.polygon, closed = False,color = 'red', fill = False)
            self.polygon_exist = True
        else : 
            if self.cont==2:
                self.polygon.remove(self.polygon[0])
            self.polygon.append(new_point)
        self.P.set_xy(self.polygon)
        self.ax.add_patch(self.P)
        self.fig.canvas.draw()
        
        #Si a1 y a2 se encuentran dentro del disco unidad:
        if self.cont<2:
            self.cont=self.cont+1
        if self.cont==2:
            a1 = self.polygon[0]
            a2 = self.polygon[1]
            if np.linalg.norm(a1)<=1 and np.linalg.norm(a2)<=1:
                self.calculate_Blaschke3(a1,a2)

    #Metodo que se activa cuando se mueve un punto
    def on_move(self,event) : 
        
        if self.touched_circle and self.cont==2:
            dx = event.xdata - self.pressed_event.xdata
            dy = event.ydata - self.pressed_event.ydata
            x0, y0 = self.touched_circle.center
            self.touched_circle.center =  self.touched_x0 + dx, self.touched_y0 + dy
            plt.cla()
            ax.add_patch(Circle((0,0),1,color='blue', fill = False))
            for circle in self.list_circles :
                self.ax.add_patch(circle)
            self.polygon = [circle.center for circle in self.list_circles]
            self.P.set_xy(self.polygon)
            self.ax.add_patch(self.P)
            self.fig.canvas.draw()
            
            if self.cont==2:
                a1 = self.polygon[0]
                a2 = self.polygon[1]
                if np.linalg.norm(a1)<=1 and np.linalg.norm(a2)<=1:
                    self.calculate_Blaschke3(a1,a2)
        
    #Metodo que se activa cuando se suelta un punto
    def on_release(self, event) :
        self.touched_circle = False
    
    #Funcion principal
    def calculate_Blaschke3(self, a1, a2):
        a1 = complex(a1[0],a1[1])
        a2 = complex(a2[0],a2[1])
        t = np.linspace(0,2*np.pi,self.num_points)
        #Para cada punto del disco unidad, calculamos sus tres imagenes inversas        
        for interv in t:
            z = np.exp(interv*1j)
            
            #Resolvemos la ecuacion para calcular las tres raices
            a = 1
            b = -(a1+a2+a1.conjugate()*a2.conjugate()*z)
            c = (a1*a2+a1.conjugate()*z+a2.conjugate()*z)
            d = -z   
            solucion = np.roots([a, b, c, d])
            sol1=complex(solucion[0])
            sol2=complex(solucion[1])
            sol3=complex(solucion[2])
            
            #Dibujamos las 3 rectas
            plane=[]
            plane.append([sol1.real,sol1.imag])
            plane.append([sol2.real,sol2.imag])
            plane.append([sol3.real,sol3.imag])
            Pdraw = Polygon(plane, closed = True,color = 'red', fill = False)
            ax.add_patch(Pdraw)
Ejemplo n.º 16
0
class PlotWidget(FigureCanvas):
    """a QtWidget and FigureCanvasAgg that displays the model plots"""

    def __init__(self, parent=None, name=None, width=5, height=4, dpi=100, bgcolor=None):
        self.fig = Figure(figsize=(width, height), dpi=dpi, facecolor=bgcolor, edgecolor=bgcolor)
        self.axes = self.fig.add_axes([0.125,0.1,0.6,0.8]) #self.fig.add_subplot(111)

        self.have_range = []

        self.axes.set_xlabel('Time (years)')
        self.axes.set_ylabel(
                "Greenhouse Gas \nEmissions/Removals (t CO"+SUB_2+ "e / ha)",
                multialignment='center')

        self.axes.axhline(y=0.,ls=':',color='k')
        self.axes.text(0, 0,'Emission',va='bottom')
        self.axes.text(0, 0,'Removal',va='top')
        self.emission_patch = None
        self.removal_patch = None
        self.updateShading()

        self.totalsBox = self.fig.text(0.75,0.1,"")

        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)

        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        self.updateGeometry()

        self.plots = {}
        self.totals = {}

    def addPlot(self,data,plotID,name):
        # No support for ranges (uncertainties) yet
        plots = []
        plots += self.axes.plot(
                np.array(range(len(data)))+1, # to make it start at year 1
                data,color=COLOURS[plotID],label=name)
        totals = (name,np.sum(data))

        self.axes.autoscale(enable=True)
        self.axes.relim()
        self.plots[plotID] = plots
        self.totals[plotID] = totals
        self.updateLegend()
        self.updateTotals()
        self.updateShading()
        self.draw()

    def updateShading(self):
        # update vertical limits
        xlim = self.axes.get_xlim()
        ylim = self.axes.get_ylim()
        ylim = (min(ylim[0],-1),max(ylim[1],1))
        self.axes.set_ylim(ylim)
        upper = [(xlim[0],0),(xlim[1],0),(xlim[1],ylim[1]),(xlim[0],ylim[1])]
        lower = [(xlim[0],ylim[0]),(xlim[1],ylim[0]),(xlim[1],0),(xlim[0],0)]
        # shade positive and negative values
        if self.emission_patch == None:
            self.emission_patch = Polygon(
                    upper, facecolor='r', alpha=0.25, fill=True,
                    edgecolor=None, zorder=-1000)
            self.axes.add_patch(self.emission_patch)
        else:
            self.emission_patch.set_xy(upper)
        if self.removal_patch == None:
            self.removal_patch = Polygon(
                    lower, facecolor='b', alpha=0.25, fill=True,
                    edgecolor=None, zorder=-1000)
            self.axes.add_patch(self.removal_patch)
        else:
            self.removal_patch.set_xy(lower)
        #self.removal_patch = None


    def updateTotals(self):
        # No support for ranges (yet)
        # get model names (as keys)
        models = {}
        for c in self.totals:
            models[self.totals[c][0]] = self.totals[c][1:]
        ms = sorted(models.keys())
        
        years =  self.axes.dataLim.get_points()[1,0]
        outstr = "Total Emissions/Removals\nover %d years " % cfg.N_ACCT
        outstr += "(t CO"+SUB_2+"e / ha):\n"
        for m in ms:
            outstr += '%s: %.1f\n' % (m, models[m][0])
        
        # Figure out total of project - baseline for each project
        if len(self.totals)>1 and 0 in self.totals:
            outstr+="\nNet impact (t CO"+SUB_2+"e / ha):\n"
            for c in self.totals:
                if c == 0: 
                    continue
                outstr += "%s: %.1f\n" % (
                        self.totals[c][0],
                        self.totals[c][1]-self.totals[0][1])

        self.totalsBox.set_text(outstr)

    def removePlot(self,plotID):
        if plotID in self.plots:
            for p in self.plots[plotID]:
                p.remove()
            self.draw()
            del self.totals[plotID]
            del self.plots[plotID]
            if plotID in self.have_range:
                self.have_range.remove(plotID)
            self.updateLegend()
            self.updateTotals()
        

    def updateLegend(self):
        if len(self.plots.keys())>0:
            handles, labels = self.axes.get_legend_handles_labels()
            if len(self.have_range) > 0:
                l = Line2D([0,1],[0,1],linestyle="--",color='k')
                handles.append(l)
                labels.append("range")
            self.axes.legend(handles,labels,bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
        else:
            self.axes.legend_ = None

    def saveFigure(self,fname):
        self.fig.savefig(fname)
                

    def sizeHint(self):
        w = self.fig.get_figwidth()
        h = self.fig.get_figheight()
        return QtCore.QSize(w, h)

    def minimumSizeHint(self):
        return QtCore.QSize(10, 10)
Ejemplo n.º 17
0
class FieldAnimation(FieldPlotter):
    def __init__(self,
                 fields,
                 ax=None,
                 dates=None,
                 facecolors=None,
                 alphas=None,
                 edgecolors=None,
                 inclcax=False):
        """ """
        super().__init__(ax=ax, inclcax=inclcax)

        self.set_fields(fields)
        self.set_dates(dates)
        self.set_properties(facecolors=facecolors,
                            alphas=alphas,
                            edgecolors=edgecolors)

    # ================= #
    #   Methods         #
    # ================= #
    def set_dates(self, dates):
        """ """
        self._dates = np.atleast_1d(dates) if dates is not None else None

    def set_fields(self, fields):
        """ """
        self._fields = fields
        self._unique_fields = np.unique(self._fields)
        self._field_vertices = {
            i: v
            for i, v in zip(self._unique_fields,
                            self.get_field_vertices(self._unique_fields))
        }

    def set_properties(self, facecolors=None, edgecolors=None, alphas=None):
        """ """
        self._display_prop = {}
        self._set_prop_("facecolor", facecolors, "0.7")
        self._set_prop_("edgecolor", edgecolors, "None")
        self._set_prop_("alpha", alphas, 1)

    def _set_prop_(self, key, value, default=None):
        """ """
        if not hasattr(self, "_display_prop"):
            self._display_prop = {}

        if value is None:
            value = default

        if len(np.atleast_1d(value)) == 1:
            self.display_prop[key] = np.atleast_1d(value)
            self.display_prop[f"unique_{key}"] = True
        else:
            self.display_prop[key] = value
            self.display_prop[f"unique_{key}"] = False

    # ---------- #
    #  SETUP     #
    # ---------- #
    def reset(self):
        """ """
        self.intpoly_ = Polygon(self.field_vertices[self.fields[0]],
                                facecolor=self.display_prop["facecolor"][0],
                                edgecolor=self.display_prop["edgecolor"][0],
                                alpha=self.display_prop["alpha"][0])

        if self._dates is not None:
            self.inttext_ = self.fig.text(0.01,
                                          0.99,
                                          self._dates[0],
                                          va="top",
                                          ha="left",
                                          weight="bold")

        p_ = self.ax.add_patch(self.intpoly_)
        return self.intpoly_

    # ---------- #
    #  Animate   #
    # ---------- #
    def update_field_to(self, i):
        """ """
        try:
            self.intpoly_.set_xy(self.field_vertices[self.fields[i]])
            if self.dates is not None and len(self.dates) > 1:
                self.inttext_.set_text(self.dates[i])
        except:
            print(f"FAILES for i={i}")

        for key in ["facecolor", "edgecolor", "alpha"]:
            if not self.display_prop[f"unique_{key}"]:
                getattr(self.intpoly_, f"set_{key}")(self.display_prop[key][i])

        return self.intpoly_

    def launch(self, interval=5, repeat=False, blit=True, savefile=None):
        """ """
        from matplotlib import animation
        self.anim = animation.FuncAnimation(self.fig,
                                            self.update_field_to,
                                            init_func=self.reset,
                                            frames=self.nfields,
                                            interval=interval,
                                            repeat=repeat,
                                            blit=blit)

    # ================= #
    #   Properties      #
    # ================= #
    @property
    def fields(self):
        """ Fields that should be shown """
        return self._fields

    @property
    def dates(self):
        """ Observation dates if any """
        return self._dates

    @property
    def nfields(self):
        """ size of self.fields """
        return len(self.fields)

    @property
    def field_vertices(self):
        """ vertices of the fields """
        return self._field_vertices

    @property
    def display_prop(self):
        """ """
        return self._display_prop
Ejemplo n.º 18
0
class PolygonInteractor(QtCore.QObject):
    """
    Polygon Interactor

    Parameters
    ----------
    axtmp : matplotlib axis
        matplotlib axis
    pntxy :

    """
    showverts = True
    epsilon = 5  # max pixel distance to count as a vertex hit
    polyi_changed = QtCore.pyqtSignal(list)

    def __init__(self, axtmp, pntxy):
        QtCore.QObject.__init__(self)
        self.ax = axtmp
        self.poly = Polygon([(1, 1)], animated=True)
        self.ax.add_patch(self.poly)
        self.canvas = self.poly.figure.canvas
        self.poly.set_alpha(0.5)
        self.pntxy = pntxy
        self.ishist = True
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

        xtmp, ytmp = list(zip(*self.poly.xy))

        self.line = Line2D(xtmp, ytmp, marker='o', markerfacecolor='r',
                           color='y', animated=True)
        self.ax.add_line(self.line)

        self.poly.add_callback(self.poly_changed)
        self._ind = None  # the active vert

        self.canvas.mpl_connect('button_press_event',
                                self.button_press_callback)
        self.canvas.mpl_connect('button_release_event',
                                self.button_release_callback)
        self.canvas.mpl_connect('motion_notify_event',
                                self.motion_notify_callback)

    def draw_callback(self):
        """ Draw callback """
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        QtWidgets.QApplication.processEvents()

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.update()

    def new_poly(self, npoly):
        """ New Polygon """
        self.poly.set_xy(npoly)
        self.line.set_data(list(zip(*self.poly.xy)))

        self.canvas.draw()
        self.update_plots()

    def poly_changed(self, poly):
        """ Changed Polygon """
        # this method is called whenever the polygon object is called
        # only copy the artist props to the line (except visibility)
        vis = self.line.get_visible()
        Artist.update_from(self.line, poly)
        self.line.set_visible(vis)  # don't use the poly visibility state

    def get_ind_under_point(self, event):
        """get the index of vertex under point if within epsilon tolerance"""

        # display coords
        xytmp = np.asarray(self.poly.xy)
        xyt = self.poly.get_transform().transform(xytmp)
        xtt, ytt = xyt[:, 0], xyt[:, 1]
        dtt = np.sqrt((xtt - event.x) ** 2 + (ytt - event.y) ** 2)
        indseq = np.nonzero(np.equal(dtt, np.amin(dtt)))[0]
        ind = indseq[0]

        if dtt[ind] >= self.epsilon:
            ind = None

        return ind

    def button_press_callback(self, event):
        """whenever a mouse button is pressed"""
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        self._ind = self.get_ind_under_point(event)

        if self._ind is None:
            xys = self.poly.get_transform().transform(self.poly.xy)
            ptmp = self.poly.get_transform().transform([event.xdata, event.ydata])
#            ptmp = event.x, event.y  # display coords

            if len(xys) == 1:
                self.poly.xy = np.array(
                    [(event.xdata, event.ydata)] +
                    [(event.xdata, event.ydata)])
                self.line.set_data(list(zip(*self.poly.xy)))

                self.canvas.restore_region(self.background)
                self.ax.draw_artist(self.poly)
                self.ax.draw_artist(self.line)
                self.canvas.update()
                return
            dmin = -1
            imin = -1
            for i in range(len(xys) - 1):
                s0tmp = xys[i]
                s1tmp = xys[i + 1]
                dtmp = dist_point_to_segment(ptmp, s0tmp, s1tmp)

                if dmin == -1:
                    dmin = dtmp
                    imin = i
                elif dtmp < dmin:
                    dmin = dtmp
                    imin = i
            i = imin

#            breakpoint()
            self.poly.xy = np.array(list(self.poly.xy[:i + 1]) +
                                    [(event.xdata, event.ydata)] +
                                    list(self.poly.xy[i + 1:]))
            self.line.set_data(list(zip(*self.poly.xy)))

            self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.poly)
            self.ax.draw_artist(self.line)
            self.canvas.update()

    def button_release_callback(self, event):
        """Whenever a mouse button is released"""
        if event.button != 1:
            return
        self._ind = None
        self.update_plots()

    def update_plots(self):
        """ Update Plots """
        polymask = Path(self.poly.xy).contains_points(self.pntxy)
        self.polyi_changed.emit(polymask.tolist())

    def motion_notify_callback(self, event):
        """on mouse movement"""
        if self._ind is None:
            return
        if event.inaxes is None:
            return
        if event.button != 1:
            return
        xtmp, ytmp = event.xdata, event.ydata

        self.poly.xy[self._ind] = xtmp, ytmp
        if self._ind == 0:
            self.poly.xy[-1] = xtmp, ytmp

        self.line.set_data(list(zip(*self.poly.xy)))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.poly)
        self.ax.draw_artist(self.line)
        self.canvas.update()
Ejemplo n.º 19
0
        # read robot orientation
        returnCode, orientation = vrep.simxGetObjectOrientation(
            clientID, robotHandle, stageHandle, vrep.simx_opmode_buffer)
        if returnCode == vrep.simx_error_noerror:
            (_, _, angle) = orientation
            robot.update_angle(angle)

        # read depth data
        returnCode, resolution, data = vrep.simxGetVisionSensorDepthBuffer(
            clientID, sensorHandle, vrep.simx_opmode_buffer)
        if returnCode == vrep.simx_error_noerror:
            # get positions from rays
            walls = robot.gen_wall_position(data, stageWidth, stageHeight)
            if len(walls) == 0:
                continue
            robotVisionToken.set_xy(list(map(grid.position, walls)))

            # update grid
            grid.update_grid(walls, sensorRange)

        # update image
        grid.draw()

        # update motion panning state
        motion.update()

        # delay time
        time.sleep(0.05)

except KeyboardInterrupt:
    print("KeyBoardInterrupt")
Ejemplo n.º 20
0
class Gate(object):
    """Gate class implements gating using Matplotlib animation and events.

    Right click to add vertex.
    Left click and drag vertex to move.
    When vertices >= 3, polygonal gate will display.
    Double click within gate to extract gated events and zoom to gated region.
    """

    def __init__(self, fcm, idxs, ax):
        self.fcm = fcm
        self.idxs = idxs
        ax.scatter(fcm[:, idxs[0]], fcm[:, idxs[1]],
                   s=1, c='b', edgecolors='none')

        self.gate = None
        self.canvas = ax.figure.canvas
        self.ax = ax
        self.vertices = []
        self.poly = None
        self.background = None
        self.t = time.time()
        self.double_click_t = 1.0

        self.cid_press = self.canvas.mpl_connect(
            'button_press_event', self.onclick)
        self.cid_draw = self.canvas.mpl_connect(
            'draw_event', self.update_background)

    def add_vertex(self, vertex):
        # print vertex.center
        self.ax.add_patch(vertex)
        dv = DraggableVertex(vertex, self)
        dv.connect()
        self.vertices.append(dv)
        self.update()

    def update_background(self, event):
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)

    def update(self):
        # print "updating"

        if len(self.vertices) >= 3:
            xy = numpy.array([v.circle.center for v in self.vertices])
            # bug in matplotlib? patch is not closed without this
            xy = numpy.concatenate([xy, [xy[0]]])
            if self.poly is None:
                self.poly = Polygon(xy, closed=True, alpha=0.5,
                                    facecolor='pink')
                self.ax.add_patch(self.poly)
            else:
                self.poly.set_xy(xy)

        if self.background is not None:
            self.canvas.restore_region(self.background)
        if self.poly is not None:
            self.ax.draw_artist(self.poly)
        for vertex in self.vertices:
            self.ax.draw_artist(vertex.circle)

        # print ">>>", self.ax.bbox

        self.canvas.blit(self.ax.bbox)

    def onclick(self, event):
        xmin, xmax, unused_ymin, unused_ymax = self.ax.axis()
        w = xmax - xmin

        if event.button == 3:
            vertex = Circle((event.xdata, event.ydata), radius=0.01 * w)
            self.add_vertex(vertex)

        # double left click triggers gating
        xy = numpy.array([v.circle.center for v in self.vertices])
        xypoints = numpy.array([[event.xdata, event.ydata]])

        if self.poly:
            if (event.button == 1 and
                points_inside_poly(xypoints, xy)):
                if (time.time() - self.t < self.double_click_t):
                    self.zoom_to_gate(event)
                self.t = time.time()

    def zoom_to_gate(self, event):
        xy = numpy.array([v.circle.center for v in self.vertices])
        gate = g(xy, self.idxs)
        gate.gate(self.fcm)
        self.gate = gate
        self.vertices = []
        self.poly = None
        self.ax.patches = []

        # get rid of old points
        del self.ax.collections[0]
        plt.close()
        
    def disconnect(self):
        'disconnect all the stored connection ids'
        self.canvas.mpl_disconnect(self.cid_press)
        self.canvas.mpl_disconnect(self.cid_draw)
Ejemplo n.º 21
0
class ChannelBody(object):
    '''
    when the channel is avulsed, convert it to a ChannelBody type
    '''
    def __init__(self, channel):
        nState = len(channel.stateList)
        # shapeState = np.shape(channel.stateList)
        stateBoxes = []
        QwList = np.zeros((nState, 1))
        sigList = np.zeros((nState, 1))

        for s, i in zip(iter(channel.stateList), np.arange(nState)):
            stateBoxes.append(self.rect2box(s.ll, s.Bc, s.H)) # different way to do this?
            # instead go straight polygon to union?

            QwList[i] = s.Qw
            sigList[i] = s.sig

        self.y_upper = channel.stateList[-1].y_upper

        self.conversionFlag = "same" # option to select how to convert states to bodies
        if self.conversionFlag == "same":
            # same method for all
            stateSeriesConvexHull = []
            for i, j in zip(stateBoxes[1:], stateBoxes[:-1]):
                seriesUnionTemp = so.cascaded_union([i, j])
                stateSeriesConvexHull.append(seriesUnionTemp.convex_hull)
            stateUnion = so.cascaded_union(stateSeriesConvexHull)
            self.polygonAsArray = np.asarray(stateUnion.exterior)
        elif self.conversionFlag == "diff":
            # different methods for polygon and multipolygon
            stateUnion = so.cascaded_union(stateBoxes) # try so.cascaded_union(stateBoxes[::2]) for speed?
            # if type is polygon
            uniontype = stateUnion.geom_type
            if uniontype == 'Polygon':
                self.polygonAsArray = np.asarray(stateUnion.exterior)
            elif uniontype == 'MultiPolygon':
                stateSeriesConvexHull = []
                for i, j in zip(stateBoxes[1:], stateBoxes[:-1]):
                    seriesUnionTemp = so.cascaded_union([i, j])
                    stateSeriesConvexHull.append(seriesUnionTemp.convex_hull)
                stateUnion = so.cascaded_union(stateSeriesConvexHull)
                self.polygonAsArray = np.asarray(stateUnion.exterior)
        else:
            raise ValueError("invalid conversionFlag in ChannelBody")

        

        self.polygonXs = self.polygonAsArray[:,0]
        self.polygonYs = self.polygonAsArray[:,1]

        self.patch = Polygon(self.polygonAsArray)

        # get all the "means" of variables for coloring values
        self.age = channel.age
        self.Qw = QwList.mean()
        self.avul_num = channel.avul_num
        self.sig = sigList.mean()

    def subside(self, dz):
        # subside method to be called each iteration
        self.polygonYs -= dz
        # self.y_upper = self.polygonYs.max()
        xsys = np.column_stack((self.polygonXs, self.polygonYs))
        self.patch.set_xy(xsys)

    def get_patch(self):
        return self.patch

    def rect2box(self, ll, Bc, H):
        box = sg.box(ll[0], ll[1], 
                     ll[0] + Bc, ll[1] + H)
        return box
Ejemplo n.º 22
0
class CreatePolygon:
    def __init__(self):
        self.circle_list = []
        self.x0 = None
        self.y0 = None
        self.fig = plt.figure()
        self.ax = plt.subplot(111)
        self.ax.set_xlim(-20, 20)
        self.ax.set_ylim(-20, 20)
        self.ax.set_title(
            'Bot' + u'ó' +
            'n izq. para poner puntos y moverlos, derecho para cerrar y terminar'
        )
        self.cidpress = self.fig.canvas.mpl_connect('button_press_event',
                                                    self.on_press)
        self.cidrelease = self.fig.canvas.mpl_connect('button_release_event',
                                                      self.on_release)
        self.cidmove = self.fig.canvas.mpl_connect('motion_notify_event',
                                                   self.on_move)
        self.press_event = None
        self.current_circle = None
        self.points = None
        self.poly = None

    def on_press(self, event):
        if event.button == 3:  #Cerrar y desconectar
            self.poly.set_closed(True)
            self.fig.canvas.draw()
            self.fig.canvas.mpl_disconnect(self.cidpress)
            self.fig.canvas.mpl_disconnect(self.cidrelease)
            self.fig.canvas.mpl_disconnect(self.cidmove)
            self.points = [list(circle.center) for circle in self.circle_list]
            return self.points

        x0, y0 = int(event.xdata), int(event.ydata)
        #Buscamos el circulo que contiene al evento, si lo hay
        for circle in self.circle_list:
            contains, attr = circle.contains(event)
            if contains:
                self.press_event = event
                self.current_circle = circle
                self.x0, self.y0 = self.current_circle.center
                return
        #Si no hemos encontrado ningun circulo:
        c = Circle((x0, y0), 0.5)
        self.ax.add_patch(c)
        self.circle_list.append(c)
        self.current_circle = None
        num_circles = len(self.circle_list)
        if num_circles == 1:
            self.fig.canvas.draw()
        else:
            self.points = [list(circle.center) for circle in self.circle_list]
            if self.poly == None:
                self.poly = Polygon(np.array(self.points),
                                    fill=False,
                                    closed=False)
                self.ax.add_patch(self.poly)
                self.fig.canvas.draw()
            else:
                self.poly.set_xy(np.array(self.points))
                print self.poly.get_xy()
                self.fig.canvas.draw()
                self.fig.canvas.draw()

    def on_release(self, event):
        self.press_event = None
        self.current_circle = None

    def on_move(self, event):
        if (self.press_event is None or event.inaxes != self.press_event.inaxes
                or self.current_circle == None):
            return
        dx = event.xdata - self.press_event.xdata
        dy = event.ydata - self.press_event.ydata
        self.current_circle.center = int(self.x0 + dx), int(self.y0 + dy)
        self.points = [list(circle.center) for circle in self.circle_list]
        self.poly.set_xy(np.array(self.points))
        self.fig.canvas.draw()