示例#1
0
   def convert_point(self,point_px, stop=False):
      '''
      given a touch point in the view space, compute the corresponding point in data coords. assumes linear scaling!
      TODO: support log scaling 
      
      there are basically two bbox transforms:  1) from figure coords to view coords, accounting for sign change in y. this then lets us compute axes box in view coords, and generate 2) transform from view to data coords.

      '''
      transFig=BboxTransformTo(Bbox([(0,self.height),(self.width,0)]))
      bbox_axes=Bbox(transFig.transform(plt.gca().get_position()))
      bbox_data=Bbox([(self.xlim[0],self.ylim[0]),(self.xlim[1],self.ylim[1])])
      transMPL=BboxTransform(bbox_axes,bbox_data)
      self.trans=transMPL
      ax_pt=transMPL.transform_point(point_px)      
      return ax_pt
示例#2
0
    def convert_point(self, point_px, stop=False):
        '''
      given a touch point in the view space, compute the corresponding point in data coords. assumes linear scaling!
      TODO: support log scaling 
      
      there are basically two bbox transforms:  1) from figure coords to view coords, accounting for sign change in y. this then lets us compute axes box in view coords, and generate 2) transform from view to data coords.

      '''
        transFig = BboxTransformTo(Bbox([(0, self.height), (self.width, 0)]))
        bbox_axes = Bbox(transFig.transform(plt.gca().get_position()))
        bbox_data = Bbox([(self.xlim[0], self.ylim[0]),
                          (self.xlim[1], self.ylim[1])])
        transMPL = BboxTransform(bbox_axes, bbox_data)
        self.trans = transMPL
        ax_pt = transMPL.transform_point(point_px)
        return ax_pt
示例#3
0
    def set_bbox_to_anchor(self, bbox, transform=None):
        """
        set the bbox that the legend will be anchored.

        *bbox* can be a BboxBase instance, a tuple of [left, bottom,
        width, height] in the given transform (normalized axes
        coordinate if None), or a tuple of [left, bottom] where the
        width and height will be assumed to be zero.
        """
        if bbox is None:
            self._bbox_to_anchor = None
            return
        elif isinstance(bbox, BboxBase):
            self._bbox_to_anchor = bbox
        else:
            try:
                l = len(bbox)
            except TypeError:
                raise ValueError("Invalid argument for bbox : %s" % str(bbox))

            if l == 2:
                bbox = [bbox[0], bbox[1], 0, 0]

            self._bbox_to_anchor = Bbox.from_bounds(*bbox)

        if transform is None:
            transform = BboxTransformTo(self.parent.bbox)

        self._bbox_to_anchor = TransformedBbox(self._bbox_to_anchor, transform)
示例#4
0
    def _set_lim_and_transforms(self):
        self.transAxes = BboxTransformTo(self.bbox)

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

        # A (possibly non-linear) projection on the (already scaled)
        # data.  This one is aware of rmin
        self.transProjection = self.PolarTransform(self)

        # This one is not aware of rmin
        self.transPureProjection = self.PolarTransform()

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

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

        # This is the transform for theta-axis ticks.  It is
        # equivalent to transData, except it always puts r == 1.0 at
        # the edge of the axis circle.
        self._xaxis_transform = (
            self.transPureProjection +
            self.PolarAffine(IdentityTransform(), Bbox.unit()) +
            self.transAxes)
        # The theta labels are moved from radius == 0.0 to radius == 1.1
        self._theta_label1_position = Affine2D().translate(0.0, 1.1)
        self._xaxis_text1_transform = (
            self._theta_label1_position +
            self._xaxis_transform)
        self._theta_label2_position = Affine2D().translate(0.0, 1.0 / 1.1)
        self._xaxis_text2_transform = (
            self._theta_label2_position +
            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 0.0 to
        # 2pi.
        self._yaxis_transform = (
            Affine2D().scale(np.pi * 2.0, 1.0) +
            self.transData)
        # The r-axis labels are put at an angle and padded in the r-direction
        self._r_label1_position = Affine2D().translate(22.5, self._rpad)
        self._yaxis_text1_transform = (
            self._r_label1_position +
            Affine2D().scale(1.0 / 360.0, 1.0) +
            self._yaxis_transform
            )
        self._r_label2_position = Affine2D().translate(22.5, self._rpad)
        self._yaxis_text2_transform = (
            self._r_label2_position +
            Affine2D().scale(1.0 / 360.0, 1.0) +
            self._yaxis_transform
            )
    def _set_lim_and_transforms(self):
        # A (possibly non-linear) projection on the (already scaled) data
        self.transProjection = self._get_core_transform(self.RESOLUTION)

        self.transAffine = self._get_affine_transform()

        self.transAxes = BboxTransformTo(self.bbox)

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

        self._latitude_axis_longitude = 30

        # This is the transform for longitude ticks.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, self._latitude_cap * 2.0) \
            .translate(0.0, -self._latitude_cap)
        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData
        self._xaxis_text1_transform = Affine2D().translate(0, self._latitude_axis_longitude) + self.transData
        self._xaxis_text2_transform = Affine2D().translate(0, self._latitude_axis_longitude) + self.transData
                                      
        # 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 0.0 to
        # 2pi.
        
#        # This is the transform for longitude ticks.
        self._yaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 89 * 2.0) \
            .translate(0.0, -89)
        self._yaxis_transform = \
            self._yaxis_pretransform + \
            self.transData

        yaxis_stretch = Affine2D().scale(360, 1.0).translate(-180, 0.0)
        
        self._yaxis_transform = yaxis_stretch + self.transData
#        self._yaxis_transform = self.transData
        # The r-axis labels are put at an angle and padded in the r-direction
        self._rpad = 0.05
        
        self._longitude_axis_latitude = -80
        self._r_label1_position = Affine2D().translate(self._longitude_axis_latitude, self._rpad)
        self._yaxis_text1_transform = self._r_label1_position + self.transData
        
        self._r_label2_position = Affine2D().translate(self._longitude_axis_latitude, self._rpad)
        self._yaxis_text2_transform = self._r_label2_position + self.transData
示例#6
0
    def _set_lim_and_transforms(self):
        self.transProjection = StereographicTransform(pole=self.pole)
        self.transAffine = StereographicAffine(pole=self.pole)
        self.transAxes = BboxTransformTo(self.bbox)

        self.transData = self.transProjection + self.transAffine + self.transAxes

        self._xaxis_pretransform = Affine2D().scale(1, self._polar_cap)
        self._xaxis_transform = self._xaxis_pretransform + self.transData

        self._yaxis_pretransform = Affine2D().scale(self._azimuth_cap, 1)
        self._yaxis_transform = self._yaxis_pretransform + self.transData
示例#7
0
 def compute_lims(self):
     '''compute new axes limits based on pan/zoom.
      basically, get limits in terms of bbox of size 1.  
      transform to bbox of size orig lims.       
   '''
     xlnorm = self.hslider.barvalue + np.array([-.5, .5
                                                ]) * self.hslider.barwidth
     ylnorm = self.vslider.barvalue + np.array([-.5, .5
                                                ]) * self.vslider.barwidth
     viewBbox = Bbox(zip(xlnorm, ylnorm))
     limBB = Bbox(zip(self.xlim, self.ylim))
     newlims = Bbox(BboxTransformTo(limBB).transform(viewBbox))
     return [(newlims.x0, newlims.x1), (newlims.y0, newlims.y1)]
示例#8
0
    def _set_lim_and_transforms(self):
        # A (possibly non-linear) projection on the (already scaled) data
        self.transProjection = self._get_core_transform(self.RESOLUTION)

        self.transAffine = self._get_affine_transform()

        self.transAxes = 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 = \
            Affine2D() \
            .scale(1.0, self._longitude_cap * 2.0) \
            .translate(0.0, -self._longitude_cap)
        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData
        self._xaxis_text1_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, 4.0)
        self._xaxis_text2_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, -4.0)

        # This is the transform for latitude ticks.
        yaxis_stretch = Affine2D().scale(np.pi * 2.0,
                                         1.0).translate(-np.pi, 0.0)
        yaxis_space = Affine2D().scale(1.0, 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 + \
            Affine2D().translate(-8.0, 0.0)
        self._yaxis_text2_transform = \
            yaxis_text_base + \
            Affine2D().translate(8.0, 0.0)
示例#9
0
    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # This code is based off of matplotlib's example for a custom Hammer
        # projection. See: https://matplotlib.org/gallery/misc/custom_projection.html#sphx-glr-gallery-misc-custom-projection-py

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # Affine2D.from_values(a, b, c, d, e, f) constructs an affine
        # transformation matrix of
        #    a c e
        #    b d f
        #    0 0 1

        # A useful reference for the different coordinate systems can be found
        # in a table in the matplotlib transforms tutorial:
        # https://matplotlib.org/tutorials/advanced/transforms_tutorial.html#transformations-tutorial

        # The goal of this transformation is to get from the data space to axes
        # space. We perform an affine transformation on the y-axis, i.e.
        # transforming the y-axis from (0, 1) to (0.5, sqrt(3)/2).
        self.transAffine = Affine2D.from_values(1., 0, 0.5,
                                                np.sqrt(3) / 2., 0, 0)
        # Affine transformation along the dependent axis
        self.transAffinedep = Affine2D.from_values(1., 0, -0.5,
                                                   np.sqrt(3) / 2., 0, 0)

        # This is the transformation from axes space to display space.
        self.transAxes = BboxTransformTo(self.bbox)

        # The data transformation is the application of the affine
        # transformation from data to axes space, then from axes to display
        # space. The '+' operator applies these in order.
        self.transData = self.transAffine + self.transAxes

        # The main data transformation is set up.  Now deal with gridlines and
        # tick labels. For these, we want the same trasnform as the, so we
        # apply transData directly.
        self._xaxis_transform = self.transData
        self._xaxis_text1_transform = self.transData
        self._xaxis_text2_transform = self.transData

        self._yaxis_transform = self.transData
        self._yaxis_text1_transform = self.transData
        self._yaxis_text2_transform = self.transData
示例#10
0
    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space to axes space.  It is separated into a non-affine
        # and affine part so that the non-affine part does not have to be
        # recomputed when a simple affine change to the figure has been
        # made (such as resizing the window or changing the dpi).

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        #self.transData = \
        #    self.transProjection + self.transAffine + self.transAxes
        self.transData = self.GingaTransform()
        self.transData.viewer = self.viewer

        # self._xaxis_transform = blended_transform_factory(
        #         self.transData, self.transAxes)
        # self._yaxis_transform = blended_transform_factory(
        #         self.transAxes, self.transData)
        self._xaxis_transform = self.transData
        self._yaxis_transform = self.transData
示例#11
0
        def _set_lim_and_transforms(self):
            self.transProjection = self._get_core_transform(self.RESOLUTION)
            self.transAffine = self._get_affine_transform()
            self.transAxes = BboxTransformTo(self.bbox)
            self.transData = \
                self.transProjection + \
                self.transAffine + \
                self.transAxes

            self._xaxis_pretransform = \
                Affine2D() \
                .scale(1.0, self._longitude_cap * 2.0)\
                .translate(0.0, -self._longitude_cap)

            self._xaxis_transform = \
                self._xaxis_pretransform + \
                self.transData
            self._xaxis_text1_transform = \
                Affine2D().scale(1.0, 0.0) + \
                self.transData + \
                Affine2D().translate(0.0, 4.0)

            self._xaxis_text2_transform = \
                Affine2D().scale(1.0, 0.0) + \
                self.transData + \
                Affine2D().translate(0.0, -4.0)

            yaxis_stretch = Affine2D().scale(np.pi * 2, 1).translate(-np.pi, 0)
            yaxis_space = Affine2D().scale(1.0, 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 + \
                Affine2D().translate(-8.0, 0.0)
            self._yaxis_text2_transform = \
                yaxis_text_base + \
                Affine2D().translate(8.0, 0.0)
示例#12
0
    def set_bbox_to_anchor(self, bbox, transform=None):
        """
        Set the bbox that the legend will be anchored to.

        Parameters
        ----------
        bbox : `~matplotlib.transforms.BboxBase` or tuple
            The bounding box can be specified in the following ways:

            - A `.BboxBase` instance
            - A tuple of ``(left, bottom, width, height)`` in the given
              transform (normalized axes coordinate if None)
            - A tuple of ``(left, bottom)`` where the width and height will be
              assumed to be zero.
            - *None*, to remove the bbox anchoring, and use the parent bbox.

        transform : `~matplotlib.transforms.Transform`, optional
            A transform to apply to the bounding box. If not specified, this
            will use a transform to the bounding box of the parent.
        """
        if bbox is None:
            self._bbox_to_anchor = None
            return
        elif isinstance(bbox, BboxBase):
            self._bbox_to_anchor = bbox
        else:
            try:
                l = len(bbox)
            except TypeError as err:
                raise ValueError("Invalid argument for bbox : %s" %
                                 str(bbox)) from err

            if l == 2:
                bbox = [bbox[0], bbox[1], 0, 0]

            self._bbox_to_anchor = Bbox.from_bounds(*bbox)

        if transform is None:
            transform = BboxTransformTo(self.parent.bbox)

        self._bbox_to_anchor = TransformedBbox(self._bbox_to_anchor,
                                               transform)
        self.stale = True
示例#13
0
    def create_artists(self, legend, orig_handle, xdescent, ydescent, width,
                       height, fontsize, trans):

        legline, _ = HandlerLine2D.create_artists(self, legend, orig_handle,
                                                  xdescent, ydescent, width,
                                                  height, fontsize, trans)

        legline.set_data(*orig_handle.get_data())

        ext = mpath.get_paths_extents([orig_handle.get_path()])
        if ext.width == 0:
            ext.x0 -= 0.1
            ext.x1 += 0.1
        bbox0 = BboxTransformFrom(ext)
        bbox1 = BboxTransformTo(
            Bbox.from_bounds(xdescent, ydescent, width, height))

        legline.set_transform(bbox0 + bbox1 + trans)
        return legline,
示例#14
0
文件: aea.py 项目: Jravis/mpl_aea
class SkymapperAxes(Axes):
    """
    A base class for a Skymapper axes that takes in ra0, dec0, dec1, dec2.

    The base class takes care of clipping and interpolating with matplotlib.

    Subclass and override class method get_projection_class.

    """
    # The subclass projection must specify a name.  This will be used be the
    # user to select the projection.

    name = None

    @classmethod
    def get_projection_class(kls):
        raise NotImplementedError('Must implement this in subclass')

    def __init__(self, *args, **kwargs):
        self.ra0 = None
        self.dec0 = None
        self.dec1 = None
        self.dec2 = None

        Axes.__init__(self, *args, **kwargs)

        self.cla()

    def _init_axis(self):
        # Axes._init_axis() -- until HammerAxes.xaxis.cla() works.
        self.xaxis = maxis.XAxis(self)
        self.spines['bottom'].register_axis(self.xaxis)
        self.spines['top'].register_axis(self.xaxis)
        self.yaxis = maxis.YAxis(self)
        self.spines['left'].register_axis(self.yaxis)
        self.spines['right'].register_axis(self.yaxis)
        self.yaxis.set_tick_params(pad=-12)
        self.xaxis.set_tick_params(pad=-12)
        self._update_transScale()

    def cla(self):
        """
        Override to set up some reasonable defaults.
        """
        # Don't forget to call the base class
        Axes.cla(self)

        self.patch.set_transform(self.transClip)

        # Turn off minor ticking altogether
        self.xaxis.set_minor_locator(NullLocator())
        self.yaxis.set_minor_locator(NullLocator())

        self.xaxis.set_major_locator(MaxNLocator(5, prune='both'))
        self.yaxis.set_major_locator(MaxNLocator(5, prune='both'))

        # Do not display ticks -- we only want gridlines and text
        self.xaxis.set_ticks_position('none')
        self.yaxis.set_ticks_position('none')

        self.set_center(None, None)

        # FIXME: probabaly want to override autoscale_view
        # to properly handle wrapping introduced by margin
        # and properlty wrap data.
        # It doesn't make sense to have xwidth > 360.
        self._tight = True
        self._xmargin = 0
        self._ymargin = 0

    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space (in this case meridian and parallel) to axes
        # space.  It is separated into a non-affine and affine part so
        # that the non-affine part does not have to be recomputed when
        # a simple affine change to the figure has been made (such as
        # resizing the window or changing the dpi).

        # 1) The core transformation from data space into
        # rectilinear space defined in the HammerTransform class.
        self.transProjection = self.get_projection_class()()
        self.transProjection.set_center((180, 0))
        self.transProjection.set_dec1(-65)
        self.transProjection.set_dec2(80)

        # 2) The above has an output range that is not in the unit
        # rectangle, so scale and translate it so it fits correctly
        # within the axes.  The peculiar calculations of xscale and
        # yscale are specific to a Aitoff-Hammer projection, so don't
        # worry about them too much.

        # This will be updated after the xy limits are set.
        self.transAffine = Affine2D()

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        self.transClip = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        # The main data transformation is set up.  Now deal with
        # gridlines and tick labels.

        # Longitude gridlines and ticklabels.  The input to these
        # transforms are in display space in x and axes space in y.
        # Therefore, the input values will be in range (-xmin, 0),
        # (xmax, 1).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the equator.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 180) \
            .translate(0.0, -90)

        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData

        self._xaxis_text1_transform = \
            self._xaxis_pretransform + \
            self.transData# + \
        #            Affine2D().translate(0.0, -8.0)
        self._xaxis_text2_transform = \
            self._xaxis_pretransform+ \
            self.transData# + \
        #            Affine2D().translate(0.0, -8.0)

        # Now set up the transforms for the parallel ticks.  The input to
        # these transforms are in axes space in x and display space in
        # y.  Therefore, the input values will be in range (0, -ymin),
        # (1, ymax).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the edge of the axes ellipse.
        self._yaxis_stretch = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_stretch1 = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_stretch2 = Affine2D().scale(360, 1.0).translate(0.0, 0.0)

        self._yaxis_transform = \
            self._yaxis_stretch + \
            self.transData

        self._yaxis_text1_transform = \
            self._yaxis_stretch1 + \
            self.transData# + \
        #            Affine2D().translate(-8.0, 0.0)

        self._yaxis_text2_transform = \
            self._yaxis_stretch2 + \
            self.transData# + \
#            Affine2D().translate(8.0, 0.0)

    def _update_affine(self):
        # update the transformations and clip paths
        # after new lims are set.
        if self.ra0 is None:
            x0, x1 = self.viewLim.intervalx
            ra0 = 0.5 * (x0 + x1)
        else:
            ra0 = self.ra0
        if self.dec0 is None:
            y0, y1 = self.viewLim.intervaly
            dec0 = 0.5 * (y0 + y1)
        else:
            dec0 = self.dec0
        if self.dec1 is None:
            y0, y1 = self.viewLim.intervaly
            dec1 = -max(abs(y0), abs(y1)) * 11. / 12
        else:
            dec1 = self.dec1

        if self.dec2 is None:
            y0, y1 = self.viewLim.intervaly
            dec2 = -dec1
        else:
            dec2 = self.dec2

        self.transProjection.set_center((ra0, dec0))
        self.transProjection.set_dec1(dec1)
        self.transProjection.set_dec2(dec2)

        self._yaxis_stretch\
            .clear() \
            .scale(self.viewLim.width, 1.0) \
            .translate(self.viewLim.x0, 0)

        self._yaxis_stretch1\
            .clear() \
            .scale(self.viewLim.width, 1.0) \
            .translate(self.viewLim.x0 - 0.00 * self.viewLim.width, 0)

        self._yaxis_stretch2\
            .clear() \
            .scale(self.viewLim.width, 1.0) \
            .translate(self.viewLim.x0 + 0.00 * self.viewLim.width, 0)

        self._xaxis_pretransform \
            .clear() \
            .scale(1.0, self.viewLim.height) \
            .translate(0.0, self.viewLim.y0)

        corners_data = np.array([
            [self.viewLim.x0, self.viewLim.y0],
            [ra0, self.viewLim.y0],
            [self.viewLim.x1, self.viewLim.y0],
            [self.viewLim.x1, self.viewLim.y1],
            [self.viewLim.x0, self.viewLim.y1],
        ])

        corners = self.transProjection.transform_non_affine(corners_data)

        x0 = corners[0][0]
        x1 = corners[2][0]

        # special case when x1 is wrapped back to x0
        # FIXME: I don't think we need it anymore.
        if x0 == x1: x1 = -x0

        y0 = corners[1][1]
        y1 = max([corners[3][1], corners[4][1]])

        xscale = x1 - x0
        yscale = y1 - y0

        self.transAffine.clear() \
            .translate( - (x0 + x1) * 0.5, - (y0 + y1) * 0.5) \
            .scale(0.95 / xscale, 0.95 / yscale)  \
            .translate(0.5, 0.5)

        if hasattr(self, 'patch'):
            # now update the clipping path
            path = Path(corners_data)
            #path0 = self.transProjection.transform_path(path)
            #path = self.transClip.transform_path(path)
            #print('self.patch', id(self.patch))
            #print('vertices', path.vertices)
            #print('self.path.transform', self.patch.get_transform())
            self.patch.set_xy(path.vertices)

    def get_xaxis_transform(self, which='grid'):
        """
        Override this method to provide a transformation for the
        x-axis grid and ticks.
        """
        assert which in ['tick1', 'tick2', 'grid']
        return self._xaxis_transform

    def get_xaxis_text1_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        x-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._xaxis_text1_transform + Affine2D().translate(
            0.0, pixelPad), 'center', 'center'

    def get_xaxis_text2_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        secondary x-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._xaxis_text2_transform + Affine2D().translate(
            0.0, pixelPad), 'center', 'center'

    def get_yaxis_transform(self, which='grid'):
        """
        Override this method to provide a transformation for the
        y-axis grid and ticks.
        """
        assert which in ['tick1', 'tick2', 'grid']
        return self._yaxis_transform

    def get_yaxis_text1_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        y-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._yaxis_text1_transform + Affine2D().translate(
            pixelPad, 0.0), 'center', 'center'

    def get_yaxis_text2_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        secondary y-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._yaxis_text2_transform + Affine2D().translate(
            pixelPad, 0.0), 'center', 'center'

    def _gen_axes_patch(self):
        """
        ClipPath.

        Initially set to a size of 2 box in transAxes.

        After xlim and ylim are set, this will be changed to the actual
        region in transData.

        For unclear reason the very initial clip path is always applied
        to the grid. Therefore we set size to 2.0 to avoid bad clipping.
        """
        return Polygon([(0, 0), (0, 0), (0, 0), (0, 0)], fill=False)

    def _gen_axes_spines(self):
        d = {
            'left': mspines.Spine.linear_spine(self, spine_type='left'),
            'right': mspines.Spine.linear_spine(self, spine_type='right'),
            'top': mspines.Spine.linear_spine(self, spine_type='top'),
            'bottom': mspines.Spine.linear_spine(self, spine_type='bottom'),
        }
        d['left'].set_position(('axes', 0))
        d['right'].set_position(('axes', 1))
        d['top'].set_position(('axes', 0))
        d['bottom'].set_position(('axes', 1))
        #FIXME: these spines can be moved wit set_position(('axes', ?)) but
        # 'data' fails. Because the transformation is non-separatable,
        # and because spines / data makes that assumption, we probably
        # do not have a easy way to support moving spines via native matplotlib
        # api on data axis.

        # also the labels currently do not follow the spines. Likely because
        # they are not registered?

        return d

    # Prevent the user from applying scales to one or both of the
    # axes.  In this particular case, scaling the axes wouldn't make
    # sense, so we don't allow it.
    def set_xscale(self, *args, **kwargs):
        if args[0] != 'linear':
            raise NotImplementedError
        Axes.set_xscale(self, *args, **kwargs)

    def set_yscale(self, *args, **kwargs):
        if args[0] != 'linear':
            raise NotImplementedError
        Axes.set_yscale(self, *args, **kwargs)

    def set_center(self, ra0, dec0):
        """ Set the center of ra """
        self.ra0 = ra0
        self.dec0 = dec0
        self._update_affine()

    def set_parallels(self, dec1, dec2):
        """ Set the parallels """
        self.dec1 = dec1
        self.dec2 = dec2
        self._update_affine()

    # when xlim and ylim are updated, the transformation
    # needs to be updated too.
    def set_xlim(self, *args, **kwargs):
        Axes.set_xlim(self, *args, **kwargs)

        # FIXME: wrap x0 x1 to ensure they enclose ra0.
        x0, x1 = self.viewLim.intervalx
        if self.ra0 is not None:
            if not x0 <= self.transProjection.ra0 or \
               not x1 > self.transProjection.ra0:
                raise ValueError("The given limit in RA does not enclose ra0")

        self._update_affine()

    def set_ylim(self, *args, **kwargs):
        Axes.set_ylim(self, *args, **kwargs)
        self._update_affine()

    def _histmap(self,
                 show,
                 ra,
                 dec,
                 weights=None,
                 nside=32,
                 perarea=False,
                 mean=False,
                 range=None,
                 **kwargs):
        r = healpix.histogrammap(ra,
                                 dec,
                                 weights,
                                 nside,
                                 perarea=perarea,
                                 range=range)

        if weights is not None:
            w, N = r
        else:
            w = r
        if mean:
            mask = N != 0
            w[mask] /= N[mask]
        else:
            mask = w > 0
        return w, mask, show(w, mask, nest=False, **kwargs)

    def histmap(self,
                ra,
                dec,
                weights=None,
                nside=None,
                perarea=False,
                mean=False,
                range=None,
                **kwargs):
        """ Making a histogram with healpix for variables located at RA, DEC.


            Parameters
            ----------
            ra, dec : angular positions
            weights : the weight at the position
            nside : band width of the healpix map. None for automatically decided.
            perarea : normalized to per unit area
            mean : use the average per pixel instead of sum per pixel.
            range : filter ra dec to ((ra0, dec0), (ra1, dec1))
            cmap : color map
            vmin, vmax : min and max.


        """
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        defaults = dict(rasterized=True, alpha=1.0, linewidth=0)
        defaults.update(kwargs)

        coll = HealpixHistogram(ra,
                                dec,
                                weights,
                                nside,
                                perarea,
                                mean,
                                range,
                                transform=self.transData,
                                **defaults)

        coll.set_clim(vmin=vmin, vmax=vmax)
        self.add_collection(coll)
        self._sci(coll)
        self.autoscale_view(tight=True)

        return coll

    def histcontour(self,
                    ra,
                    dec,
                    weights=None,
                    nside=32,
                    perarea=False,
                    mean=False,
                    range=None,
                    **kwargs):
        return self._histmap(self.mapcontour, ra, dec, weights, nside, perarea,
                             mean, range, **kwargs)

    def histcontourf(self,
                     ra,
                     dec,
                     weights=None,
                     nside=32,
                     perarea=False,
                     mean=False,
                     range=None,
                     **kwargs):
        kwargs['filled'] = True
        return self._histmap(self.mapcontour, ra, dec, weights, nside, perarea,
                             mean, range, **kwargs)

    def mapshow(self, map, mask=None, nest=False, shading='smooth', **kwargs):
        """ Display a healpix map """
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        defaults = dict(rasterized=True, alpha=1.0, linewidth=0)
        defaults.update(kwargs)
        if mask is None:
            mask = map == map

        if shading == 'flat':
            coll = HealpixQuadCollection(map,
                                         mask,
                                         transform=self.transData,
                                         **defaults)
        elif shading == 'smooth':
            coll = HealpixTriCollection(map,
                                        mask,
                                        transform=self.transData,
                                        **defaults)

        coll.set_clim(vmin=vmin, vmax=vmax)
        self.add_collection(coll)
        self._sci(coll)
        self.autoscale_view(tight=True)

        return coll

    def mapcontour(self, map, mask=None, nest=False, **kwargs):
        """ Display a healpix map as coutours. This is approximate. """
        if mask is None:
            mask = map == map

        ra, dec = healpix.pix2radec(healpix.npix2nside(len(map)),
                                    mask.nonzero()[0])
        filled = kwargs.pop('filled', False)
        if filled:
            im = self.tricontourf(ra, dec, map[mask], **kwargs)
        else:
            im = self.tricontour(ra, dec, map[mask], **kwargs)
        self._sci(im)
        self.autoscale_view(tight=True)
        return im

    def format_coord(self, lon, lat):
        """
        Override this method to change how the values are displayed in
        the status bar.

        In this case, we want them to be displayed in degrees N/S/E/W.
        """
        lon = lon
        lat = lat
        if lat >= 0.0:
            ns = 'N'
        else:
            ns = 'S'
        if lon >= 0.0:
            ew = 'E'
        else:
            ew = 'W'
        # \u00b0 : degree symbol
        return '%f\u00b0%s, %f\u00b0%s' % (abs(lat), ns, abs(lon), ew)

    class DegreeFormatter(Formatter):
        """
        This is a custom formatter that converts the native unit of
        radians into (truncated) degrees and adds a degree symbol.
        """
        def __init__(self, round_to=1.0):
            self._round_to = round_to

        def __call__(self, x, pos=None):
            degrees = round(x / self._round_to) * self._round_to
            # \u00b0 : degree symbol
            return "%d\u00b0" % degrees

    def set_meridian_grid(self, degrees):
        """
        Set the number of degrees between each meridian grid.

        It provides a more convenient interface to set the ticking than set_xticks would.
        """
        # Set up a FixedLocator at each of the points, evenly spaced
        # by degrees.
        x0, x1 = self.get_xlim()
        number = abs((x1 - x0) / degrees) + 1
        self.xaxis.set_major_locator(
            FixedLocator(np.linspace(x0, x1, number, True)[1:-1]))
        # Set the formatter to display the tick labels in degrees,
        # rather than radians.
        self.xaxis.set_major_formatter(self.DegreeFormatter(degrees))

    def set_parallel_grid(self, degrees):
        """
        Set the number of degrees between each meridian grid.

        It provides a more convenient interface than set_yticks would.
        """
        # Set up a FixedLocator at each of the points, evenly spaced
        # by degrees.
        y0, y1 = self.get_ylim()
        number = ((y1 - y0) / degrees) + 1
        self.yaxis.set_major_locator(
            FixedLocator(np.linspace(y0, y1, number, True)[1:-1]))
        # Set the formatter to display the tick labels in degrees,
        # rather than radians.
        self.yaxis.set_major_formatter(self.DegreeFormatter(degrees))

    # Interactive panning and zooming is not supported with this projection,
    # so we override all of the following methods to disable it.
    def _in_axes(self, mouseevent):
        if hasattr(self._pan_trans):
            return True
        else:
            return Axes._in_axes(self, mouseevent)

    def can_zoom(self):
        """
        Return True if this axes support the zoom box
        """
        return True

    def start_pan(self, x, y, button):
        self._pan_trans = self.transAxes.inverted() + \
                blended_transform_factory(
                        self._yaxis_stretch,
                        self._xaxis_pretransform,)

    def end_pan(self):
        delattr(self, '_pan_trans')

    def drag_pan(self, button, key, x, y):
        pan1 = self._pan_trans.transform([(x, y)])[0]
        self.set_ra0(360 - pan1[0])
        self.set_dec0(pan1[1])
        self._update_affine()
class GeoAxes(Axes):
    """
    An abstract base class for geographic projections
    """
    
    RESOLUTION = 75

    def _init_axis(self):
        self.xaxis = maxis.XAxis(self)
        self.yaxis = maxis.YAxis(self)
        # Do not register xaxis or yaxis with spines -- as done in
        # Axes._init_axis() -- until GeoAxes.xaxis.cla() works.
        # self.spines['geo'].register_axis(self.yaxis)
        self._update_transScale()

    def coastlines(self):
        cartopy.coastlines.add_coastlines()

    def cla(self):
        Axes.cla(self)

        self.set_longitude_grid(30)
        self.set_latitude_grid(10)
        self.set_longitude_grid_ends(89)
        self.set_latitude_grid_ends(89)
        self.xaxis.set_minor_locator(NullLocator())
        self.yaxis.set_minor_locator(NullLocator())
        self.xaxis.set_ticks_position('none')
        self.yaxis.set_ticks_position('none')
#        self.yaxis.set_tick_params(label1On=True)
        # Why do we need to turn on yaxis tick labels, but
        # xaxis tick labels are already on?

        self.grid(rcParams['axes.grid'])

        Axes.set_xlim(self, -180, 179.999)
#        Axes.set_ylim(self, -90, 90)
        Axes.set_ylim(self, -80, 80)
        
    def _set_lim_and_transforms(self):
        # A (possibly non-linear) projection on the (already scaled) data
        self.transProjection = self._get_core_transform(self.RESOLUTION)

        self.transAffine = self._get_affine_transform()

        self.transAxes = BboxTransformTo(self.bbox)

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

        self._latitude_axis_longitude = 30

        # This is the transform for longitude ticks.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, self._latitude_cap * 2.0) \
            .translate(0.0, -self._latitude_cap)
        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData
        self._xaxis_text1_transform = Affine2D().translate(0, self._latitude_axis_longitude) + self.transData
        self._xaxis_text2_transform = Affine2D().translate(0, self._latitude_axis_longitude) + self.transData
                                      
        # 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 0.0 to
        # 2pi.
        
#        # This is the transform for longitude ticks.
        self._yaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 89 * 2.0) \
            .translate(0.0, -89)
        self._yaxis_transform = \
            self._yaxis_pretransform + \
            self.transData

        yaxis_stretch = Affine2D().scale(360, 1.0).translate(-180, 0.0)
        
        self._yaxis_transform = yaxis_stretch + self.transData
#        self._yaxis_transform = self.transData
        # The r-axis labels are put at an angle and padded in the r-direction
        self._rpad = 0.05
        
        self._longitude_axis_latitude = -80
        self._r_label1_position = Affine2D().translate(self._longitude_axis_latitude, self._rpad)
        self._yaxis_text1_transform = self._r_label1_position + self.transData
        
        self._r_label2_position = Affine2D().translate(self._longitude_axis_latitude, self._rpad)
        self._yaxis_text2_transform = self._r_label2_position + self.transData

    def _get_affine_transform(self):
        # The scaling transform to go from proj XY meters to axes coords
        transform = self._get_core_transform(1)
        
#        x_extreme, y_extreme = self.projection.get_extreme_points()
#        xscale, _ = transform.transform_point(x_extreme)
#        _, yscale = transform.transform_point(y_extreme)
#        return Affine2D().scale(0.5 / xscale, 0.5 / yscale).translate(0.5, 0.5)

        
        x_extreme, y_extreme = self.projection.forward(self.projection.edge.interpolated(100).vertices[:, 0], 
                                                       self.projection.edge.interpolated(100).vertices[:, 1], nans=True)
#        print x_extreme, y_extreme
        xscale, yscale = np.nanmax(np.abs(x_extreme)), np.nanmax(np.abs(y_extreme))

#        print 'scales: ', xscale, yscale
        return Affine2D().scale(0.5 / xscale, 0.5 / yscale).translate(0.5, 0.5)

    def get_xaxis_transform(self,which='grid'):
        assert which in ['tick1','tick2','grid']
        return self._xaxis_transform

    def get_xaxis_text1_transform(self, pad):
        return self._xaxis_text1_transform, 'bottom', 'center'

    def get_xaxis_text2_transform(self, pad):
        return self._xaxis_text2_transform, 'top', 'center'

    def get_yaxis_transform(self, which='grid'):
        assert which in ['tick1','tick2','grid']
        return self._yaxis_transform

    def get_yaxis_text1_transform(self, pad):
        return self._yaxis_text1_transform, 'center', 'right'

    def get_yaxis_text2_transform(self, pad):
        return self._yaxis_text2_transform, 'center', 'left'

    def _gen_axes_patch(self):
        import matplotlib.patches as mpatches
        s = self.projection.edge
        p = self.transData.transform_path(s)
        p = self.transAxes.inverted().transform_path(p)
        return mpatches.PathPatch(p, transform=self.transAxes)
#        return mpatches.Rectangle([0,0], 1, 1, transform=self.transAxes)
        return Circle((0.5, 0.5), 0.5, transform=self.transAxes)

    def _gen_axes_spines(self):
        return {}
    
    def set_yscale(self, *args, **kwargs):
        if args[0] != 'linear':
            raise NotImplementedError

    set_xscale = set_yscale

    def set_xlim(self, *args, **kwargs):
        Axes.set_xlim(self, -180, 180)
        Axes.set_ylim(self, -90, 90)

    set_ylim = set_xlim

    def format_coord(self, long, lat):
        """"return a format string formatting the coordinate."""
        ns = 'N' if lat >= 0.0 else 'S'
        ew = 'E' if long >= 0.0 else 'W'
        
        # XXX adaptive resolution
        return u'%f\u00b0%s, %f\u00b0%s' % (abs(lat), ns, abs(long), ew)
        
    def set_longitude_grid(self, degrees):
        """
        Set the number of degrees between each longitude grid.
        """
        self.xaxis.set_major_locator(LinearLocator(6))
        self.xaxis.set_major_formatter(ThetaFormatter())

    def set_latitude_grid(self, degrees):
        """
        Set the number of degrees between each longitude grid.
        """
        self.yaxis.set_major_locator(FixedLocator(np.linspace(-90, 90, degrees)[1:-1]))
        self.yaxis.set_major_formatter(ThetaFormatter())

    def set_longitude_grid_ends(self, degrees):
        """
        Set the latitude(s) at which to stop drawing the longitude grids.
        """
        self._latitude_cap = degrees
        self._xaxis_pretransform \
            .clear() \
            .scale(1.0, self._latitude_cap * 2.0) \
            .translate(0.0, -self._latitude_cap)

    def set_latitude_grid_ends(self, degrees):
        """
        Set the longitude(s) at which to stop drawing the latitude grids.
        """
        return
        self._latitude_cap = degrees
        self._yaxis_pretransform \
            .clear() \
            .scale(1.0, self._latitude_cap * 2.0) \
            .translate(0.0, -self._latitude_cap)

    def get_data_ratio(self):
        '''
        Return the aspect ratio of the data itself.
        '''
        return 1.0

    def start_pan(self, x, y, button):
        pass

    def end_pan(self):
        pass

    def drag_pan(self, button, key, x, y):
        pass
示例#16
0
 def __call__(self, ax, renderer):
     bbox_parent = self.parent.get_position(original=False)
     trans = BboxTransformTo(bbox_parent)
     bbox_inset = Bbox.from_bounds(*self.lbwh)
     bb = TransformedBbox(bbox_inset, trans)
     return bb
示例#17
0
    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space (in this case meridian and parallel) to axes
        # space.  It is separated into a non-affine and affine part so
        # that the non-affine part does not have to be recomputed when
        # a simple affine change to the figure has been made (such as
        # resizing the window or changing the dpi).

        # 1) The core transformation from data space into
        # rectilinear space defined in the HammerTransform class.
        self.transProjection = self.get_projection_class()()
        self.transProjection.set_center((180, 0))
        self.transProjection.set_dec1(-65)
        self.transProjection.set_dec2(80)

        # 2) The above has an output range that is not in the unit
        # rectangle, so scale and translate it so it fits correctly
        # within the axes.  The peculiar calculations of xscale and
        # yscale are specific to a Aitoff-Hammer projection, so don't
        # worry about them too much.

        # This will be updated after the xy limits are set.
        self.transAffine = Affine2D()

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        self.transClip = \
            self.transProjection + \
            self.transAffine

        # The main data transformation is set up.  Now deal with
        # gridlines and tick labels.

        # Longitude gridlines and ticklabels.  The input to these
        # transforms are in display space in x and axes space in y.
        # Therefore, the input values will be in range (-xmin, 0),
        # (xmax, 1).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the equator.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 180) \
            .translate(0.0, -90)

        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData

        # modify this transformation to move x labels.
        self._xaxis_text_shift = \
            Affine2D().translate(0, 0)

        self._xaxis_text1_transform = \
            self._xaxis_text_shift + \
            self.transData + \
            Affine2D().translate(0.0, -8.0)
        self._xaxis_text2_transform = \
            self._xaxis_text_shift + \
            self.transData + \
            Affine2D().translate(0.0, -8.0)

        # Now set up the transforms for the parallel ticks.  The input to
        # these transforms are in axes space in x and display space in
        # y.  Therefore, the input values will be in range (0, -ymin),
        # (1, ymax).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the edge of the axes ellipse.
        self._yaxis_stretch = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_transform = \
            self._yaxis_stretch + \
            self.transData
        yaxis_text_base = \
            self._yaxis_stretch + \
            self.transProjection + \
            (self.transAffine +
             self.transAxes)
        self._yaxis_text1_transform = \
            yaxis_text_base + \
            Affine2D().translate(8.0, 0.0)
        self._yaxis_text2_transform = \
            yaxis_text_base + \
            Affine2D().translate(-8.0, 0.0)
示例#18
0
    numSamples, numRows = 800,4
    data = fromstring(file('data/eeg.dat', 'rb').read(), float)
    data.shape = numSamples, numRows
    t = arange(numSamples)/float(numSamples)*10.0
    ticklocs = []
    ax = subplot(212)
    xlim(0,10)
    xticks(arange(10))

    boxin = Bbox.from_extents(ax.viewLim.x0, -20, ax.viewLim.x1, 20)

    height = ax.bbox.height
    boxout = Bbox.from_extents(ax.bbox.x0, -1.0 * height,
                               ax.bbox.x1,  1.0 * height)

    transOffset = BboxTransformTo(
        Bbox.from_extents(0.0, ax.bbox.y0, 1.0, ax.bbox.y1))


    for i in range(numRows):
        # effectively a copy of transData
        trans = BboxTransform(boxin, boxout)
        offset = (i+1)/(numRows+1)

        trans += Affine2D().translate(*transOffset.transform_point((0, offset)))

        thisLine = Line2D(
            t, data[:,i]-data[0,i],
            )

        thisLine.set_transform(trans)
示例#19
0
 def __init__(self, ax, bbox, color, *, extent=(0, 1, 0, 1), **kwargs):
     super().__init__(ax, extent=extent, **kwargs)
     self._bbox = bbox
     self._ribbonbox = RibbonBox(color)
     self.set_transform(BboxTransformTo(bbox))
示例#20
0
    def _set_lim_and_transforms(self):
        """
        Hanya akan berlangsung sekali saja ketika plot/alur sudah 
        menentukan pengaturan umum pada transformasi pada, teks dan tempat
        """
        #	Ada beberapa bagian yang harus anda ketahui :
        #1. Data space 		: ruang pada data itu sendiri
        #2. Axes space 		: unit segiempat (0, 0) to (1, 1) untuk
        #				 	  melengkapi area masukan
        #3. Display space 	: kordinat yang dihasilkan pada gambar
        #       			   biasanya dalam pixel atau dpi/inch
        #
        #fungsi ini lumayan berat pada transformasi kelas dalam
        # ``lib/matplotlib/transforms.py.``
        #tujuan dari transformasi awal kedua transformasi adalah menetapkan
        #data space dalam hal ini adalah longitude dan latitude pada ruang sumbu
        #hal ini kemudian dibagi menjadi non-affine dan affine yang dimaksud dengan
        #non-affine adalah dimana tidak ada perhitungan kembali ketika
        #affine sudah dirubah menjadi gambar yang sudah jadi seperti
        #merubah ukuran tampilan dan mengubah dpi
        #
        # 1) Inti transfrmasi dari data space menjadi rectilinear space
        #sudah dijelaskan dalam kelas HammerTransform
        self.transProjection = self.HammerTransform()

        # 2) Rentang hasil keluaran sebelumnya bukan dalam segiempat unit
        #maka skala dan juga penerjemahannya menjadi cocok dengan sumbu
        #perhitungan yang unik pada xscale dan yscale spesifik pada
        #projek Aitoff-Hammer maka tidak usah ragu
        xscale = 2.0 * np.sqrt(2.0) * np.sin(0.5 * np.pi)
        yscale = np.sqrt(2.0) * np.sin(0.5 * np.pi)
        self.transAffine = Affine2D() \
            .scale(0.5 / xscale, 0.5 / yscale) \
            .translate(0.5, 0.5)

        # 3) Menstransformasikan dari ruang sumbu pada ruang tampilan
        self.transAxes = BboxTransformTo(self.bbox)

        #tambahkan ke 3 transormasi ini bersama-sama dari seluruh data
        #untuk mencapai tampilan kordinat menggunakan operator '+' ,
        #ditransformasi menjadi "in order". Transformasi secara otomatis
        #sangatlah sederhana, kalaupun bisa dengan dasar framework transformasi
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        #data utama transformasi sudah ditentukan
        #maka sekarang tentukan gridlines and tick labels.
        #Longitude gridlines dan ticklabels. Masukan pada transformasi
        #dalam display space x and sumbu ruang y.
        #Maka, nilai masukan dalam rentang(-xmin, 0), (xmax, 1)
        #Tujuan akhir dari transformasi ini adalah mencapai ruang display space
        #ketebalan label akan menjadi offset 4 pixels dari the equator
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, np.pi) \
            .translate(0.0, -np.pi)
        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData
        self._xaxis_text1_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, 4.0)
        self._xaxis_text2_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, -4.0)

        #menentukan ketebalan latitude. Masukan pada transformasi dalam
        #sumbu ruang pada x dan display space pada y. Selanjutnya,
        #masukan pada transformasidalam display space x and sumbu ruang y.
        #Maka, nilai masukan dalam rentang(-xmin, 0), (xmax, 1)
        #Tujuan akhir dari transformasi ini adalah mencapai ruang display space
        #ketebalan label akan menjadi offset 4 pixels dari the equator
        yaxis_stretch = Affine2D().scale(np.pi * 2.0,
                                         1.0).translate(-np.pi, 0.0)
        yaxis_space = Affine2D().scale(1.0, 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 + \
            Affine2D().translate(-8.0, 0.0)
        self._yaxis_text2_transform = \
            yaxis_text_base + \
            Affine2D().translate(8.0, 0.0)
示例#21
0
    def _set_lim_and_transforms(self):
        # A (possibly non-linear) projection on the (already scaled) data

        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space (in this case longitude and latitude) to axes
        # space.  It is separated into a non-affine and affine part so
        # that the non-affine part does not have to be recomputed when
        # a simple affine change to the figure has been made (such as
        # resizing the window or changing the dpi).

        # 1) The core transformation from data space into
        # rectilinear space defined in the HammerTransform class.
        self.transProjection = self._get_core_transform(self.RESOLUTION)

        # 2) The above has an output range that is not in the unit
        # rectangle, so scale and translate it so it fits correctly
        # within the axes.  The peculiar calculations of xscale and
        # yscale are specific to a Aitoff-Hammer projection, so don't
        # worry about them too much.
        self.transAffine = self._get_affine_transform()

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        # The main data transformation is set up.  Now deal with
        # gridlines and tick labels.

        # Longitude gridlines and ticklabels.  The input to these
        # transforms are in display space in x and axes space in y.
        # Therefore, the input values will be in range (-xmin, 0),
        # (xmax, 1).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the equator.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, self._longitude_cap * 2.0) \
            .translate(0.0, -self._longitude_cap)
        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData
        self._xaxis_text1_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, 4.0)
        self._xaxis_text2_transform = \
            Affine2D().scale(1.0, 0.0) + \
            self.transData + \
            Affine2D().translate(0.0, -4.0)

        # Now set up the transforms for the latitude ticks.  The input to
        # these transforms are in axes space in x and display space in
        # y.  Therefore, the input values will be in range (0, -ymin),
        # (1, ymax).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the edge of the axes ellipse.
        yaxis_stretch = Affine2D().scale(np.pi * 2, 1).translate(-np.pi, 0)
        yaxis_space = Affine2D().scale(1.0, 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 + \
            Affine2D().translate(-8.0, 0.0)
        self._yaxis_text2_transform = \
            yaxis_text_base + \
            Affine2D().translate(8.0, 0.0)
示例#22
0
    numSamples, numRows = 800, 4
    data = fromstring(file('data/eeg.dat', 'rb').read(), float)
    data.shape = numSamples, numRows
    t = arange(numSamples) / float(numSamples) * 10.0
    ticklocs = []
    ax = subplot(212)
    xlim(0, 10)
    xticks(arange(10))

    boxin = Bbox.from_extents(ax.viewLim.x0, -20, ax.viewLim.x1, 20)

    height = ax.bbox.height
    boxout = Bbox.from_extents(ax.bbox.x0, -1.0 * height, ax.bbox.x1,
                               1.0 * height)

    transOffset = BboxTransformTo(
        Bbox.from_extents(0.0, ax.bbox.y0, 1.0, ax.bbox.y1))

    for i in range(numRows):
        # effectively a copy of transData
        trans = BboxTransform(boxin, boxout)
        offset = (i + 1) / (numRows + 1)

        trans += Affine2D().translate(*transOffset.transform_point((0,
                                                                    offset)))

        thisLine = Line2D(
            t,
            data[:, i] - data[0, i],
        )

        thisLine.set_transform(trans)
示例#23
0
class SkymapperAxes(Axes):
    """
    A base class for a Skymapper axes that takes in ra_0, dec_0, dec_1, dec_2.

    The base class takes care of clipping and interpolating with matplotlib.

    Subclass and override class method get_projection_class.

    """
    # The subclass projection must specify a name.  This will be used be the
    # user to select the projection.

    name = None

    @classmethod
    def get_projection_class(kls):
        raise NotImplementedError('Must implement this in subclass')

    def __init__(self, *args, **kwargs):
        self.ra_0 = None
        self.dec_0 = None
        self.dec_1 = None
        self.dec_2 = None

        Axes.__init__(self, *args, **kwargs)

        self.cla()

    def _init_axis(self):
        self.xaxis = maxis.XAxis(self)
        self.yaxis = maxis.YAxis(self)
        # FIXME: we probably want to register axis with spines.
        # Axes._init_axis() -- until HammerAxes.xaxis.cla() works.
        #self.spines['hammer'].register_axis(self.yaxis)
        self._update_transScale()

    def cla(self):
        """
        Override to set up some reasonable defaults.
        """
        # Don't forget to call the base class
        Axes.cla(self)

        # Turn off minor ticking altogether
        self.xaxis.set_minor_locator(NullLocator())
        self.yaxis.set_minor_locator(NullLocator())

        self.xaxis.set_major_locator(MaxNLocator(5, prune='both'))
        self.yaxis.set_major_locator(MaxNLocator(5, prune='both'))

        # Do not display ticks -- we only want gridlines and text
        self.xaxis.set_ticks_position('none')
        self.yaxis.set_ticks_position('none')

        self.set_center(None, None)

        # FIXME: probabaly want to override autoscale_view
        # to properly handle wrapping introduced by margin
        # and properlty wrap data. 
        # It doesn't make sense to have xwidth > 360. 
        self._tight = True

    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space (in this case meridian and parallel) to axes
        # space.  It is separated into a non-affine and affine part so
        # that the non-affine part does not have to be recomputed when
        # a simple affine change to the figure has been made (such as
        # resizing the window or changing the dpi).

        # 1) The core transformation from data space into
        # rectilinear space defined in the HammerTransform class.
        self.transProjection = self.get_projection_class()()
        self.transProjection.set_center((180, 0))
        self.transProjection.set_dec1(-65)
        self.transProjection.set_dec2(80)

        # 2) The above has an output range that is not in the unit
        # rectangle, so scale and translate it so it fits correctly
        # within the axes.  The peculiar calculations of xscale and
        # yscale are specific to a Aitoff-Hammer projection, so don't
        # worry about them too much.

        # This will be updated after the xy limits are set.
        self.transAffine = Affine2D()

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        self.transClip = \
            self.transProjection + \
            self.transAffine

        # The main data transformation is set up.  Now deal with
        # gridlines and tick labels.

        # Longitude gridlines and ticklabels.  The input to these
        # transforms are in display space in x and axes space in y.
        # Therefore, the input values will be in range (-xmin, 0),
        # (xmax, 1).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the equator.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 180) \
            .translate(0.0, -90)

        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData

        # modify this transformation to move x labels.
        self._xaxis_text_shift = \
            Affine2D().translate(0, 0)

        self._xaxis_text1_transform = \
            self._xaxis_text_shift + \
            self.transData + \
            Affine2D().translate(0.0, -8.0)
        self._xaxis_text2_transform = \
            self._xaxis_text_shift + \
            self.transData + \
            Affine2D().translate(0.0, -8.0)

        # Now set up the transforms for the parallel ticks.  The input to
        # these transforms are in axes space in x and display space in
        # y.  Therefore, the input values will be in range (0, -ymin),
        # (1, ymax).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the edge of the axes ellipse.
        self._yaxis_stretch = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_transform = \
            self._yaxis_stretch + \
            self.transData
        yaxis_text_base = \
            self._yaxis_stretch + \
            self.transProjection + \
            (self.transAffine +
             self.transAxes)
        self._yaxis_text1_transform = \
            yaxis_text_base + \
            Affine2D().translate(8.0, 0.0)
        self._yaxis_text2_transform = \
            yaxis_text_base + \
            Affine2D().translate(-8.0, 0.0)

    def _update_affine(self):
        # update the transformations and clip paths
        # after new lims are set.
        if self.ra_0 is None:
            x0, x1 = self.viewLim.intervalx
            ra_0 = 0.5 * (x0 + x1)
        else:
            ra_0 = self.ra_0
        if self.dec_0 is None:
            y0, y1 = self.viewLim.intervaly
            dec_0 = 0.5 * (y0 + y1)
        else:
            dec_0 = self.dec_0
        if self.dec_1 is None:
            y0, y1 = self.viewLim.intervaly
            dec_1 = y0 + (y1 - y0) / 12.
        else:
            dec_1 = self.dec_1
        if self.dec_2 is None:
            y0, y1 = self.viewLim.intervaly
            dec_2 = y1 - (y1 - y0) / 12.
        else:
            dec_2 = self.dec_2

        self.transProjection.set_center((ra_0, dec_0))
        self.transProjection.set_dec1(dec_1)
        self.transProjection.set_dec2(dec_2)

        self._yaxis_stretch\
            .clear() \
            .scale(self.viewLim.width, 1.0) \
            .translate(self.viewLim.x0, 0)
        self._xaxis_pretransform \
            .clear() \
            .scale(1.0, self.viewLim.height) \
            .translate(0.0, self.viewLim.y0)

        # FIXME: allow moving xtick labels to any dec.
        y0, y1 = self.viewLim.intervaly
        self._xaxis_text_shift \
            .clear()  \
            .translate(0, y0)

        corners_data = np.array([[self.viewLim.x0, self.viewLim.y0],
                      [ra_0,            self.viewLim.y0],
                      [self.viewLim.x1, self.viewLim.y0],
                      [self.viewLim.x1, self.viewLim.y1],
                      [self.viewLim.x0, self.viewLim.y1],])

        corners = self.transProjection.transform_non_affine(corners_data)

        x_0 = corners[0][0]
        x_1 = corners[2][0]

        # special case when x_1 is wrapped back to x_0
        # FIXME: I don't think we need it anymore.
        if x_0 == x_1: x_1 = - x_0

        y_0 = corners[1][1]
        y_1 = max([corners[3][1], corners[4][1]])

        xscale = np.abs(x_0 - x_1)
        yscale = np.abs(y_0 - y_1)

        self.transAffine.clear() \
            .translate( - x_0 + xscale * 0.5, - y_1 + yscale * 0.5) \
            .scale(0.95 / xscale, 0.95 / yscale)  \
            .translate(0.5, 0.5)

        # now update the clipping path
        path = Path(corners_data)
        path0 = self.transProjection.transform_path(path)
        path = self.transClip.transform_path(path)
        self.patch.set_xy(path.vertices)

    def get_xaxis_transform(self, which='grid'):
        """
        Override this method to provide a transformation for the
        x-axis grid and ticks.
        """
        assert which in ['tick1', 'tick2', 'grid']
        return self._xaxis_transform

    def get_xaxis_text1_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        x-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._xaxis_text1_transform, 'top', 'center'

    def get_xaxis_text2_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        secondary x-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._xaxis_text2_transform, 'bottom', 'center'

    def get_yaxis_transform(self, which='grid'):
        """
        Override this method to provide a transformation for the
        y-axis grid and ticks.
        """
        assert which in ['tick1', 'tick2', 'grid']
        return self._yaxis_transform

    def get_yaxis_text1_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        y-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._yaxis_text1_transform, 'center', 'left'

    def get_yaxis_text2_transform(self, pixelPad):
        """
        Override this method to provide a transformation for the
        secondary y-axis tick labels.

        Returns a tuple of the form (transform, valign, halign)
        """
        return self._yaxis_text2_transform, 'center', 'right'

    def _gen_axes_patch(self):
        """
        ClipPath.

        Initially set to a size of 2 box in transAxes.

        After xlim and ylim are set, this will be changed to the actual
        region in transData.

        For unclear reason the very initial clip path is always applied
        to the grid. Therefore we set size to 2.0 to avoid bad clipping.
        """
        return Polygon([(0, 0), (2, 0), (2, 2), (0, 2)], fill=False)

    def _gen_axes_spines(self):
        d = {
            'left': mspines.Spine.linear_spine(self, spine_type='left'),
            'right': mspines.Spine.linear_spine(self, spine_type='right'),
            'top': mspines.Spine.linear_spine(self, spine_type='top'),
            'bottom': mspines.Spine.linear_spine(self, spine_type='bottom'),
        }
        d['left'].set_position(('axes', 0))
        d['right'].set_position(('axes', 1))
        d['top'].set_position(('axes', 0))
        d['bottom'].set_position(('axes', 1))
        #FIXME: these spines can be moved wit set_position(('axes', ?)) but
        # 'data' fails. Because the transformation is non-separatable,
        # and because spines / data makes that assumption, we probably
        # do not have a easy way to support moving spines via native matplotlib
        # api on data axis.

        # also the labels currently do not follow the spines. Likely because
        # they are not registered?

        return d

    # Prevent the user from applying scales to one or both of the
    # axes.  In this particular case, scaling the axes wouldn't make
    # sense, so we don't allow it.
    def set_xscale(self, *args, **kwargs):
        if args[0] != 'linear':
            raise NotImplementedError
        Axes.set_xscale(self, *args, **kwargs)

    def set_yscale(self, *args, **kwargs):
        if args[0] != 'linear':
            raise NotImplementedError
        Axes.set_yscale(self, *args, **kwargs)

    def set_center(self, ra0, dec0):
        """ Set the center of ra """
        self.ra_0 = ra0
        self.dec_0 = dec0
        self._update_affine()

    def set_parallels(self, dec1, dec2):
        """ Set the parallels """
        self.dec_1 = dec1
        self.dec_2 = dec2
        self._update_affine()

    # when xlim and ylim are updated, the transformation
    # needs to be updated too.
    def set_xlim(self, *args, **kwargs):
        Axes.set_xlim(self, *args, **kwargs)

        # FIXME: wrap x0 x1 to ensure they enclose ra0.
        x0, x1 = self.viewLim.intervalx
        if self.ra_0 is not None:
            if not x0 <= self.transProjection.ra_0 or \
               not x1 > self.transProjection.ra_0:
                raise ValueError("The given limit in RA does not enclose ra_0")

        self._update_affine()

    def set_ylim(self, *args, **kwargs):
        Axes.set_ylim(self, *args, **kwargs)
        self._update_affine()

    def histmap(self, ra, dec, weights=None, nside=32, mean=False, **kwargs):
        r = histogrammap(ra, dec, weights, nside)

        if weights is not None:
            w, N = r
        else:
            w = r
        if mean:
            mask = N != 0
            w[mask] /= N[mask]
        else:
            mask = w > 0

        return w, mask, self.mapshow(w, mask, nest=False, **kwargs)

    def mapshow(self, map, mask=None, nest=False, **kwargs):
        """ Display a healpix map """
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        defaults = dict(rasterized=True,
                    alpha=0.8,
                    linewidth=0)
        defaults.update(kwargs)
        if mask is None:
            mask = map == map
        v = _boundary(mask, nest)
        coll = PolyCollection(v, array=map[mask], 
                transform=self.transData, **defaults)
        coll.set_clim(vmin=vmin, vmax=vmax)
        self.add_collection(coll)
        return coll

    def format_coord(self, lon, lat):
        """
        Override this method to change how the values are displayed in
        the status bar.

        In this case, we want them to be displayed in degrees N/S/E/W.
        """
        lon = lon
        lat = lat
        if lat >= 0.0:
            ns = 'N'
        else:
            ns = 'S'
        if lon >= 0.0:
            ew = 'E'
        else:
            ew = 'W'
        # \u00b0 : degree symbol
        return '%f\u00b0%s, %f\u00b0%s' % (abs(lat), ns, abs(lon), ew)

    class DegreeFormatter(Formatter):
        """
        This is a custom formatter that converts the native unit of
        radians into (truncated) degrees and adds a degree symbol.
        """

        def __init__(self, round_to=1.0):
            self._round_to = round_to

        def __call__(self, x, pos=None):
            degrees = round(x / self._round_to) * self._round_to
            # \u00b0 : degree symbol
            return "%d\u00b0" % degrees

    def set_meridian_grid(self, degrees):
        """
        Set the number of degrees between each meridian grid.

        It provides a more convenient interface to set the ticking than set_xticks would.
        """
        # Set up a FixedLocator at each of the points, evenly spaced
        # by degrees.
        x0, x1 = self.get_xlim()
        number = ((x1 - x0) / degrees) + 1
        self.xaxis.set_major_locator(
            FixedLocator(
                np.linspace(x0, x1, number, True)[1:-1]))
        # Set the formatter to display the tick labels in degrees,
        # rather than radians.
        self.xaxis.set_major_formatter(self.DegreeFormatter(degrees))

    def set_parallel_grid(self, degrees):
        """
        Set the number of degrees between each meridian grid.

        It provides a more convenient interface than set_yticks would.
        """
        # Set up a FixedLocator at each of the points, evenly spaced
        # by degrees.
        y0, y1 = self.get_ylim()
        number = ((y1 - y0) / degrees) + 1
        self.yaxis.set_major_locator(
            FixedLocator(
                np.linspace(y0, y1, number, True)[1:-1]))
        # Set the formatter to display the tick labels in degrees,
        # rather than radians.
        self.yaxis.set_major_formatter(self.DegreeFormatter(degrees))

    # Interactive panning and zooming is not supported with this projection,
    # so we override all of the following methods to disable it.
    def _in_axes(self, mouseevent):
        if hasattr(self._pan_trans):
            return True
        else:
            return Axes._in_axes(self, mouseevent)

    def can_zoom(self):
        """
        Return True if this axes support the zoom box
        """
        return True

    def start_pan(self, x, y, button):
        self._pan_trans = self.transAxes.inverted() + \
                blended_transform_factory(
                        self._yaxis_stretch,
                        self._xaxis_pretransform,)

    def end_pan(self):
        delattr(self, '_pan_trans')

    def drag_pan(self, button, key, x, y):
        pan1 = self._pan_trans.transform([(x, y)])[0]
        self.set_ra0(360 - pan1[0])
        self.set_dec0(pan1[1])
        self._update_affine()
示例#24
0
文件: aea.py 项目: Jravis/mpl_aea
    def _set_lim_and_transforms(self):
        """
        This is called once when the plot is created to set up all the
        transforms for the data, text and grids.
        """
        # There are three important coordinate spaces going on here:
        #
        #    1. Data space: The space of the data itself
        #
        #    2. Axes space: The unit rectangle (0, 0) to (1, 1)
        #       covering the entire plot area.
        #
        #    3. Display space: The coordinates of the resulting image,
        #       often in pixels or dpi/inch.

        # This function makes heavy use of the Transform classes in
        # ``lib/matplotlib/transforms.py.`` For more information, see
        # the inline documentation there.

        # The goal of the first two transformations is to get from the
        # data space (in this case meridian and parallel) to axes
        # space.  It is separated into a non-affine and affine part so
        # that the non-affine part does not have to be recomputed when
        # a simple affine change to the figure has been made (such as
        # resizing the window or changing the dpi).

        # 1) The core transformation from data space into
        # rectilinear space defined in the HammerTransform class.
        self.transProjection = self.get_projection_class()()
        self.transProjection.set_center((180, 0))
        self.transProjection.set_dec1(-65)
        self.transProjection.set_dec2(80)

        # 2) The above has an output range that is not in the unit
        # rectangle, so scale and translate it so it fits correctly
        # within the axes.  The peculiar calculations of xscale and
        # yscale are specific to a Aitoff-Hammer projection, so don't
        # worry about them too much.

        # This will be updated after the xy limits are set.
        self.transAffine = Affine2D()

        # 3) This is the transformation from axes space to display
        # space.
        self.transAxes = BboxTransformTo(self.bbox)

        # Now put these 3 transforms together -- from data all the way
        # to display coordinates.  Using the '+' operator, these
        # transforms will be applied "in order".  The transforms are
        # automatically simplified, if possible, by the underlying
        # transformation framework.
        self.transData = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        self.transClip = \
            self.transProjection + \
            self.transAffine + \
            self.transAxes

        # The main data transformation is set up.  Now deal with
        # gridlines and tick labels.

        # Longitude gridlines and ticklabels.  The input to these
        # transforms are in display space in x and axes space in y.
        # Therefore, the input values will be in range (-xmin, 0),
        # (xmax, 1).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the equator.
        self._xaxis_pretransform = \
            Affine2D() \
            .scale(1.0, 180) \
            .translate(0.0, -90)

        self._xaxis_transform = \
            self._xaxis_pretransform + \
            self.transData

        self._xaxis_text1_transform = \
            self._xaxis_pretransform + \
            self.transData# + \
        #            Affine2D().translate(0.0, -8.0)
        self._xaxis_text2_transform = \
            self._xaxis_pretransform+ \
            self.transData# + \
        #            Affine2D().translate(0.0, -8.0)

        # Now set up the transforms for the parallel ticks.  The input to
        # these transforms are in axes space in x and display space in
        # y.  Therefore, the input values will be in range (0, -ymin),
        # (1, ymax).  The goal of these transforms is to go from that
        # space to display space.  The tick labels will be offset 4
        # pixels from the edge of the axes ellipse.
        self._yaxis_stretch = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_stretch1 = Affine2D().scale(360, 1.0).translate(0.0, 0.0)
        self._yaxis_stretch2 = Affine2D().scale(360, 1.0).translate(0.0, 0.0)

        self._yaxis_transform = \
            self._yaxis_stretch + \
            self.transData

        self._yaxis_text1_transform = \
            self._yaxis_stretch1 + \
            self.transData# + \
        #            Affine2D().translate(-8.0, 0.0)

        self._yaxis_text2_transform = \
            self._yaxis_stretch2 + \
            self.transData# + \