Source code for gdt.core.headers

# CONTAINS TECHNICAL DATA/COMPUTER SOFTWARE DELIVERED TO THE U.S. GOVERNMENT WITH UNLIMITED RIGHTS
#
# Contract No.: CA 80MSFC17M0022
# Contractor Name: Universities Space Research Association
# Contractor Address: 7178 Columbia Gateway Drive, Columbia, MD 21046
#
# Copyright 2017-2022 by Universities Space Research Association (USRA). All rights reserved.
#
# Developed by: William Cleveland and Adam Goldstein
#               Universities Space Research Association
#               Science and Technology Institute
#               https://sti.usra.edu
#
# Developed by: Daniel Kocevski
#               National Aeronautics and Space Administration (NASA)
#               Marshall Space Flight Center
#               Astrophysics Branch (ST-12)
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under the License
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing permissions and limitations under the
# License.
#
import warnings
from typing import Any, List, Tuple

import astropy.io.fits as fits
from astropy.time import Time

from gdt.core import __version__
import copy

__all__ = ['Header', 'FileHeaders']



    

[docs]class FileHeaders: """A collection of FITS headers. This class should be furthered sub-classed with the class variables: * _header_templates - A list of :class:`Header`, where each header is a template of values. Once initialized, each header can be accessed either by the extension name, e.g., 'PRIMARY' or by extension index. """ _header_templates: List[Header] | None def __init__(self): if not hasattr(self, '_header_templates'): raise AttributeError('FileHeaders must have class attribute ' '_header_templates') self._headers = {h.name: h for h in copy.deepcopy(self._header_templates)} self._header_templates = None self.update() @property def num_headers(self): """(int): The number of headers""" return len(self._headers)
[docs] def copy(self): """Return a copy of the FileHeaders. Returns: (:class:`FileHeaders`) """ return type(self).from_headers([self[i] for i in \ range(self.num_headers)])
[docs] def keys(self): """A list of the extension names Returns: (list) """ return list(self._headers.keys())
[docs] def update(self): """Update the 'DATE' keywords to the current time. """ date = Time.now().utc.isot for hdr in self._headers.values(): try: hdr['DATE'] = date except KeyError: pass
[docs] @classmethod def from_headers(cls, headers): """Create a FileHeaders object from a list of Headers. The header types and keyword types must match those in ``_header_templates`` or an exception is raised. Args: headers (list): A list of :class:`Headers` Returns: (:class:`FileHeaders`) """ obj = cls() num_headers = len(headers) if num_headers != len(obj._headers): raise ValueError('Incorrect number of headers for ' \ '{}'.format(cls.__name__)) for i in range(num_headers): cidx = 0 hidx = 0 for key in obj[i].keys(): if key == 'COMMENT': try: obj[i][key][cidx] = headers[i][key][cidx] cidx += 1 except KeyError: warnings.warn(f'{key} not found in header {obj[i].name}', RuntimeWarning, stacklevel=2) elif key == 'HISTORY': try: obj[i][key][hidx] = headers[i][key][hidx] hidx += 1 except KeyError: warnings.warn(f'{key} not found in header {obj[i].name}', RuntimeWarning, stacklevel=2) else: try: obj[i][key] = headers[i][key] except KeyError: warnings.warn(f'{key} not found in header {obj[i].name}', RuntimeWarning, stacklevel=2) return obj
[docs] @staticmethod def creator(): """The Creator card""" return Header.creator()
def __getitem__(self, key): if isinstance(key, int): num_keys = len(self.keys()) if key < 0 or key > num_keys-1: raise IndexError('Out of range for {} headers'.format(num_keys)) return self._headers[self.keys()[key]] else: if key not in list(self._headers.keys()): raise KeyError('{} header does not exist'.format(key)) return self._headers[key] def __repr__(self): s = '<{0}: {1} headers>'.format(self.__class__.__name__, self.num_headers) return s