Coverage for src/susi/base/config/base.py: 98%
45 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 to specify base configuration
6@author: hoelken
7"""
8import os
9from dataclasses import dataclass, field
11from ..globals import IOSpeed
12from ..header_keys import *
13from ..exceptions import MissConfigurationException
16@dataclass
17class Base:
18 #: List of Header fields to be copied in any case!
19 #: This is relevant so far only in blocks D and B. TODO: review
20 DEFAULT_HEADER_FIELDS = [
21 PROJECT_NAME,
22 CAMERA_NAME,
23 CAMERA_ID,
24 DATE_OBS,
25 TIMESTAMP_US,
26 TIMESTAMP_MS,
27 INTEGRATION_TIME,
28 F2_MECH,
29 HK_PMU_CUR,
30 HK_PMU_ANG,
31 HK_PMU_ANG_ERR,
32 MOD_STATE,
33 ADC15_CF_TEMP,
34 GMTEMP,
35 TEGMHOUS,
36 TESMMBAS,
37 TEPMUCHA,
38 TEM34BHT,
39 TESWCPHT,
40 TESLTWLL,
41 TEM3,
42 TEM4,
43 TEM5,
44 TEM8,
45 TEM9,
46 TEM7,
47 TEPBSBAS,
48 TEFWBASE,
49 TETOCOHT,
50 TESP12CR,
51 TESJCRAD,
52 TEEBXRAD,
53 TESJCPSP,
54 TESJFCOF,
55 TESJCCOF,
56 TESJFPCB,
57 TES1CPSP,
58 TES1FCOF,
59 TES1CCOF,
60 TES1FPCB,
61 TES2CPSP,
62 TES2FCOF,
63 TES2CCOF,
64 TES2FPCB,
65 SHPX_MODE,
66 HOTPX_MODE,
67 DARK_IMAGE,
68 FLAT_MAP,
69 FLAT_MAP_MOVING,
70 FLAT_MAP_SOFT,
71 DEMOD_MAT,
72 DEMOD_MODE,
73 SHEAR_CORR,
74 ROTATION_ANG,
75 SLIT_FLAT_OFFSET,
76 SLIT_FLAT_SLOPE,
77 SLIT_FLAT_REF_OFFSET,
78 SLIT_FLAT_REF_FILE,
79 SLIT_FLAT_REF_SLOPE,
80 SHIFT_APPLIED,
81 SHIFT_APPLIED_MOVING_FLAT,
82 OFFSET_MAP,
83 WL_CALIBRATED,
84 MIN_WL_NM,
85 MIN_WL_PX,
86 MAX_WL_NM,
87 MAX_WL_PX,
88 DISPERSION,
89 PROCESSOR_NAME,
90 PROCESSOR_VERS,
91 PROCESSING_TIME,
92 PROCESSING_PIPELINE,
93 BLOCKS_APPLIED,
94 IMG_RMS,
95 IMG_MEAN,
96 IMG_CONTRAST,
97 IMG_SNR,
98 SPATIAL_BIN,
99 TEMPORAL_BIN,
100 ROI_X0,
101 ROI_X1,
102 ROI_Y0,
103 ROI_Y1,
104 NAXIS,
105 NAXIS1,
106 NAXIS2,
107 NAXIS3,
108 NAXIS4,
109 XSCALE,
110 XCEN,
111 YCEN,
112 COSTHETA,
113 GPS_TIME,
114 GPS_LON,
115 GPS_LAT,
116 GPS_ALT,
117 ELEV,
118 AZIMUTH,
119 PARANGLE,
120 P_ANGLE,
121 SOLAR_B0,
122 SOLAR_L0,
123 EARTH_D,
124 SOLAR_R0,
125 CW_LOOP,
126 FLAT_MOD,
127 PS_STATE,
128 AP_DOOR,
129 M2_XPOS,
130 M2_YPOS,
131 M2_ZPOS,
132 M3_POS,
133 M4_POS,
134 GMANGU,
135 GMSTATUS,
136 GMSTATEX,
137 SMPOS,
138 SMEXPOS,
139 SMSTATUS,
140 PMUTEMP,
141 PMUROTSP,
142 ]
144 #: The pipeline to use
145 pipeline: str = 'pipeline_dev'
147 #: The URL of the SUSI observation log.
148 obslog_url: str = 'http://10.104.83.191/'
150 #: Flag to indicate if pipeline results should be pushed to the obslog
151 publish_results: bool = True
153 # Obslog id. For internal use
154 obsid: int = None
156 # ====== Header keys ======
157 #: Header field that provides the timestamp information. For SUSI we use the `us` timestamp.
158 timestamp_field: str = TIMESTAMP_US
160 #: The max allowed delta of two consecutively frames in the scale of the timestamp header field.
161 #: The default for SUSI is `21.4ms` in us.
162 time_delta: int = 21400
164 #: The max allowed delta of frames from different cameras in us.
165 #: The default for SUSI is 0.45 * time_delta
166 time_delta_cam_sync: float = 0.45 * time_delta
168 #: Header field that provides the information on the Temperature
169 #: For SUSI this is the coldfinger tempsensor of the cam(s).
170 temp_field: str = ADC15_CF_TEMP
172 #: The max allowed temperature deviation in degree (Default=`0.1`) for all frames
173 temp_threshold: float = 0.1
175 #: Header copy information. These header fields will be copied to the generated fits file.
176 #: fields configured in `equal_header_values` are mandatory here, since this is checked later steps
177 header_copy_fields: list = field(default_factory=lambda: Base.DEFAULT_HEADER_FIELDS)
179 #: ROI keys define the Region of Interest in the data. This is provided by the modulation matrix metadata
180 roi_keys: list = field(default_factory=lambda: [[ROI_X0, ROI_X1], [ROI_Y0, ROI_Y1]])
182 #: Define a list of header fields where all files must have the same value, i.e. `Camera ID`
183 equal_header_values: list = field(default_factory=lambda: [CAMERA_ID, INTEGRATION_TIME])
185 # ====== Multi processing ======
186 #: Number of workers for MP.simultaneous (multiprocessing)
187 #: Default = 10% of available CPUs
188 workers: int = round(os.cpu_count() * 0.2)
190 #: Configure the IO speed of the data connection
191 io_speed: IOSpeed = IOSpeed.MEDIUM
193 #: Default niceness level of the process: +5
194 #: This value will be added to the nice level of the process (range -20 to 20, default 0).
195 niceness: int = 5
197 # ====== Turn Features on and off ======
198 #: Set to True if you really do NOT want to apply a dark file
199 no_dark_correction: bool = False
201 #: Set to true if you want to prevent images to be automatically cropped to the lid area
202 no_auto_cropping: bool = False
204 #: Set to correct for shear distortion (incl.a global rotation)
205 shear_and_rot_correction: bool = True
207 #: Set to perform slit flat correction in block F
208 slit_flat_corr_block_f: bool = False
210 #: Set to perform slit flat correction in block S
211 slit_flat_corr_block_s: bool = True
213 #: Set to perform the slit flat shift analysis
214 slit_flat_shift_analysis: bool = False
216 #: prefilter map correction in block f (using amended soft flat Fits, extension 1)
217 prefilter_correction: bool = True
219 #: soft flat correction in block f. The soft flat may be provided just for prefilter corr
220 soft_flat_correction: bool = False
222 #: Allows to disable sanity header checks
223 check_header: bool = True
225 def __repr__(self) -> str:
226 txt = f'== {self.__class__.__name__} ==\n'
227 txt += '\n'.join(['{:<21} = {}'.format(k, v) for k, v in self.__dict__.items()])
228 return txt
230 def amend_from_dict(self, data: dict):
231 """
232 Overwrites the parameters with the values from the given dictionary.
233 All instance variable names are supported as keywords.
234 All keywords are optional, if the keyword is not present the previous value will be kept.
236 There is a special key that must follow a specific syntax if given
238 - 'roi_keys': The Region Of Interest (ROI) keys must be given as a list of lists with length two (2) in
239 the order of ROI_X, ROI_Y for the 2D image part. (e.g. ROI_X is the ROI in wl direction for SPC cameras)
240 Example `[['ROI_X0', 'ROI_X1'], ['ROI_Y0', 'ROI_Y1']]`
242 ### Params
243 - data: The dictionary to parse.
244 - c_name: The name of the camera to set defaults for.
246 ### Returns
247 the created Config
248 """
249 io_speed = data.pop('io_speed') if 'io_speed' in data else None
250 for k, v in data.items():
251 if not hasattr(self, k):
252 raise MissConfigurationException(f'{self.__class__.__name__} config has no attribute {k}')
253 setattr(self, k, v)
254 if io_speed:
255 self.io_speed = IOSpeed[io_speed]