.. _whatsnew-4.1: ************************** 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: * :ref:`whatsnew-4.1-spectralcoord` * :ref:`whatsnew-4.1-fitsdask` * :ref:`whatsnew-4.1-teme` * :ref:`whatsnew-4.1-inplace-skycoord` * :ref:`whatsnew-4.1-coordinate-equality` * :ref:`whatsnew-4.1-skycoord-stack` * :ref:`whatsnew-4.1-table-skycoord-crossmatch` * :ref:`whatsnew-4.1-table-custom-attr` * :ref:`whatsnew-4.1-time-unix-tai` * :ref:`whatsnew-4.1-fits-wcs-tab` * :ref:`whatsnew-4.1-replace-submodels` * :ref:`whatsnew-4.1-models-units` * :ref:`whatsnew-4.1-models-serialization` In addition to these major changes, Astropy v4.0 includes a large number of smaller improvements and bug fixes, which are described in the :ref:`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 .. _whatsnew-4.1-spectralcoord: A new ``SpectralCoord`` class for representing and transforming spectral quantities =================================================================================== The :ref:`astropy-coordinates` sub-package now includes a new :class:`~astropy.coordinates.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 # doctest: +FLOAT_CMP >>> sc.to(u.micron) # doctest: +FLOAT_CMP >>> sc.to(u.eV) # doctest: +FLOAT_CMP >>> sc.to(u.THz) # doctest: +FLOAT_CMP .. testsetup:: >>> from astropy.coordinates import EarthLocation >>> location = EarthLocation(2225015.30883296, -5440016.41799762, -2481631.27428014, unit='m') 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') # doctest: +SKIP >>> 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) # doctest: +IGNORE_WARNINGS 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') # doctest: +FLOAT_CMP +REMOTE_DATA or to the rest frame of the target:: >>> sc_ttau.with_observer_stationary_relative_to(sc_ttau.target) # doctest: +FLOAT_CMP +REMOTE_DATA For more information and examples, see :ref:`astropy-spectralcoord`. .. _whatsnew-4.1-fitsdask: Support for writing Dask arrays to FITS files ============================================= It is now possible to set the data array for :class:`~astropy.io.fits.PrimaryHDU` and :class:`~astropy.io.fits.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: .. doctest-requires:: dask >>> import dask.array as da >>> array = da.random.random((1000, 1000)) >>> from astropy.io import fits >>> hdu = fits.PrimaryHDU(data=array) >>> hdu.writeto('test_dask.fits', overwrite=True) .. _whatsnew-4.1-teme: Added True Equator Mean Equinox (TEME) frame for satellite two-line ephemeris data ================================================================================== The True Equator Mean Equinox (`~astropy.coordinates.TEME`) frame has been added to the built-in frames within :ref:`astropy.coordinates `. For more details, see :ref:`astropy-coordinates-satellites`. .. _whatsnew-4.1-inplace-skycoord: 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 For more details, see :ref:`astropy-coordinates-modifying-in-place`. .. _whatsnew-4.1-coordinate-equality: 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: :ref:`coordinates-skycoord-comparing`. .. _whatsnew-4.1-skycoord-stack: 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. .. _whatsnew-4.1-table-skycoord-crossmatch: 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 :ref:`astropy-table-join-functions`. .. _whatsnew-4.1-table-custom-attr: 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 :ref:`table-custom-attributes`. .. _whatsnew-4.1-time-unix-tai: 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: `~astropy.time.TimeUnixTai`. .. _whatsnew-4.1-fits-wcs-tab: 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. .. _whatsnew-4.1-replace-submodels: Support for replacing submodels in ``CompoundModel`` ==================================================== It is now possible to create a new ``CompoundModel`` by modifying an existing one with the :meth:`~astropy.modeling.core.CompoundModel.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) .. _whatsnew-4.1-models-units: Support for units on otherwise unitless models via the ``Model.coerce_units`` method. ===================================================================================== A new :meth:`~astropy.modeling.core.Model.coerce_units` method provides a way to add input and return units to a unitless model (e.g. polynomial) by enclosing it with two :class:`~astropy.modeling.mappings.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) .. _whatsnew-4.1-models-serialization: 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 :ref:`changelog`. Contributors to the v4.0 release ================================ The people who have contributed to the code for this release are: .. hlist:: :columns: 4 * 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.