What’s New in Astropy 4.1?¶

Overview¶

Astropy 4.1 is a major release that contains bug fixes and new features since the 4.0.x series of releases.

In particular, this release includes:

In addition to these major changes, Astropy v4.0 includes a large number of smaller improvements and bug fixes, which are described in the Full Changelog. By the numbers:

• 211 issues have been closed since v4.0

• 275 pull requests have been merged since v4.0

• 62 distinct people have contributed code to this release, 25 of which are first time contributors to Astropy

A new SpectralCoord class for representing and transforming spectral quantities¶

The Astronomical Coordinate Systems (astropy.coordinates) sub-package now includes a new SpectralCoord class which can be used to represent spectral coordinates, and transform between different velocity reference frames. It can be used for simple spectral conversions:

>>> from astropy import units as u
>>> from astropy.coordinates import SpectralCoord, SkyCoord
>>> sc = SpectralCoord([654.2, 654.4, 654.6] * u.nm)
>>> sc
<SpectralCoord [654.2, 654.4, 654.6] nm>
>>> sc.to(u.micron)
<SpectralCoord [0.6542, 0.6544, 0.6546] micron>
>>> sc.to(u.eV)
<SpectralCoord [1.89520328, 1.89462406, 1.89404519] eV>
>>> sc.to(u.THz)
<SpectralCoord [458.25811373, 458.11805929, 457.97809044] THz>


It can also hold information about the observer and target:

>>> from astropy.time import Time
>>> from astropy.coordinates import EarthLocation
>>> location = EarthLocation.of_site('ALMA')
>>> alma = location.get_itrs(obstime=Time('2019-04-24T02:32:10'))
>>> ttau = SkyCoord('04h21m59.43s +19d32m06.4', frame='icrs',
...                 radial_velocity=23.9 * u.km / u.s,
...                 distance=144.321 * u.pc)
>>> sc_ttau = SpectralCoord([200, 250, 300] * u.GHz,
...                         observer=alma, target=ttau)


which then allows for example transforming these spectral values to different velocity frame, including for example to local standard of rest frames (the following example uses the Kinematic Local Standard of Rest definition):

>>> sc_ttau.with_observer_stationary_relative_to('lsrk')
<SpectralCoord
...
[200.01903338, 250.02379172, 300.02855007] GHz>


or to the rest frame of the target:

>>> sc_ttau.with_observer_stationary_relative_to(sc_ttau.target)
<SpectralCoord
...
[200.02737811, 250.03422264, 300.04106717] GHz>


For more information and examples, see Using the SpectralCoord Class.

Support for writing Dask arrays to FITS files¶

It is now possible to set the data array for PrimaryHDU and ImageHDU to a dask array. If this is written to disk, the dask array will be computed as it is being written, which will avoid using excessive memory:

>>> import dask.array as da
>>> array = da.random.random((1000, 1000))
>>> from astropy.io import fits
>>> hdu = fits.PrimaryHDU(data=array)


Added True Equator Mean Equinox (TEME) frame for satellite two-line ephemeris data¶

The True Equator Mean Equinox (TEME) frame has been added to the built-in frames within astropy.coordinates.

For more details, see Working with Earth Satellites Using Astropy Coordinates.

Support for in-place setting of array-valued SkyCoord and frame objects¶

Coordinate values in a array-valued SkyCoord object can now be modified in-place using the standard syntax for setting elements of a numpy array:

>>> sc1 = SkyCoord([1, 2] * u.deg, [3, 4] * u.deg)
>>> sc2 = SkyCoord(10 * u.deg, 20 * u.deg)
>>> sc1[0] = sc2
>>> sc1
<SkyCoord (ICRS): (ra, dec) in deg
[(10., 20.), ( 2.,  4.)]>


For more details, see Modifying Coordinate Objects In-place.

Change in the definition of equality comparison for coordinate classes¶

When comparing coordinate SkyCoord or frame objects using the equality operators == or !=, the result is now a boolean scalar or array corresponding to the equality of the corresponding representation data (including velocities if defined). The comparison is now done in a strict way that requires all of the frame attributes and representation types to be identical, where an exception is raised if that is not the case.

Previous to version 4.1, coordinate equality meant only that the two objects were the same object. In other words, comparing two SkyCoord objects sc1 == sc2 was the same as writing sc1 is sc2. Some astropy tests were relying on this definition so you should check your package tests as well.

This updated equality operator is mostly useful for writing package tests. For most science analysis or processing work, you should check that the separation between the coordinates is below a specified angular distance.

For details see: Comparing SkyCoord Objects.

Support use of SkyCoord in table vstack, dstack, and insert_row¶

SkyCoord mixin columns can now be used in table operations vstack, dstack, and insert_row (as long as they do not result in missing values). This new functionality is a direct outcome of the new support for setting SkyCoord items in-place.

Support for table cross-match join with SkyCoord or N-d columns¶

It is now possible to join two source catalog tables using a cross-match join on the source coordinates (as SkyCoord mixin columns) with an angular separation matching tolerance. This can greatly simplify combining different catalogs retrieved from astroquery or elsewhere.

This concept of a “fuzzy” join is also available for columns that represent N-D cartesian points where the physical separation must be within a specified threshold. This works with Quantity mixin columns and normal 1-D or N-D columns.

In all cases the cross-matching is done efficiently using a KD-Tree algorithm, and thus requires SciPy to be installed.

These join functions are built-in examples of a more generalized new functionality in table joining that allows users to create custom fuzzy join functions. An example would be to use natural language processing tools to join on words that are sufficiently similar.

For detais see Joining Coordinates and Custom Join Functions.

Support for custom attributes in Table subclasses¶

One simple table customization that can be useful is adding new attributes to the table object. This is easy enough, for example t.foo = 'hello', but this attribute will be lost if the table is sliced, copied, pickled, or stored to FITS or ECSV. In astropy 4.1 there is now an included mechanism to add custom attributes which are persistent through all those normal operations.

For details see Adding Custom Table Attributes.

Added a new Time subformat unix_tai¶

A new Time subformat unix_tai has been added which is analogous to the standard unix time subformat but includes leap-seconds. This value matches the definition for linux CLOCK_TAI.

For recent times (after about 1972) the unix_tai value will differ from unix by the cumulative integral number of leap seconds since 1970-01-01 UTC. There were 8.0 leap seconds in place at that time.

For details see: TimeUnixTai.

Added support for the -TAB convention in FITS WCS¶

astropy.wcs is now able to read and interpret WCSs implementing the -TAB convention as described in WCS Paper III, Greisen, E. W., Calabretta, M. R., Valdes, F. G., and Allen, S. L., Astronomy & Astrophysics, 446, 747-771, 2006. Currently there is no support for programmatically constructing such WCSs.

Support for replacing submodels in CompoundModel¶

It is now possible to create a new CompoundModel by modifying an existing one with the replace_submodel() method. The replacement model can have an arbitrary number of submodels. The only requirement is that the number of inputs and outputs must match. The model to be replaced is identified by its name:

>>> from astropy.modeling import models
>>> m1 = models.Polynomial2D(2) & models.Polynomial2D(2)
>>> m2 = models.Rotation2D(21.3) | models.Pix2Sky_TAN()
>>> m2.name = "Rotate_and_Project"
>>> model = m1 | m2
>>> model_subst = models.Shift(1) & models.Shift(2)
>>> new_model = model.replace_submodel("Rotate_and_Project", model_subst | m2)


Support for units on otherwise unitless models via the Model.coerce_units method.¶

A new coerce_units() method provides a way to add input and return units to a unitless model (e.g. polynomial) by enclosing it with two UnitsMapping instances and returning a compound model.

>>> from astropy.modeling import models
>>> p = models.Polynomial1D(1, c0=1, c1=0)
>>> p_with_units = p.coerce_units({'x': u.m}, {'y': u.s})
>>> p_with_units(2 * u.m)
<Quantity 1. s>


Support for ASDF serialization of models¶

All models (excluding model sets) can be written to an ASDF file. Constraints of type fixed and bounds can also be serialized.

Full change log¶

To see a detailed list of all changes in version v4.1, including changes in API, please see the Full Changelog.

Contributors to the v4.0 release¶

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

 Adrian Price-Whelan Albert Y. Shih Alex Conley Anne Archibald Antetokounpo * Arthur Eigenbrot Benjamin Alan Weaver Benjamin Roulston Brett Morris Brigitta Sipőcz Carl Schaffer * Chris Osborne * Chris Simpson * Clara Brasseur Clare Shanahan Dan Foreman-Mackey Daniel Ruschel Dutra * David Stansby Derek Homeier Ed Slavich * Erik Tollerud Erin Allard * Gabriel Perren * Hans Moritz Günther James Davies Jan Skowron * Jerry Ma Juan Luis Cano Rodríguez Julien Woillez Kris Stern Larry Bradley Lauren Glattly Leo Singer M S R Dinesh * Manodeep Sinha * Marten van Kerkwijk Max Voronkov * Maximilian Nöthe Michael Lindner-D’Addario * Miguel de Val-Borro Mihai Cara Nadia Dencheva Nathanial Hendler * Neal McBurnett * Nicholas Earl * Nick Lloyd * Nick Murphy Perry Greenfield Peter Cock * Pey Lian Lim Ricky O’Steen * Robel Geda * Shivansh Mishra * Shreyas Bapat Simon Conseil Stuart Littlefair Stuart Mumford Thomas Robitaille Tim Jenness Tom Aldcroft Tom Donaldson Zlatan Vasović *

Where a * indicates their first contribution to the core astropy package.