What’s New in SunPy 2.1?#

Overview#

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

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

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

By the numbers:

  • 1148 commits have been added since 2.0

  • 202 issues have been closed since 2.0

  • 306 pull requests have been merged since 2.0

  • 38 people have contributed since 2.0

  • 19 of which are new contributors

Please find below a selection of what we consider to be the biggest changes or features with this release.

Support for GOES-16 and GOES-17 X-Ray Sensor (XRS) data#

We have now included support for the GOES-16 and GOES-17 XRS 1-second data. This data can now be queried and downloaded with sunpy.net.Fido and the files read in and analysed as a sunpy.timeseries.TimeSeries.

Flare times on a GOES XRS plot

Flare times on a GOES XRS plot

Retrieving and analyzing GOES X-Ray Sensor (XRS) data

Retrieving and analyzing GOES X-Ray Sensor (XRS) data

The TimeSeriesMetaData class

The TimeSeriesMetaData class

Fido Metadata#

Fido provides a unified interface to download data from several services but lacked support for search for metadata provided by catalogues or data providers. This has now changed and you can query JSOC, HEK and HEC with Fido:

>>> from sunpy.net import Fido
>>> from sunpy.net import attrs as a
>>> results = Fido.search(timerange,
                  a.hek.FL & (a.hek.FL.PeakFlux > 1000) |
                  a.jsoc.Series('hmi.m_45s'))
>>> results
Results from 2 Providers:

2 Results from the HEKClient:
                                                                                                                    gs_thumburl                                                                                                                       ...
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ...
http://sdowww.lmsal.com/sdomedia/ssw/ssw_client/data/ssw_service_100731_205448_25495028/www/EDS_FlareDetective-TriggerModule_20100801T033001-20100801T035225_AIA_171_S21W87_ssw_cutout_20100801_033013_AIA_171_S21W87_20100801_033012_context_0180.gif ...
http://sdowww.lmsal.com/sdomedia/ssw/ssw_client/data/ssw_service_100801_234037_25860951/www/EDS_FlareDetective-TriggerModule_20100801T033008-20100801T035232_AIA_193_S21W87_ssw_cutout_20100801_033020_AIA_193_S21W87_20100801_033019_context_0180.gif ...

1 Results from the JSOCClient:
        T_REC          TELESCOP  INSTRUME  WAVELNTH CAR_ROT
----------------------- -------- ---------- -------- -------
2010.08.01_03:40:30_TAI  SDO/HMI HMI_FRONT2   6173.0    2099

Alongside this, there is easier access to the results from a client by indexing the results by the client name:

>>> hek_results, jsoc_results = results['hek'], results['jsoc']

In the first example you can see the search results from HEK are not too useful by default. The results are truncated as the long urls for the thumbnail take up too many characters and HEK can return up to 100 columns of information. With a new method show() on the results itself, you directly select the columns to display:

>>> hek_results.show('event_peaktime', 'obs_instrument', 'fl_peakflux')
event_peaktime   obs_instrument fl_peakflux
------------------- -------------- -----------
2010-08-01T03:40:37            AIA     1027.64
2010-08-01T03:40:44            AIA     1441.78

To find the keys for all of the columns you can do:

>>> hek_results.keys()
['gs_thumburl',
'comment_count',
'hpc_bbox',
...
'area_unit',
'obs_lastprocessingdate',
'refs']

In addition, if you pass the entire search query into Fido.fetch() and it will ignore results that have no corresponding data files to retrieve.

Querying Metadata clients

Querying Metadata clients

Flare times on a GOES XRS plot

Flare times on a GOES XRS plot

Querying the GOES flare event list

Querying the GOES flare event list

Fido Results Refactor#

While working on the above change, several changes were made to the way that results are returned from sunpy.net.Fido.search and the search methods of the underlying clients.

We have tried to minimize any breaking changes here and we believe that for most users the difference between 2.0 and 2.1 will be minor.

The key highlights you will want to be aware of are:

  • Previously slicing the result of Fido.search() (a UnifiedResponse object) so that it had a length of one returned another UnifiedResponse object, now it will return a QueryResponseTable object, which is a subclass of astropy.table.Table.

  • All result objects contained within the results of a Fido.search() are now QueryResponseTable objects (or subclasses thereof). These objects are subclasses of astropy.table.Table and can therefore be filtered and inspected as tabular objects, and the modified tables can be passed to Fido.fetch().

  • The keys available to be used when formatting the path= argument to Fido.fetch() have changed. This is to standardise them over the results from more clients and make them easier to use. You can use the ~.UnifiedResponse.path_format_keys method to see all the possible keys for a particular search.

  • The search results object returned from Fido.search now correctly counts all results in its file_num property.

  • Results from the NOAAIndicesClient and the NOAAPredictClient no longer have Start Time or End Time in their results table as the results returned from the client are not dependent upon the time parameter of a search.

New synoptic map sources and clients#

MDISynopticMap and HMISynopticMap have been added as new data sources, and automatically fix common issues with FITS metadata from these sources. You do not need to change any code to use these, as sunpy automatically detects and uses the appropriate map sources for each file.

It is now possible to search for GONG synoptic maps within sunpy.net.Fido, using a.Instrument('GONG').

Requesting cutouts from the JSOC#

Fido can now be used to request cutouts from JSOC via the new a.jsoc.Cutout attr. This includes the ability to adjust the requested field of view to “track” a feature as it moves across the solar disk, perform sub-pixel image registration, and mask off-disk pixels.

Requesting cutouts of AIA images from the JSOC

Requesting cutouts of AIA images from the JSOC

Coordinates with velocities#

It is now supported to transform coordinates with attached velocities, and the various ephemeris functions can optionally include velocity information. Transformations between coordinate frames will account for both any change in orientation of the velocity vector and any induced velocity due to relative motion between the frames. For example, consider Mars’s position/velocity in HeliographicStonyhurst:

>>> from astropy.coordinates import SkyCoord
>>> from sunpy.coordinates import get_body_heliographic_stonyhurst
>>> mars = SkyCoord(get_body_heliographic_stonyhurst('mars', '2021-01-01',
...                                                  include_velocity=True))
>>> mars
<SkyCoord( HeliographicStonyhurst: obstime=2021-01-01T00:00:00.000): (lon, lat, radius) in (deg, deg, AU)
    (-34.46752135, 1.77496469, 1.50936573)
 (d_lon, d_lat, d_radius) in (arcsec / s, arcsec / s, km / s)
    (-0.00048971, 0.00060976, 19.54950062)>
>>> mars.velocity.norm()
<Quantity 19.56823076 km / s>

However, HeliographicStonyhurst is a non-inertial frame that rotates over time. By transforming this coordinate to HeliocentricInertial, we can see that Mars’s actual velocity is larger:

>>> mars.heliocentricinertial
<SkyCoord (HeliocentricInertial: obstime=2021-01-01T00:00:00.000): (lon, lat, distance) in (deg, deg, AU)
    (-9.91128592, 1.77496469, 1.50936573)
 (d_lon, d_lat, d_distance) in (arcsec / s, arcsec / s, km / s)
    (0.04174239, 0.00060976, 19.54950058)>
>>> mars.heliocentricinertial.velocity.norm()
<Quantity 49.68592218 km / s>

See Coordinates with velocity information for more information.

Alternatives for reprojecting a Helioprojective map#

The typical observation in Helioprojective coordinates does not contain full 3D information for the sources of emission, so an assumption needs to be made when transforming such coordinates to other coordinate frames. By default, SunPy assumes that the emission is coming from the surface of the Sun, which enables reprojections such as in the example Reprojecting Images to Different Observers. However, this assumption is not appropriate for some observations, e.g., from coronagraphs.

There is now a context manager (assume_spherical_screen()) to override the default assumption such that any 2D coordinates are interpreted as being on the inside of a large spherical screen. See the following example for how this context manager enables alternative reprojections.

Aligning AIA and HMI Data with Reproject

Aligning AIA and HMI Data with Reproject

Reprojecting Using a Spherical Screen

Reprojecting Using a Spherical Screen

Blending maps using mplcairo

Blending maps using mplcairo

Creating a Composite Plot with Three Maps

Creating a Composite Plot with Three Maps

Overlay an AIA image on a LASCO C2 coronagraph

Overlay an AIA image on a LASCO C2 coronagraph

Visualizing 3D stereoscopic images

Visualizing 3D stereoscopic images

Finding map contours#

The new sunpy.map.GenericMap.contour() method can be used to extract contours from a map. It returns contours as a SkyCoord, allowing contours to be easily overplotted on the original or other maps.

Finding contours of a map

Finding contours of a map

Performance improvements#

Several functions in sunpy.map have been significantly sped up with improved algorithms.

In addition, sunpy.map.GenericMap.wcs is now cached when the map metadata remains unchanged, significantly improving performance in applications which make multiple requests for the map WCS (e.g. plotting), and reducing the number of repeated warnings thrown when metadata is missing.

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 2.1:

  • python 3.7

  • astropy 4.0

  • scipy 1.2

  • parfive 1.1

  • drms 0.6.1

  • matplotlib 2.2.2

Contributors to this Release#

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

  • Abhijeet Manhas

  • Abhishek Pandey *

  • Adrian Price-Whelan

  • Albert Y. Shih

  • Aryan Chouhan *

  • Conor MacBride *

  • Daniel Ryan

  • David Pérez-Suárez

  • David Stansby

  • Dipanshu Verma *

  • Erik Tollerud *

  • Jai Ram Rideout

  • Jeffrey Aaron Paul *

  • Johan L. Freiherr von Forstner *

  • Kateryna Ivashkiv *

  • Koustav Ghosh *

  • Kris Akira Stern

  • Kritika Ranjan *

  • Laura Hayes

  • Lazar Zivadinovic

  • Nabil Freij

  • Rutuja Surve

  • Sashank Mishra

  • Shane Maloney

  • Shubham Jain *

  • SophieLemos *

  • Steven Christe

  • Stuart Mumford

  • Sudeep Sidhu *

  • Tathagata Paul *

  • Thomas A Caswell *

  • Will Barnes

  • honey

  • mridulpandey

  • nakul-shahdadpuri *

  • platipo *

  • resakra *

  • sophielemos *

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