SunPy map

Overview

One of core classes in SunPy is a Map. A SunPy Map object is simply a spatially-aware data array, often an image. In order to make it easy to work with image data in SunPy, the Map object provides a number of methods for commonly performed operations.

2D map objects are subclasses of MapBase and all Map objects are created using the Map factory Map.

A number of instrument are supported by subclassing this base object. See Instrument Map Classes to see a list of all of them. More complex subclasses are also available. See Map Classes.

Creating Map Objects

SunPy Map objects are constructed using the special factory class Map:

x = sunpy.map.Map('file.fits')

The result of a call to Map will be either a GenericMap object, or a subclass of GenericMap which either deals with a specific type of data, e.g. AIAMap or LASCOMap (see Map Classes to see a list of all of them), or if no instrument matches, a 2D map GenericMap.

class sunpy.map.map_factory.MapFactory(*args, **kwargs)[source] [edit on github]

Map factory class. Used to create a variety of Map objects. Valid map types are specified by registering them with the factory.

Examples

>>> import sunpy.map
>>> sunpy.data.download_sample_data(overwrite=False)   
>>> import sunpy.data.sample
>>> mymap = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)

The SunPy Map factory accepts a wide variety of inputs for creating maps

  • Preloaded tuples of (data, header) pairs
>>> mymap = sunpy.map.Map((data, header))   

headers are some base of dict or collections.OrderedDict, including sunpy.io.header.FileHeader or sunpy.map.MapMeta classes.

  • data, header pairs, not in tuples
>>> mymap = sunpy.map.Map(data, header)   
  • File names
>>> mymap = sunpy.map.Map('file1.fits')   
  • All fits files in a directory by giving a directory
>>> mymap = sunpy.map.Map('local_dir/sub_dir')   
  • Some regex globs
>>> mymap = sunpy.map.Map('eit_*.fits')   
  • URLs
>>> mymap = sunpy.map.Map(url_str)   
  • DatabaseEntry
>>> mymap = sunpy.map.Map(db_result)   
  • Lists of any of the above
>>> mymap = sunpy.map.Map(['file1.fits', 'file2.fits', 'file3.fits', 'directory1/'])   
  • Any mixture of the above not in a list
>>> mymap = sunpy.map.Map((data, header), data2, header2, 'file1.fits', url_str, 'eit_*.fits')   

Using Map Objects

Once a map object has been created using Map it will be a instance or a subclass of the GenericMap class. Irrespective of the instrument the map is constructed for, all maps behave the same and are interchangeable with one another. It is possible to manipulate the map or access meta data about the map from the methods and properties of the map class. The following documentation of GenericMap lists the attributes and methods that are available on all Map objects.

class sunpy.map.mapbase.GenericMap(data, header, **kwargs)[source] [edit on github]

A Generic spatially-aware 2D data array

Parameters:

data : ndarray, list

A 2d list or ndarray containing the map data

meta : dict

A dictionary of the original image header tags

Notes

A number of the properties of this class are returned as two-value named tuples that can either be indexed by position ([0] or [1]) or be accessed by name (.x or .y). The names “x” and “y” here refer to the first and second axes of the map, and may not necessarily correspond to any similarly named axes in the coordinate system.

This class makes some assumptions about the WCS information contained in the meta data. The first and most extensive assumption is that it is FITS-like WCS information as defined in the FITS WCS papers.

Within this scope it also makes some other assumptions.

  • In the case of APIS convention headers where the CROTAi/j arguments are provided it assumes that these can be converted to the standard PCi_j notation using equations 32 in Thompson (2006).
  • If a CDi_j matrix is provided it is assumed that it can be converted to a PCi_j matrix and CDELT keywords as described in Greisen & Calabretta (2002).
  • The ‘standard’ FITS keywords that are used by this class are the PCi_j matrix and CDELT, along with the other keywords specified in the WCS papers. All subclasses of this class must convert their header information to this formalism. The CROTA to PCi_j conversion is done in this class.

Warning

This class currently assumes that a header with the CDi_j matrix information also includes the CDELT keywords, without these keywords this class will not process the WCS information. This will be fixed. Also the rotation_matrix does not work if the CDELT1 and CDELT2 keywords are exactly equal.

References

Examples

>>> import sunpy.map
>>> import sunpy.data
>>> sunpy.data.download_sample_data(overwrite=False)   
>>> import sunpy.data.sample
>>> aia = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)
>>> aia   
SunPy AIAMap
---------
Observatory:         SDO
Instrument:  AIA 3
Detector:    AIA
Measurement:         171.0 Angstrom
Wavelength:  171.0 Angstrom
Obs Date:    2011-03-19 10:54:00
dt:          1.999601 s
Dimension:   [ 1024.  1024.] pix
scale:               [ 2.4  2.4] arcsec / pix

array([[ 0.3125, -0.0625, -0.125 , ...,  0.625 , -0.625 ,  0.    ],
       [ 1.    ,  0.1875, -0.8125, ...,  0.625 , -0.625 ,  0.    ],
       [-1.1875,  0.375 , -0.5   , ..., -0.125 , -0.625 , -1.1875],
       ...,
       [-0.625 ,  0.0625, -0.3125, ...,  0.125 ,  0.125 ,  0.125 ],
       [ 0.5625,  0.0625,  0.5625, ..., -0.0625, -0.0625,  0.    ],
       [ 0.5   , -0.125 ,  0.4375, ...,  0.6875,  0.6875,  0.6875]])
>>> aia.spatial_units
Pair(x=Unit("arcsec"), y=Unit("arcsec"))
>>> aia.peek()   
carrington_longitude

Carrington longitude (crln_obs)

center

Return the world (data) coordinates of the center pixel of the array.

coordinate_frame

An astropy.coordinates.BaseFrame instance created from the coordinate information for this Map.

coordinate_system

Coordinate system used for x and y axes (ctype1/2)

data_to_pixel(x, y, origin=0)[source] [edit on github]

Convert a data (world) coordinate to a pixel coordinate by using wcs_world2pix.

Parameters:

x : Quantity

Data coordinate of the CTYPE1 axis. (Normally solar-x).

y : Quantity

Data coordinate of the CTYPE2 axis. (Normally solar-y).

origin : int

Origin of the top-left corner. i.e. count from 0 or 1. Normally, origin should be 0 when passing numpy indices, or 1 if passing values from FITS header or map attributes. See wcs_world2pix for more information.

Returns:

x : Quantity

Pixel coordinate on the CTYPE1 axis.

y : Quantity

Pixel coordinate on the CTYPE2 axis.

date

Image observation time

detector

Detector name

dimensions

The dimensions of the array (x axis first, y axis second).

draw_contours(levels, axes=None, **contour_args)[source] [edit on github]

Draw contours of the data

Parameters:

levels : Quantity

A list of numbers indicating the level curves to draw given in percent.

axes : matplotlib.axes.Axes

The axes on which to plot the rectangle, defaults to the current axes.

Returns:

cs : list

The QuadContourSet object, after it has been added to axes.

Notes

Extra keyword arguments to this function are passed through to the contour function.

draw_grid(axes=None, grid_spacing=<Quantity 15.0 deg>, **kwargs)[source] [edit on github]

Draws a grid over the surface of the Sun

Parameters:

axes: `~matplotlib.axes` 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

draw_limb(axes=None, **kwargs)[source] [edit on github]

Draws a circle representing the solar limb

Parameters:

axes: `~matplotlib.axes` 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

draw_rectangle(bottom_left, width, height, axes=None, **kwargs)[source] [edit on github]

Draw a rectangle defined in world coordinates on the plot.

Parameters:

bottom_left : astropy.units.Quantity

The bottom left corner of the rectangle.

width : astropy.units.Quantity

The width of the rectangle.

height : astropy.units.Quantity

The height of the rectangle.

axes : matplotlib.axes.Axes

The axes on which to plot the rectangle, defaults to the current axes.

Returns:

rect : list

A list containing the Rectangle object, after it has been added to axes.

Notes

Extra keyword arguments to this function are passed through to the Rectangle instance.

dsun

The observer distance from the Sun.

dtype

The numpy.dtype of the array of the map.

exposure_time

Exposure time of the image in seconds.

heliographic_latitude

Heliographic latitude

heliographic_longitude

Heliographic longitude

instrument

Instrument name

max(*args, **kwargs)[source] [edit on github]

Calculate the maximum value of the data array.

mean(*args, **kwargs)[source] [edit on github]

Calculate the mean of the data array.

measurement

Measurement name, defaults to the wavelength of image

min(*args, **kwargs)[source] [edit on github]

Calculate the minimum value of the data array.

name

Human-readable description of map-type

ndim

The value of numpy.ndarray.ndim of the data array of the map.

nickname

An abbreviated human-readable description of the map-type; part of the Helioviewer data model

observatory

Observatory or Telescope name

peek(draw_limb=False, draw_grid=False, colorbar=True, basic_plot=False, **matplot_args)[source] [edit on github]

Displays the map in a new figure

Parameters:

draw_limb : bool

Whether the solar limb should be plotted.

draw_grid : bool or Quantity

Whether solar meridians and parallels are plotted. If Quantity then sets degree difference between parallels and meridians.

gamma : float

Gamma value to use for the color map

colorbar : bool

Whether to display a colorbar next to the plot

basic_plot : bool

If true, the data is plotted by itself at it’s natural scale; no title, labels, or axes are shown.

**matplot_args : dict

Matplotlib Any additional imshow arguments that should be used when plotting.

pixel_to_data(x, y, origin=0)[source] [edit on github]

Convert a pixel coordinate to a data (world) coordinate by using wcs_pix2world.

Parameters:

x : Quantity

Pixel coordinate of the CTYPE1 axis. (Normally solar-x).

y : Quantity

Pixel coordinate of the CTYPE2 axis. (Normally solar-y).

origin : int

Origin of the top-left corner. i.e. count from 0 or 1. Normally, origin should be 0 when passing numpy indices, or 1 if passing values from FITS header or map attributes. See wcs_pix2world for more information.

Returns:

x : Quantity

Coordinate of the CTYPE1 axis. (Normally solar-x).

y : Quantity

Coordinate of the CTYPE2 axis. (Normally solar-y).

plot(annotate=True, axes=None, title=True, **imshow_kwargs)[source] [edit on github]

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
>>> aia.plot()   
>>> plt.colorbar()   
>>> # Add a limb line and grid
>>> aia.plot()   
>>> aia.draw_limb()   
>>> aia.draw_grid()   
reference_coordinate

Reference point WCS axes in data units (i.e. crval1, crval2). This value includes a shift if one is set.

reference_pixel

Reference point axes in pixels (i.e. crpix1, crpix2)

resample(dimensions, method='linear')[source] [edit on github]

Returns a new Map that has been resampled up or down

Arbitrary resampling of the Map to new dimension sizes.

Uses the same parameters and creates the same co-ordinate lookup points as IDL’’s congrid routine, which apparently originally came from a VAX/VMS routine of the same name.

Parameters:

dimensions : Quantity

Pixel dimensions that new Map should have. Note: the first argument corresponds to the ‘x’ axis and the second argument corresponds to the ‘y’ axis.

method : {‘neighbor’ | ‘nearest’ | ‘linear’ | ‘spline’}

Method to use for resampling interpolation.
  • neighbor - Closest value from original data
  • nearest and linear - Uses n x 1-D interpolations using scipy.interpolate.interp1d
  • spline - Uses ndimage.map_coordinates
Returns:

out : GenericMap or subclass

A new Map which has been resampled to the desired dimensions.

References

rotate(angle=None, rmatrix=None, order=4, scale=1.0, recenter=False, missing=0.0, use_scipy=False)[source] [edit on github]

Returns a new rotated and rescaled map. Specify either a rotation angle or a rotation matrix, but not both. If neither an angle or a rotation matrix are specified, the map will be rotated by the rotation angle in the metadata.

The map will be rotated around the reference coordinate defined in the meta data.

Also updates the rotation_matrix attribute and any appropriate header data so that they correctly describe the new map.

Parameters:

angle : Quantity

The angle (degrees) to rotate counterclockwise.

rmatrix : 2x2

Linear transformation rotation matrix.

order : int 0-5

Interpolation order to be used. When using scikit-image this parameter is passed into skimage.transform.warp() (e.g., 4 corresponds to bi-quartic interpolation). When using scipy it is passed into scipy.ndimage.interpolation.affine_transform() where it controls the order of the spline. Faster performance may be obtained at the cost of accuracy by using lower values. Default: 4

scale : float

A scale factor for the image, default is no scaling

recenter : bool

If True, position the axis of rotation at the center of the new map Default: False

missing : float

The numerical value to fill any missing points after rotation. Default: 0.0

use_scipy : bool

If True, forces the rotation to use scipy.ndimage.interpolation.affine_transform(), otherwise it uses the skimage.transform.warp(). Default: False, unless scikit-image can’t be imported

Returns:

out : GenericMap or subclass

A new Map instance containing the rotated and rescaled data of the original map.

See also

sunpy.image.transform.affine_transform
The routine this method calls for the rotation.

Notes

This function will remove old CROTA keywords from the header. This function will also convert a CDi_j matrix to a PCi_j matrix.

See sunpy.image.transform.affine_transform() for details on the transformations, situations when the underlying data is modified prior to rotation, and differences from IDL’s rot().

rotation_matrix

Matrix describing the rotation required to align solar North with the top of the image.

rsun_meters

Radius of the sun in meters

rsun_obs

Radius of the Sun.

save(filepath, filetype='auto', **kwargs)[source] [edit on github]

Saves the SunPy Map object to a file.

Currently SunPy can only save files in the FITS format. In the future support will be added for saving to other formats.

Parameters:

filepath : str

Location to save file to.

filetype : str

‘auto’ or any supported file extension

scale

Image scale along the x and y axes in units/pixel (i.e. cdelt1, cdelt2)

shift(x, y)[source] [edit on github]

Returns a map shifted by a specified amount to, for example, correct for a bad map location. These values are applied directly to the reference_coordinate. To check how much shift has already been applied see shifted_value

Parameters:

x : Quantity

The shift to apply to the X coordinate.

y : Quantity

The shift to apply to the Y coordinate

Returns:

out : GenericMap or subclass

A new shifted Map.

shifted_value

The total shift applied to the reference coordinate by past applications of shift.

size

The number of pixels in the array of the map.

spatial_units

Image coordinate units along the x and y axes (i.e. cunit1, cunit2).

std(*args, **kwargs)[source] [edit on github]

Calculate the standard deviation of the data array.

submap(range_a, range_b)[source] [edit on github]

Returns a submap of the map with the specified range.

Parameters:

range_a : astropy.units.Quantity

The range of the Map to select across either the x axis. Can be either in data units (normally arcseconds) or pixel units.

range_b : astropy.units.Quantity

The range of the Map to select across either the y axis. Can be either in data units (normally arcseconds) or pixel units.

Returns:

out : GenericMap or subclass

A new map instance is returned representing to specified sub-region

Examples

>>> import astropy.units as u
>>> import sunpy.map
>>> import sunpy.data
>>> sunpy.data.download_sample_data(overwrite=False)   
>>> import sunpy.data.sample
>>> aia = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)
>>> aia.submap([-5,5]*u.arcsec, [-5,5]*u.arcsec)   
SunPy AIAMap
---------
Observatory:         SDO
Instrument:  AIA 3
Detector:    AIA
Measurement:         171.0 Angstrom
Wavelength:  171.0 Angstrom
Obs Date:    2011-03-19 10:54:00
dt:          1.999601 s
Dimension:   [ 4.  4.] pix
scale:               [ 2.4  2.4] arcsec / pix

array([[ 273.4375,  247.4375,  303.5   ,  305.3125],
       [ 302.3125,  298.125 ,  299.    ,  261.5   ],
       [ 289.75  ,  269.25  ,  256.375 ,  242.3125],
       [ 241.75  ,  248.8125,  263.0625,  249.0625]])
>>> aia.submap([0,5]*u.pixel, [0,5]*u.pixel)   
SunPy AIAMap
---------
Observatory:         SDO
Instrument:  AIA 3
Detector:    AIA
Measurement:         171.0 Angstrom
Wavelength:  171.0 Angstrom
Obs Date:    2011-03-19 10:54:00
dt:          1.999601 s
Dimension:   [ 5.  5.] pix
scale:               [ 2.4  2.4] arcsec / pix

array([[ 0.3125, -0.0625, -0.125 ,  0.    , -0.375 ],
       [ 1.    ,  0.1875, -0.8125,  0.125 ,  0.3125],
       [-1.1875,  0.375 , -0.5   ,  0.25  , -0.4375],
       [-0.6875, -0.3125,  0.8125,  0.0625,  0.1875],
       [-0.875 ,  0.25  ,  0.1875,  0.    , -0.6875]])
superpixel(dimensions, offset=<Quantity [ 0., 0.] pix>, func=<function sum>)[source] [edit on github]

Returns a new map consisting of superpixels formed by applying ‘func’ to the original map data.

Parameters:

dimensions : tuple

One superpixel in the new map is equal to (dimension[0], dimension[1]) pixels of the original map. Note: the first argument corresponds to the ‘x’ axis and the second argument corresponds to the ‘y’ axis.

offset : tuple

Offset from (0,0) in original map pixels used to calculate where the data used to make the resulting superpixel map starts.

func : function applied to the original data

The function ‘func’ must take a numpy array as its first argument, and support the axis keyword with the meaning of a numpy axis keyword (see the description of sum for an example.) The default value of ‘func’ is sum; using this causes superpixel to sum over (dimension[0], dimension[1]) pixels of the original map.

Returns:

out : GenericMap or subclass

A new Map which has superpixels of the required size.

References

wavelength

wavelength of the observation

wcs

The WCS property of the map.

xrange

Return the X range of the image from edge to edge.

yrange

Return the Y range of the image from edge to edge.

Map Classes

Defined in sunpy.map.sources are a set of GenericMap subclasses which convert the specific metadata and other differences in each instruments data to the standard GenericMap interface. These ‘sources’ also define things like the colormap and default normalisation for each instrument. These subclasses also provide a method, which describes to the Map factory which data and metadata pairs match its instrument.

Classes

CompositeMap(map1 [,map2,..]) A Composite Map class
GenericMap(data, header, **kwargs) A Generic spatially-aware 2D data array
MapCube(*args, **kwargs) A series of spatially aligned Maps.
MapMeta(*args) A class to hold meta data associated with a Map derivative.

Class Inheritance Diagram

Inheritance diagram of sunpy.map.compositemap.CompositeMap, sunpy.map.mapbase.GenericMap, sunpy.map.mapcube.MapCube, sunpy.map.header.MapMeta

Instrument Map Classes

sunpy.map.sources Package

Datasource-specific classes

This is where datasource specific logic is implemented. Each mission should have its own file with one or more classes defined. Typically, these classes will be subclasses of the :mod`sunpy.map.Map` class.

Classes

XRTMap(data, header, **kwargs) Hinode XRT map definition.
SOTMap(data, header, **kwargs) Hinode SOT Image Map definition.
SWAPMap(data, header, **kwargs) PROBA2 SWAP Image Map.
RHESSIMap(data, header, **kwargs) RHESSI Image Map.
AIAMap(data, header, **kwargs) AIA Image Map.
HMIMap(data, header, **kwargs) HMI Image Map.
EITMap(data, header, **kwargs) SOHO EIT Image Map.
LASCOMap(data, header, **kwargs) SOHO LASCO Image Map
MDIMap(data, header, **kwargs) SOHO MDI Image Map
EUVIMap(data, header, **kwargs) STEREO-SECCHI EUVI Image Map
CORMap(data, header, **kwargs) STEREO-SECCHI CORonograph Image Map.
HIMap(data, header, **kwargs) STEREO-SECCHI Heliospheric Imager (HI) Map.
SXTMap(data, header, **kwargs) Yohkoh SXT Image Map
SJIMap(data, header, **kwargs) A 2D IRIS Slit Jaw Imager Map.
TRACEMap(data, header, **kwargs) TRACE Image Map

Class Inheritance Diagram

Inheritance diagram of sunpy.map.sources.hinode.XRTMap, sunpy.map.sources.hinode.SOTMap, sunpy.map.sources.proba2.SWAPMap, sunpy.map.sources.rhessi.RHESSIMap, sunpy.map.sources.sdo.AIAMap, sunpy.map.sources.sdo.HMIMap, sunpy.map.sources.soho.EITMap, sunpy.map.sources.soho.LASCOMap, sunpy.map.sources.soho.MDIMap, sunpy.map.sources.stereo.EUVIMap, sunpy.map.sources.stereo.CORMap, sunpy.map.sources.stereo.HIMap, sunpy.map.sources.yohkoh.SXTMap, sunpy.map.sources.iris.SJIMap, sunpy.map.sources.trace.TRACEMap

Writing a new Instrument Map Class

Any subclass of GenericMap which defines a method named is_datasource_for will automatically be registered with the Map factory. The is_datasource_for method describes the form of the data and metadata for which the GenericMap subclass is valid. For example it might check the value of the INSTRUMENT key in the metadata dictionary. This makes it straightforward to define your own GenericMap subclass for a new instrument or a custom data source like simulated data. These classes only have to be imported for this to work, as demonstrated by the following example.

import sunpy.map
class FutureMap(sunpy.map.GenericMap):

    def __init__(self, data, header, **kwargs):

        super(FutureMap, self).__init__(data, header, **kwargs)

        # Any Future Instrument specific keyword manipulation

   # Specify a classmethod that determines if the data-header pair matches
   # the new instrument
   @classmethod
   def is_datasource_for(cls, data, header, **kwargs):
        """Determines if header corresponds to an AIA image"""
        return header.get('instrume', '').startswith('FUTURESCOPE')

This class will now be available through the Map factory as long as this class has been defined, i.e. imported into the current session.

If you do not want to create a method named is_datasource_for you can manually register your class and matching method using the following method

import sunpy.map

sunpy.map.Map.register(FutureMap, FutureMap.some_matching_method)