예제 #1
0
def axline(ax, slope, intercept, **kwargs):
    '''
    originally described (July '18) in ../pluto/hole_areas.ipynb
    see https://github.com/dstansby/matplotlib/blob/49da75e46ccc4714009b124a58784eaeaea53970/lib/matplotlib/axes/_axes.py
    and
    https://github.com/matplotlib/matplotlib/pull/9321
    '''
    import matplotlib.transforms as mtransforms
    import matplotlib.lines as mlines

    if "transform" in kwargs:
        raise ValueError("'transform' is not allowed as a kwarg; "
                         "axline generates its own transform.")

    xtrans = mtransforms.BboxTransformTo(ax.viewLim)
    viewLimT = mtransforms.TransformedBbox(
        ax.viewLim,
        mtransforms.Affine2D().rotate_deg(90).scale(-1, 1))
    ytrans = (mtransforms.BboxTransformTo(viewLimT) +
              mtransforms.Affine2D().scale(slope).translate(0, intercept))
    trans = mtransforms.blended_transform_factory(xtrans, ytrans)

    line = mlines.Line2D([0, 1], [0, 1],
                         transform=trans + ax.transData,
                         **kwargs)
    ax.add_line(line)
    return line
예제 #2
0
def plot_model(axes, model):
    n = len(model.waveforms)
    offset_step = 1/(n+1)
    plots = []

    text_trans = T.blended_transform_factory(axes.figure.transFigure,
                                             axes.transAxes)


    limits = [(w.y.min(), w.y.max()) for w in model.waveforms]
    base_scale = np.mean(np.abs(np.array(limits)))

    bscale_in_box = T.Bbox([[0, -base_scale], [1, base_scale]])
    bscale_out_box = T.Bbox([[0, -1], [1, 1]])
    bscale_in = T.BboxTransformFrom(bscale_in_box)
    bscale_out = T.BboxTransformTo(bscale_out_box)

    tscale_in_box = T.Bbox([[0, -1], [1, 1]])
    tscale_out_box = T.Bbox([[0, 0], [1, offset_step]])
    tscale_in = T.BboxTransformFrom(tscale_in_box)
    tscale_out = T.BboxTransformTo(tscale_out_box)

    boxes = {
        'tscale': tscale_in_box,
        'tnorm': [],
        'norm_limits': limits/base_scale,
    }

    for i, waveform in enumerate(model.waveforms):
        y_min, y_max = waveform.y.min(), waveform.y.max()
        tnorm_in_box = T.Bbox([[0, -1], [1, 1]])
        tnorm_out_box = T.Bbox([[0, -1], [1, 1]])
        tnorm_in = T.BboxTransformFrom(tnorm_in_box)
        tnorm_out = T.BboxTransformTo(tnorm_out_box)
        boxes['tnorm'].append(tnorm_in_box)

        offset = offset_step * i + offset_step * 0.5
        translate = T.Affine2D().translate(0, offset)

        y_trans = bscale_in + bscale_out + \
            tnorm_in + tnorm_out + \
            tscale_in + tscale_out + \
            translate + axes.transAxes
        trans = T.blended_transform_factory(axes.transData, y_trans)

        plot = WaveformPlot(waveform, axes, trans)
        plots.append(plot)

        text_trans = T.blended_transform_factory(axes.transAxes, y_trans)
        axes.text(-0.05, 0, f'{waveform.level}', transform=text_trans)

    axes.set_yticks([])
    axes.grid()
    for spine in ('top', 'left', 'right'):
        axes.spines[spine].set_visible(False)

    return plots, boxes
예제 #3
0
def _coords2index(im, x, y, inverted=False):
    """
    Converts data coordinates to index coordinates of the array.

    Parameters
    -----------
    im : An AxesImage instance
        The image artist to operation on
    x : number
        The x-coordinate in data coordinates.
    y : number
        The y-coordinate in data coordinates.
    inverted : bool, optional
        If True, convert index to data coordinates instead of data coordinates
        to index.

    Returns
    --------
    i, j : Index coordinates of the array associated with the image.
    """
    xmin, xmax, ymin, ymax = im.get_extent()
    if im.origin == 'upper':
        ymin, ymax = ymax, ymin
    data_extent = mtransforms.Bbox([[ymin, xmin], [ymax, xmax]])
    array_extent = mtransforms.Bbox([[0, 0], im.get_array().shape[:2]])
    trans = mtransforms.BboxTransformFrom(data_extent) +\
            mtransforms.BboxTransformTo(array_extent)

    if inverted:
        trans = trans.inverted()

    return trans.transform_point([y, x]).astype(int)
예제 #4
0
def axline(ax, slope, intercept, **kwargs):
    if "transform" in kwargs:
        raise ValueError("'transform' is not allowed as a kwarg; "
                         "axline generates its own transform.")

    xtrans = mtransforms.BboxTransformTo(ax.viewLim)
    viewLimT = mtransforms.TransformedBbox(
        ax.viewLim,
        mtransforms.Affine2D().rotate_deg(90).scale(-1, 1))
    ytrans = (mtransforms.BboxTransformTo(viewLimT) +
              mtransforms.Affine2D().scale(slope).translate(0, intercept))
    trans = mtransforms.blended_transform_factory(xtrans, ytrans)

    l = mlines.Line2D([0, 1], [0, 1], transform=trans + ax.transData, **kwargs)
    ax.add_line(l)
    return l
예제 #5
0
 def _update_patch_transform(self):
     x = self.convert_xunits(self._x)
     y = self.convert_yunits(self._y)
     width = self.convert_xunits(self._width)
     height = self.convert_yunits(self._height)
     bbox = transforms.Bbox.from_bounds(x, y, width, height)
     self._rect_transform = transforms.BboxTransformTo(bbox)
예제 #6
0
def coords2index(im, x, y):
    """
    This function is modified from here:
    https://github.com/joferkington/mpldatacursor/blob/7dabc589ed02c35ac5d89de5931f91e0323aa795/mpldatacursor/pick_info.py#L28

    Converts data coordinates to index coordinates of the array.

    Parameters
    -----------
    im : An AxesImage instance
        The image artist to operate on
    x : number
        The x-coordinate in data coordinates.
    y : number
        The y-coordinate in data coordinates.

    Returns
    --------
    i, j : Index coordinates of the array associated with the image.
    """
    xmin, xmax, ymin, ymax = im.get_extent()
    if im.origin == 'upper':
        ymin, ymax = ymax, ymin
    data_extent = mtransforms.Bbox([[ymin, xmin], [ymax, xmax]])
    array_extent = mtransforms.Bbox([[0, 0], im.get_array().shape[:2]])
    trans = (mtransforms.BboxTransformFrom(data_extent) +
             mtransforms.BboxTransformTo(array_extent))

    return trans.transform_point([y, x]).astype(int)
예제 #7
0
    def _set_lim_and_transforms(self):
        """
        Override transform initialization
        """

        # axis coords to display coords
        self.transAxes = transforms.BboxTransformTo(self.bbox)

        # X and Y axis scaling
        self.transScale = transforms.TransformWrapper(
            transforms.IdentityTransform())
        # transform from given Bbox to unit Bbox
        # the given transformedBbox is updated every time the
        # viewLim changes or the transScale changes
        self.transLimits = transforms.BboxTransformFrom(
            transforms.TransformedBbox(self.viewLim, self.transScale))

        # data to display coordinates
        self.transData = self.transScale + (self.transLimits + self.transAxes)

        # blended transforms for xaxis and yaxis
        self._xaxis_transform = transforms.blended_transform_factory(
            self.transData, self.transAxes)
        self._yaxis_transform = transforms.blended_transform_factory(
            self.transAxes, self.transData)
def _update_patch_transfrom_about_center(self):
    x = self.convert_xunits(self._x0)
    y = self.convert_yunits(self._y0)
    width = self.convert_xunits(self._width)
    height = self.convert_yunits(self._height)
    bbox = transforms.Bbox.from_bounds(x, y, width, height)
    rot_trans = transforms.Affine2D()
    rot_trans.rotate_deg_around(x + 0.5 * width, y + 0.5 * height, self.angle)
    self._rect_transform = transforms.BboxTransformTo(bbox)
    self._rect_transform += rot_trans
예제 #9
0
파일: plots.py 프로젝트: samiroid/TADAT
def axaline(m, y0, ax=None, **kwargs):
    if not ax:
        ax = plt.gca()
    tr = mtransforms.BboxTransformTo(
            mtransforms.TransformedBbox(ax.viewLim, ax.transScale))  + \
         ax.transScale.inverted()
    aff = mtransforms.Affine2D.from_values(1, m, 0, 0, 0, y0)
    trinv = ax.transData
    line = plt.Line2D([0, 1], [0, 0], transform=tr + aff + trinv, **kwargs)
    ax.add_line(line)
예제 #10
0
 def _set_transform(self):
     if self.coord == 'data':
         self.set_transform(self.Q.ax.transData)
     elif self.coord == 'axes':
         self.set_transform(self.Q.ax.transAxes)
     elif self.coord == 'figure':
         self.set_transform(self.Q.ax.figure.transFigure)
     elif self.coord == 'inches':
         dx = ax.figure.dpi
         bb = transforms.Bbox.from_extents(0, 0, dx, dy)
         trans = transforms.BboxTransformTo(bb)
         self.set_transform(trans)
     else:
         raise ValueError('unrecognized coordinates')
예제 #11
0
 def _coords2index(im, x, y):
     """
     Convert data coordinates to index coordinates of the image array.
     Credit: mpldatacursor developers. Copyright (c) 2012. BSD License
     Modified from original found at:
     https://github.com/joferkington/mpldatacursor/blob/master/mpldatacursor/pick_info.py
     """
     xmin, xmax, ymin, ymax = im.get_extent()
     if im.origin == 'upper':
         ymin, ymax = ymax, ymin
     im_shape = im.get_array().shape[:2]
     data_extent = mtransforms.Bbox([[ymin, xmin], [ymax, xmax]])
     array_extent = mtransforms.Bbox([[0, 0], im_shape])
     trans = (mtransforms.BboxTransformFrom(data_extent) +
              mtransforms.BboxTransformTo(array_extent))
     j, i = trans.transform_point([y, x]).astype(int)
     # Clip the coordinates to the array bounds.
     return min(max(j, 0), im_shape[0] - 1), min(max(i, 0), im_shape[1] - 1)
예제 #12
0
    def _set_lim_and_transforms(self):
        self.transProjection = self._get_core_transform(self.RESOLUTION)

        self.transAffine = self._get_affine_transform()

        self.transAxes = mtransforms.BboxTransformTo(self.bbox)

        # The complete data transformation stack -- from data all the
        # way to display coordinates
        self.transData = self.transProjection + self.transAffine + self.transAxes

        # This is the transform for longitude ticks.
        self._xaxis_pretransform = (
            mtransforms.Affine2D()
            .scale(1, self._longitude_cap * 2)
            .translate(0, -self._longitude_cap)
        )
        self._xaxis_transform = self._xaxis_pretransform + self.transData
        self._xaxis_text1_transform = (
            mtransforms.Affine2D().scale(1, 0)
            + self.transData
            + mtransforms.Affine2D().translate(0, 4)
        )
        self._xaxis_text2_transform = (
            mtransforms.Affine2D().scale(1, 0)
            + self.transData
            + mtransforms.Affine2D().translate(0, -4)
        )

        # This is the transform for latitude ticks.
        yaxis_stretch = mtransforms.Affine2D().scale(1, 1)
        yaxis_space = mtransforms.Affine2D().scale(1, 1.1)
        self._yaxis_transform = yaxis_stretch + self.transData
        yaxis_text_base = (
            yaxis_stretch
            + self.transProjection
            + (yaxis_space + self.transAffine + self.transAxes)
        )
        self._yaxis_text1_transform = yaxis_text_base + mtransforms.Affine2D().translate(
            -8, 0
        )
        self._yaxis_text2_transform = yaxis_text_base + mtransforms.Affine2D().translate(
            8, 0
        )
예제 #13
0
        def visitor(y, x, value):
            color = value[:3] / value[3]
            radius = numpy.sqrt(value[3] / value[4])

            tx, ty = transform.transform_point((x, y))

            #print tx, ty, radius

            #mypath = path.Path(numpy.array([
            #    [ tx-radius, ty-radius ],
            #    [ tx+radius, ty-radius ],
            #    [ tx+radius, ty+radius ],
            #    [ tx-radius, ty+radius ],
            #    [ tx-radius, ty-radius ],
            #]))

            rtrans = transforms.BboxTransformTo(
                transforms.Bbox.from_bounds(tx, ty, radius, radius))
            #tpath = rtrans.transform_path(upath)

            renderer.draw_path(gc, marker_path, rtrans, tuple(color))
예제 #14
0
def _coords2index(im, x, y):
    """
    Converts data coordinates to index coordinates of the array.

    Parameters
    -----------
    im : A matplotlib image artist.
    x : The x-coordinate in data coordinates.
    y : The y-coordinate in data coordinates.

    Returns
    --------
    i, j : Index coordinates of the array associated with the image.
    """
    xmin, xmax, ymin, ymax = im.get_extent()
    if im.origin == 'upper':
        ymin, ymax = ymax, ymin
    data_extent = mtransforms.Bbox([[ymin, xmin], [ymax, xmax]])
    array_extent = mtransforms.Bbox([[0, 0], im.get_array().shape[:2]])
    trans = mtransforms.BboxTransformFrom(data_extent) +\
            mtransforms.BboxTransformTo(array_extent)
    return trans.transform_point([y, x]).astype(int)
예제 #15
0
    def _set_lim_and_transforms(self):
        # A view limit where the minimum radius can be locked if the user
        # specifies an alternate origin.
        self._originViewLim = mtransforms.LockableBbox(self.viewLim)

        # Handle angular offset and direction.
        self._direction = mtransforms.Affine2D() \
            .scale(self._default_theta_direction, 1.0)
        self._theta_offset = mtransforms.Affine2D() \
            .translate(self._default_theta_offset, 0.0)
        self.transShift = self._direction + self._theta_offset
        # A view limit shifted to the correct location after accounting for
        # orientation and offset.
        self._realViewLim = mtransforms.TransformedBbox(
            self.viewLim, self.transShift)

        # Transforms the x and y axis separately by a scale factor
        # It is assumed that this part will have non-linear components
        self.transScale = mtransforms.TransformWrapper(
            mtransforms.IdentityTransform())

        # Scale view limit into a bbox around the selected wedge. This may be
        # smaller than the usual unit axes rectangle if not plotting the full
        # circle.
        self.axesLim = _WedgeBbox((0.5, 0.5), self._realViewLim,
                                  self._originViewLim)

        # Scale the wedge to fill the axes.
        self.transWedge = mtransforms.BboxTransformFrom(self.axesLim)

        # Scale the axes to fill the figure.
        self.transAxes = mtransforms.BboxTransformTo(self.bbox)

        # A (possibly non-linear) projection on the (already scaled)
        # data.  This one is aware of rmin
        self.transProjection = self.PolarTransform(
            self, _apply_theta_transforms=False)
        # Add dependency on rorigin.
        self.transProjection.set_children(self._originViewLim)

        # An affine transformation on the data, generally to limit the
        # range of the axes
        self.transProjectionAffine = self.PolarAffine(self.transScale,
                                                      self._originViewLim)

        # The complete data transformation stack -- from data all the
        # way to display coordinates
        self.transData = (
            self.transScale + self.transShift + self.transProjection +
            (self.transProjectionAffine + self.transWedge + self.transAxes))

        # This is the transform for theta-axis ticks.  It is
        # equivalent to transData, except it always puts r == 0.0 and r == 1.0
        # at the edge of the axis circles.
        self._xaxis_transform = (mtransforms.blended_transform_factory(
            mtransforms.IdentityTransform(),
            mtransforms.BboxTransformTo(self.viewLim)) + self.transData)
        # The theta labels are flipped along the radius, so that text 1 is on
        # the outside by default. This should work the same as before.
        flipr_transform = mtransforms.Affine2D() \
            .translate(0.0, -0.5) \
            .scale(1.0, -1.0) \
            .translate(0.0, 0.5)
        self._xaxis_text_transform = flipr_transform + self._xaxis_transform

        # This is the transform for r-axis ticks.  It scales the theta
        # axis so the gridlines from 0.0 to 1.0, now go from thetamin to
        # thetamax.
        self._yaxis_transform = (mtransforms.blended_transform_factory(
            mtransforms.BboxTransformTo(self.viewLim),
            mtransforms.IdentityTransform()) + self.transData)
        # The r-axis labels are put at an angle and padded in the r-direction
        self._r_label_position = mtransforms.Affine2D() \
            .translate(self._default_rlabel_position, 0.0)
        self._yaxis_text_transform = mtransforms.TransformWrapper(
            self._r_label_position + self.transData)
예제 #16
0
def plot_bot(dset,
             image_axes,
             data_slices,
             image_scales=(0, 0),
             clim=None,
             even_scale=False,
             cmap='RdBu_r',
             axes=None,
             figkw={},
             title=None,
             func=None,
             visible_axes=True):
    """
    Plot a 2d slice of the grid data of a dset/field.

    Parameters
    ----------
    dset : h5py dset or Dedalus Field object
        Dataset to plot
    image_axes: tuple of ints (xi, yi)
        Data axes to use for image x and y axes
    data_slices: tuple of slices, ints
        Slices selecting image data from global data
    image_scales: tuple of ints or strs (xs, ys)
        Axis scales (default: (0,0))
    clim : tuple of floats, optional
        Colorbar limits (default: (data min, data max))
    even_scale : bool, optional
        Expand colorbar limits to be symmetric around 0 (default: False)
    cmap : str, optional
        Colormap name (default: 'RdBu_r')
    axes : matplotlib.Axes object, optional
        Axes to overplot.  If None (default), a new figure and axes will be created.
    figkw : dict, optional
        Keyword arguments to pass to plt.figure (default: {})
    title : str, optional
        Title for plot (default: dataset name)
    func : function(xmesh, ymesh, data), optional
        Function to apply to selected meshes and data before plotting (default: None)
    visible_axes : bool, optional
        Set to false to remove x and y ticks, ticklabels, and labels

    """

    # Wrap fields
    if isinstance(dset, Field):
        dset = FieldWrapper(dset)

    # Unpack image axes
    xaxis, yaxis = image_axes
    xscale, yscale = image_scales

    # Get meshes and data
    xmesh, ymesh, data = get_plane(dset, xaxis, yaxis, data_slices, xscale,
                                   yscale)
    if func is not None:
        xmesh, ymesh, data = func(xmesh, ymesh, data)

    # Setup figure
    if axes is None:
        fig = plt.figure(**figkw)
        axes = fig.add_subplot(1, 1, 1)

    # Setup axes
    # Bounds (left, bottom, width, height) relative-to-axes
    pbbox = transforms.Bbox.from_bounds(0.03, 0, 0.94, 0.94)
    cbbox = transforms.Bbox.from_bounds(0.03, 0.95, 0.94, 0.05)
    # Convert to relative-to-figure
    to_axes_bbox = transforms.BboxTransformTo(axes.get_position())
    pbbox = pbbox.transformed(to_axes_bbox)
    cbbox = cbbox.transformed(to_axes_bbox)
    # Create new axes and suppress base axes
    paxes = axes.figure.add_axes(pbbox)
    caxes = axes.figure.add_axes(cbbox)
    axes.axis('off')

    # Colormap options
    cmap = copy.copy(matplotlib.cm.get_cmap(cmap))
    cmap.set_bad('0.7')

    # Plot
    plot = paxes.pcolormesh(xmesh, ymesh, data, cmap=cmap, zorder=1)
    paxes.axis(pad_limits(xmesh, ymesh))
    paxes.tick_params(length=0, width=0)
    if clim is None:
        if even_scale:
            lim = max(abs(data.min()), abs(data.max()))
            clim = (-lim, lim)
        else:
            clim = (data.min(), data.max())
    plot.set_clim(*clim)

    # Colorbar
    cbar = plt.colorbar(plot,
                        cax=caxes,
                        orientation='horizontal',
                        ticks=ticker.MaxNLocator(nbins=5))
    cbar.outline.set_visible(False)
    caxes.xaxis.set_ticks_position('top')

    # Labels
    if title is None:
        try:
            title = dset.attrs['name']
        except KeyError:
            title = dset.name
    caxes.set_xlabel(title)
    caxes.xaxis.set_label_position('top')
    if isinstance(xscale, str):
        paxes.set_xlabel(xscale)
    else:
        paxes.set_xlabel(dset.dims[xaxis].label)
    if isinstance(yscale, str):
        paxes.set_ylabel(yscale)
    else:
        paxes.set_ylabel(dset.dims[yaxis].label)
    if not visible_axes:
        paxes.xaxis.set_visible(False)
        paxes.yaxis.set_visible(False)

    return paxes, caxes
예제 #17
0
    def draw(self, renderer):
        """
        Ellipses are normally drawn using an approximation that uses
        eight cubic bezier splines.  The error of this approximation
        is 1.89818e-6, according to this unverified source:

          Lancaster, Don.  Approximating a Circle or an Ellipse Using
          Four Bezier Cubic Splines.

          http://www.tinaja.com/glib/ellipse4.pdf

        There is a use case where very large ellipses must be drawn
        with very high accuracy, and it is too expensive to render the
        entire ellipse with enough segments (either splines or line
        segments).  Therefore, in the case where either radius of the
        ellipse is large enough that the error of the spline
        approximation will be visible (greater than one pixel offset
        from the ideal), a different technique is used.

        In that case, only the visible parts of the ellipse are drawn,
        with each visible arc using a fixed number of spline segments
        (8).  The algorithm proceeds as follows:

          1. The points where the ellipse intersects the axes bounding
          box are located.  (This is done be performing an inverse
          transformation on the axes bbox such that it is relative to
          the unit circle -- this makes the intersection calculation
          much easier than doing rotated ellipse intersection
          directly).

          This uses the "line intersecting a circle" algorithm from:

            Vince, John.  Geometry for Computer Graphics: Formulae,
            Examples & Proofs.  London: Springer-Verlag, 2005.

          2. The angles of each of the intersection points are
          calculated.

          3. Proceeding counterclockwise starting in the positive
          x-direction, each of the visible arc-segments between the
          pairs of vertices are drawn using the bezier arc
          approximation technique implemented in Path.arc().
        """
        if not hasattr(self, 'axes'):
            raise RuntimeError('Arcs can only be used in Axes instances')

        self._recompute_transform()

        # Get the width and height in pixels
        width = self.convert_xunits(self.width)
        height = self.convert_yunits(self.height)
        width, height = self.get_transform().transform_point(
            (width, height))
        inv_error = (1.0 / 1.89818e-6) * 0.5

        if width < inv_error and height < inv_error:
            self._path = Path.arc(self.theta1, self.theta2)
            return Patch.draw(self, renderer)

        def iter_circle_intersect_on_line(x0, y0, x1, y1):
            dx = x1 - x0
            dy = y1 - y0
            dr2 = dx*dx + dy*dy
            D = x0*y1 - x1*y0
            D2 = D*D
            discrim = dr2 - D2

            # Single (tangential) intersection
            if discrim == 0.0:
                x = (D*dy) / dr2
                y = (-D*dx) / dr2
                yield x, y
            elif discrim > 0.0:
                # The definition of "sign" here is different from
                # np.sign: we never want to get 0.0
                if dy < 0.0:
                    sign_dy = -1.0
                else:
                    sign_dy = 1.0
                sqrt_discrim = np.sqrt(discrim)
                for sign in (1., -1.):
                    x = (D*dy + sign * sign_dy * dx * sqrt_discrim) / dr2
                    y = (-D*dx + sign * np.abs(dy) * sqrt_discrim) / dr2
                    yield x, y

        def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
            epsilon = 1e-9
            if x1 < x0:
                x0e, x1e = x1, x0
            else:
                x0e, x1e = x0, x1
            if y1 < y0:
                y0e, y1e = y1, y0
            else:
                y0e, y1e = y0, y1
            x0e -= epsilon
            y0e -= epsilon
            x1e += epsilon
            y1e += epsilon
            for x, y in iter_circle_intersect_on_line(x0, y0, x1, y1):
                if x >= x0e and x <= x1e and y >= y0e and y <= y1e:
                    yield x, y

        # Transforms the axes box_path so that it is relative to the unit
        # circle in the same way that it is relative to the desired
        # ellipse.
        box_path = Path.unit_rectangle()
        box_path_transform = transforms.BboxTransformTo(self.axes.bbox) + \
            self.get_transform().inverted()
        box_path = box_path.transformed(box_path_transform)

        PI = np.pi
        TWOPI = PI * 2.0
        RAD2DEG = 180.0 / PI
        DEG2RAD = PI / 180.0
        theta1 = self.theta1
        theta2 = self.theta2
        thetas = {}
        # For each of the point pairs, there is a line segment
        for p0, p1 in zip(box_path.vertices[:-1], box_path.vertices[1:]):
            x0, y0 = p0
            x1, y1 = p1
            for x, y in iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
                theta = np.arccos(x)
                if y < 0:
                    theta = TWOPI - theta
                # Convert radians to angles
                theta *= RAD2DEG
                if theta > theta1 and theta < theta2:
                    thetas[theta] = None

        thetas = thetas.keys()
        thetas.sort()
        thetas.append(theta2)

        last_theta = theta1
        theta1_rad = theta1 * DEG2RAD
        inside = box_path.contains_point((np.cos(theta1_rad), np.sin(theta1_rad)))
        for theta in thetas:
            if inside:
                self._path = Path.arc(last_theta, theta, 8)
                Patch.draw(self, renderer)
                inside = False
            else:
                inside = True
            last_theta = theta
예제 #18
0
def axline(a, b, **kwargs):
    """
    Add an infinite straight line across an axis.

    Parameters
    ----------
    a, b: scalar or tuple
        Acceptable forms are
        y0, b:
            y = y0 + b * x
        (x0, y0), b:
            y = y0 + b * (x - x0)
        (x0, y0), (x1, y1):
            y = y0 + (y1 - y0) / (x1 - x0) * (x - x0)
    Additional arguments are passed to the <matplotlib.lines.Line2D> constructor.

    Returns
    -------
    :class:`~matplotlib.lines.Line2D`

    Other Parameters
    ----------------
    Valid kwargs are :class:`~matplotlib.lines.Line2D` properties,
    with the exception of 'transform':
    %(Line2D)s

    Examples
    --------
    * Draw a thick red line with slope 1 and y-intercept 0::
        >>> axline(0, 1, linewidth=4, color='r')
    * Draw a default line with slope 1 and y-intercept 1::
        >>> axline(1, 1)

    See Also
    --------
    axhline : for horizontal lines
    axvline : for vertical lines

    Notes
    -----
    Currently this method does not work properly with log scaled axes.
    Taken from https://github.com/matplotlib/matplotlib/pull/9321
    """
    from matplotlib import pyplot as plt
    import matplotlib.transforms as mtransforms
    import matplotlib.lines as mlines

    if np.isscalar(a):
        if not np.isscalar(b):
            raise ValueError("Invalid line parameters.")
        point, slope = (0, a), b
    elif np.isscalar(b):
        if not len(a) == 2:
            raise ValueError("Invalid line parameters.")
        point, slope = a, b
    else:
        if not len(a) == len(b) == 2:
            raise ValueError("Invalid line parameters.")
        if b[0] != a[0]:
            point, slope = a, (b[1] - a[1]) / (b[0] - a[0])
        else:
            point, slope = a, np.inf

    ax = plt.gca()
    if "transform" in kwargs:
        raise ValueError("'transform' is not allowed as a kwarg; "
                         "axline generates its own transform.")

    if slope == 0:
        return ax.axhline(point[1], **kwargs)
    elif np.isinf(slope):
        return ax.axvline(point[0], **kwargs)

    xtrans = mtransforms.BboxTransformTo(ax.viewLim)
    viewLimT = mtransforms.TransformedBbox(
        ax.viewLim,
        mtransforms.Affine2D().rotate_deg(90).scale(-1, 1))
    ytrans = (mtransforms.BboxTransformTo(viewLimT) +
              mtransforms.Affine2D().scale(slope).translate(*point))
    trans = mtransforms.blended_transform_factory(xtrans, ytrans)
    line = mlines.Line2D([0, 1], [0, 1],
                         transform=trans + ax.transData,
                         **kwargs)
    ax.add_line(line)
    return line
예제 #19
0
 def __call__(self, ax, renderer):
     bbox_parent = self.parent.get_position(original=False)
     trans = mtrans.BboxTransformTo(bbox_parent)
     bbox_inset = mtrans.Bbox.from_bounds(*self.lbwh)
     bb = mtrans.TransformedBbox(bbox_inset, trans)
     return bb
예제 #20
0
    def plot_crit(self, axes=None, transpose=False, xlabel = None, ylabel = None, zlabel="growth rate", cmap="viridis"):
        """Create a 2D colormap of the grid of growth rates.  

        If available, the root values that have been found will be plotted
        over the colormap.

        Parameters
        ----------
        transpose : bool, optional
            If True, plot dim 0 on the y axis and dim 1 on the x axis.
        xlabel : str, optional
            If not None, the x-label of the plot. Otherwise, use parameter name from EVP
        ylabel : str, optional 
            If not None, the y-label of the plot. Otherwise, use parameter name from EVP
        zlabel : str, optional
            Label for the colorbar. (default: growth rate)
        cmp : str, optional
            matplotlib colormap name (default: viridis)
        """
        if self.rank != 0:
            return
        
        if axes is None:
            fig = plt.figure(figsize=[8,8])
            ax = fig.add_subplot(111)
        else:
            ax = axes
            fig = axes.figure

        # Grab out grid data for colormap
        if transpose:
            xx = self.parameter_grids[1].T
            yy = self.parameter_grids[0].T
            grid = self.evalue_grid.real.T
        else:
            xx = self.parameter_grids[0]
            yy = self.parameter_grids[1]
            grid = self.evalue_grid.real
        # Plot colormap, only plot 2 stdevs off zero
        biggest_val = 2*np.abs(grid).std()

        # Setup axes
        # Bounds (left, bottom, width, height) relative-to-axes
        pbbox = transforms.Bbox.from_bounds(0.03, 0, 0.94, 0.94)
        cbbox = transforms.Bbox.from_bounds(0.03, 0.95, 0.94, 0.05)
        # Convert to relative-to-figure
        to_axes_bbox = transforms.BboxTransformTo(ax.get_position())
        pbbox = pbbox.transformed(to_axes_bbox)
        cbbox = cbbox.transformed(to_axes_bbox)
        # Create new axes and suppress base axes
        pax = ax.figure.add_axes(pbbox)
        cax = ax.figure.add_axes(cbbox)

        plot = pax.pcolormesh(xx,yy,grid,cmap=cmap,vmin=-biggest_val,vmax=biggest_val)
        ax.axis('off')
        cbar = plt.colorbar(plot, cax=cax, label=zlabel, orientation='horizontal')
        cbar.outline.set_visible(False)
        cax.xaxis.set_ticks_position('top')
        cax.xaxis.set_label_position('top')
        # Plot root data if they're available
        if self.roots is not None:
            if transpose:
                x = self.roots[:]
                y = self.parameter_grids[0][0,:]
            else:
                x = self.parameter_grids[0][0,:]
                y = self.roots[:]

            if transpose:
                y, x = y[np.isfinite(x)], x[np.isfinite(x)]
            else:
                y, x = y[np.isfinite(y)], x[np.isfinite(y)]
            pax.scatter(x,y, color='k')
        
        # Pretty up the plot, save.
        pax.set_ylim(yy.min(),yy.max())
        pax.set_xlim(xx.min(),xx.max())
        if xlabel is None:
            xlabel = self.param_names[0]
        if ylabel is None:
            ylabel = self.param_names[1]
        pax.set_xlabel(xlabel)
        pax.set_ylabel(ylabel)
        
        return pax,cax