Coverage for python/astro_metadata_translator/serialize/fits.py: 15%
36 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-06 03:48 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-06 03:48 -0700
1# This file is part of astro_metadata_translator.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the LICENSE file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
12"""Transform ObservationInfo into "standard" FITS headers."""
13from __future__ import annotations
15__all__ = ("info_to_fits", "dates_to_fits", "group_to_fits")
17from typing import TYPE_CHECKING, Any
19if TYPE_CHECKING:
20 import astropy.time
22 from ..observationGroup import ObservationGroup
23 from ..observationInfo import ObservationInfo
26def dates_to_fits(date_begin: astropy.time.Time, date_end: astropy.time.Time) -> dict[str, Any]:
27 """Convert two dates into FITS form.
29 Parameters
30 ----------
31 date_begin : `astropy.time.Time`
32 Date representing the beginning of the observation.
33 date_end : `astropy.time.Time`
34 Date representing the end of the observation.
36 Returns
37 -------
38 cards : `dict` of `str` to `str` or `float`
39 Header card keys and values following the FITS standard.
40 If neither date is defined this may be empty.
41 """
42 cards: dict[str, Any] = {}
43 if date_begin is None and date_end is None:
44 # no date headers can be written
45 return cards
47 cards["TIMESYS"] = "TAI"
49 date_avg = None
50 if date_begin is not None and date_end is not None:
51 date_avg = date_begin + (date_end - date_begin) / 2.0
53 for fragment, date in (("OBS", date_begin), ("BEG", date_begin), ("END", date_end), ("AVG", date_avg)):
54 if date is not None:
55 tai = date.tai
56 cards[f"DATE-{fragment}"] = tai.isot
57 cards[f"MJD-{fragment}"] = tai.mjd
59 return cards
62def info_to_fits(obs_info: ObservationInfo) -> tuple[dict[str, Any], dict[str, str]]:
63 """Convert an `ObservationInfo` to something suitable for writing
64 to a FITS file.
66 Parameters
67 ----------
68 obs_info : `ObservationInfo`
69 Standardized observation information to transform to FITS headers.
71 Returns
72 -------
73 cards : `dict` of `str` to (`int`, `float`, `str`, `bool`)
74 FITS header keys and values in form understood by FITS.
75 comments : `dict` of `str` to `str`
76 Suitable comment string. There will be at most one entry for each key
77 in ``cards``.
78 """
79 cards = {}
80 comments = {}
82 if obs_info.instrument is not None:
83 cards["INSTRUME"] = obs_info.instrument
84 comments["INSTRUME"] = "Name of instrument"
86 cards.update(dates_to_fits(obs_info.datetime_begin, obs_info.datetime_end))
88 return cards, comments
91def group_to_fits(obs_group: ObservationGroup) -> tuple[dict[str, Any], dict[str, str]]:
92 """Convert an `ObservationGroup` to something suitable for writing
93 to a FITS file.
95 Parameters
96 ----------
97 obs_group : `ObservationGroup`
98 Collection of observation information to transform to a single
99 FITS header.
101 Returns
102 -------
103 cards : `dict` of `str` to (`int`, `float`, `str`, `bool`)
104 FITS header keys and values in form understood by FITS.
105 comments : `dict` of `str` to `str`
106 Suitable comment string. There will be at most one entry for each key
107 in ``cards``.
108 """
109 cards = {}
110 comments = {}
112 oldest, newest = obs_group.extremes()
114 instruments = obs_group.property_values("instrument")
115 if len(instruments) == 1:
116 cards["INSTRUME"] = list(instruments)[0]
117 comments["INSTRUME"] = "Name of instrument"
119 cards.update(dates_to_fits(oldest.datetime_begin, newest.datetime_end))
121 return cards, comments