.. _whatsnew-5.3:

**************************
What's New in Astropy 5.3?
**************************

Overview
========

Astropy 5.3 is a major release that adds significant new functionality since
the 5.2 release.

In particular, this release includes:

.. * :ref:`whatsnew-5.3-cosmology`
.. * :ref:`whatsnew-5.3-table-union-operators`
.. * :ref:`whatsnew-5.3-compressed-fits`
.. * :ref:`whatsnew-5.3-compressed-fits-nocompress`
.. * :ref:`whatsnew-5.3-unit-formats-fraction`
.. * :ref:`whatsnew-5.3-unit-formats-order`
.. * :ref:`whatsnew-5.3-nddata-collapse-arbitrary-axes`
.. * :ref:`whatsnew-5.3-modeling-measurement-uncertainties`
.. * :ref:`whatsnew-5.3-coordinates-refresh-site-registry`

In addition to these major changes, Astropy v5.3 includes a large number of
smaller improvements and bug fixes, which are described in the :ref:`changelog`.
By the numbers:

* 984 commits have been added since 5.2
* 156 issues have been closed since 5.2
* 238 pull requests have been merged since 5.2
* 46 people have contributed since 5.2
* 16 of which are new contributors

.. _whatsnew-5.3-cosmology:

New flat :mod:`astropy.cosmology` classes
=========================================

Two new cosmologies have been added, :class:`~astropy.cosmology.FlatwpwaCDM` and
:class:`~astropy.cosmology.Flatw0wzCDM`, which are the flat variants of
:class:`~astropy.cosmology.wpwaCDM` and :class:`~astropy.cosmology.w0wzCDM`,
respectively.

    >>> from astropy.cosmology import Flatw0wzCDM
    >>> cosmo = Flatw0wzCDM(H0=70, Om0=0.3, w0=-0.9, wz=0.2)
    >>> cosmo.comoving_distance(0.5)  # doctest: +SKIP
    <Quantity 1982.66012926 Mpc>

.. _whatsnew-5.3-table-union-operators:

New union operators for |Table|
===============================

We have added support for dictionary-style merge (``|``) and update (``|=``)
of columns in the |Table| class. This follows the  behavior for ``dict`` defined
in `PEP 584 <https://peps.python.org/pep-0584/>`_. ``|=`` works the same way as
:meth:`~astropy.table.Table.update` and updates the table in place. ``|``
return the updated table::

	>>> from astropy.table import Table, QTable
	>>> t1 = Table({'a': ['foo', 'bar'], 'b': [0., 0.]})
	>>> t2 = QTable({'b': [1., 2.], 'c': [7., 11.]})
	>>> t3 = t1 | t2  # Create new table which merges columns from t1 and t2
	>>> t3
	<Table length=2>
	a      b       c
	str3 float64 float64
	---- ------- -------
	foo     1.0     7.0
	bar     2.0    11.0

	>>> t2 |= t1  # Update t2 columns in-place with t1 columns
	>>> t2
	<QTable length=2>
	   b       c     a
	float64 float64 str3
	------- ------- ----
	    0.0     7.0  foo
	    0.0    11.0  bar

When using ``|=``, the other object does not need to be a |Table|, it can be
anything that can be used for :ref:`construct_table` with a compatible number
of rows.

.. _whatsnew-5.3-compressed-fits:

Efficient data access for compressed FITS files
===============================================

In previous astropy versions, when accessing data for a compressed
FITS file via the :attr:`~astropy.io.fits.CompImageHDU.data` property of
:class:`~astropy.io.fits.CompImageHDU`,
the whole data was read in and decompressed even if only a small part of
the data was required. The :class:`~astropy.io.fits.CompImageHDU` class
now has a :attr:`~astropy.io.fits.CompImageHDU.section` property which
can be used to access specific sections of the data and will result in
as little data as possible being read in and decompressed. For a compressed
image:

.. doctest-skip::

    >>> hdu.section[300:400, 100:200]

will therefore return the same result as:

.. doctest-skip::

    >>> hdu.data[300:400, 100:200]

but the former will be faster. The exact speedup will depend on the size of the
data and the size of the tiles but could be 10-100x or more.

.. _whatsnew-5.3-compressed-fits-nocompress:

Added support for ``NOCOMPRESS`` for compressed FITS files
==========================================================

It is now possible to read and write compressed FITS files that make use of the
``NOCOMPRESS`` compression algorithm. This allows users to store data in
uncompressed tiles by specifying ``compression_type='NOCOMPRESS'`` in
:class:`~astropy.io.fits.CompImageHDU`.

.. _whatsnew-5.3-unit-formats-fraction:

New ``fraction`` option for representing units as strings
=========================================================

A new formatting option is added to switch between using fractions or
using negative powers directly, with the fraction option also
allowing to switch between inline and multiline prettyprinting of
units::

	>>> import astropy.units as u
	>>> unit = u.Unit('erg / (s cm2)')
	>>> print(unit.to_string('console'))
	erg s^-1 cm^-2
	>>> print(unit.to_string('console', fraction='inline'))
        erg / (s cm^2)
	>>> print(unit.to_string('console', fraction='multiline'))
         erg
        ------
        s cm^2
	>>> print(unit.to_string('unicode'))
	erg s⁻¹ cm⁻²
	>>> print(unit.to_string('unicode', fraction='inline'))
        erg / (s cm²)
	>>> print(unit.to_string('unicode', fraction='multiline'))
         erg
        ─────
        s cm²

Note that the ``'console'`` and ``'unicode'`` formats now use
``fraction=False`` by default, since this will more reliably produce
readable results when printing quantities, table headers and cells, etc.
For ``'latex'`` the default remains ``fraction='display'``, for an
unchanged experience with IPython notebook.

.. _whatsnew-5.3-unit-formats-order:

Change in order in unit string representations
==============================================

In string representations of units, the order of bases now is by decreasing
power first, then alphabetical, instead of alphabetical independent of power.
This is also how unit bases are stored internally and helps particularly for
units without fractions (such as FITS), where a unit like ``Jy/beam`` was
typeset as ``beam-1 Jy`` instead of the more logical ``Jy beam-1``.

For typesetting with fractions, there is usually less effect, but the string
representations of complicated units will change (e.g., what previously was
``erg / (Angstrom cm2 s)`` will now be ``erg / (Angstrom s cm2)``).

Unfortunately, this is a breaking change if you test for unit *string*
downstream. To workaround a unit string comparison failure that you see,
you can filter by ``astropy`` version either in the Python module or
in ``setup.cfg``. We provide some examples below but these are not
exhaustive; please adapt them to your own use cases and refer to
`pytest-doctestplus documentation <https://github.com/astropy/pytest-doctestplus>`_.

Example in a Python module that enables the same test for all
supported ``astropy`` versions::

    import astropy
    from astropy.utils.introspection import minversion

    ASTROPY_LT_5_3 = not minversion(astropy, "5.3.dev")

    if ASTROPY_LT_5_3:
        flux_unit_str = "erg / (Angstrom cm2 s)"
    else:
        flux_unit_str = "erg / (Angstrom s cm2)"
    # Some code that compares against flux_unit_str here.

Example in a Python module that skips doctest for ``astropy`` 5.3 or later::

    # ASTROPY_LT_5_3
    __doctest_requires__ = {"class_or_function_name": ["astropy<5.3"]}

Example in ``setup.cfg``::

    doctest_subpackage_requires =
        docs/somedocpage.rst = astropy>=5.3  # units updated to new ordering
        package/somemodule.py = astropy<5.3  # TODO: update units to new ordering

.. _whatsnew-5.3-nddata-collapse-arbitrary-axes:

Support for collapse operations on arbitrary axes in ``nddata``
===============================================================

Take the sum, mean, maximum, or minimum along one or more axes,
reducing the dimensions of the output, on `~astropy.nddata.NDData` objects
with appropriate propagation of uncertainties, masks, and units. For example,
we can take the sum of ND masked quantities along the ``1`` axis like so::

    >>> import numpy as np
    >>> import astropy.units as u
    >>> from astropy.nddata import NDDataArray, StdDevUncertainty
    >>>
    >>> data = [
    ...     [1, 2, 3],
    ...     [2, 3, 4]
    ... ]
    >>> mask = [
    ...     [True, False, False],
    ...     [False, False, False]
    ... ]
    >>> uncertainty = StdDevUncertainty(np.ones_like(data))
    >>> nddata = NDDataArray(data=data, uncertainty=uncertainty, mask=mask, unit='m')
    >>> sum_axis_1 = nddata.sum(axis=1)
    >>> sum_axis_1, sum_axis_1.mask, sum_axis_1.uncertainty
    (NDDataArray([6., 9.], unit='m'),
     array([ True, False]),
     StdDevUncertainty([1.41421356, 1.73205081]))


.. _whatsnew-5.3-coordinates-refresh-site-registry:

Refresh cached observatory site registry for |EarthLocation| methods
====================================================================

The |EarthLocation| convenience methods
:meth:`~astropy.coordinates.EarthLocation.of_site` and
:meth:`~astropy.coordinates.EarthLocation.get_site_names` use the observatory
site registry from the
`astropy-data repository <https://github.com/astropy/astropy-data>`_ to
return site data by name.  Usually, the site registry is cached on the
user's computer for quick access.  The online version of the registry,
however, is updated from time to time to include new locations.  The user
may refresh their locally cached site registry by passing the new
``refresh_cache=True`` option to these two functions.

.. _whatsnew-5.3-modeling-measurement-uncertainties:

Support for collapse operations on arbitrary axes in ``nddata``
===============================================================

Propagate measurement uncertainties into the best-fit parameter covariances
via the ``weights`` keyword argument in non-linear fitters. Decreasing
the ``weights`` will now increase the uncertainties on the best-fit parameters.


.. _whatsnew-5.3-multiband-lombscargle:

New :class:`~astropy.timeseries.LombScargleMultiband` class for multiband datasets
==================================================================================

:class:`~astropy.timeseries.LombScargleMultiband` is a newly released extension
of the :class:`~astropy.timeseries.LombScargle` class. It enables the
generation of periodograms for datasets with measurements taken in more than
one photometric bands.

The code is adapted from the `astroml`_ package and the
`gatspy`_ package, but conforms closely to the design paradigms
established in :class:`~astropy.timeseries.LombScargle`.

Two implementations of the Multiband Lomb-Scargle Periodogram are available
within :class:`~astropy.timeseries.LombScargleMultiband`, ``flexible`` and
``fast``. ``flexible`` is a direct port of the LombScargleMultiband algorithm
used in the gatspy `gatspy`_ package. ``flexible`` serves as a similar
implementation to ``flexible`` LombScargleMultibandFast, but leverages
:class:`~astropy.timeseries.LombScargle` to do it's independent band-by-band
fits.

.. _gatspy: https://www.astroml.org/gatspy/
.. _astroml: https://www.astroml.org/

Full change log
===============

To see a detailed list of all changes in version v5.3, including changes in
API, please see the :ref:`changelog`.

Contributors to the v5.3 release
================================

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

.. hlist::
  :columns: 4

  -  Abdu Zoghbi  *
  -  Albert Y. Shih
  -  Brett Graham  *
  -  Brett M. Morris  *
  -  Brigitta Sipőcz
  -  Caden Gobat  *
  -  Chiara Marmo
  -  David Stansby
  -  Derek Homeier
  -  Doug Branton  *
  -  E. Rykoff
  -  Eero Vaher
  -  Felipe Cybis Pereira  *
  -  Jamie Kennea  *
  -  Larry Bradley
  -  Manon Marchand  *
  -  Markus Demleitner
  -  Marten van Kerkwijk
  -  Maximilian Linhoff
  -  Michael Brewer
  -  Mihai Cara
  -  Mubin17  *
  -  Nabil Freij
  -  Nathaniel Starkman
  -  naveen  *
  -  Nick Murphy
  -  Ole Streicher
  -  P. L. Lim
  -  Paul Price
  -  Roy Smart
  -  Samruddhi Khandale  *
  -  Sandeep Desai  *
  -  Simon Alinder  *
  -  Simon Conseil
  -  Stuart Mumford
  -  Telomelonia  *
  -  Thomas J. Fan  *
  -  Thomas Robitaille
  -  Tiago Gomes
  -  Tiago Ribeiro  *
  -  Timothy P. Ellsworth Bowers
  -  Tom Aldcroft
  -  Tom Donaldson
  -  William Jamieson

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