Skip to main content
`Ctrl`+`K`

# What’s New in Astropy 8.0?

## Overview

Astropy 8.0 is a release that adds significant new functionality since the 7.2 release.

In particular, this release includes:

- Cosmology

- CODATA 2022 is now default in constants

- Table formats

- Overhaul of cache and configuration path discovery mechanism

- Write table indices to FITS, HDF5 and ECSV formats

- Variable-length array logical columns in FITS

- Fast Lomb-Scargle: Low Rank Approximation

- Preserving NULL values in FITS logical columns

- Table display and pandas conversion

- FITS string column changes

- New imshow_simple_norm convenience function

- Parsing vector strings into Quantity

- Deprecation of the built-in test runner

- NumPy 2.0 is now required

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

- 1014 commits have been added since v7.2

- 179 issues have been closed since v7.2

- 364 pull requests have been merged since v7.2

- 70 people have contributed since v7.2

- 37 of which are new contributors

## Full change log

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

## Cosmology

The `astropy.cosmology` module has several updates in this release.

### Module Simplification

The deprecated module-level shim files in `astropy.cosmology` have been removed. These compatibility modules were originally deprecated in v7.1. With this release, all cosmology classes and functions must be imported directly from `astropy.cosmology`.

The following deprecated modules have been removed:

- `astropy.cosmology.connect`

- `astropy.cosmology.core`

- `astropy.cosmology.flrw`

- `astropy.cosmology.funcs`

- `astropy.cosmology.parameter`

Migration Guide

If your code was still using the old import paths, you need to update them to import directly from `astropy.cosmology`.

Before:

    from astropy.cosmology.flrw import FlatLambdaCDM
    from astropy.cosmology.core import Cosmology
    from astropy.cosmology.funcs import z_at_value

After:

    from astropy.cosmology import Cosmology, FlatLambdaCDM, z_at_value

### Cosmology Traits

The `traits` module provides reusable components, called traits, that encapsulate specific cosmological properties or behaviors. For example, the `NeutrinoComponent` trait provides the neutrino component and related methods. By combining these traits, you can easily construct custom cosmology classes with precisely the features you need, without having to reimplement common functionality. Here is an example of how to use the `NeutrinoComponent` trait in custom cosmology classes:

    >>> import numpy as np
    >>> from astropy import units as u
    >>> from astropy.cosmology import Cosmology
    >>> from astropy.cosmology.traits import TemperatureCMB, NeutrinoComponent
    >>> NEUTRINO_FERMI_DIRAC_CORRECTION = 0.22710731766  # 7/8 (4/11)^4/3
    >>>
    >>> class SimpleNeutrinoCosmology(Cosmology, TemperatureCMB, NeutrinoComponent):
    ...     '''Minimal cosmology demonstrating NeutrinoComponent trait.'''
    ...     def __init__(self, Tcmb0=2.7255, Neff=3.046, Ogamma0=5e-5):
    ...         self.Tcmb0 = u.Quantity(Tcmb0, "K")
    ...         self.Neff = Neff
    ...         self.Ogamma0 = Ogamma0
    ...         super().__init__()
    ...     @property
    ...     def has_massive_nu(self):
    ...         return False
    ...     @property
    ...     def Onu0(self):
    ...         return NEUTRINO_FERMI_DIRAC_CORRECTION * self.Neff * self.Ogamma0
    ...     def nu_relative_density(self, z):
    ...         return NEUTRINO_FERMI_DIRAC_CORRECTION * self.Neff * np.ones_like(np.asarray(z))
    ...     def Ogamma(self, z):
    ...         return self.Ogamma0 * (np.asarray(z) + 1.0) ** 4
    ...     @property
    ...     def is_flat(self):
    ...         return True
    >>>
    >>> cosmo = SimpleNeutrinoCosmology()
    >>> cosmo.Tnu0
    <Quantity 1.94... K>
    >>> cosmo.has_massive_nu
    False
    >>> cosmo.Onu0
    3.4...e-05
    >>> cosmo.Onu(0)
    np.float64(3.4...e-05)
    >>> cosmo.Tnu(1)
    <Quantity 3.89... K>

### Machine Readable Table (MRT) I/O

The `astropy.cosmology` module now supports reading and writing cosmological objects in the Machine Readable Table (MRT) format. This adds MRT to the existing I/O options for cosmology, which include YAML, ECSV, HTML, and LaTeX formats.

MRT format is commonly used in astronomical publications and data archives. You can now save and load cosmological parameters using the `.read()` and `.write()` methods with `format="ascii.mrt"`:

    from astropy.cosmology import Planck18

    # Write to MRT file
    Planck18.write("cosmology.mrt")

    # Read from MRT file
    cosmo = Cosmology.read("cosmology.mrt")

Note that since MRT format does not preserve table metadata, the cosmology class is included as a column in the table rather than in metadata (similar to HTML and LaTeX formats). Multi-dimensional columns (such as neutrino masses) are automatically JSON-encoded when writing and decoded when reading.

### Angular diameter distance between two redshifts

The `angular_diameter_distance()` method now accepts either one or two redshift arguments. When two redshifts are supplied, it returns the angular diameter distance from an object at `z1` to an object at `z2`, replacing the use of the now-deprecated `angular_diameter_distance_z1z2` method:

    from astropy.cosmology import Planck18

    Planck18.angular_diameter_distance(0.5)        # observer to z=0.5
    Planck18.angular_diameter_distance(0.5, 2.0)   # z=0.5 to z=2.0

## CODATA 2022 is now default in constants

CODATA 2022 has replaced CODATA 2018 as default. `astropyconst80` is available for `constants` science state, combining CODATA 2022 with IAU 2015. To use previous version of CODATA, see Collections of Constants (and Prior Versions).

## Table formats

A new table reader has been added to read history and profile output files from MESA, a well-known code for stellar evolution calculations.

## Overhaul of cache and configuration path discovery mechanism

Cache and configuration directories now adhere to the XDG specification by default. For example, the default cache location was changed from `$HOME/.astropy/cache` to `$XDG_CACHE_HOME/astropy`, where `XDG_CACHE_HOME` itself defaults to `$HOME/.cache`. Legacy cache and configuration default locations are still silently selected if present and in case the new default locations do not exist.

In addition, temporary directories set through `set_temp_cache` or `set_temp_config` will now not be symlinked to default locations. The new behavior is also meant as 100% cross platform: Windows isn’t special cased like it used to.

`set_temp_cache` and `set_temp_config` themselves (hereafter, legacy APIs) are now soft-deprecated, meaning their use is discouraged for new code but will not emit deprecation warnings, in favor of new, similar, but not drop-in replacement APIS: `temporary_cache_dir_path` and `temporary_config_dir_path` respectively. These alternative functions come with a couple differences in design:

- easily predictable behavior

- safer defaults:

  - temporary files and directories are not leaked by default (`delete=True` is the default)

  - pre-existing contents are never deleted (because the final dir is always created)

- `delete` is keyword-only

- `dir_` (path) is positional only

- support `suffix` and `prefix`

- `yield` value is a `pathlib.Path` (not a `str`)

- the `namespace` argument is keyword-only and required, whereas legacy API’s equivalent argument (`rootname`) was allowed positionally and defaulted to `'astropy'`, which contributed to confusion surrounding these APIs.

`ASTROPY_CACHE_DIR` and `ASTROPY_CONFIG_DIR` environment variables are now supported, allowing finer, tool-specific control as compared with `XDG_CACHE_HOME` and `XDG_CONFIG_HOME` which will only be used if astropy-specific environment variables are undefined or invalid (e.g., defined as relative paths or pointing to files).

## Write table indices to FITS, HDF5 and ECSV formats

It is now possible to write `Table` indices to FITS, HDF5, and ECSV formats and subsequently read them back in order to round-trip the original indexed table. This stores the index data as temporary columns in the output and includes other relevant metadata in the file output, similar to the mechanism for serializing mixin columns like `SkyCoord`.

This functionality is enabled by passing `write_indices=True` to the table `write` method. For example:

    >>> import io
    >>> from astropy.table import QTable
    >>> t = QTable({"a": ["x", "z", "y"], "b": [2.0, 1.0, 1.5], "c": ["a", "b", "c"]})
    >>> t.add_index("a")
    >>> out = io.StringIO()
    >>> t.write(out, format="ecsv", write_indices=True)
    >>> t2 = QTable.read(out.getvalue(), format="ecsv")
    >>> t2.loc["x"]
    <Row index=0>
     a      b     c
    str1 float64 str1
    ---- ------- ----
       x     2.0    a

## Variable-length array logical columns in FITS

Variable-length array columns of FITS logical type (`PL`/`QL`) are now read and written correctly. Previously, bool input was written as raw 1/0 bytes rather than the ASCII `T`/`F` bytes required by the FITS specification, and on read these columns were exposed as `int8` arrays containing the byte values (84 for `T`, 70 for `F`) instead of as bool. Files written by astropy <= 7.2.0 are still readable: the legacy `0x00`/`0x01` encoding is auto-detected on read and decoded as bool, with an `AstropyUserWarning` so that users are aware the file does not strictly conform to the FITS standard.

For example:

    >>> from astropy.io import fits
    >>> col = fits.Column(name="a", format="PL", array=[[True, False, True]])
    >>> hdu = fits.BinTableHDU.from_columns([col])
    >>> hdu.writeto("example.fits", overwrite=True)
    >>> fits.getdata("example.fits")["a"][0]
    array([ True, False,  True])

## Fast Lomb-Scargle: Low Rank Approximation

The fast Lomb-Scargle Periodograms (`fast` and `fastchi2` implementations) now use Low Rank Approximation (LRA) algorithm by default. The LRA implementation may be a little slower than the previous fast implementation (although this is architecture-dependent) but is 8 to 10 orders of magnitude more accurate, on par with their slow (non `fast`) counterparts.

This change of default allows eliminating previously seen issues with negative powers.

## Preserving NULL values in FITS logical columns

The FITS standard allows logical (`L` / `PL` / `QL`) column entries to take three byte values: `b'T'` (True), `b'F'` (False), or `b'\x00'` (undefined / NULL). Astropy has historically converted such columns to a numpy `bool` array on read, which silently maps NULL to `False`.

A new `logical_as_bytes` keyword argument has been added to `open()` (mirroring the existing `character_as_bytes` switch). When set to `True`, both fixed-length and variable-length logical columns are returned as `|S1` byte arrays rather than `bool`, so `b'\x00'` is distinguishable from `b'F'`. Bytes read this way also round-trip through writing: a column read as `|S1` and written back to a FITS file preserves NULL bytes verbatim.

A `AstropyUserWarning` is now also issued whenever a logical column being read with `logical_as_bytes=False` (the default) contains NULL bytes, alerting users to lost information.

## Table display and pandas conversion

Two improvements make tables with multidimensional columns easier to work with.

A new `conf.multidim_threshold` configuration option controls how multidimensional columns are displayed. Setting it to a small value (for example, `3`) shows full content for short arrays such as 3-vectors (`[1 2 3]`), while larger arrays still fall back to the abbreviated `first .. last` representation.

In addition, `to_pandas()` now accepts tables with multidimensional columns: previously this would raise a `ValueError`, but they are now converted to 1D object arrays compatible with pandas.

## FITS string column changes

A few changes affect how string columns are read from FITS binary tables.

When reading FITS files via `read()`, the `strip_spaces` option now defaults to `True`, so trailing whitespace in fixed-width string columns is stripped automatically. Pass `strip_spaces=False` to recover the previous behavior.

In preparation for the deprecation of `np.char.chararray` in NumPy 2.5, `astropy.io.fits` will in a future release return ordinary NumPy arrays rather than `chararray` instances for string columns. Code that relies on `chararray`-specific methods (such as `.rstrip()` or `.decode()`) should migrate to the equivalent functions in `np.strings`.

## New imshow_simple_norm convenience function

A new `imshow_simple_norm()` function provides a compact one-call alternative to building a `SimpleNorm`/`simple_norm` and passing it to `imshow`, which is convenient for quick image previews:

    from astropy.visualization import imshow_simple_norm

    imshow_simple_norm(image, stretch="asinh", percent=99.5)

## Parsing vector strings into Quantity

It is now possible to construct a `Quantity` from a 1D vector-like string, with or without units:

    from astropy import units as u

    u.Quantity("[1, 2, 3] m")
    u.Quantity("1, 2, 3", unit="m")

## Deprecation of the built-in test runner

The `astropy.test()` entry point and the `~astropy.tests.runner.TestRunner` / `~astropy.tests.runner.TestRunnerBase` classes are now formally deprecated and will be removed in a future release. Downstream packages that expose a `packagename.test()` function generated via `TestRunner` are affected and should migrate to invoking `pytest` directly. The previously deprecated `astropy.tests.command` module has been removed in this release.

## Deprecation of astropy.samp

The `astropy.samp` module has been moved downstream into the PyVO package and is available since the PyVO v1.9 release. Therefore it is now deprecated in astropy itself.

## NumPy 2.0 is now required

The minimum supported NumPy version is now 2.0. Code and downstream packages that still rely on the NumPy 1.x C API or the Python-level behaviours that changed in NumPy 2.0 will need to be updated.

For users that cannot yet move to NumPy 2.0, the 7.2.x series of releases will continue to receive support for six months following the 8.0 release. That branch remains compatible with NumPy 1.

## Contributors to the 8.0 release

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

- Adam Ginsburg

- Aditya Lohuni *

- Albert Y. Shih

- Ana Clara Galvão *

- Arthur Sardella *

- Ben Green *

- Bill Wolf *

- Bodhi Silberling *

- Brett Morris

- Brigitta Sipőcz

- Bruno Sanchez *

- Charalampos Stratakis *

- Clara Brasseur

- Clément Robert

- Curtis McCully

- Cyrus *

- Dhruv Yadav *

- Duncan Macleod

- Eero Vaher

- Erik Tollerud

- Evan Chen *

- Fazeel Usmani *

- Hans Moritz Günther

- Ikbar Faiz *

- 10. Berg *

- Jett Higgins *

- Joren Hammudoglu *

- Julian Harbeck *

- Kacper Rutkowski *

- Kang Wang

- Kartavay Verma *

- Kyle Oman

- Larry Bradley

- M Bussonnier *

- Macdara Ó Murchú *

- Marten van Kerkwijk

- Maximilian Linhoff

- Mohsin Mehmood

- Nabil Freij

- Nadia Dencheva

- Naksh Yadav *

- Nathaniel Starkman

- Om S Habib *

- 16. 12. Lim

- Pierre Sassoulas *

- Preshanth Jagannathan

- 18. Virinchi *

- Raphael Erik Hviding

- Reem Hamraz *

- RinZ27 *

- Simon Conseil

- Stelios Voutsinas

- Stuart Mumford

- Surya K. *

- Syn Pu *

- Thomas Dutkiewicz *

- Thomas Robitaille

- Tiago Gomes

- Tim Jenness

- Tom Aldcroft

- Varun Kasyap Pentamaraju *

- Varun Nikam

- Vishwas *

- Wang Rui *

- William Jamieson

- Yaocheng Chen *

- gilles.landais *

- github-actions

- xbreak *

- Περικλής Παντελαίος *

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