Coverage for src/susi/io/fits_header.py: 69%
48 statements
« prev ^ index » next coverage.py v7.5.0, created at 2025-06-13 14:15 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2025-06-13 14:15 +0000
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4module provides classes to deal with the FITS header
6@author: hoelken
7"""
8import re
9from ..base import Logging
10from ..base.header_keys import *
12logger = Logging.get_logger()
15class Card:
16 """
17 ## Card
18 Class holds FITS header field information (name, value, comment) and provides methods to
19 write them to a FITS file header.
20 """
22 @staticmethod
23 def from_orig(orig, card_name):
24 """
25 Creates a Card instance from an original FITS header.
27 ### Params
28 - orig: [FitsHeader] the original header
29 - card_name: [String] the name of the card to copy from orig
31 ### Returns
32 The created Card instance
33 """
34 return Card(card_name, value=orig[card_name], comment=orig.comments[card_name])
36 @staticmethod
37 def copy_all(orig) -> list:
38 cards = []
39 for key in orig.keys():
40 if key in ['SIMPLE', 'BITPIX', 'NAXIS', 'NAXIS1', 'NAXIS2', 'NAXIS3', 'NAXIS4', 'EXTEND', 'COMMENT']:
41 continue
42 cards.append(Card(key, value=orig[key], comment=re.sub(r'[^\x00-\x7F]+', '?', str(orig.comments[key]))))
43 return cards
45 def __init__(self, name, value=None, comment=None):
46 #: Header Card name
47 self.name = name
48 #: Header Card value
49 self.value = value
50 #: Explanatory comment
51 self.comment = comment
53 def to_card(self):
54 """
55 Converts the content of the card to a tuple suitable for use with `hdu.header.append()`
57 ### Returns
58 A 2 or 3-tuple (depending on if a comment is set)
59 """
60 prefix = ''
61 if len(self.name) > 8 or ' ' in self.name or '_' in self.name:
62 prefix = 'hierarch '
63 if len(str(self.value)) > 75 - len(prefix + self.name):
64 self.value = self.value[0 : 75 - len(prefix + self.name)]
65 logger.warning('Key "%s" too long. Truncated to "%s"', self.name, self.value)
66 if self.comment:
67 return prefix + self.name, self.value, self.comment
68 return prefix + self.name, self.value
71class HeaderCards:
72 """
73 ## HeaderCards
74 Container for a set of FITS header `Card`s.
75 Can be used to generate FITS headers.
76 """
78 def __init__(self):
79 # Generated header cards
80 self.cards = [
81 Card('Project Name', value='Sunrise3'),
82 Card('Camera Name', value='SUSI '),
83 ]
85 def append(self, name: str, value: object, comment: str = None):
86 """
87 Append data to header
88 ### Params
89 - name: The name of the new card
90 - value: the value to set
91 - comment: an optional comment for the card
92 :return: Nothing
93 """
94 self.cards.append(Card(name, value=value, comment=comment))
96 def copy_card(self, orig, card_name):
97 """
98 Appends the value and comment of the original card
99 ### Params
100 - orig: [FitsHeader] the original header
101 - card_name: [String] the name of the card to copy from orig
102 """
103 self.cards.append(Card.from_orig(orig, card_name))
106class SUSIStandardHeader:
107 """
108 creates/updates the final SUSI standard header of a single image file
109 with dimensions [spectral, slit, stokes] for [NAXIS1, NAXIS2, NAXIS3]
111 # Translate header keys to desired standard names and units
112 # Add WCS keywords to the header
113 # Add other HK metadata to the header
115 @author: iglesias, castellanos, sanchez
116 """
117 def __init__(self, header=None):
118 self.header = header
120 def update(self):
121 """
122 Updates the header with the standard header information
123 ### Params
124 - header: [FitsHeader] the header to update
125 """
126 if self.header is None:
127 logger.error('No header to update')
128 return
130 # SLIT dimension
131 # removes XSCALE and adds CDELT2
132 self.header['CDELT2'] = self.header['XSCALE']
133 del self.header['XSCALE']
134 # removes XCEN and adds CRPIX2
135 # TODO must workout rotation to translate XCEN, YCEN to CRPIX2,CRPIX3
136 return