Coverage for src/spectroflat/sensor/flat.py: 59%
22 statements
« prev ^ index » next coverage.py v7.3.2, created at 2024-03-28 07:59 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2024-03-28 07:59 +0000
1import numpy as np
3from .smooth_model import SmoothModel
4from ..base.sensor_flat_config import SensorFlatConfig
7class Flat:
8 """
9 The `SensorFlat` class is a pre-flat field that contains most of the hard flat field features.
10 Most prominently the following is corrected:
11 - Sensor features (e.g. dust on the sensor itself)
12 - Slit features (e.g. dust on the slit resulting in line features in the spectral direction)
13 - (Some of) polarimetric fringes.
15 Note 1: The `SensorFlat` is not a full flat and does not correct for gradients nor all fringes.
17 Note 2: This class expects 2D data. It is a good idea to have such a flat per modulation state.
18 """
20 @staticmethod
21 def from_frame(flat_frame: np.array, config: SensorFlatConfig):
22 """
23 Create a `SensorFlat` from an average flat frame.
24 Please note that this method expects a 2d image.
25 """
26 model = SmoothModel(flat_frame, config).create()
27 if config.roi is None:
28 flat = Flat.save_divide(flat_frame, model.img)
29 flat = flat / np.mean(flat)
30 else:
31 temp = Flat.save_divide(flat_frame[config.roi], model.img[config.roi])
32 temp = temp / np.mean(temp)
33 flat = np.ones(flat_frame.shape)
34 flat[config.roi] = temp
35 # import matplotlib.pyplot as plt
36 # fig, ax = plt.subplots(nrows=3)
37 # ax[0].imshow(model.img)
38 # ax[1].imshow(flat_frame)
39 # ax[2].imshow(flat)
40 # plt.show()
41 return Flat(flat)
43 def __init__(self, flat: np.array):
44 self.flat = flat
46 def correct(self, img: np.array):
47 return Flat.save_divide(img, self.flat)
49 @staticmethod
50 def save_divide(a: np.array, b: np.array) -> np.array:
51 return np.true_divide(a.astype('float32'), b.astype('float32'), out=a.astype('float32'),
52 where=b != 0, dtype='float64')