ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
Fits.py
Go to the documentation of this file.
1 from typing import Union, Optional
2 from io import StringIO
3 
4 from robot.api import logger
5 import numpy as np
6 from astropy.io import fits
7 
8 MaybeHdu = Union[fits.HDUList, str]
9 
10 
11 class Fits:
12  """Robot library providing FITS related keywords"""
13 
14  ROBOT_LIBRARY_SCOPE = "GLOBAL"
15 
16  def _get_hdu(self, arg: MaybeHdu):
17  if isinstance(arg, str):
18  return fits.open(arg)
19  return arg
20 
22  self, path_or_hdu: MaybeHdu, with_checksum: Optional[bool] = None
23  ):
24  """Returns list of keywords from primary HDU as a list of pairs
25  [["KEYWORD": "VALUE"], ...]
26  """
27  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
28  if len(hdul) == 0:
29  raise Exception("FITS file contains no HDUs")
30  if with_checksum:
31  return [list(tup) for tup in hdul[0].header.items()]
32  redact = ["CHECKSUM", "DATASUM", "ARCFILE"]
33  kws = [list(tup) for tup in hdul[0].header.items()]
34  # Redact certain keywords to make testing easier
35  for r in redact:
36  for kw in kws:
37  if r == kw[0]:
38  kw[1] = "XXXX"
39  return kws
40 
41  def fits_get_hdu_ext_names(self, path_or_hdu: MaybeHdu):
42  """Returns list of keywords from primary HDU as a list of pairs"""
43  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
44  if len(hdul) == 0:
45  raise Exception("FITS file contains no HDUs")
46  if len(hdul) > 1:
47  # Note: keywords are tuples with (name, value, comment)
48  return [(hdu.header.get("EXTNAME")) for hdu in hdul[1:]]
49  else:
50  return []
51 
52  def fits_create_empty(self):
53  """"""
54  hdul = fits.HDUList([fits.PrimaryHDU()])
55  return hdul
56 
57  def fits_create_image(self):
58  """"""
59  hdul = fits.HDUList([fits.PrimaryHDU(np.ones((100, 100)))])
60  return hdul
61 
62  def fits_get_info(self, path_or_hdu: MaybeHdu):
63  s = StringIO()
64  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
65  hdul.info(output=s)
66 
67  return s.getvalue()
68 
70  self, path_or_hdu: MaybeHdu, *, name, value, comment="", hdu_num=0
71  ):
72  """"""
73  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
74  logger.info(
75  "Setting keyword in hdu %s: %s=%s (%s)" % (hdu_num, name, value, comment)
76  )
77  hdul[hdu_num].header.set(name, value, comment)
78  return hdul
79 
80  def fits_add_image_ext(self, path_or_hdu: MaybeHdu, *, name):
81  """"""
82  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
83  logger.info("Setting extname %s" % name)
84  hdul.append(fits.ImageHDU(np.ones((100, 100)), name=name))
85  return hdul
86 
87  def fits_add_bintable_ext(self, path_or_hdu: MaybeHdu, *, name):
88  """"""
89  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
90  c1 = fits.Column(name="a", array=np.array([1, 2]), format="K")
91  c2 = fits.Column(name="b", array=np.array([4, 5]), format="K")
92  c3 = fits.Column(name="c", array=np.array([7, 8]), format="K")
93  ext = fits.BinTableHDU.from_columns([c1, c2, c3])
94  logger.info("Setting extname %s" % name)
95  ext.name = name
96  hdul.append(ext)
97  return hdul
98 
99  def fits_close(self, hdul: fits.HDUList):
100  hdul.close()
101 
102  def fits_write_to(self, path_or_hdu: MaybeHdu, path: str):
103  self._get_hdu_get_hdu_get_hdu(path_or_hdu).writeto(path, overwrite=True)
104 
105  def fits_verify(self, path_or_hdu: MaybeHdu):
106  """
107  Executes astropy verify() verify_checksum() and verify_datasum()
108  """
109  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
110  hdul.verify("exception")
111  mapping = {0: "FAILURE", 1: "SUCCESS", 2: "ABSENT"}
112  for hdu in hdul:
113  res = hdu.verify_checksum()
114  if res != 1:
115  raise AssertionError(
116  "FITS checksum verification failed. Expected '%s' but got '%s"
117  % (mapping[res], expected)
118  )
119  res = hdu.verify_datasum()
120  if res != 1:
121  raise AssertionError(
122  "FITS datsum verification failed. Expected '%s' but got '%s"
123  % (mapping[res], expected)
124  )
125 
127  self,
128  path_or_hdu: MaybeHdu,
129  hdu_num: Union[str, int],
130  expected: Optional[str] = None,
131  ):
132  """Verify checksum"""
133  hdu_num = int(hdu_num)
134  mapping = {0: "FAILURE", 1: "SUCCESS", 2: "ABSENT"}
135  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
136  hdu = hdul[hdu_num]
137  res = hdu.verify_checksum()
138  res_str = mapping[res]
139  if expected is not None:
140  raise AssertionError(
141  "FITS checksum verification failed. Expected '%s' but got '%s"
142  % (res_str, expected)
143  )
144  return res_str
145 
147  self,
148  path_or_hdu: MaybeHdu,
149  hdu_num: Union[str, int],
150  expected: Optional[str] = None,
151  ):
152  """Verify datasum"""
153  mapping = {0: "FAILURE", 1: "SUCCESS", 2: "ABSENT"}
154  hdul = self._get_hdu_get_hdu_get_hdu(path_or_hdu)
155  hdu = hdul[hdu_num]
156  res = hdu.verify_datasum()
157  res_str = mapping[res]
158  if expected is not None:
159  raise AssertionError(
160  "FITS datasum verification failed. Expected '%s' but got '%s"
161  % (res_str, expected)
162  )
163  return res_str
Robot library providing FITS related keywords.
Definition: Fits.py:12
def fits_add_image_ext(self, MaybeHdu path_or_hdu, *name)
Definition: Fits.py:80
def fits_verify(self, MaybeHdu path_or_hdu)
Executes astropy verify() verify_checksum() and verify_datasum()
Definition: Fits.py:108
def fits_write_to(self, MaybeHdu path_or_hdu, str path)
Definition: Fits.py:102
def fits_set_keyword(self, MaybeHdu path_or_hdu, *name, value, comment="", hdu_num=0)
Definition: Fits.py:71
def fits_close(self, fits.HDUList hdul)
Definition: Fits.py:99
def fits_get_hdu_ext_names(self, MaybeHdu path_or_hdu)
Returns list of keywords from primary HDU as a list of pairs.
Definition: Fits.py:42
def fits_create_empty(self)
Definition: Fits.py:52
def _get_hdu(self, MaybeHdu arg)
Definition: Fits.py:16
def fits_verify_checksum(self, MaybeHdu path_or_hdu, Union[str, int] hdu_num, Optional[str] expected=None)
Verify checksum.
Definition: Fits.py:132
def fits_add_bintable_ext(self, MaybeHdu path_or_hdu, *name)
Definition: Fits.py:87
def fits_create_image(self)
Definition: Fits.py:57
def fits_get_info(self, MaybeHdu path_or_hdu)
Definition: Fits.py:62
def fits_read_primary_hdu(self, MaybeHdu path_or_hdu, Optional[bool] with_checksum=None)
Returns list of keywords from primary HDU as a list of pairs [["KEYWORD": "VALUE"],...
Definition: Fits.py:26
def fits_verify_datasum(self, MaybeHdu path_or_hdu, Union[str, int] hdu_num, Optional[str] expected=None)
Verify datasum.
Definition: Fits.py:152