예제 #1
0
        def updatefig(i, im, annotate, ani_data, removes):
            while removes:
                removes.pop(0).remove()

            im.set_array(ani_data[i].data)
            im.set_cmap(ani_data[i].plot_settings['cmap'])

            norm = deepcopy(ani_data[i].plot_settings['norm'])
            # The following explicit call is for bugged versions of Astropy's
            # ImageNormalize
            norm.autoscale_None(ani_data[i].data)
            im.set_norm(norm)

            if wcsaxes_compat.is_wcsaxes(axes):
                im.axes.reset_wcs(ani_data[i].wcs)
                wcsaxes_compat.default_wcs_grid(axes)
            else:
                bl = ani_data[i]._get_lon_lat(ani_data[i].bottom_left_coord)
                tr = ani_data[i]._get_lon_lat(ani_data[i].top_right_coord)
                x_range = list(u.Quantity([bl[0], tr[0]]).to(ani_data[i].spatial_units[0]).value)
                y_range = list(u.Quantity([bl[1], tr[1]]).to(ani_data[i].spatial_units[1]).value)

                im.set_extent(np.concatenate((x_range.value, y_range.value)))

            if annotate:
                annotate_frame(i)
            removes += list(plot_function(fig, axes, ani_data[i]))
예제 #2
0
        def updatefig(i, im, annotate, ani_data, removes):
            while removes:
                removes.pop(0).remove()

            im.set_array(ani_data[i].data)
            im.set_cmap(ani_data[i].plot_settings['cmap'])

            norm = deepcopy(ani_data[i].plot_settings['norm'])
            # The following explicit call is for bugged versions of Astropy's
            # ImageNormalize
            norm.autoscale_None(ani_data[i].data)
            im.set_norm(norm)

            if wcsaxes_compat.is_wcsaxes(axes):
                im.axes.reset_wcs(ani_data[i].wcs)
                wcsaxes_compat.default_wcs_grid(axes)
            else:
                bl = ani_data[i]._get_lon_lat(ani_data[i].bottom_left_coord)
                tr = ani_data[i]._get_lon_lat(ani_data[i].top_right_coord)
                x_range = list(
                    u.Quantity([bl[0],
                                tr[0]]).to(ani_data[i].spatial_units[0]).value)
                y_range = list(
                    u.Quantity([bl[1],
                                tr[1]]).to(ani_data[i].spatial_units[1]).value)

                im.set_extent(np.concatenate((x_range.value, y_range.value)))

            if annotate:
                annotate_frame(i)
            removes += list(plot_function(fig, axes, ani_data[i]))
예제 #3
0
    def _drawFallback(self, model):
        self.figure.clear()
        try:
            s_map = model.map
            plot_preferences = model.plot_preferences

            ax = self.figure.add_subplot(111, projection=s_map)
            image = ax.imshow(model.data,
                              cmap=model.cmap,
                              norm=model.norm,
                              interpolation=model.interpolation,
                              origin=model.origin)

            if plot_preferences["show_colorbar"]:
                self.figure.colorbar(image)
            if plot_preferences["show_limb"]:
                s_map.draw_limb(axes=ax)
            if plot_preferences["contours"]:
                levels = sorted(plot_preferences["contours"])
                s_map.draw_contours(levels * u.percent, axes=ax)
            if plot_preferences["draw_grid"]:
                s_map.draw_grid(grid_spacing=10 * u.deg, axes=ax)
            if plot_preferences["wcs_grid"] and wcsaxes_compat.is_wcsaxes(ax):
                wcsaxes_compat.default_wcs_grid(ax,
                                                units=s_map.spatial_units,
                                                ctypes=s_map.wcs.wcs.ctype)
        except Exception as ex:
            self.figure.clear()
            self.figure.text(0.5,
                             0.5,
                             s="Error during rendering data: " + str(ex),
                             ha="center",
                             va="center")
예제 #4
0
        def updatefig(i, im, annotate, ani_data, removes):
            while removes:
                removes.pop(0).remove()

            im.set_array(ani_data[i].data)
            im.set_cmap(ani_data[i].plot_settings['cmap'])

            norm = deepcopy(ani_data[i].plot_settings['norm'])
            # The following explicit call is for bugged versions of Astropy's
            # ImageNormalize
            norm.autoscale_None(ani_data[i].data)
            im.set_norm(norm)

            if wcsaxes_compat.is_wcsaxes(axes):
                im.axes.reset_wcs(ani_data[i].wcs)
                wcsaxes_compat.default_wcs_grid(axes,
                                                ani_data[i].spatial_units,
                                                ani_data[i].coordinate_system)
            else:
                im.set_extent(
                    np.concatenate(
                        (ani_data[i].xrange.value, ani_data[i].yrange.value)))

            if annotate:
                annotate_frame(i)
            removes += list(plot_function(fig, axes, ani_data[i]))
예제 #5
0
    def updatefig(self, val, im, slider):
        # Remove all the objects that need to be removed from the
        # plot
        while self.remove_obj:
            self.remove_obj.pop(0).remove()

        i = int(val)
        im.set_array(self.data[i].data)
        im.set_cmap(self.mapcube[i].plot_settings['cmap'])

        norm = deepcopy(self.mapcube[i].plot_settings['norm'])
        # The following explicit call is for bugged versions of Astropy's ImageNormalize
        norm.autoscale_None(self.data[i].data)
        im.set_norm(norm)

        if wcsaxes_compat.is_wcsaxes(im.axes):
            im.axes.reset_wcs(self.mapcube[i].wcs)
            wcsaxes_compat.default_wcs_grid(im.axes)

        # Having this line in means the plot will resize for non-homogenous
        # maps. However it also means that if you zoom in on the plot bad
        # things happen.
        # im.set_extent(self.mapcube[i].xrange + self.mapcube[i].yrange)
        if self.annotate:
            self._annotate_plot(i)

        self.remove_obj += list(self.user_plot_function(self.fig, self.axes, self.mapcube[i]))
예제 #6
0
    def updatefig(self, val, im, slider):
        # Remove all the objects that need to be removed from the
        # plot
        while self.remove_obj:
            self.remove_obj.pop(0).remove()

        i = int(val)
        im.set_array(self.data[i].data)
        im.set_cmap(self.mapcube[i].plot_settings['cmap'])

        norm = deepcopy(self.mapcube[i].plot_settings['norm'])
        # The following explicit call is for bugged versions of Astropy's ImageNormalize
        norm.autoscale_None(self.data[i].data)
        im.set_norm(norm)

        if wcsaxes_compat.is_wcsaxes(im.axes):
            im.axes.reset_wcs(self.mapcube[i].wcs)
            wcsaxes_compat.default_wcs_ticks(im.axes,
                                             self.mapcube[i].spatial_units,
                                             self.mapcube[i].coordinate_system)

        # Having this line in means the plot will resize for non-homogenous
        # maps. However it also means that if you zoom in on the plot bad
        # things happen.
        # im.set_extent(self.mapcube[i].xrange + self.mapcube[i].yrange)
        if self.annotate:
            self._annotate_plot(i)

        self.remove_obj += list(
            self.user_plot_function(self.fig, self.axes, self.mapcube[i]))
예제 #7
0
def prime_meridian(axes, *, rsun: u.m = R_sun, resolution=500, **kwargs):
    """
    Draws the solar prime meridian (zero Carrington longitude) as seen by the
    axes observer. Hidden parts are drawn as a dotted line.

    Parameters
    ----------
    axes : `matplotlib.axes.Axes`
        The axes to plot the prime meridian on, or "None" to use current axes.
    rsun : `~astropy.units.Quantity`
        Solar radius (in physical length units) at which to draw the solar
        prime meridian. Defaults to the standard photospheric radius.
    resolution : `int`
        The number of points used to represent the prime meridian.

    Returns
    -------
    visible : `~matplotlib.patches.Polygon`
        The patch added to the axes for the visible part of the solar equator.
    hidden : `~matplotlib.patches.Polygon`
        The patch added to the axes for the hidden part of the solar equator.
    """
    if not wcsaxes_compat.is_wcsaxes(axes):
        raise ValueError('axes must be a WCSAxes')
    axes_frame = wcsapi_to_celestial_frame(axes.wcs)

    if not hasattr(axes_frame, 'observer'):
        raise ValueError(
            'the coordinate frame of the WCSAxes does not have an observer, '
            'so zero Carrington longitude cannot be determined.')
    observer = axes_frame.observer

    lon = 0 * u.deg
    lon0 = SkyCoord(np.ones(resolution) * lon,
                    np.linspace(-90, 90, resolution) * u.deg,
                    radius=rsun,
                    frame=HeliographicCarrington(observer=observer,
                                                 obstime=axes_frame.obstime))
    visible, hidden = _plot_vertices(lon0,
                                     axes,
                                     axes_frame,
                                     rsun,
                                     close_path=False,
                                     **kwargs)
    return visible, hidden
예제 #8
0
파일: mapbase.py 프로젝트: bsipocz/sunpy
    def _mpl_imshow_kwargs(self, axes, cmap):
        """
        Return the keyword arguments for imshow to display this map
        """
        if wcsaxes_compat.is_wcsaxes(axes):
            kwargs = {'cmap': cmap,
                      'origin': 'lower',
                      'norm': self.mpl_color_normalizer,
                      'interpolation': 'nearest'}
        else:
            # make imshow kwargs a dict
            kwargs = {'origin': 'lower',
                      'cmap': cmap,
                      'norm': self.mpl_color_normalizer,
                      'extent': list(self.xrange.value) + list(self.yrange.value),
                      'interpolation': 'nearest'}

        return kwargs
예제 #9
0
def equator(axes, *, rsun: u.m = R_sun, resolution=500, **kwargs):
    """
    Draws the solar equator as seen by the axes observer.
    Hidden parts are drawn as a dotted line.

    Parameters
    ----------
    axes : `matplotlib.axes.Axes`
        The axes to plot the equator on.
    rsun : `~astropy.units.Quantity`
        Solar radius (in physical length units) at which to draw the solar
        equator. Defaults to the standard photospheric radius.
    resolution : `int`
        The number of points used to represent the equator.

    Returns
    -------
    visible : `~matplotlib.patches.Polygon`
        The patch added to the axes for the visible part of the solar equator.
    hidden : `~matplotlib.patches.Polygon`
        The patch added to the axes for the hidden part of the solar equator.

    Examples
    --------
    >>> import sunpy.map
    >>> from sunpy.visualization import draw
    >>> import sunpy.data.sample   # doctest: +REMOTE_DATA
    >>> aia = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)   # doctest: +REMOTE_DATA
    >>> fig = plt.figure()   # doctest: +SKIP
    >>> ax = fig.add_subplot(projection=aia)   # doctest: +SKIP
    >>> aia.plot()   # doctest: +SKIP
    >>> draw.equator(ax)   # doctest: +SKIP
    """
    if not wcsaxes_compat.is_wcsaxes(axes):
        raise ValueError('axes must be a WCSAxes')
    axes_frame = wcsapi_to_celestial_frame(axes.wcs)

    lat = 0 * u.deg
    lat0 = SkyCoord(np.linspace(-180, 179, resolution) * u.deg,
                    np.ones(resolution) * lat,
                    radius=rsun,
                    frame=HeliographicStonyhurst(obstime=axes_frame.obstime))
    visible, hidden = _plot_vertices(lat0, axes, axes_frame, rsun, **kwargs)
    return visible, hidden
예제 #10
0
파일: mapbase.py 프로젝트: bsipocz/sunpy
    def draw_limb(self, axes=None, **kwargs):
        """Draws a circle representing the solar limb

            Parameters
            ----------
            axes: matplotlib.axes object or None
                Axes to plot limb on or None to use current axes.

            Returns
            -------
            circ: list
                A list containing the `matplotlib.patches.Circle` object that
                has been added to the axes.

            Notes
            -----
            keyword arguments are passed onto the Circle Patch, see:
            http://matplotlib.org/api/artist_api.html#matplotlib.patches.Patch
            http://matplotlib.org/api/artist_api.html#matplotlib.patches.Circle
        """

        if not axes:
            axes = wcsaxes_compat.gca_wcs(self.wcs)

        transform = wcsaxes_compat.get_world_transform(axes)
        if wcsaxes_compat.is_wcsaxes(axes):
            radius = self.rsun_obs.to(u.deg).value
        else:
            radius = self.rsun_obs.value
        c_kw = {'radius':radius,
                'fill':False,
                'color':'white',
                'zorder':100,
                'transform': transform
                }
        c_kw.update(kwargs)

        circ = patches.Circle([0, 0], **c_kw)
        axes.add_artist(circ)

        return [circ]
예제 #11
0
        def updatefig(i, im, annotate, ani_data, removes):
            while removes:
                removes.pop(0).remove()

            im.set_array(ani_data[i].data)
            im.set_cmap(self.maps[i].plot_settings['cmap'])

            norm = deepcopy(self.maps[i].plot_settings['norm'])
            # The following explicit call is for bugged versions of Astropy's ImageNormalize
            norm.autoscale_None(ani_data[i].data)
            im.set_norm(norm)

            if wcsaxes_compat.is_wcsaxes(axes):
                im.axes.reset_wcs(self.maps[i].wcs)
                wcsaxes_compat.default_wcs_grid(axes)
            else:
                im.set_extent(np.concatenate((self.maps[i].xrange.value,
                                              self.maps[i].yrange.value)))

            if annotate:
                annotate_frame(i)
            removes += list(plot_function(fig, axes, self.maps[i]))
예제 #12
0
    def updatefig(self, val, im, slider):
        """
        ?

        Parameters
        ----------
            val : ?
                ?

            im : ?
                ?

        Returns
        -------
        .. todo::
            improve documentation
        """
        # Remove all the objects that need to be removed from the
        # plot
        while self.remove_obj:
            self.remove_obj.pop(0).remove()

        i = int(val)
        im.set_array(self.data[i].data)
        im.set_cmap(self.mapcube[i].plot_settings['cmap'])
        im.set_norm(self.mapcube[i].plot_settings['norm'])
        if wcsaxes_compat.is_wcsaxes(im.axes):
            im.axes.reset_wcs(self.mapcube[i].wcs)
            wcsaxes_compat.default_wcs_grid(im.axes)

        # Having this line in means the plot will resize for non-homogenous
        # maps. However it also means that if you zoom in on the plot bad
        # things happen.
        # im.set_extent(self.mapcube[i].xrange + self.mapcube[i].yrange)
        if self.annotate:
            self._annotate_plot(i)

        self.remove_obj += list(self.user_plot_function(self.fig, self.axes, self.mapcube[i]))
예제 #13
0
    def updatefig(self, val, im, slider):
        # Remove all the objects that need to be removed from the
        # plot
        while self.remove_obj:
            self.remove_obj.pop(0).remove()

        i = int(val)
        im.set_array(self.data[i].data)
        im.set_cmap(self.mapsequence[i].plot_settings['cmap'])
        norm = deepcopy(self.mapsequence[i].plot_settings['norm'])
        im.set_norm(norm)

        if wcsaxes_compat.is_wcsaxes(im.axes):
            im.axes.reset_wcs(self.mapsequence[i].wcs)
        # Having this line in means the plot will resize for non-homogenous
        # maps. However it also means that if you zoom in on the plot bad
        # things happen.
        # im.set_extent(self.mapsequence[i].xrange + self.mapsequence[i].yrange)
        if self.annotate:
            self._annotate_plot(i)

        self.remove_obj += list(
            self.user_plot_function(self.fig, self.axes, self.mapsequence[i]))
예제 #14
0
파일: mapbase.py 프로젝트: bsipocz/sunpy
    def plot(self, gamma=None, annotate=True, axes=None, **imshow_args):
        """ Plots the map object using matplotlib, in a method equivalent
        to plt.imshow() using nearest neighbour interpolation.

        Parameters
        ----------
        gamma : float
            Gamma value to use for the color map

        annotate : bool
            If true, the data is plotted at it's natural scale; with
            title and axis labels.

        axes: matplotlib.axes object or None
            If provided the image will be plotted on the given axes. Else the
            current matplotlib axes will be used.

        **imshow_args : dict
            Any additional imshow arguments that should be used
            when plotting the image.

        Examples
        --------
        #Simple Plot with color bar
        >>> aiamap.plot()
        >>> plt.colorbar()

        #Add a limb line and grid
        >>> aia.plot()
        >>> aia.draw_limb()
        >>> aia.draw_grid()

        """

        #Get current axes
        if not axes:
            axes = wcsaxes_compat.gca_wcs(self.wcs)

        # Check that the image is properly oriented
        if (not wcsaxes_compat.is_wcsaxes(axes) and
            not np.array_equal(self.rotation_matrix, np.matrix(np.identity(2)))):
            warnings.warn("This map is not properly oriented. Plot axes may be incorrect",
                          Warning)

        # Normal plot
        if annotate:
            axes.set_title("{name} {date:{tmf}}".format(name=self.name,
                                                        date=parse_time(self.date),
                                                        tmf=TIME_FORMAT))

            # x-axis label
            if self.coordinate_system.x == 'HG':
                xlabel = 'Longitude [{lon}]'.format(lon=self.units.x)
            else:
                xlabel = 'X-position [{xpos}]'.format(xpos=self.units.x)

            # y-axis label
            if self.coordinate_system.y == 'HG':
                ylabel = 'Latitude [{lat}]'.format(lat=self.units.y)
            else:
                ylabel = 'Y-position [{ypos}]'.format(ypos=self.units.y)

            axes.set_xlabel(xlabel)
            axes.set_ylabel(ylabel)


        cmap = deepcopy(self.cmap)
        if gamma is not None:
            cmap.set_gamma(gamma)

        kwargs = self._mpl_imshow_kwargs(axes, cmap)
        kwargs.update(imshow_args)

        if self.mask is None:
            ret = axes.imshow(self.data, **kwargs)
        else:
            ret = axes.imshow(np.ma.array(np.asarray(self.data), mask=self.mask), **kwargs)

        if wcsaxes_compat.is_wcsaxes(axes):
            wcsaxes_compat.default_wcs_grid(axes)

        #Set current image (makes colorbar work)
        plt.sca(axes)
        plt.sci(ret)
        return ret
예제 #15
0
파일: limb.py 프로젝트: samiali12/sunpy
def draw_limb(axes, observer, *, rsun: u.m = R_sun, resolution=1000, **kwargs):
    """
    Draws the solar limb as seen by the specified observer.

    The limb is a circle for only the simplest plots.  If the specified
    observer of the limb is different from the observer of the coordinate frame
    of the plot axes, not only may the limb not be a true circle, a portion of
    the limb may be hidden from the observer.  In that case, the circle is
    divided into visible and hidden segments, represented by solid and dotted
    lines, respectively.

    Parameters
    ----------
    axes : `~matplotlib.axes` or ``None``
        Axes to plot limb on.
    observer : `astropy.coordinates.SkyCoord`
        Observer coordinate for which the limb is drawn.
    rsun : `~astropy.units.Quantity`
        Solar radius (in physical length units) at which to draw the limb.
        Defaults to the standard photospheric radius.
    resolution : `int`
        The number of points to use to represent the limb.

    Returns
    -------
    visible : `~matplotlib.patches.Polygon` or `~matplotlib.patches.Circle` or None
        The patch added to the axes for the visible part of the limb (i.e., the
        "near" side of the Sun).
    hidden : `~matplotlib.patches.Polygon` or None
        The patch added to the axes for the hidden part of the limb (i.e., the
        "far" side of the Sun).

    Notes
    -----
    Keyword arguments are passed onto the patches.

    If the limb is a true circle, ``visible`` will instead be
    `~matplotlib.patches.Circle` and ``hidden`` will be ``None``.

    If there are no hidden points (e.g., on a synoptic map any limb is fully
    visible) ``hidden`` will be ``None``.

    If there are no visible points (e.g., for an observer on the opposite side
    of the Sun to the map observer) ``visible`` will be ``None``.

    To avoid triggering Matplotlib auto-scaling, these patches are added as
    artists instead of patches.  One consequence is that the plot legend is not
    populated automatically when the limb is specified with a text label.  See
    :ref:`sphx_glr_gallery_text_labels_and_annotations_custom_legends.py` in
    the Matplotlib documentation for examples of creating a custom legend.
    """
    if not wcsaxes_compat.is_wcsaxes(axes):
        raise ValueError('axes must be a WCSAxes')

    c_kw = {'fill': False, 'color': 'white', 'zorder': 100}
    c_kw.update(kwargs)

    transform = axes.get_transform('world')
    # transform is always passed on as a keyword argument
    c_kw.setdefault('transform', transform)

    # If the observer matches the axes's observer frame and is Helioprojective, use a Circle
    axes_frame = axes._transform_pixel2world.frame_out
    if isinstance(axes_frame, Helioprojective):
        axes_observer = SkyCoord(axes_frame.observer)
        if axes_observer.separation_3d(observer) < 1 * u.m:
            distance = observer.transform_to(
                HeliocentricInertial).spherical.distance
            # Obtain the solar radius and the world->pixel transform
            angular_radius = _angular_radius(rsun, distance)
            circ = patches.Circle([0, 0],
                                  radius=angular_radius.to_value(u.deg),
                                  **c_kw)
            axes.add_artist(circ)
            return circ, None

    # Otherwise, we use Polygon to be able to distort the limb
    # Create the limb coordinate array using Heliocentric Radial
    limb = get_limb_coordinates(observer, rsun, resolution)

    # Transform the limb to the axes frame and get the 2D vertices
    limb_in_axes = limb.transform_to(axes_frame)
    Tx = limb_in_axes.spherical.lon.to_value(u.deg)
    Ty = limb_in_axes.spherical.lat.to_value(u.deg)
    vertices = np.array([Tx, Ty]).T

    # Determine which points are visible
    if hasattr(axes_frame, 'observer'):
        # The reference distance is the distance to the limb for the axes
        # observer
        rsun = getattr(axes_frame, 'rsun', rsun)
        reference_distance = np.sqrt(axes_frame.observer.radius**2 - rsun**2)
        is_visible = limb_in_axes.spherical.distance <= reference_distance
    else:
        # If the axes has no observer, the entire limb is considered visible
        is_visible = np.ones_like(limb_in_axes.spherical.distance,
                                  bool,
                                  subok=False)

    # Identify discontinuities in the limb. Uses the same approach as
    # astropy.visualization.wcsaxes.grid_paths.get_lon_lat_path()
    step = np.sqrt((vertices[1:, 0] - vertices[:-1, 0])**2 +
                   (vertices[1:, 1] - vertices[:-1, 1])**2)
    continuous = np.concatenate([[True, True], step[1:] < 100 * step[:-1]])

    visible, hidden = None, None
    if np.sum(is_visible) > 0:
        # Create the Polygon for the near side of the Sun (using a solid line)
        if 'linestyle' not in kwargs:
            c_kw['linestyle'] = '-'
        visible = patches.Polygon(vertices, **c_kw)
        _modify_polygon_visibility(visible, is_visible & continuous)
        # Add patches as artists rather than patches to avoid triggering auto-scaling
        axes.add_artist(visible)

    if np.sum(~is_visible) > 0:
        # Create the Polygon for the far side of the Sun (using a dotted line)
        if 'linestyle' not in kwargs:
            c_kw['linestyle'] = ':'
        hidden = patches.Polygon(vertices, **c_kw)
        _modify_polygon_visibility(hidden, ~is_visible & continuous)
        axes.add_artist(hidden)

    return visible, hidden
예제 #16
0
    def plot(self, axes=None, annotate=True,
             title="SunPy Composite Plot", **matplot_args):
        """Plots the composite map object by calling :meth:`~sunpy.map.GenericMap.plot`
        or :meth:`~sunpy.map.GenericMap.draw_contours`.

        By default, each map is plotted as an image.  If a given map has levels
        defined (via :meth:`~sunpy.map.CompositeMap.set_levels`), that map will instead
        be plotted as contours.

        Parameters
        ----------

        axes: `~matplotlib.axes.Axes` or None
            If provided the image will be plotted on the given axes. Else the
            current matplotlib axes will be used.

        annotate : `bool`
            If true, the data is plotted at it's natural scale; with
            title and axis labels.

        title : `str`
            Title of the composite map.

        **matplot_args : `dict`
            Any additional Matplotlib arguments that should be used
            when plotting.

        Returns
        -------
        ret : `list`
            List of axes image or quad contour sets that have been plotted.

        Notes
        -----
        If a line-width Matplotlib argument (``linewidth``, ``linewidths``, or ``lw``)
        is provided, it will apply only to those maps that are plotted as contours.

        If a transformation is required to overlay the maps with the correct
        alignment, the plot limits may need to be manually set because
        Matplotlib autoscaling may not work as intended.
        """

        # If axes are not provided, create a WCSAxes based on the first map
        if not axes:
            axes = wcsaxes_compat.gca_wcs(self._maps[0].wcs)

        if annotate:
            axes.set_xlabel(axis_labels_from_ctype(self._maps[0].coordinate_system[0],
                                                   self._maps[0].spatial_units[0]))
            axes.set_ylabel(axis_labels_from_ctype(self._maps[0].coordinate_system[1],
                                                   self._maps[0].spatial_units[1]))
            axes.set_title(title)

        # Define a list of plotted objects
        ret = []
        # Plot layers of composite map
        for m in self._maps:
            # Parameters for plotting
            params = {
                "alpha": m.alpha,
                "zorder": m.zorder,
            }
            params.update(matplot_args)

            # The request to show a map layer rendered as a contour is indicated by a
            # non False levels property.
            if m.levels is False:
                # Check if any linewidth argument is provided, if so, then delete it from params.
                for item in ['linewidth', 'linewidths', 'lw']:
                    if item in matplot_args:
                        del params[item]

                # We tell GenericMap.plot() that we need to autoalign the map
                if wcsaxes_compat.is_wcsaxes(axes):
                    params['autoalign'] = True

                params['annotate'] = False
                ret.append(m.plot(**params))
            else:
                ret.append(m.draw_contours(m.levels, **params))

                # Set the label of the first line so a legend can be created
                ret[-1].collections[0].set_label(m.name)

        # Adjust axes extents to include all data
        axes.axis('image')

        # Set current image (makes colorbar work)
        plt.sci(ret[0])
        return ret
예제 #17
0
파일: limb.py 프로젝트: wtbarnes/sunpy
def draw_limb(axes, observer, *, rsun: u.m = R_sun, resolution=1000, **kwargs):
    """
    Draws the solar limb as seen by the specified observer.

    The limb is a circle for only the simplest plots.  If the specified
    observer of the limb is different from the observer of the coordinate frame
    of the plot axes, not only may the limb not be a true circle, a portion of
    the limb may be hidden from the observer.  In that case, the circle is
    divided into visible and hidden segments, represented by solid and dotted
    lines, respectively.

    Parameters
    ----------
    axes : `~matplotlib.axes` or ``None``
        Axes to plot limb on.
    observer : `astropy.coordinates.SkyCoord`
        Observer coordinate for which the limb is drawn.
    rsun : `~astropy.units.Quantity`
        Solar radius (in physical length units) at which to draw the limb.
        Defaults to the standard photospheric radius.
    resolution : `int`
        The number of points to use to represent the limb.

    Returns
    -------
    visible : `~matplotlib.patches.Polygon` or `~matplotlib.patches.Circle` or None
        The patch added to the axes for the visible part of the limb (i.e., the
        "near" side of the Sun).
    hidden : `~matplotlib.patches.Polygon` or None
        The patch added to the axes for the hidden part of the limb (i.e., the
        "far" side of the Sun).

    Notes
    -----
    Keyword arguments are passed onto the patches.

    If the limb is a true circle, ``visible`` will instead be
    `~matplotlib.patches.Circle` and ``hidden`` will be ``None``.

    If there are no hidden points (e.g., on a synoptic map any limb is fully
    visible) ``hidden`` will be ``None``.

    If there are no visible points (e.g., for an observer on the opposite side
    of the Sun to the map observer) ``visible`` will be ``None``.

    To avoid triggering Matplotlib auto-scaling, these patches are added as
    artists instead of patches.  One consequence is that the plot legend is not
    populated automatically when the limb is specified with a text label.  See
    :ref:`sphx_glr_gallery_text_labels_and_annotations_custom_legends.py` in
    the Matplotlib documentation for examples of creating a custom legend.
    """
    if not wcsaxes_compat.is_wcsaxes(axes):
        raise ValueError('axes must be a WCSAxes')

    c_kw = {'fill': False, 'color': 'white', 'zorder': 100}
    c_kw.update(kwargs)

    transform = axes.get_transform('world')
    # transform is always passed on as a keyword argument
    c_kw.setdefault('transform', transform)

    # If the observer matches the axes's observer frame and is Helioprojective, use a Circle
    axes_frame = axes._transform_pixel2world.frame_out
    if isinstance(axes_frame, Helioprojective):
        axes_observer = SkyCoord(axes_frame.observer)
        if axes_observer.separation_3d(observer) < 1 * u.m:
            distance = observer.transform_to(
                HeliocentricInertial).spherical.distance
            # Obtain the solar radius and the world->pixel transform
            angular_radius = _angular_radius(rsun, distance)
            circ = patches.Circle([0, 0],
                                  radius=angular_radius.to_value(u.deg),
                                  **c_kw)
            axes.add_artist(circ)
            return circ, None

    # Otherwise, we use Polygon to be able to distort the limb
    # Create the limb coordinate array using Heliocentric Radial
    limb = get_limb_coordinates(observer, rsun, resolution)

    # Transform the limb to the axes frame and get the 2D vertices
    visible, hidden = _plot_vertices(limb, axes, axes_frame, rsun, **kwargs)

    return visible, hidden
예제 #18
0
    def plot(self, axes=None, annotate=True,
             title="SunPy Composite Plot", **matplot_args):
        """Plots the composite map object by calling :meth:`~sunpy.map.GenericMap.plot`
        or :meth:`~sunpy.map.GenericMap.draw_contours`.

        By default, each map is plotted as an image.  If a given map has levels
        defined (via :meth:`~sunpy.map.CompositeMap.set_levels`), that map will instead
        be plotted as contours.

        Parameters
        ----------

        axes: `~matplotlib.axes.Axes` or None
            If provided the image will be plotted on the given axes. Else the
            current matplotlib axes will be used.

        annotate : `bool`
            If true, the data is plotted at it's natural scale; with
            title and axis labels.

        title : `str`
            Title of the composite map.

        **matplot_args : `dict`
            Any additional Matplotlib arguments that should be used
            when plotting.

        Returns
        -------
        ret : `list`
            List of axes image or quad contour sets that have been plotted.

        Notes
        -----
        Images are plotted using either `~matplotlib.axes.Axes.imshow` or
        `~matplotlib.axes.Axes.pcolormesh`, and contours are plotted using
        `~matplotlib.axes.Axes.contour`.
        The Matplotlib arguments accepted by the plotting method are passed to it.
        (For compatability reasons, we enforce a more restrictive set of
        accepted `~matplotlib.axes.Axes.pcolormesh` arguments.)
        If any Matplotlib arguments are not used by any plotting method,
        a ``TypeError`` will be raised.
        The ``sunpy.map.compositemap`` module includes variables which list the
        full set of arguments passed to each plotting method. These are:

        >>> import sunpy.map.compositemap
        >>> sorted(sunpy.map.compositemap.ACCEPTED_IMSHOW_KWARGS)
        {ACCEPTED_IMSHOW_KWARGS}
        >>> sorted(sunpy.map.compositemap.ACCEPTED_PCOLORMESH_KWARGS)
        {ACCEPTED_PCOLORMESH_KWARGS}
        >>> sorted(sunpy.map.compositemap.ACCEPTED_CONTOUR_KWARGS)
        {ACCEPTED_CONTOUR_KWARGS}

        If a transformation is required to overlay the maps with the correct
        alignment, the plot limits may need to be manually set because
        Matplotlib autoscaling may not work as intended.
        """

        # If axes are not provided, create a WCSAxes based on the first map
        if not axes:
            axes = wcsaxes_compat.gca_wcs(self._maps[0].wcs)

        if annotate:
            axes.set_xlabel(axis_labels_from_ctype(self._maps[0].coordinate_system[0],
                                                   self._maps[0].spatial_units[0]))
            axes.set_ylabel(axis_labels_from_ctype(self._maps[0].coordinate_system[1],
                                                   self._maps[0].spatial_units[1]))
            axes.set_title(title)

        # Checklist to determine unused keywords in `matplot_args`
        unused_kwargs = set(matplot_args.keys())

        # Define a list of plotted objects
        ret = []
        # Plot layers of composite map
        for m in self._maps:
            # Parameters for plotting
            params = {
                "alpha": m.alpha,
                "zorder": m.zorder,
            }
            params.update(matplot_args)

            # The request to show a map layer rendered as a contour is indicated by a
            # non False levels property.
            if m.levels is False:
                # We tell GenericMap.plot() that we need to autoalign the map
                if wcsaxes_compat.is_wcsaxes(axes):
                    params['autoalign'] = True

                # Filter `matplot_args`
                if params.get('autoalign', None) in (True, 'pcolormesh'):
                    accepted_kwargs = ACCEPTED_PCOLORMESH_KWARGS
                else:
                    accepted_kwargs = ACCEPTED_IMSHOW_KWARGS
                for item in matplot_args.keys():
                    if item not in accepted_kwargs:
                        del params[item]
                    else:  # mark as used
                        unused_kwargs -= {item}

                params['annotate'] = False
                ret.append(m.plot(**params))
            else:
                # Filter `matplot_args`
                for item in matplot_args.keys():
                    if item not in ACCEPTED_CONTOUR_KWARGS:
                        del params[item]
                    else:  # mark as used
                        unused_kwargs -= {item}

                ret.append(m.draw_contours(m.levels, **params))

                # Set the label of the first line so a legend can be created
                ret[-1].collections[0].set_label(m.name)

        if len(unused_kwargs) > 0:
            raise TypeError(f'plot() got unexpected keyword arguments {unused_kwargs}')

        # Adjust axes extents to include all data
        axes.axis('image')

        # Set current image (makes colorbar work)
        plt.sci(ret[0])
        return ret
예제 #19
0
    def plot(self, annotate=True, axes=None, title=True, **imshow_kwargs):
        """ Plots the map object using matplotlib, in a method equivalent
        to plt.imshow() using nearest neighbour interpolation.

        Parameters
        ----------
        annotate : bool
            If True, the data is plotted at it's natural scale; with
            title and axis labels.

        axes: `~matplotlib.axes` or None
            If provided the image will be plotted on the given axes. Else the
            current matplotlib axes will be used.

        **imshow_kwargs  : dict
            Any additional imshow arguments that should be used
            when plotting.

        Examples
        --------
        #Simple Plot with color bar
        >>> aiamap.plot()   # doctest: +SKIP
        >>> plt.colorbar()   # doctest: +SKIP

        #Add a limb line and grid
        >>> aia.plot()   # doctest: +SKIP
        >>> aia.draw_limb()   # doctest: +SKIP
        >>> aia.draw_grid()   # doctest: +SKIP

        """

        # Get current axes
        if not axes:
            axes = wcsaxes_compat.gca_wcs(self.wcs)

        # Check that the image is properly oriented
        if not wcsaxes_compat.is_wcsaxes(axes) and not np.array_equal(self.rotation_matrix, np.matrix(np.identity(2))):
            warnings.warn("This map is not properly oriented. Plot axes may be incorrect", Warning)

        # Normal plot
        imshow_args = deepcopy(self.plot_settings)
        if imshow_args.has_key("title"):
            plot_settings_title = imshow_args.pop("title")
        else:
            plot_settings_title = self.name

        if annotate:
            if title is True:
                title = plot_settings_title

            if title:
                axes.set_title(title)

            # x-axis label
            if self.coordinate_system.x == "HG":
                xlabel = "Longitude [{lon}]".format(lon=self.units.x)
            else:
                xlabel = "X-position [{xpos}]".format(xpos=self.units.x)

            # y-axis label
            if self.coordinate_system.y == "HG":
                ylabel = "Latitude [{lat}]".format(lat=self.units.y)
            else:
                ylabel = "Y-position [{ypos}]".format(ypos=self.units.y)

            axes.set_xlabel(xlabel)
            axes.set_ylabel(ylabel)

        if not wcsaxes_compat.is_wcsaxes(axes):
            imshow_args.update({"extent": list(self.xrange.value) + list(self.yrange.value)})
        imshow_args.update(imshow_kwargs)

        if self.mask is None:
            ret = axes.imshow(self.data, **imshow_args)
        else:
            ret = axes.imshow(np.ma.array(np.asarray(self.data), mask=self.mask), **imshow_args)

        if wcsaxes_compat.is_wcsaxes(axes):
            wcsaxes_compat.default_wcs_grid(axes)

        # Set current image (makes colorbar work)
        plt.sca(axes)
        plt.sci(ret)
        return ret
예제 #20
0
파일: mapbase.py 프로젝트: bsipocz/sunpy
    def draw_grid(self, axes=None, grid_spacing=15*u.deg, **kwargs):
        """Draws a grid over the surface of the Sun

        Parameters
        ----------
        axes: matplotlib.axes object or None
        Axes to plot limb on or None to use current axes.

        grid_spacing: float
            Spacing (in degrees) for longitude and latitude grid.

        Returns
        -------
        lines: list
            A list of `matplotlib.lines.Line2D` objects that have been plotted.

        Notes
        -----
        keyword arguments are passed onto matplotlib.pyplot.plot
        """

        if not axes:
            axes = wcsaxes_compat.gca_wcs(self.wcs)

        lines = []

        # Do not automatically rescale axes when plotting the overlay
        axes.set_autoscale_on(False)

        transform = wcsaxes_compat.get_world_transform(axes)

        XX, YY = np.meshgrid(np.arange(self.data.shape[0]),
                             np.arange(self.data.shape[1]))
        x, y = self.pixel_to_data(XX*u.pix, YY*u.pix)
        dsun = self.dsun

        b0 = self.heliographic_latitude.to(u.deg).value
        l0 = self.heliographic_longitude.to(u.deg).value
        units = self.units

        #Prep the plot kwargs
        plot_kw = {'color':'white',
                   'linestyle':'dotted',
                   'zorder':100,
                   'transform':transform}
        plot_kw.update(kwargs)

        hg_longitude_deg = np.linspace(-180, 180, num=361) + l0
        hg_latitude_deg = np.arange(-90, 90, grid_spacing.to(u.deg).value)

        # draw the latitude lines
        for lat in hg_latitude_deg:
            x, y = wcs.convert_hg_hpc(hg_longitude_deg, lat * np.ones(361),
                                      b0_deg=b0, l0_deg=l0, dsun_meters=dsun,
                                      angle_units=units.x, occultation=True)
            valid = np.logical_and(np.isfinite(x), np.isfinite(y))
            x = x[valid]
            y = y[valid]
            if wcsaxes_compat.is_wcsaxes(axes):
                x = (x*u.arcsec).to(u.deg).value
                y = (y*u.arcsec).to(u.deg).value
            lines += axes.plot(x, y, **plot_kw)

        hg_longitude_deg = np.arange(-180, 180, grid_spacing.to(u.deg).value) + l0
        hg_latitude_deg = np.linspace(-90, 90, num=181)

        # draw the longitude lines
        for lon in hg_longitude_deg:
            x, y = wcs.convert_hg_hpc(lon * np.ones(181), hg_latitude_deg,
                                      b0_deg=b0, l0_deg=l0, dsun_meters=dsun,
                                      angle_units=units[0], occultation=True)
            valid = np.logical_and(np.isfinite(x), np.isfinite(y))
            x = x[valid]
            y = y[valid]
            if wcsaxes_compat.is_wcsaxes(axes):
                x = (x*u.arcsec).to(u.deg).value
                y = (y*u.arcsec).to(u.deg).value
            lines += axes.plot(x, y, **plot_kw)

        # Turn autoscaling back on.
        axes.set_autoscale_on(True)
        return lines