/astropy/cosmology/io/row.py

https://github.com/astrofrog/astropy
Python | 148 lines | 123 code | 7 blank | 18 comment | 2 complexity | 55cfc32342c52369c095a6a5af978be1 MD5 | raw file
  1. # Licensed under a 3-clause BSD style license - see LICENSE.rst
  2. import copy
  3. from collections import defaultdict
  4. from astropy.cosmology.connect import convert_registry
  5. from astropy.cosmology.core import Cosmology
  6. from astropy.table import QTable, Row
  7. from .mapping import from_mapping
  8. def from_row(row, *, move_to_meta=False, cosmology=None):
  9. """Instantiate a `~astropy.cosmology.Cosmology` from a `~astropy.table.Row`.
  10. Parameters
  11. ----------
  12. row : `~astropy.table.Row`
  13. The object containing the Cosmology information.
  14. move_to_meta : bool (optional, keyword-only)
  15. Whether to move keyword arguments that are not in the Cosmology class'
  16. signature to the Cosmology's metadata. This will only be applied if the
  17. Cosmology does NOT have a keyword-only argument (e.g. ``**kwargs``).
  18. Arguments moved to the metadata will be merged with existing metadata,
  19. preferring specified metadata in the case of a merge conflict
  20. (e.g. for ``Cosmology(meta={'key':10}, key=42)``, the ``Cosmology.meta``
  21. will be ``{'key': 10}``).
  22. cosmology : str, `~astropy.cosmology.Cosmology` class, or None (optional, keyword-only)
  23. The cosmology class (or string name thereof) to use when constructing
  24. the cosmology instance. The class also provides default parameter values,
  25. filling in any non-mandatory arguments missing in 'table'.
  26. Returns
  27. -------
  28. `~astropy.cosmology.Cosmology` subclass instance
  29. Examples
  30. --------
  31. To see loading a `~astropy.cosmology.Cosmology` from a Row with
  32. ``from_row``, we will first make a `~astropy.table.Row` using
  33. :func:`~astropy.cosmology.Cosmology.to_format`.
  34. >>> from astropy.cosmology import Cosmology, Planck18
  35. >>> cr = Planck18.to_format("astropy.row")
  36. >>> cr
  37. <Row index=0>
  38. cosmology name H0 Om0 Tcmb0 Neff m_nu Ob0
  39. km / (Mpc s) K eV
  40. str13 str8 float64 float64 float64 float64 float64[3] float64
  41. ------------- -------- ------------ ------- ------- ------- ----------- -------
  42. FlatLambdaCDM Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897
  43. Now this row can be used to load a new cosmological instance identical
  44. to the ``Planck18`` cosmology from which it was generated.
  45. >>> cosmo = Cosmology.from_format(cr, format="astropy.row")
  46. >>> cosmo
  47. FlatLambdaCDM(name="Planck18", H0=67.66 km / (Mpc s), Om0=0.30966,
  48. Tcmb0=2.7255 K, Neff=3.046, m_nu=[0. 0. 0.06] eV, Ob0=0.04897)
  49. """
  50. # special values
  51. name = row['name'] if 'name' in row.columns else None # get name from column
  52. meta = defaultdict(dict, copy.deepcopy(row.meta))
  53. # Now need to add the Columnar metadata. This is only available on the
  54. # parent table. If Row is ever separated from Table, this should be moved
  55. # to ``to_table``.
  56. for col in row._table.itercols():
  57. if col.info.meta: # Only add metadata if not empty
  58. meta[col.name].update(col.info.meta)
  59. # turn row into mapping, filling cosmo if not in a column
  60. mapping = dict(row)
  61. mapping["name"] = name
  62. mapping.setdefault("cosmology", meta.pop("cosmology", None))
  63. mapping["meta"] = dict(meta)
  64. # build cosmology from map
  65. return from_mapping(mapping, move_to_meta=move_to_meta, cosmology=cosmology)
  66. def to_row(cosmology, *args, cosmology_in_meta=False, table_cls=QTable):
  67. """Serialize the cosmology into a `~astropy.table.Row`.
  68. Parameters
  69. ----------
  70. cosmology : `~astropy.cosmology.Cosmology` subclass instance
  71. *args
  72. Not used. Needed for compatibility with
  73. `~astropy.io.registry.UnifiedReadWriteMethod`
  74. table_cls : type (optional, keyword-only)
  75. Astropy :class:`~astropy.table.Table` class or subclass type to use.
  76. Default is :class:`~astropy.table.QTable`.
  77. cosmology_in_meta : bool
  78. Whether to put the cosmology class in the Table metadata (if `True`) or
  79. as the first column (if `False`, default).
  80. Returns
  81. -------
  82. `~astropy.table.Row`
  83. With columns for the cosmology parameters, and metadata in the Table's
  84. ``meta`` attribute. The cosmology class name will either be a column
  85. or in ``meta``, depending on 'cosmology_in_meta'.
  86. Examples
  87. --------
  88. A Cosmology as a `~astropy.table.Row` will have the cosmology's name and
  89. parameters as columns.
  90. >>> from astropy.cosmology import Planck18
  91. >>> cr = Planck18.to_format("astropy.row")
  92. >>> cr
  93. <Row index=0>
  94. cosmology name H0 Om0 Tcmb0 Neff m_nu Ob0
  95. km / (Mpc s) K eV
  96. str13 str8 float64 float64 float64 float64 float64[3] float64
  97. ------------- -------- ------------ ------- ------- ------- ----------- -------
  98. FlatLambdaCDM Planck18 67.66 0.30966 2.7255 3.046 0.0 .. 0.06 0.04897
  99. The cosmological class and other metadata, e.g. a paper reference, are in
  100. the Table's metadata.
  101. """
  102. from .table import to_table
  103. table = to_table(cosmology, cls=table_cls, cosmology_in_meta=cosmology_in_meta)
  104. return table[0] # extract row from table
  105. def row_identify(origin, format, *args, **kwargs):
  106. """Identify if object uses the `~astropy.table.Row` format.
  107. Returns
  108. -------
  109. bool
  110. """
  111. itis = False
  112. if origin == "read":
  113. itis = isinstance(args[1], Row) and (format in (None, "astropy.row"))
  114. return itis
  115. # ===================================================================
  116. # Register
  117. convert_registry.register_reader("astropy.row", Cosmology, from_row)
  118. convert_registry.register_writer("astropy.row", Cosmology, to_row)
  119. convert_registry.register_identifier("astropy.row", Cosmology, row_identify)