Coverage for src/susi/io/multi_hdu_writer.py: 98%
48 statements
« prev ^ index » next coverage.py v7.5.0, created at 2025-08-11 10:03 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2025-08-11 10:03 +0000
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Module provides `MultiHDUWriter`
6@author: hoelken
7"""
9from astropy.io import fits
10import numpy as np
12from .fits_header import Card
15class MultiHDUWriter:
16 """
17 ## MultiHDUWriter
18 Writes the given datasets / header(s) to individual HDUs in a FITS file
19 """
21 def __init__(self, path):
22 #: path of the fits to read/write
23 self.path = path
24 #: list of the data to set.
25 self.data = []
26 #: List of headers for each hdu, if set self.header and self.global_header are ignored
27 self.headers = None
28 #: A list of header information per dataset (align indices with data)
29 self.header = []
30 #: The header to apply to all datasets
31 self.global_header = []
32 #: Flag to tell if it has been saved
33 self.saved = False
35 def custom_header(self, card: Card, idx: int = None):
36 """
37 Appends the given card to the current header
39 ### Params
40 - card: the card to append
41 - idx:Optional, defines the data-id to add the header to.
42 If not set (default) the card is added to the global header for all HDUs
44 ### Returns
45 `self`
46 """
47 if idx is None:
48 self.global_header.append(card)
49 else:
50 self.header[idx].append(card)
51 self.saved = False
52 return self
54 def append(self, data: np.array, header: list = None):
55 """
56 Append data to the
58 ### Params
59 - data: the data array to append to the HDUList
60 - header: Optional list of custom header `Cards`.
61 """
62 self.data.append(data)
63 self.header.append([] if header is None else header)
64 self.saved = False
66 def write_to_disk(self, overwrite: bool = False, astype: str = 'float32'):
67 """
68 Writes the data to the configured path
70 ### Params
71 - overwrite: bool, optional
72 If `True`, overwrite the output file if it exists. Raises an
73 `OSError` if `False` and the output file exists. (Default=`False`)
74 - astype: string, optional
75 Define the datatype of the HDU data array. Default: float32
77 ### Returns
78 The HDUList written to file
79 """
80 hdul = fits.HDUList(self.__gen_hdu(0, astype))
81 for idx in range(1, len(self.data)):
82 hdul.append(self.__gen_hdu(idx, astype))
83 hdul.writeto(self.path, overwrite=overwrite)
84 self.saved = True
85 return hdul
87 def __gen_hdu(self, idx, astype):
88 hdu = fits.PrimaryHDU(self.data[idx].astype(astype))
89 if self.headers is not None:
90 hdu.header = self.headers[idx]
91 else:
92 for card in self.global_header:
93 hdu.header.append(card.to_card())
94 for card in self.header[idx]:
95 hdu.header.append(card.to_card())
96 return hdu
98 def __repr__(self):
99 txt = '{}: {}\n'.format(self.__class__.__name__, self.path)
100 txt += '{:<21} = {}\n{:<21} = {}\n'.format('Saved', self.saved, 'HDUS', len(self.data))
101 txt += '==== Global Header ====\n'
102 txt += '\n'.join(['{:<21} = {} | {}'.format(c.name, c.value, c.comment) for c in self.global_header])
103 for i in range(len(self.data)):
104 txt += '\n==== HDU [{}] ====\n'.format(i)
105 txt += '{:<21} = {}\n'.format('Data Shape', self.data[i].shape)
106 txt += '\n'.join(['{:<21} = {} | {}'.format(c.name, c.value, c.comment) for c in self.header[i]])
107 return txt