What’s New in SunPy 3.1?

The SunPy project is pleased to announce the 3.1 release of the sunpy core package.

On this page, you can read about some of the big changes in this release.

SunPy 3.1 also includes a large number of smaller improvements and bug fixes, which are described in the Full Changelog.

By the numbers:

  • 610 commits have been added since 3.0

  • 56 issues have been closed since 3.0

  • 145 pull requests have been merged since 3.0

  • 16 people have contributed since 3.0

  • 8 of which are new contributors

Increase in required package versions

We have bumped the minimum version of several packages we depend on; these are the new minimum versions for sunpy 3.1:

  • astropy >= 4.2

  • matplotlib >= 3.2.0

  • numpy >= 1.17.0

  • pandas >= 1.0.0

Increased in-situ data support

Two new features have significantly increased support for in-situ data returned by heliospheric missions. See Getting data from CDAWeb for a full example of searching for, downloading, and loading a CDF file into sunpy.

New CDAWeb client

A new Fido client to search the Coordinated Data Analysis Web (CDAWeb) has been added to sunpy.net. This allows one to search for and download data from many space physics missions that take in-situ data (including Parker Solar Probe and Solar Orbiter). In combination with the new CDF reading abilities of sunpy.timeseries.TimeSeries, this provides a full workflow for searching for, downloading, and analysing in-situ data contained within CDF files.

Support for .cdf files

sunpy.timeseries.TimeSeries now supports loading CDF files if the external library cdflib is installed.

New limb drawing function

The solar limb as seen from an arbitrary observer coordinate can now be drawn on a world coordinate system aware Axes using the sunpy.visualization.draw_limb() function.

New WISPR map source

A new map source for the WISPR instrument on Parker Solar Probe has been added. This improves the name of the map and adds correct information for the processing_level and exposure_time.

Changes to map metadata fixes

The GenericMap map sources are primarily used to modify metadata values to either fix known incorrect values in a given data source, or make the metadata comply with the FITS standard. There are two ways in which the sunpy map sources can do this:

  1. Directly edit the values stored in the FITS metadata.

  2. Overload properties (e.g. sunpy.map.GenericMap.unit) such that they return the correct information without modifying the underlying metadata.

In previous versions of sunpy there has been no consistency in which of these two approaches is taken.

As of sunpy 3.1, the second approach is now consistently taken, and sunpy no longer edits any FITS metadata values when constructing a Map. GenericMap properties now consistently provide corrected information. For details of any corrections applied, the docstrings of different map sources (e.g., HMIMap - see Instrument Map Classes for a list of map sources) provide information on any assumptions made beyond the original FITS metadata when constructing the map properties.

For all maps, the following fixes are no longer made:

  • DATE-OBS is no longer replaced by DATE_OBS as a fallback

  • NAXIS, NAXIS1, NAXIS2, BITPIX are no longer populated if not present

  • BUNIT is no longer corrected to be a FITS compliant unit string

  • WAVEUNIT is no longer automatically populated from the header comments if it is not present.

For specific map sources, the following keywords are no longer modified or added:

  • KCorMap: OBSERVATORY, DETECTOR, WAVEUNIT, DSUN_OBS, HGLN_OBS

  • SWAPMap: OBSRVTRY, DETECTOR

  • RHESSIMap: CUNIT1, CUNIT2, CTYPE1, CTYPE2, WAVEUNIT, WAVELNTH

  • AIAMap: BUNIT, DETECTOR

  • HMIMap: DETECTOR, CRDER1, CRDER2

  • HMISynopticMap: CUNIT1, CUNIT2, CDELT1, CDELT2, DATE-OBS

  • EITMap: WAVEUNIT, CUNIT1, CUNIT2

  • LASCOMap: DATE-OBS, DATE_OBS, CROTA, CROTA1, CROTA2, CUNIT1, CUNIT2

  • MDIMap: CUNIT1, CUNIT2

  • MDISynopticMap: CUNIT1, CUNIT2, CDELT2, DATE-OBS, CRDER1, CRDER2

  • EUVIMap: WAVEUNIT, DATE-OBS, CROTA, CROTA2

  • CORMap: DATE-OBS

  • HIMap: DATE-OBS

  • SUVIMap: DETECTOR, TELESCOP

  • TRACEMap: DETECTOR, OBSRVTRY, CUNIT1, CUNIT2

  • SXTMap: DETECTOR, TELESCOP, DSUN_APPARENT

  • XRTMap: DETECTOR, TELESCOP, TIMESYS

  • SOTMap: DETECTOR, TELESCOP

  • SJIMap: DETECTOR, WAVEUNIT, WAVELNTH, CUNIT1, CUNIT2

  • EUIMap: CROTA, CROTA2

Changes to map date/time handling

New date properties

The properties date_start, date_end, and date_average have been added to be drawn from the relevant FITS metadata, if present in the map header. These are from new keywords defined in version 4 of the FITS standard, which have precise meanings compared to the previously ill-defined DATE-OBS.

Changes to date

sunpy.map.GenericMap.date now looks for more metadata than just DATE-OBS. This property can return any one of the new properties (see above) depending on the metadata present in the map. It now draws from, in order of preference:

  1. The DATE-OBS FITS keyword

  2. date_average

  3. date_start

  4. date_end

  5. The current time.

If DATE-OBS is present alongside DATE-AVG or DATE-BEG and DATE-END, this results in a behaviour change to favour the new (more precisely defined) keywords. It is recommended to use date_average, date_start, or date_end instead if you need one of these specific times.

Addition of new time format TimeTaiSeconds

The new TimeTaiSeconds format is the number of SI seconds from 1958-01-01 00:00:00, which includes UTC leap seconds. 1958-01-01 00:00:00 is the defined time when International Atomic Time (TAI) and Universal Time (UT) are synchronized.

This format is equivalent to the output of the SSW anytim2tai routine, and related routines, for times after 1972-01-01. Be aware that the SSW routines are not written to provide valid results for times before 1972-01-01.

This format is equivalent to TimeUnixTai, except that the epoch is 12 years earlier.

Propagating solar-surface coordinates in time

There is now an easy-to-use context manager (propagate_with_solar_surface()) to enable coordinate transformations to take solar rotation into account. Normally, a coordinate refers to a point in inertial space, so transforming it to a different observation time does not move the point at all. Under this context manager, a coordinate will be treated as if it were referring to a point on the solar surface. Coordinate transformations with a change in observation time will automatically rotate the point in heliographic longitude for the time difference, with the amount of rotation depending on the specified differential-rotation model.

Convenient reprojection of maps

Map objects now have the reproject_to() method to easily reproject the map to a new WCS. The returned map will be of type GenericMap, with no metadata preserved from the original map, so copy over any desired metadata from the original map. This method requires the optional package reproject to be installed.

JSOC keyword filtering with Fido

Support for filtering searches with JSOC keywords has been added to Fido.search:

>>> from sunpy.net import Fido, attrs as a
>>> import astropy.units as u
>>> Fido.search(a.Time('2014-01-01T00:00:00', '2014-01-01T01:00:00'),
    a.jsoc.Series('aia.lev1_euv_12s'), a.Wavelength(304*u.AA), a.jsoc.Keyword("EXPTIME") > 1)
<sunpy.net.fido_factory.UnifiedResponse object at 0x7fe16a5d20d0>
Results from 1 Provider:

301 Results from the JSOCClient:
Source: http://jsoc.stanford.edu

    T_REC         TELESCOP INSTRUME WAVELNTH CAR_ROT
-------------------- -------- -------- -------- -------
2014-01-01T00:00:01Z  SDO/AIA    AIA_4      304    2145
2014-01-01T00:00:13Z  SDO/AIA    AIA_4      304    2145
2014-01-01T00:00:25Z  SDO/AIA    AIA_4      304    2145
2014-01-01T00:00:37Z  SDO/AIA    AIA_4      304    2145
                ...      ...      ...      ...     ...
2014-01-01T00:59:25Z  SDO/AIA    AIA_4      304    2145
2014-01-01T00:59:37Z  SDO/AIA    AIA_4      304    2145
2014-01-01T00:59:49Z  SDO/AIA    AIA_4      304    2145
2014-01-01T01:00:01Z  SDO/AIA    AIA_4      304    2145
Length = 301 rows
>>> Fido.search(a.Time('2014-01-01T00:00:00', '2014-01-01T01:00:00'),
    a.jsoc.Series('aia.lev1_euv_12s'), a.Wavelength(304*u.AA), a.jsoc.Keyword("EXPTIME") == 1)
<sunpy.net.fido_factory.UnifiedResponse object at 0x7fe16a5d20d0>
Results from 1 Provider:

0 Results from the JSOCClient:
Source: http://jsoc.stanford.edu

Please be aware of two caveats:

  • We do not validate the value used for comparison.

  • Passing in a keyword without comparison to a value (e.g. ==0, < 10) will error.

Arithmetic operations with maps

GenericMap objects now support arithmetic operations (i.e. addition, subtraction, multiplication, division) with array-like quantities. This includes scalar quantities as well as Numpy arrays. Notably, arithmetic operations between two GenericMap objects are not supported.

Contributors to this Release

The people who have contributed to the code for this release are:

  • Alasdair Wilson *

  • Albert Y. Shih

  • Anubhav Sinha *

  • Conor MacBride

  • David Stansby

  • Devansh Shukla *

  • Jeffrey Aaron Paul

  • Nabil Freij

  • Noah Altunian *

  • Rohan Sharma *

  • Samriddhi Agarwal

  • Stuart Mumford

  • Thomas Braccia *

  • Tim Gates *

  • Will Barnes

Where a * indicates that this release contains their first contribution to SunPy.