Skip to content

Commit

Permalink
Add method __astropy_table__
Browse files Browse the repository at this point in the history
Allows for ``Table(cosmo)``.

Signed-off-by: Nathaniel Starkman (@nstarman) <nstarkman@protonmail.com>
  • Loading branch information
nstarman committed Oct 28, 2021
1 parent 147b5d5 commit c1cd0c1
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 8 deletions.
20 changes: 20 additions & 0 deletions astropy/cosmology/core.py
Expand Up @@ -428,6 +428,26 @@ def __repr__(self):

return namelead + ", ".join(fmtps) + ")"

def __astropy_table__(self, cls, copy, **kwargs):
"""Return a `~astropy.table.Table` of type ``cls``.
Parameters
----------
cls : type
Astropy ``Table`` class or subclass.
copy : bool
Ignored.
**kwargs : dict, optional
Additional keyword arguments. Passed to ``self.to_format()``.
See ``Cosmology.to_format.help("astropy.table")`` for allowed kwargs.
Returns
-------
`astropy.table.Table` or subclass instance
Instance of type ``cls``.
"""
return self.to_format("astropy.table", cls=cls, **kwargs)


class FlatCosmologyMixin(metaclass=abc.ABCMeta):
"""
Expand Down
7 changes: 4 additions & 3 deletions astropy/cosmology/io/tests/test_table.py
Expand Up @@ -110,8 +110,9 @@ def test_to_from_table_instance(self, cosmo, to_format, from_format):
got = from_format(tbl, format="astropy.table")
assert got == cosmo

# and it will also work if the cosmology is a string
tbl.meta["cosmology"] = _COSMOLOGY_CLASSES[tbl.meta["cosmology"]].__qualname__
# and it will also work if the cosmology is a class
# Note this is not the default output of ``to_format``.
tbl.meta["cosmology"] = _COSMOLOGY_CLASSES[tbl.meta["cosmology"]]
got = from_format(tbl, format="astropy.table")
assert got == cosmo

Expand Down Expand Up @@ -194,4 +195,4 @@ class TestToFromTable(ToFromFormatTestBase, ToFromTableTestMixin):
"""

def setup_class(self):
self.io_functions = {"to": to_table, "from": from_table}
self.functions = {"to": to_table, "from": from_table}
24 changes: 24 additions & 0 deletions astropy/cosmology/tests/test_core.py
Expand Up @@ -306,6 +306,30 @@ def test_is_equivalent(self, cosmo):
# different class
assert not cosmo.is_equivalent(2)

# ------------------------------------------------

@pytest.mark.parametrize("in_meta", [True, False])
@pytest.mark.parametrize("table_cls", [Table, QTable])
def test_astropy_table(self, cosmo, table_cls, in_meta):
"""Test ``astropy.table.Table(cosmology)``."""
tbl = table_cls(cosmo, cosmology_in_meta=in_meta)

assert isinstance(tbl, table_cls)
# the name & all parameters are columns
for n in ("name", *cosmo.__parameters__):
assert n in tbl.colnames
assert all(tbl[n] == getattr(cosmo, n))
# check if Cosmology is in metadata or a column
if in_meta:
assert tbl.meta["cosmology"] == cosmo.__class__.__qualname__
assert "cosmology" not in tbl.colnames
else:
assert "cosmology" not in tbl.meta
assert tbl["cosmology"][0] == cosmo.__class__.__qualname__
# the metadata is transferred
for k, v in cosmo.meta.items():
assert np.all(tbl.meta[k] == v)


class CosmologySubclassTest(TestCosmology):
"""
Expand Down
1 change: 1 addition & 0 deletions docs/changes/cosmology/12213.feature.rst
@@ -1,2 +1,3 @@
Register Astropy Table into Cosmology's ``to/from_format`` I/O, allowing
a Cosmology instance to be parsed from or converted to a Table instance.
Also adds the ``__astropy_table__`` method allowing ``Table(cosmology)``.
19 changes: 17 additions & 2 deletions docs/cosmology/io.rst
Expand Up @@ -142,8 +142,8 @@ to the ``Planck18`` cosmology from which it was created.
.. EXAMPLE START: Planck18 to QTable and back
Another pre-registered format is "table", for converting a |Cosmology| to
and from a |QTable|.
Another pre-registered format is "table", for converting a |Cosmology| to
and from a |QTable|.

.. code-block::
Expand All @@ -156,6 +156,21 @@ to the ``Planck18`` cosmology from which it was created.
-------- ------------ ------- ------- ------- ----------- -------
Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897
Cosmology supports the astropy Table-like protocol (see :ref:`Table-like Objects`)
to the same effect:

.. code-block::
>>> from astropy.table import QTable
>>> ct = QTable(Planck18)
>>> ct
<QTable length=1>
name H0 Om0 Tcmb0 Neff m_nu [3] Ob0
km / (Mpc s) K eV
str8 float64 float64 float64 float64 float64 float64
-------- ------------ ------- ------- ------- ----------- -------
Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897
Now this :class:|QTable| can be used to load a new cosmological
instance identical to the ``Planck18`` cosmology from which it was created.

Expand Down
2 changes: 2 additions & 0 deletions docs/table/construct_table.rst
Expand Up @@ -1184,6 +1184,8 @@ units, see the :ref:`columns_with_units` section.

.. EXAMPLE END
.. _Table-like Objects:

Table-like Objects
==================

Expand Down
27 changes: 24 additions & 3 deletions docs/whatsnew/5.0.rst
Expand Up @@ -16,7 +16,7 @@ Support for reading, writing, and converting ``Cosmology``

Four new methods -- ``read``, ``write``, ``to_format``, ``from_format`` -- have
been added to the ``Cosmology`` class, enabling reading from and writing to
files and converting between different python objects.
files and converting between different Python objects.
The methods use Astropy's Unified I/O registry so custom formats can be
registered. Details are discussed in an addition to the docs.

Expand All @@ -36,14 +36,17 @@ Currently no file formats are registered, but the syntax is as follows:
The transformations between ``Cosmology`` and `dict`/``QTable`` are
pre-registered, e.g. enabling::

>>> from astropy.cosmology import Planck18
>>> from astropy.cosmology import Cosmology, Planck18
>>> cm = Planck18.to_format("mapping")
>>> cm
{'cosmology': <class 'astropy.cosmology.flrw.FlatLambdaCDM'>,
'name': 'Planck18',
'H0': <Quantity 67.66 km / (Mpc s)>,
'Om0': 0.30966,
...

or to a Table with:

>>> ct = Planck18.to_format("astropy.table")
>>> ct
<QTable length=1>
Expand All @@ -53,11 +56,29 @@ pre-registered, e.g. enabling::
-------- ------------ ------- ------- ------- ----------- -------
Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897

>>> from astropy.cosmology import Cosmology
Even more succinctly:

>>> from astropy.table import QTable
>>> QTable(Planck18)
<QTable length=1>
name H0 Om0 Tcmb0 Neff m_nu [3] Ob0
km / (Mpc s) eV
str8 float64 float64 float64 float64 float64 float64
-------- ------------ ------- ------- ------- ----------- -------
Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897

All the format conversions can be reversed:

>>> cosmo = Cosmology.from_format(cm, format="mapping")
>>> cosmo
FlatLambdaCDM(name="Planck18", H0=67.7 km / (Mpc s), Om0=0.31,
Tcmb0=2.725 K, Neff=3.05, m_nu=[0. 0. 0.06] eV, Ob0=0.049)

>>> cosmo = Cosmology.from_format(ct, format="astropy.table")
>>> cosmo == Planck18
True


.. _whatsnew-5.0-cosmology-units:

``Cosmology`` units module
Expand Down

0 comments on commit c1cd0c1

Please sign in to comment.