Exemple #1
0
 def secondary_locator(ax, renderer):
     # delay evaluating transform until draw time because the
     # parent transform may have changed (i.e. if window reesized)
     bb = mtransforms.TransformedBbox(_rect, parent.transAxes)
     tr = parent.figure.transFigure.inverted()
     bb = mtransforms.TransformedBbox(bb, tr)
     return bb
Exemple #2
0
def _connect_spines(left_ax,
                    right_ax,
                    left_y,
                    right_y,
                    linestyle="solid",
                    **line_kwds):
    """ Connects the y-spines between two Axes

    Parameters
    ----------
    left_ax, right_ax : matplotlib Axes objects
        The Axes that need to be connected.
    left_y, right_y : float
        Values on the spines that wil be connected.
    linestyle : string, optional (default = 'solid')
        The line style to use. Valid values are 'solid', 'dashed',
        'dashdot', 'dotted'.
    **line_kwds : keyword arguments
        Additional options for style the line.

    Returns
    -------
    connector : BboxConnector
        The weird mpl-line-like-thingy that connects the spines.

    """

    import matplotlib.transforms as mtrans
    import mpl_toolkits.axes_grid1.inset_locator as inset

    left_trans = mtrans.blended_transform_factory(left_ax.transData,
                                                  left_ax.transAxes)
    right_trans = mtrans.blended_transform_factory(right_ax.transData,
                                                   right_ax.transAxes)

    left_data_trans = left_ax.transScale + left_ax.transLimits
    right_data_trans = right_ax.transScale + right_ax.transLimits

    left_pos = left_data_trans.transform((0, left_y))[1]
    right_pos = right_data_trans.transform((0, right_y))[1]

    bbox = mtrans.Bbox.from_extents(0, left_pos, 0, right_pos)
    right_bbox = mtrans.TransformedBbox(bbox, right_trans)
    left_bbox = mtrans.TransformedBbox(bbox, left_trans)

    # deal with the linestyle
    connector = inset.BboxConnector(left_bbox,
                                    right_bbox,
                                    loc1=3,
                                    loc2=2,
                                    linestyle=linestyle,
                                    **line_kwds)
    connector.set_clip_on(False)
    left_ax.add_line(connector)

    return connector
Exemple #3
0
    def plot_barbs(self, p, u, v, c=None, xloc=1.0, x_clip_radius=0.08,
                   y_clip_radius=0.08, **kwargs):
        r"""Plot wind barbs.

        Adds wind barbs to the skew-T plot. This is a wrapper around the
        `barbs` command that adds to appropriate transform to place the
        barbs in a vertical line, located as a function of pressure.

        Parameters
        ----------
        p : array_like
            pressure values
        u : array_like
            U (East-West) component of wind
        v : array_like
            V (North-South) component of wind
        c:
            An optional array used to map colors to the barbs
        xloc : float, optional
            Position for the barbs, in normalized axes coordinates, where 0.0
            denotes far left and 1.0 denotes far right. Defaults to far right.
        x_clip_radius : float, optional
            Space, in normalized axes coordinates, to leave before clipping
            wind barbs in the x-direction. Defaults to 0.08.
        y_clip_radius : float, optional
            Space, in normalized axes coordinates, to leave above/below plot
            before clipping wind barbs in the y-direction. Defaults to 0.08.
        kwargs
            Other keyword arguments to pass to :func:`~matplotlib.pyplot.barbs`

        Returns
        -------
        matplotlib.quiver.Barbs
            instance created

        See Also
        --------
        :func:`matplotlib.pyplot.barbs`

        """
        # Assemble array of x-locations in axes space
        x = np.empty_like(p)
        x.fill(xloc)

        # Do barbs plot at this location
        if c is not None:
            b = self.ax.barbs(x, p, u, v, c,
                              transform=self.ax.get_yaxis_transform(which='tick2'),
                              clip_on=True, **kwargs)
        else:
            b = self.ax.barbs(x, p, u, v,
                              transform=self.ax.get_yaxis_transform(which='tick2'),
                              clip_on=True, **kwargs)

        # Override the default clip box, which is the axes rectangle, so we can have
        # barbs that extend outside.
        ax_bbox = transforms.Bbox([[xloc - x_clip_radius, -y_clip_radius],
                                   [xloc + x_clip_radius, 1.0 + y_clip_radius]])
        b.set_clip_box(transforms.TransformedBbox(ax_bbox, self.ax.transAxes))
        return b
Exemple #4
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)
Exemple #5
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
Exemple #6
0
def plot_colorbars(fig, all_colorbars):
    """
    Plot colorbars *after* tight_layout(), otherwise it will move them around.
    """

    # Ignore warning issued by colorbar.
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fig.tight_layout()

    # Plot colorbar down here so tight_layout won't move it around.
    for (plot_colorbar, sca, trans, v_min_mp, v_max_mp) in all_colorbars:
        if plot_colorbar is True:
            import matplotlib.transforms as mts
            # Position and dimensions relative to the axes.
            x0, y0, width, height = [0.74, 0.93, 0.2, 0.04]
            # Transform them to get the ABSOLUTE POSITION AND DIMENSIONS
            Bbox = mts.Bbox.from_bounds(x0, y0, width, height)
            l, b, w, h = mts.TransformedBbox(Bbox, trans).bounds
            # Create the axes and the colorbar.
            cbaxes = fig.add_axes([l, b, w, h])
            cbar = plt.colorbar(sca,
                                cax=cbaxes,
                                ticks=[v_min_mp, v_max_mp],
                                orientation='horizontal')
            cbar.ax.minorticks_off()
Exemple #7
0
    def make_image(self, magnification=1.0):
        if self._A is None:
            raise RuntimeError('You must first set the image'
                               ' array or the image attribute')

        # image is created in the canvas coordinate.
        x1, x2, y1, y2 = self.get_extent()
        trans = self.get_transform()
        xy = trans.transform(np.array([(x1, y1),
                                       (x2, y2),
                                       ]))
        _x1, _y1 = xy[0]
        _x2, _y2 = xy[1]

        transformed_viewLim = mtransforms.TransformedBbox(self.axes.viewLim,
                                                          trans)

        im, xmin, ymin, dxintv, dyintv, sx, sy = \
            self._get_unsampled_image(self._A, [_x1, _x2, _y1, _y2],
                                      transformed_viewLim)

        fc = self.axes.patch.get_facecolor()
        bg = mcolors.colorConverter.to_rgba(fc, 0)
        im.set_bg(*bg)

        # image input dimensions
        im.reset_matrix()
        numrows, numcols = im.get_size()
        if numrows < 1 or numcols < 1:   # out of range
            return None
        im.set_interpolation(self._interpd[self._interpolation])

        im.set_resample(self._resample)

        # the viewport translation
        if dxintv == 0.0:
            tx = 0.0
        else:
            tx = (xmin-transformed_viewLim.x0)/dxintv * numcols
        if dyintv == 0.0:
            ty = 0.0
        else:
            ty = (ymin-transformed_viewLim.y0)/dyintv * numrows

        im.apply_translation(tx, ty)

        l, b, r, t = self.axes.bbox.extents
        widthDisplay = ((round(r*magnification) + 0.5) -
                        (round(l*magnification) - 0.5))
        heightDisplay = ((round(t*magnification) + 0.5) -
                         (round(b*magnification) - 0.5))

        # resize viewport to display
        rx = widthDisplay / numcols
        ry = heightDisplay / numrows
        im.apply_scaling(rx*sx, ry*sy)
        im.resize(int(widthDisplay+0.5), int(heightDisplay+0.5),
                  norm=self._filternorm, radius=self._filterrad)
        return im
Exemple #8
0
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)
Exemple #9
0
   def get_extent(self, renderer):

      bb = mtrans.TransformedBbox(self.axes.viewLim, self.parent_axes.transData)

      x, y, w, h = bb.bounds

      xd, yd = 0, 0

      fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
      pad = self.pad * fontsize

      return w*self.zoom+2*pad, h*self.zoom+2*pad, xd+pad, yd+pad
Exemple #10
0
    def _set_lim_and_transforms(self):
        super()._set_lim_and_transforms()
        transTernaryScale = TernaryScaleTransform(self.ternary_scale)
        transTLimits = mtransforms.BboxTransformFrom(
            mtransforms.TransformedBbox(self.viewTLim, self.transScale))
        transLLimits = mtransforms.BboxTransformFrom(
            mtransforms.TransformedBbox(self.viewLLim, self.transScale))
        transRLimits = mtransforms.BboxTransformFrom(
            mtransforms.TransformedBbox(self.viewRLim, self.transScale))

        corners_axes = self.corners_axes

        taxis_transform = TernaryTransform(corners_axes, 0)
        laxis_transform = TernaryTransform(corners_axes, 1)
        raxis_transform = TernaryTransform(corners_axes, 2)

        self._taxis_transform = transTLimits + taxis_transform + self.transAxes
        self._laxis_transform = transLLimits + laxis_transform + self.transAxes
        self._raxis_transform = transRLimits + raxis_transform + self.transAxes

        # For axis labels
        t_l_t = TernaryPerpendicularTransform(self.transAxes, corners_axes, 0)
        l_l_t = TernaryPerpendicularTransform(self.transAxes, corners_axes, 1)
        r_l_t = TernaryPerpendicularTransform(self.transAxes, corners_axes, 2)
        self._taxis_label_transform = t_l_t
        self._laxis_label_transform = l_l_t
        self._raxis_label_transform = r_l_t

        # From ternary coordinates to the original data coordinates
        self.transProjection = (transTernaryScale +
                                BarycentricTransform(self.corners_data))

        # From ternary coordinates to the original Axes coordinates
        self._ternary_axes_transform = self.transProjection + self.transLimits

        # From barycentric coordinates to the original Axes coordinates
        self.transAxesProjection = BarycentricTransform(self.corners_axes)

        # From barycentric coordinates to display coordinates
        self.transTernaryAxes = self.transAxesProjection + self.transAxes
Exemple #11
0
   def __call__(self, ax, renderer):

       fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
       self._update_offset_func(renderer, fontsize)

       width, height, xdescent, ydescent = self.get_extent(renderer)

       px, py = self.get_offset(width, height, 0, 0, renderer)
       bbox_canvas = mtrans.Bbox.from_bounds(px, py, width, height)
       tr = ax.figure.transFigure.inverted()
       bb = mtrans.TransformedBbox(bbox_canvas, tr)

       return bb
Exemple #12
0
def _make_secondary_locator(rect, parent):
    """
    Helper function to locate the secondary axes.

    A locator gets used in `Axes.set_aspect` to override the default
    locations...  It is a function that takes an axes object and
    a renderer and tells `set_aspect` where it is to be placed.

    This locator make the transform be in axes-relative co-coordinates
    because that is how we specify the "location" of the secondary axes.

    Here *rect* is a rectangle [l, b, w, h] that specifies the
    location for the axes in the transform given by *trans* on the
    *parent*.
    """
    _rect = mtransforms.Bbox.from_bounds(*rect)
    bb = mtransforms.TransformedBbox(_rect, parent.transAxes)
    tr = parent.figure.transFigure.inverted()
    bb = mtransforms.TransformedBbox(bb, tr)

    def secondary_locator(ax, renderer):
        return bb

    return secondary_locator
Exemple #13
0
def connect_spines(left_ax, right_ax, left_y, right_y, **line_kwds):
    left_trans = mtrans.blended_transform_factory(left_ax.transData,
                                                  left_ax.transAxes)
    right_trans = mtrans.blended_transform_factory(right_ax.transData,
                                                   right_ax.transAxes)

    left_data_trans = left_ax.transScale + left_ax.transLimits
    right_data_trans = right_ax.transScale + right_ax.transLimits

    left_pos = left_data_trans.transform((0, left_y))[1]
    right_pos = right_data_trans.transform((0, right_y))[1]

    bbox = mtrans.Bbox.from_extents(0, left_pos, 0, right_pos)
    right_bbox = mtrans.TransformedBbox(bbox, right_trans)
    left_bbox = mtrans.TransformedBbox(bbox, left_trans)

    connecter = inset.BboxConnector(left_bbox,
                                    right_bbox,
                                    loc1=3,
                                    loc2=2,
                                    **line_kwds)
    connecter.set_clip_on(False)

    return connecter
Exemple #14
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
Exemple #15
0
def axcolorbar(cbobj,
               pos=[0.7, 0.8, 0.2, 0.04],
               ax=None,
               fig=None,
               orientation='horizontal',
               **kwargs):
    """
	Inserts a colorbar with a position relative to an axes and not a figure
	
	Inputs:
		cbobj - plot object for colorbar
		pos - position vector [x0, y0, width, height] in dimensionless coordinates
		ax - axes to insert colobar
		figure - figure 
		**kwargs - arguments for plt.colorbar
	
	Returns a colorbar object
	
	Derived from this post:
		http://stackoverflow.com/questions/22413211/cant-fix-position-of-colorbar-in-image-with-multiple-subplots
	"""
    if fig == None:
        fig = plt.gcf()
    if ax == None:
        ax = plt.gca()

    fig.tight_layout(
    )  # You call fig.tight_layout BEFORE creating the colorbar

    # You input the POSITION AND DIMENSIONS RELATIVE TO THE AXES
    x0, y0, width, height = pos

    # and transform them after to get the ABSOLUTE POSITION AND DIMENSIONS
    Bbox = transforms.Bbox.from_bounds(x0, y0, width, height)
    trans = ax.transAxes + fig.transFigure.inverted()
    l, b, w, h = transforms.TransformedBbox(Bbox, trans).bounds

    # Now just create the axes and the colorbar
    cbaxes = fig.add_axes([l, b, w, h])
    cbar = plt.colorbar(cbobj, cax=cbaxes, orientation=orientation, **kwargs)
    cbar.ax.tick_params(labelsize=9)

    return cbar
Exemple #16
0
def plot_observed_cluster(fig, gs, gs_y1, gs_y2, x_ax, y_ax, cl_max_mag,
                          x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd, err_lst,
                          v_min_mp, v_max_mp, obs_x, obs_y, obs_MPs, cl_sz_pt,
                          hess_xedges, hess_yedges, x_isoch, y_isoch,
                          phot_Nsigma):
    """
    This function is called separately since we need to retrieve some
    information from it to plot that #$%&! colorbar.
    """
    err_bar = prep_plots.error_bars(cl_max_mag, x_min_cmd, err_lst)

    # pl_mps_phot_diag
    plot_colorbar, sca, trans = mp_bestfit_CMD.pl_mps_phot_diag(
        gs, gs_y1, gs_y2, fig, x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd,
        x_ax, y_ax, v_min_mp, v_max_mp, obs_x, obs_y, obs_MPs, err_bar,
        cl_sz_pt, hess_xedges, hess_yedges, x_isoch, y_isoch, phot_Nsigma)

    # Ignore warning issued by colorbar plotted in photometric diagram with
    # membership probabilities.
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fig.tight_layout()

    # Force to not plot colorbar after the first row.
    plot_colorbar = False if gs_y1 != 0 else plot_colorbar

    # Plot colorbar down here so tight_layout won't move it around.
    if plot_colorbar is True:
        import matplotlib.transforms as mts
        # Position and dimensions relative to the axes.
        x0, y0, width, height = [0.74, 0.93, 0.2, 0.04]
        # Transform them to get the ABSOLUTE POSITION AND DIMENSIONS
        Bbox = mts.Bbox.from_bounds(x0, y0, width, height)
        l, b, w, h = mts.TransformedBbox(Bbox, trans).bounds
        # Create the axes and the colorbar.
        cbaxes = fig.add_axes([l, b, w, h])
        cbar = plt.colorbar(sca,
                            cax=cbaxes,
                            ticks=[v_min_mp, v_max_mp],
                            orientation='horizontal')
        cbar.ax.minorticks_off()
Exemple #17
0
def get_figure_bbox(fig, bbox) -> Tuple[float, float, float, float]:
    """Transforms a bounding box into units matching the dimension of `fig`.

    This can be used to transform pixel values to inches, which are internally
    used by Matplotlib.

    Args:
        fig (matplotlib.figure.Figure): A Matplotlib figure.
        bbox (matplotlib.transforms.Bbox): A bounding box.

    Returns:
        Tuple[float, float, float, float]: A bounding box in inches represented
            as a tuple `(x, y, width, height)`.
    """
    trans_bbox = trans.TransformedBbox(bbox, fig.transFigure.inverted())
    x = trans_bbox.xmin
    y = trans_bbox.ymin
    width = trans_bbox.width
    height = trans_bbox.height

    return (x, y, width, height)
    def __init__(self, ax, img=None, mask_shape=None, canmove=True, size=None):
        self.canmove = canmove
        self.ax = ax
        if size is None:
            size = 10

        self.bbox = mtrans.Bbox(np.array([[0, 0], [10, 10]]))
        bbox = mtrans.TransformedBbox(self.bbox, ax.transData)
        self.mask_img = mimage.BboxImage(bbox,
                                         animated=True,
                                         alpha=0.6,
                                         zorder=1000)
        self.ax.add_artist(self.mask_img)

        self.create_mask(img, mask_shape)

        self.canvas = ax.figure.canvas
        self.event_ids = [
            self.canvas.mpl_connect('motion_notify_event', self.on_move),
            self.canvas.mpl_connect('draw_event', self.on_draw),
            self.canvas.mpl_connect('button_press_event', self.on_press),
            self.canvas.mpl_connect('button_release_event', self.on_release),
            self.canvas.mpl_connect('scroll_event', self.on_scroll),
        ]
        self.circle = mpatches.Circle((0, 0),
                                      size,
                                      facecolor="red",
                                      alpha=0.5,
                                      animated=True)
        self.ax.add_patch(self.circle)

        self.mask_circle = mpatches.Circle((0, 0), 10, facecolor="white", lw=0)
        self.mask_line = plt.Line2D((0, 0), (0, 0),
                                    lw=18,
                                    solid_capstyle="round",
                                    color="white")
        self.background = None
        self.last_pos = None

        self.timer = Timer(40, self.check_dirty)
Exemple #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
Exemple #20
0
    def plot_barbs(self,
                   pressure,
                   u,
                   v,
                   c=None,
                   xloc=1.0,
                   x_clip_radius=0.1,
                   y_clip_radius=0.08,
                   **kwargs):
        r"""Plot wind barbs.

        Adds wind barbs to the skew-T plot. This is a wrapper around the
        `barbs` command that adds to appropriate transform to place the
        barbs in a vertical line, located as a function of pressure.

        Parameters
        ----------
        pressure : array_like
            pressure values
        u : array_like
            U (East-West) component of wind
        v : array_like
            V (North-South) component of wind
        c:
            An optional array used to map colors to the barbs
        xloc : float, optional
            Position for the barbs, in normalized axes coordinates, where 0.0
            denotes far left and 1.0 denotes far right. Defaults to far right.
        x_clip_radius : float, optional
            Space, in normalized axes coordinates, to leave before clipping
            wind barbs in the x-direction. Defaults to 0.1.
        y_clip_radius : float, optional
            Space, in normalized axes coordinates, to leave above/below plot
            before clipping wind barbs in the y-direction. Defaults to 0.08.
        plot_units: `pint.unit`
            Units to plot in (performing conversion if necessary). Defaults to given units.
        kwargs
            Other keyword arguments to pass to :func:`~matplotlib.pyplot.barbs`

        Returns
        -------
        matplotlib.quiver.Barbs
            instance created

        See Also
        --------
        :func:`matplotlib.pyplot.barbs`

        """
        # If plot_units specified, convert the data to those units
        plotting_units = kwargs.pop('plot_units', None)
        if plotting_units:
            if hasattr(u, 'units') and hasattr(v, 'units'):
                u = u.to(plotting_units)
                v = v.to(plotting_units)
            else:
                raise ValueError(
                    'To convert to plotting units, units must be attached to '
                    'u and v wind components.')

        # Assemble array of x-locations in axes space
        x = np.empty_like(pressure)
        x.fill(xloc)

        # Do barbs plot at this location
        if c is not None:
            b = self.ax.barbs(
                x,
                pressure,
                u,
                v,
                c,
                transform=self.ax.get_yaxis_transform(which='tick2'),
                clip_on=True,
                zorder=2,
                **kwargs)
        else:
            b = self.ax.barbs(
                x,
                pressure,
                u,
                v,
                transform=self.ax.get_yaxis_transform(which='tick2'),
                clip_on=True,
                zorder=2,
                **kwargs)

        # Override the default clip box, which is the axes rectangle, so we can have
        # barbs that extend outside.
        ax_bbox = transforms.Bbox([[xloc - x_clip_radius, -y_clip_radius],
                                   [xloc + x_clip_radius,
                                    1.0 + y_clip_radius]])
        b.set_clip_box(transforms.TransformedBbox(ax_bbox, self.ax.transAxes))
        return b
Exemple #21
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
Exemple #22
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)
Exemple #23
0
def main(output_subdir, clust_name, x_data, y_data, bin_width,
         center_params, rdp_params, field_dens, radius_params,
         cont_index, mag_data, col_data, err_plot, err_flags, kp_params,
         cl_region, stars_out, stars_in_rjct, stars_out_rjct,
         integr_return, n_memb, n_memb_da, flag_no_fl_regs,
         field_regions, flag_pval_test, pval_test_params,
         decont_algor_return, lum_func, completeness, ip_list,
         red_return, err_lst, bf_return):
    '''
    Make all plots.
    '''

    # Unpack params.
    # Parameters from get_center function.
    cent_bin, center_cl, e_cent, approx_cents, st_dev_lst, hist_2d_g, \
        kde_pl = center_params[:7]
    # RDP params.
    radii, ring_density, poisson_error = rdp_params[:3]
    # Parameters from get_radius function.
    clust_rad, e_rad = radius_params[:2]
    # Luminosity functions.
    x_cl, y_cl, x_fl, y_fl = lum_func
    # Best fitting process results.
    isoch_fit_params, isoch_fit_errors, shift_isoch, synth_clst, syn_b_edges =\
        bf_return

    # Plot all outputs
    # figsize(x1, y1), GridSpec(y2, x2) --> To have square plots: x1/x2 =
    # y1/y2 = 2.5
    fig = plt.figure(figsize=(30, 25))  # create the top-level container
    gs = gridspec.GridSpec(10, 12)      # create a GridSpec object
    # Add version number to top left.
    ver = '[ASteCA ' + __version__ + ']'
    x_coord = 0.957 - (len(__version__) - 6) * 0.001
    plt.figtext(x_coord, .988, ver, fontsize=9, color='#585858')

    # Obtain plotting parameters and data.
    x_min, x_max, y_min, y_max = prep_plots.frame_max_min(x_data, y_data)
    asp_ratio = prep_plots.aspect_ratio(x_min, x_max, y_min, y_max)
    coord, x_name, y_name = prep_plots.coord_syst()
    x_zmin, x_zmax, y_zmin, y_zmax = prep_plots.frame_zoomed(
        x_min, x_max, y_min, y_max, center_cl, clust_rad)
    x_ax, y_ax, x_ax0, y_axis = prep_plots.ax_names()
    phot_x, phot_y = prep_plots.ax_data(mag_data, col_data)
    x_max_cmd, x_min_cmd, y_min_cmd, y_max_cmd = prep_plots.diag_limits(
        y_axis, phot_x, phot_y)
    x_data_z, y_data_z, mag_data_z, stars_f_rjct, stars_f_acpt = \
        prep_plots.separate_stars(x_data, y_data, mag_data, x_zmin, x_zmax,
                                  y_zmin, y_zmax, stars_out_rjct,
                                  field_regions)
    st_sizes_arr = prep_plots.star_size(mag_data)
    st_sizes_arr_z = prep_plots.star_size(mag_data_z)
    f_sz_pt = prep_plots.phot_diag_st_size(len(stars_f_acpt[0]))
    cl_sz_pt = prep_plots.phot_diag_st_size(len(cl_region))
    v_min_mp, v_max_mp, plot_colorbar, chart_fit_inv, chart_no_fit_inv, \
        out_clust_rad, diag_fit_inv, diag_no_fit_inv, err_bar = \
        prep_plots.da_plots(center_cl, clust_rad, stars_out, x_zmin, x_zmax,
                            y_zmin, y_zmax, x_max_cmd, col_data, err_lst,
                            red_return)

    #
    # Structure plots.
    arglist = [
        # pl_hist_g: 2D Gaussian convolved histogram.
        [gs, fig, asp_ratio, x_name, y_name, coord, cent_bin, clust_rad,
            bin_width, hist_2d_g],
        # pl_centers: 2D Gaussian histograms' centers.
        [gs, x_name, y_name, coord, x_min, x_max, y_min, y_max, asp_ratio,
            approx_cents, bin_width, st_dev_lst],
        # pl_full_frame: x,y finding chart of full frame.
        [gs, fig, x_name, y_name, coord, x_min, x_max, y_min, y_max, asp_ratio,
            center_cl, clust_rad, e_cent, kp_params, mag_data, x_data, y_data,
            st_sizes_arr],
        # pl_rad_dens: Radial density plot.
        [gs, radii, ring_density, field_dens, coord, clust_name, kp_params,
            clust_rad, e_rad, poisson_error, bin_width],
        # pl_zoom_frame: Zoom on x,y finding chart.
        [gs, fig, x_name, y_name, coord, x_zmin, x_zmax, y_zmin, y_zmax,
            cont_index, kde_pl, x_data_z, y_data_z,
            st_sizes_arr_z, center_cl, clust_rad],
        # pl_cl_fl_regions: Cluster and field regions defined.
        [gs, fig, x_name, y_name, coord, x_min, x_max, y_min, y_max, asp_ratio,
            center_cl, clust_rad, field_regions, cl_region, flag_no_fl_regs]
    ]
    for n, args in enumerate(arglist):
        # with timeblock("{}".format(n)):
        mp_structure.plot(n, *args)

    #
    # Photometric analysis plots.
    arglist = [
        # pl_phot_err: Photometric error rejection.
        [gs, fig, 'up', x_ax, y_ax, mag_data, err_plot, err_flags,
            cl_region, stars_in_rjct, stars_out, stars_out_rjct],
        [gs, fig, 'low', x_ax, y_ax, mag_data, err_plot, err_flags,
            cl_region, stars_in_rjct, stars_out, stars_out_rjct],
        # pl_fl_diag: Field stars CMD/CCD diagram.
        [gs, x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd, x_ax, y_ax,
            stars_f_rjct, stars_f_acpt, f_sz_pt],
        # pl_cl_diag: Cluster's stars diagram (stars inside cluster's radius)
        [gs, x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd, x_ax, y_ax,
            stars_in_rjct, cl_region, n_memb, cl_sz_pt],
        # pl_lum_func: LF of stars in cluster region and outside.
        [gs, mag_data, y_ax, x_cl, y_cl, flag_no_fl_regs, x_fl, y_fl,
            completeness],
        # pl_integ_mag: Integrated magnitudes.
        [gs, integr_return, y_ax, x_ax0, flag_no_fl_regs],
        # pl_p_vals: Distribution of KDE p_values.
        [gs, flag_pval_test, pval_test_params]
    ]
    for n, args in enumerate(arglist):
        mp_phot_analysis.plot(n, *args)

    #
    # Decontamination algorithm plots.
    flag_decont_skip = decont_algor_return[1]
    mode_red_memb = g.rm_params[0]
    bf_flag = g.bf_params[0]

    # If the DA and the best fit functions were skipped and the reduced
    # membership mode is any mode but 'local', do not plot.
    if flag_decont_skip and bf_flag is False and mode_red_memb != 'local':
        pass
    else:
        arglist = [
            [gs, n_memb_da, red_return, decont_algor_return],
            [gs, fig, x_name, y_name, coord, x_zmin, x_zmax, y_zmin, y_zmax,
                center_cl, clust_rad, field_dens, flag_decont_skip,
                v_min_mp, v_max_mp, chart_fit_inv, chart_no_fit_inv,
                out_clust_rad]
        ]
        for n, args in enumerate(arglist):
            mp_decont_algor.plot(n, *args)

        # This function is called separately since we need to retrieve some
        # information from it to plot that #$%&! colorbar.
        try:
            sca, trans = mp_decont_algor.pl_mps_phot_diag(
                gs, fig, x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd, x_ax,
                y_ax, v_min_mp, v_max_mp, red_return, diag_fit_inv,
                diag_no_fit_inv, shift_isoch, err_bar)
        except:
            # import traceback
            # print traceback.format_exc()
            print("  WARNING: error when plotting MPs on cluster's "
                  "photom diagram.")

    #
    # Best fit plots.
    if bf_flag:
        arglist = [
            # pl_bf_synth_cl: Best fit synthetic cluster obtained.
            [gs, x_min_cmd, x_max_cmd, y_min_cmd, y_max_cmd, x_ax, y_ax,
                synth_clst, syn_b_edges, isoch_fit_params[0], isoch_fit_errors,
                shift_isoch]
        ]
        for n, args in enumerate(arglist):
            mp_best_fit.plot(n, *args)

    # Best fitting process plots for GA.
    best_fit_algor = g.bf_params[1]
    if bf_flag and best_fit_algor == 'genet':

        min_max_p = prep_plots.param_ranges(ip_list)
        # Get special axis ticks for metallicity.
        xp_min, xp_max = min_max_p[0]
        # The maximum number of characters in the axis, '30', is HARD-CODED.
        # Add values to the end of this list.
        min_max_p.append(prep_plots.BestTick(xp_min, xp_max, 30))

        # Unpack.
        lkl_old, new_bs_indx, model_done = isoch_fit_params[1:4]
        l_min_max = prep_plots.likl_y_range(lkl_old)

        arglist = [
            # pl_ga_lkl: Likelihood evolution for the GA.
            [gs, l_min_max, lkl_old, model_done, new_bs_indx],
            # pl_2_param_dens: Parameter vs parameters solutions scatter map.
            [gs, 'age-metal', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, 'dist-ext', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, 'metal-dist', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, 'mass-binar', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            # pl_lkl_dens: Parameter likelihood density plot.
            [gs, '$z$', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, '$log(age)$', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, '$E_{{(B-V)}}$', min_max_p, isoch_fit_params,
                isoch_fit_errors, model_done],
            [gs, '$(m-M)_o$', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done],
            [gs, '$M\,(M_{{\odot}})$', min_max_p, isoch_fit_params,
                isoch_fit_errors, model_done],
            [gs, '$b_{{frac}}$', min_max_p, isoch_fit_params, isoch_fit_errors,
                model_done]
        ]
        for n, args in enumerate(arglist, 1):
            mp_best_fit.plot(n, *args)

    # Ignore warning issued by colorbar plotted in photometric diagram with
    # membership probabilities.
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fig.tight_layout()

    # Plot colorbar down here so tight_layout won't move it around.
    try:
        if plot_colorbar is True:
            import matplotlib.transforms as mts
            # Position and dimensions relative to the axes.
            x0, y0, width, height = [0.67, 0.92, 0.2, 0.04]
            # Transform them to get the ABSOLUTE POSITION AND DIMENSIONS
            Bbox = mts.Bbox.from_bounds(x0, y0, width, height)
            l, b, w, h = mts.TransformedBbox(Bbox, trans).bounds
            # Create the axes and the colorbar.
            cbaxes = fig.add_axes([l, b, w, h])
            cbar = plt.colorbar(sca, cax=cbaxes, ticks=[v_min_mp, v_max_mp],
                                orientation='horizontal')
            cbar.ax.tick_params(labelsize=9)
    except:
        # import traceback
        # print traceback.format_exc()
        print("  WARNING: error when plotting colorbar on cluster's "
              "photometric diagram.")

    # Generate output file for each data file.
    pl_fmt, pl_dpi = g.pl_params[1:3]
    plt.savefig(join(output_subdir, str(clust_name) + '.' + pl_fmt),
                dpi=pl_dpi)

    # Close to release memory.
    plt.clf()
    plt.close()

    print 'Plots created.'