Coverage for python / lsst / obs / base / formatters / fitsGeneric.py: 0%
33 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 09:02 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-17 09:02 +0000
1# This file is part of obs_base.
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 COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22__all__ = ("FitsGenericFormatter",)
24import importlib.metadata
25from typing import Any
27from packaging import version
29from lsst.daf.butler import DatasetProvenance, FormatterV2
30from lsst.resources import ResourcePath
32from ..utils import add_provenance_to_fits_header
34_astropy_version = version.Version(importlib.metadata.version("astropy"))
35_ALLOW_LONG_FITS_STRINGS = True
36if _astropy_version < version.Version("7.1.0"):
37 # Astropy cannot handle long values for HIERARCH strings.
38 _ALLOW_LONG_FITS_STRINGS = False
41class FitsGenericFormatter(FormatterV2):
42 """Interface for reading and writing objects that support the standard
43 afw I/O readFits/writeFits methods.
44 """
46 supported_extensions = frozenset({".fits", ".fits.gz", ".fits.fz", ".fz", ".fit"})
47 default_extension = ".fits"
48 can_read_from_local_file = True
50 def read_from_local_file(self, path: str, component: str | None = None, expected_size: int = -1) -> Any:
51 pytype = self.file_descriptor.storageClass.pytype
52 if self.file_descriptor.parameters:
53 try:
54 return pytype.readFitsWithOptions( # type: ignore
55 path, options=self.file_descriptor.parameters
56 )
57 except AttributeError:
58 pass
60 return pytype.readFits(path) # type: ignore
62 def write_local_file(self, in_memory_dataset: Any, uri: ResourcePath) -> None:
63 in_memory_dataset.writeFits(uri.ospath)
65 def add_provenance(
66 self, in_memory_dataset: Any, /, *, provenance: DatasetProvenance | None = None
67 ) -> Any:
68 if hasattr(in_memory_dataset, "getMetadata"):
69 metadata = in_memory_dataset.getMetadata()
70 elif hasattr(in_memory_dataset, "metadata"):
71 metadata = in_memory_dataset.metadata
72 else:
73 # Unable to find compliant metadata attribute.
74 return in_memory_dataset
75 # Sometimes astropy is used to write FITS headers and astropy
76 # cannot write long HIERARCH values. Therefore always elide some
77 # of the provenance just in case astropy is used.
78 add_provenance_to_fits_header(
79 metadata, self.dataset_ref, provenance, allow_long_headers=_ALLOW_LONG_FITS_STRINGS
80 )
81 return in_memory_dataset