Coverage for src/susi/io/camera_decode_hk.py: 90%
513 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"""
2Decoding of MPS GSENSE camera image data and user HK headers
4Authors: A. Zerr, K. Heerlein, A. Feller, F. Iglesias
5"""
7import sys
8import numpy as np
9import struct
10from enum import Enum
11from dataclasses import dataclass
12from bitstring import BitArray
14from . import camera_definitions as cam_defs
15from . import camera_calibration_constants as calibration_constants
16from . import camera_param_convertion as convert
18from ..base import Logging
20logger = Logging.get_logger()
23s_Project_name = "Project Name"
24s_Camera_Name = "Camera name"
25s_Camera_ID = "Camera ID"
26s_Timestamp_us = "Timestamp us"
27s_Timestamp_ms = "Timestamp ms"
28s_ImageCounter = "Image Counter"
29s_Trigger_counter = "Trigger counter"
30s_Trigger_lost_counter = "Trigger lost counter"
31s_Number_of_frames = "Number of frames"
32s_Integration_time = "Integration time"
33s_FPGA_ID = "FPGA ID"
34s_Trigger_flag = "Trigger flag"
36s_PMU_HK7 = "HK_PMUS_I_-12V"
37s_PMU_HK6 = "HK_PMUS_I_+12V"
38s_PMU_HK5 = "HK_PMUS_I_+5V"
39s_PMU_HK4 = "HK_PMUS_TMP"
40s_PMU_HK3 = "HK_PMU_TMP"
41s_PMU_HK2 = "HK_PMU_ANG_ERR"
42s_PMU_HK1 = "HK_PMU_ANG"
43s_PMU_HK0 = "HK_PMU_CUR"
45s_MeanSignal = 'Mean Signal'
46s_timediffus = "Time Difference us"
48s_Start = 'Start_'
49s_End = 'End_'
51s_ADC_CH15 = "ADC15_" + cam_defs.cst_CF_TEMP
52s_ADC_CH14 = 'ADC14_VTX_H'
53s_ADC_CH13 = 'ADC13_' + cam_defs.cst_VHDR_L_n
54s_ADC_CH12 = 'ADC12_' + cam_defs.cst_VRST_L_n
55s_ADC_CH11 = 'ADC11_VRST_H'
56s_ADC_CH10 = 'ADC10_' + cam_defs.cst_VTX_L_n
57s_ADC_CH09 = 'ADC09_VHDR_H'
58s_ADC_CH08 = 'ADC08_TEST_VREF'
59s_ADC_CH07 = 'ADC07_VREF'
60s_ADC_CH06 = 'ADC06_TEST_VSIG'
61s_ADC_CH05 = 'ADC05_RAMP_VREF'
62s_ADC_CH04 = 'ADC04_RAMP_VSIG'
63s_ADC_CH03 = 'ADC03_VDDPIX'
64s_ADC_CH02 = 'ADC02_' + cam_defs.cst_PCB_TEMP
65s_ADC_CH01 = 'ADC01_' + cam_defs.cst_CF_TEMP2
66s_ADC_CH00 = 'ADC00_Util_3p3V'
68s_DAC_CH15 = cam_defs.kw_DAC15_SPARE
69s_DAC_CH14 = cam_defs.kw_DAC14_SPARE
70s_DAC_CH13 = cam_defs.kw_DAC13_TEST_VREF
71s_DAC_CH12 = cam_defs.kw_DAC12_TEST_VSIG
72s_DAC_CH11 = cam_defs.kw_DAC11_VDDPIX
73s_DAC_CH10 = cam_defs.kw_DAC10_RAMP_VREF
74s_DAC_CH09 = cam_defs.kw_DAC09_VREF
75s_DAC_CH08 = cam_defs.kw_DAC08_RAMP_VSIG
76s_DAC_CH07 = cam_defs.kw_DAC07_SPARE
77s_DAC_CH06 = cam_defs.kw_DAC06_VHDR_H
78s_DAC_CH05 = cam_defs.kw_DAC05_SPARE
79s_DAC_CH04 = cam_defs.kw_DAC04_VRST_H
80s_DAC_CH03 = cam_defs.kw_DAC03_VRST_L
81s_DAC_CH02 = cam_defs.kw_DAC02_VTX_L
82s_DAC_CH01 = cam_defs.kw_DAC01_VHDR_L
83s_DAC_CH00 = cam_defs.kw_DAC00_VTX_H
86class ValueType(enumerate):
87 integer = "Integer"
88 float = "Float"
89 enum = "Enumeration"
90 string = "String"
91 command = "Command"
92 boolean = "Boolean"
93 undef = "undefined"
94 readcur = 'pmHKreadcurr'
95 readang = 'pmHKreadang'
96 readangerr = 'pmHKreadangerr'
97 readtmp = 'pmHKreadtmp'
100class DataType(Enum):
101 integer = "Integer"
102 float = "Float"
103 enum = "Enumeration"
104 string = "String"
105 command = "Command"
106 boolean = "Boolean"
107 undef = "undefined"
110@dataclass
111class ImageHKStructure:
112 name: str = ""
113 word: int = -1
114 msb: int = 0
115 lsb: int = 0
116 type: ValueType = ValueType.undef
117 trnslate: str = ""
118 val = []
119 converted = []
120 formatstr = []
121 unit: str = ""
124@dataclass
125class DataTypeID:
126 field_id = 0x80
127 string = 0x0
128 int32 = 0x1
129 int64 = 0x2
130 float32 = 0x3
131 float64 = 0x4
134def calcExpSTD(numlines, SensorTimingCycle):
135 """calculate the exposure time in seconds, standard mode"""
136 cst_pixelclk = 25E6
137 TLine = SensorTimingCycle * 1 / cst_pixelclk # SensorTimingCylce is normally 513
138 Result = numlines * TLine + 380 * 1 / cst_pixelclk
139 return Result
142def getfactoroffset(Aname, cf):
143 if cam_defs.kw_DAC00_VTX_H in Aname:
144 factor = cf.f_DAC_cst_VTX_H
145 offset = cf.o_DAC_cst_VTX_H
146 elif cam_defs.kw_DAC01_VHDR_L in Aname:
147 factor = cf.f_DAC_cst_VHDR_L
148 offset = cf.o_DAC_cst_VHDR_L
149 elif cam_defs.kw_DAC02_VTX_L in Aname:
150 factor = cf.f_DAC_cst_VTX_L
151 offset = cf.o_DAC_cst_VTX_L
152 elif cam_defs.kw_DAC03_VRST_L in Aname:
153 factor = cf.f_DAC_cst_VRST_L
154 offset = cf.o_DAC_cst_VRST_L
155 elif cam_defs.kw_DAC04_VRST_H in Aname:
156 factor = cf.f_DAC_cst_VRST_H
157 offset = cf.o_DAC_cst_VRST_H
158 elif cam_defs.kw_DAC05_SPARE in Aname:
159 factor = cf.f_DAC_cst_SPARE
160 offset = cf.o_DAC_cst_SPARE
161 elif cam_defs.kw_DAC06_VHDR_H in Aname:
162 factor = cf.f_DAC_cst_VHDR_H
163 offset = cf.o_DAC_cst_VHDR_H
164 elif cam_defs.kw_DAC07_SPARE in Aname:
165 factor = cf.f_DAC_cst_SPARE
166 offset = cf.o_DAC_cst_SPARE
167 elif cam_defs.kw_DAC08_RAMP_VSIG in Aname:
168 factor = cf.f_DAC_cst_RAMP_VSIG
169 offset = cf.o_DAC_cst_RAMP_VSIG
170 elif cam_defs.kw_DAC09_VREF in Aname:
171 factor = cf.f_DAC_cst_VREF
172 offset = cf.o_DAC_cst_VREF
173 elif cam_defs.kw_DAC10_RAMP_VREF in Aname:
174 factor = cf.f_DAC_cst_RAMP_VREF
175 offset = cf.o_DAC_cst_RAMP_VREF
176 elif cam_defs.kw_DAC11_VDDPIX in Aname:
177 factor = cf.f_DAC_cst_VDDPIX
178 offset = cf.o_DAC_cst_VDDPIX
179 elif cam_defs.kw_DAC12_TEST_VSIG in Aname:
180 factor = cf.f_DAC_cst_TEST_VSIG
181 offset = cf.o_DAC_cst_TEST_VSIG
182 elif cam_defs.kw_DAC13_TEST_VREF in Aname:
183 factor = cf.f_DAC_cst_TEST_VREF
184 offset = cf.o_DAC_cst_TEST_VREF
185 elif cam_defs.kw_DAC14_SPARE in Aname:
186 factor = cf.f_DAC_cst_SPARE
187 offset = cf.o_DAC_cst_SPARE
188 elif cam_defs.kw_DAC15_SPARE in Aname:
189 factor = cf.f_DAC_cst_SPARE
190 offset = cf.o_DAC_cst_SPARE
191 return factor, offset
194def convDACtoBiasV(Aname, valueDec, cf):
195 """Pass name and dec value and get converted Bias Voltage"""
196 factor, offsetV = getfactoroffset(Aname, cf)
197 if isinstance(valueDec, list):
198 val = [float(x * factor + offsetV) for x in valueDec]
199 else:
200 val = valueDec * factor + offsetV
201 return val
204def downto_range(bits, i_start, i_end, downto=True):
205 # convert bit(s) position into slice range. Default format is 'VHDL downto'
206 if downto:
207 s_start = -(i_start + 1)
208 if i_end == 0:
209 s_end = None
210 else:
211 s_end = -i_end
212 else:
213 s_start = i_start
214 s_end = i_end + 1
215 # get the field from the bits array
216 field = bits[s_start:s_end]
217 return field
220def getCFfromCameraID(id):
221 if not (id is None):
222 if id == 2: # EM camera
223 data = calibration_constants.HardwarefromId_2
224 elif id == 3:
225 data = calibration_constants.HardwarefromId_4
226 elif id == 4:
227 data = calibration_constants.HardwarefromId_4
228 elif id == 5:
229 data = calibration_constants.HardwarefromId_5
230 elif id == 6:
231 data = calibration_constants.HardwarefromId_6
232 elif id == 7:
233 data = calibration_constants.HardwarefromId_7
234 elif id == 8:
235 data = calibration_constants.HardwarefromId_8
236 else:
237 data = calibration_constants.HardwarefromId_unknown
238 logger.warning("setting calibrations Hardware unknown".format())
239 else:
240 logger.error("Error: setHardwarefromBoardId failed - camera register value CAM_ID was None")
241 return data
244class ImageHousekeeping():
246 def setHKStructure(self):
247 self.hk_structure = [
248 ImageHKStructure(s_Project_name, 0, 63, 0, DataType.string),
249 ImageHKStructure(s_Camera_Name, 1, 47, 16, DataType.string),
250 ImageHKStructure(s_Camera_ID, 1, 4, 0, DataType.integer),
251 ImageHKStructure(s_Timestamp_us, 2, 40, 0, DataType.integer),
252 ImageHKStructure(s_Timestamp_ms, 3, 63, 32, DataType.integer),
253 ImageHKStructure(s_ImageCounter, 3, 31, 0, DataType.integer),
254 ImageHKStructure(s_Trigger_counter, 4, 63, 32, DataType.integer),
255 ImageHKStructure(s_Trigger_lost_counter, 4, 31, 0, DataType.integer),
256 ImageHKStructure(s_Number_of_frames, 5, 59, 48, DataType.integer),
257 ImageHKStructure(s_Integration_time, 5, 47, 24, DataType.integer),
258 ImageHKStructure(s_FPGA_ID, 5, 23, 8, DataType.integer),
259 ImageHKStructure(s_Trigger_flag, 5, 0, 0, DataType.integer),
261 # PMU
262 ImageHKStructure(s_PMU_HK7, 8, 63, 48, DataType.integer),
263 ImageHKStructure(s_PMU_HK6, 8, 47, 32, DataType.integer),
264 ImageHKStructure(s_PMU_HK5, 8, 31, 16, DataType.integer),
265 ImageHKStructure(s_PMU_HK4, 8, 15, 0, DataType.integer),
266 ImageHKStructure(s_PMU_HK3, 9, 63, 48, DataType.integer),
267 ImageHKStructure(s_PMU_HK2, 9, 47, 32, DataType.integer),
268 ImageHKStructure(s_PMU_HK1, 9, 31, 16, DataType.integer),
269 ImageHKStructure(s_PMU_HK0, 9, 15, 0, DataType.integer),
271 # ADC
272 ImageHKStructure(s_ADC_CH15, 10, 63, 48, DataType.integer),
273 ImageHKStructure(s_ADC_CH14, 10, 47, 32, DataType.integer),
274 ImageHKStructure(s_ADC_CH13, 10, 31, 16, DataType.integer),
275 ImageHKStructure(s_ADC_CH12, 10, 15, 0, DataType.integer),
276 ImageHKStructure(s_ADC_CH11, 11, 63, 48, DataType.integer),
277 ImageHKStructure(s_ADC_CH10, 11, 47, 32, DataType.integer),
278 ImageHKStructure(s_ADC_CH09, 11, 31, 16, DataType.integer),
279 ImageHKStructure(s_ADC_CH08, 11, 15, 0, DataType.integer),
280 ImageHKStructure(s_ADC_CH07, 12, 63, 48, DataType.integer),
281 ImageHKStructure(s_ADC_CH06, 12, 47, 32, DataType.integer),
282 ImageHKStructure(s_ADC_CH05, 12, 31, 16, DataType.integer),
283 ImageHKStructure(s_ADC_CH04, 12, 15, 0, DataType.integer),
284 ImageHKStructure(s_ADC_CH03, 13, 63, 48, DataType.integer),
285 ImageHKStructure(s_ADC_CH02, 13, 47, 32, DataType.integer),
286 ImageHKStructure(s_ADC_CH01, 13, 31, 16, DataType.integer),
287 ImageHKStructure(s_ADC_CH00, 13, 15, 0, DataType.integer),
289 # DAC
290 ImageHKStructure(s_DAC_CH15, 14, 63, 48, DataType.integer),
291 ImageHKStructure(s_DAC_CH14, 14, 47, 32, DataType.integer),
292 ImageHKStructure(s_DAC_CH13, 14, 31, 16, DataType.integer),
293 ImageHKStructure(s_DAC_CH12, 14, 15, 0, DataType.integer),
294 ImageHKStructure(s_DAC_CH11, 15, 63, 48, DataType.integer),
295 ImageHKStructure(s_DAC_CH10, 15, 47, 32, DataType.integer),
296 ImageHKStructure(s_DAC_CH09, 15, 31, 16, DataType.integer),
297 ImageHKStructure(s_DAC_CH08, 15, 15, 0, DataType.integer),
298 ImageHKStructure(s_DAC_CH07, 16, 63, 48, DataType.integer),
299 ImageHKStructure(s_DAC_CH06, 16, 47, 32, DataType.integer),
300 ImageHKStructure(s_DAC_CH05, 16, 31, 16, DataType.integer),
301 ImageHKStructure(s_DAC_CH04, 16, 15, 0, DataType.integer),
302 ImageHKStructure(s_DAC_CH03, 17, 63, 48, DataType.integer),
303 ImageHKStructure(s_DAC_CH02, 17, 47, 32, DataType.integer),
304 ImageHKStructure(s_DAC_CH01, 17, 31, 16, DataType.integer),
305 ImageHKStructure(s_DAC_CH00, 17, 15, 0, DataType.integer),
307 # Sensor register DataIn
308 ImageHKStructure("SensorReg_DataIn_7", 18, 63, 32, DataType.integer),
309 ImageHKStructure("SensorReg_DataIn_6", 18, 31, 0, DataType.integer),
310 ImageHKStructure("SensorReg_DataIn_5", 19, 63, 32, DataType.integer),
311 ImageHKStructure("SensorReg_DataIn_4", 19, 31, 0, DataType.integer),
312 ImageHKStructure("SensorReg_DataIn_3", 20, 63, 32, DataType.integer),
313 ImageHKStructure("SensorReg_DataIn_2", 20, 31, 0, DataType.integer),
314 ImageHKStructure("SensorReg_DataIn_1", 21, 63, 32, DataType.integer),
315 ImageHKStructure("SensorReg_DataIn_0", 21, 31, 0, DataType.integer),
317 # Sensor register DataOut
318 ImageHKStructure("SensorReg_DataOut_7", 22, 63, 32, DataType.integer),
319 ImageHKStructure("SensorReg_DataOut_6", 22, 31, 0, DataType.integer),
320 ImageHKStructure("SensorReg_DataOut_5", 23, 63, 32, DataType.integer),
321 ImageHKStructure("SensorReg_DataOut_4", 23, 31, 0, DataType.integer),
322 ImageHKStructure("SensorReg_DataOut_3", 24, 63, 32, DataType.integer),
323 ImageHKStructure("SensorReg_DataOut_2", 24, 31, 0, DataType.integer),
324 ImageHKStructure("SensorReg_DataOut_1", 25, 63, 32, DataType.integer),
325 ImageHKStructure("SensorReg_DataOut_0", 25, 31, 0, DataType.integer),
326 ImageHKStructure("SensorReg_Temperature", 26, 63, 48, DataType.integer),
328 # SysMon
329 ImageHKStructure("SysMon_Status", 27, 61, 60, DataType.integer),
330 ImageHKStructure("SysMon_Temperature", 27, 57, 48, DataType.integer),
331 ImageHKStructure("SysMon_VCCINT", 27, 41, 32, DataType.integer),
332 ImageHKStructure("SysMon_VCCAUX", 27, 25, 16, DataType.integer),
333 ImageHKStructure("SysMon_VCCBRAM", 27, 9, 0, DataType.integer),
335 # PID and status
336 ImageHKStructure("AcquisitionMode", 28, 62, 61, DataType.integer),
337 ImageHKStructure("HK_Status: hk_adc_busy", 28, 60, 60, DataType.integer),
338 ImageHKStructure("Trigger_Select", 28, 59, 59, DataType.integer),
339 ImageHKStructure("HeaterRelays: RLY_HTR_NEG_F", 28, 58, 58, DataType.integer),
340 ImageHKStructure("HeaterRelays: RLY_HTR_POS_F", 28, 57, 57, DataType.integer),
341 ImageHKStructure("Heater_Select", 28, 56, 56, DataType.integer),
342 ImageHKStructure("PID_Status: pid_high_limit_flag", 28, 55, 55, DataType.integer),
343 ImageHKStructure("PID_Status: pid_low_limit_flag", 28, 54, 54, DataType.integer),
344 ImageHKStructure("PID_Status: pid_active", 28, 53, 53, DataType.integer),
345 ImageHKStructure("PID_Config: pid_en", 28, 52, 52, DataType.integer),
346 ImageHKStructure("PID_Config: select_temp_sensor", 28, 51, 48, DataType.integer),
347 ImageHKStructure("PID_SetTemperature", 28, 43, 32, DataType.integer),
348 ImageHKStructure("PID_TemperatureLimit: pid_low_limit", 28, 27, 16, DataType.integer),
349 ImageHKStructure("PID_TemperatureLimit: pid_high_limit", 28, 11, 0, DataType.integer),
351 # Image size
352 ImageHKStructure("Height", 29, 60, 48, DataType.integer),
353 ImageHKStructure("Width", 29, 44, 32, DataType.integer),
354 ImageHKStructure("Sensor_RowStart", 29, 27, 16, DataType.integer),
355 ImageHKStructure("Sensor_RowLength", 29, 11, 0, DataType.integer)
356 ]
358 def __init__(self, raw_file_name=None, image_array=None):
359 self.hk_line = np.zeros(2048 * 2, dtype=">u1")
360 self.hk_resorted = np.zeros(384 * 64 // 8, dtype=">u1")
361 self.hk_array64 = []
362 self.hk_array32 = []
363 self.image_hk = {}
364 self.user_hk = {}
365 self.max_field_name_len = 60
366 self.exit_by_wrong_id = True
367 self.setHKStructure()
369 if raw_file_name is not None:
370 self.file_name = raw_file_name
371 # read data (byte aligned) from image raw file
372 image_array = np.fromfile(raw_file_name, dtype="uint8", count=-1)
373 self.hk_line = self.get_hk_line(image_array)
374 elif image_array is not None:
375 # logger.debug("ImageHousekeeping.__init__() - Getting HK line from Image Array")
376 self.hk_line = self.get_hk_line(image_array)
377 self.resort_hk_line(self.hk_line)
379 def get_hk_line(self, image_array):
380 if image_array.dtype == np.uint16:
381 hkarray = image_array[-1]
382 hk_line = np.frombuffer(hkarray.tobytes(), dtype='uint8')
383 self.hk_line = hk_line
384 else:
385 # re-shape to 2D array
386 image_array = np.reshape(image_array, (2049, 2048 * 2))
387 # keep only the line with HKs
388 self.hk_line = image_array[-1]
389 return self.hk_line
391 def resort_hk_line(self, hk_line=None):
392 # Resort (re-pack) the HK line
393 # Use input parameter or already read hk line
394 if hk_line is None:
395 hk_line = self.hk_line
396 # resort (re-pack) the bytes
397 for index in range(len(self.hk_resorted) // 3):
398 self.hk_resorted[index * 3] = hk_line[index * 4]
399 self.hk_resorted[index * 3 + 1] = hk_line[index * 4 + 2] << 4 | hk_line[index * 4 + 1]
400 self.hk_resorted[index * 3 + 2] = hk_line[index * 4 + 3] << 4 | hk_line[index * 4 + 2] >> 4
401 # Store as array of 4bits words
402 for index in range(len(self.hk_resorted) // 8):
403 self.hk_array64.append(np.frombuffer(self.hk_resorted[index * 8:index * 8 + 8].tobytes(), ">u8")[-1])
404 return self.hk_array64
406 def get_image_hk(self):
407 # Extract single HKs from the HK line
408 # Use input parameter or already read hk line
409 if not self.hk_array64:
410 self.image_hk = {}
411 logger.error("Array hk_array64 is empty! Can't extract image HKs")
412 else:
413 # extract single fields from the HK array
414 for field in self.hk_structure:
415 rawvalue = []
416 value: BitArray
417 word = BitArray("0x{:>016X}".format(self.hk_array64[field.word]))
418 # get field value (field msb downto lsb)
419 value = downto_range(word, field.msb, field.lsb)
420 # check data type: string or unsigned integer
421 if field.name == s_Camera_ID:
422 HWInfofromID = getCFfromCameraID(value.int)
423 cf = HWInfofromID[calibration_constants.s_calibration]
425 rawvalue.append(value.uint)
426 field.formatstr = '{:}'
427 field.converted = []
428 field.converted.append('{:} {:}'.format(HWInfofromID[cam_defs.s_hardwareid], HWInfofromID[
429 cam_defs.s_model]))
430 elif field.type == DataType.string:
431 # convert 64 ASCII value to string (uint -> bytes -> string)
432 str_length = (field.msb - field.lsb + 1) // 8 # calculate the string length
433 rawvalue.append(int(value.int).to_bytes(str_length, "big").decode())
434 field.converted = []
435 field.formatstr = '{:s}'
437 else:
438 # Unsigned integer
439 rawvalue.append(value.uint)
440 converted, formatstr, unitstr = decodeHK(field.name, rawvalue, cf)
442 if isinstance(converted, list):
443 field.converted = converted
444 else:
445 field.converted = []
446 field.converted.append(converted)
447 field.formatstr = formatstr
448 field.unit = unitstr
450 field.val = rawvalue
452 # Store image HKs in dictionary
453 self.image_hk[field.name] = field
454 # Check the header
455 hk_header = self.hk_structure[0].val[0]
456 if hk_header != "Sunrise3":
457 logger.warning("Image HK header is wrong! Expected: Sunrise3, got: {}".format(hk_header))
458 return self.image_hk
460 def get_user_hk(self):
461 # Use input parameter or already read hk line
462 if not self.hk_array64:
463 self.user_hk = {}
464 logger.error("Array hk_array64 is empty! Can't extract user HKs")
465 else:
466 # split the 64bits into 32bits
467 for word64 in self.hk_array64[64:319]:
468 self.hk_array32.append(int(word64) & 0xFFFFFFFF)
469 self.hk_array32.append(int(word64) >> 32)
471 # get user HKs
472 self.user_hk = self.decode_user_hk(self.hk_array32)
473 return self.user_hk
475 def decode_user_hk(self, data_array32: list):
476 user_hk_dict = {}
477 word_i = 0
478 while True:
479 # decode and check header. Only field ID 0x80 is supported now
480 header = data_array32[word_i]
481 word_i += 1
482 # Check the field ID of the header
483 if DataTypeID.field_id != (header >> 24):
484 if not self.exit_by_wrong_id:
485 logger.debug("Wrong field ID! Skip the word.")
486 continue
487 else:
488 logger.debug("Wrong field ID! Finish the parsing.")
489 break
490 # decode name field
491 name_type = (header >> 20) & 0xF
492 name_length = (header >> 16) & 0xF
493 name = data_array32[word_i:word_i + name_length]
494 name = self.decode_field(name_type, name)
495 word_i += name_length
496 # decode data field
497 data_type = (header >> 12) & 0xF
498 data_length = (header >> 0) & 0xFFF
499 if data_length != 0:
500 data = data_array32[word_i:word_i + data_length]
501 data = self.decode_field(data_type, data)
502 else:
503 data = None
504 word_i += data_length
505 # check and add item to the dictionary
506 if name in user_hk_dict:
507 logger.warning("Name '{}' is already defined!".format(name))
508 else:
509 user_hk_dict[name] = data
511 # Exit the loop if all elements are parsed
512 if (word_i + 1) > len(data_array32):
513 break
514 return user_hk_dict
516 def decode_field(self, field_type: DataTypeID, field_data: list):
517 if field_type == DataTypeID.string:
518 ret_data = ""
519 for i in field_data:
520 ret_data = ret_data + i.to_bytes(4, "big").decode()
521 elif field_type == DataTypeID.int32:
522 ret_data = field_data[0]
523 elif field_type == DataTypeID.float32:
524 ret_data = field_data[0].to_bytes(4, "big")
525 ret_data = struct.unpack(">f", ret_data)[0]
526 else:
527 ret_data = None
528 return ret_data
531def decodeHK(itemname, rawdata, cf):
532 try:
533 formatstr = '{:}'
534 converted = []
535 unitstr = ''
536 if s_ADC_CH15.lower() in itemname.lower():
537 converted = [x for x in rawdata]
538 converted, format, unitstr = convert.convertADC15toTemperature(rawdata, cf)
539 formatstr = '{:3.3f}'
540 unitstr = 'degC'
541 elif s_ADC_CH02.lower() in itemname.lower():
542 rawdata = [x for x in rawdata]
543 converted, format, unitstr = convert.convertADC2toTemperature(rawdata, cf)
544 formatstr = '{:3.1f}'
545 unitstr = 'degC'
546 elif s_ADC_CH01.lower() in itemname.lower():
547 rawdata = [x for x in rawdata]
548 converted, format, unitstr = convert.convertADC1toTemperature(rawdata, cf)
549 formatstr = '{:3.1f}'
550 unitstr = 'degC'
551 elif s_ADC_CH13.lower() in itemname.lower():
552 converted = [-(x * cf.cst_ADCconv) + 2 for x in rawdata]
553 formatstr = '{:2.3f}'
554 unitstr = 'V'
555 elif s_ADC_CH10.lower() in itemname.lower():
556 converted = [-(x * cf.cst_ADCconv) + 2 for x in rawdata]
557 formatstr = '{:2.3f}'
558 unitstr = 'V'
559 elif s_ADC_CH11.lower() in itemname.lower():
560 converted = [x * cf.cst_ADCconv for x in rawdata]
561 formatstr = '{:2.3f}'
562 unitstr = 'V'
563 elif s_ADC_CH12.lower() in itemname.lower():
564 converted = [x * cf.cst_ADCconv for x in rawdata]
565 formatstr = '{:2.3f}'
566 unitstr = 'V'
567 elif cam_defs.name_SysMon_Temperature.lower() in itemname.lower():
568 rawdata = [x for x in rawdata]
569 converted = [x * 502.9098 / 1024 - 273.8195 for x in rawdata]
570 formatstr = '{:3.2f}'
571 unitstr = 'degC'
572 elif cam_defs.name_SysMon_VCCINT.lower() in itemname.lower():
573 rawdata = [x for x in rawdata]
574 converted = [x / 1024 * 3 for x in rawdata]
575 formatstr = '{:2.3f}'
576 unitstr = 'V'
577 elif cam_defs.name_SysMon_VCCAUX.lower() in itemname.lower():
578 rawdata = [x for x in rawdata]
579 converted = [x / 1024 * 3 for x in rawdata]
580 formatstr = '{:2.3f}'
581 unitstr = 'V'
582 elif cam_defs.name_SysMon_VCCBRAM.lower() in itemname.lower():
583 rawdata = [x for x in rawdata]
584 converted = [x / 1024 * 3 for x in rawdata]
585 formatstr = '{:2.3f}'
586 unitstr = 'V'
587 elif s_ADC_CH03.lower() in itemname.lower():
588 converted = [x * cf.cst_ADCconv for x in rawdata]
589 formatstr = '{:2.3f}'
590 unitstr = 'V'
591 elif s_ADC_CH00.lower() in itemname.lower():
592 converted = [x * cf.cst_ADCconv for x in rawdata]
593 formatstr = '{:2.3f}'
594 unitstr = 'V'
595 elif s_ADC_CH04.lower() in itemname.lower():
596 converted = [x * cf.cst_ADCconv for x in rawdata]
597 formatstr = '{:2.3f}'
598 unitstr = 'V'
599 elif s_ADC_CH05.lower() in itemname.lower():
600 converted = [x * cf.cst_ADCconv for x in rawdata]
601 formatstr = '{:2.3f}'
602 unitstr = 'V'
603 elif itemname.lower() == s_ADC_CH06.lower():
604 converted = [x * cf.cst_ADCconv for x in rawdata]
605 formatstr = '{:2.3f}'
606 unitstr = 'V'
607 elif itemname.lower() == s_ADC_CH07.lower():
608 converted = [x * cf.cst_ADCconv for x in rawdata]
609 formatstr = '{:2.3f}'
610 unitstr = 'V'
611 elif itemname.lower() == s_ADC_CH08.lower():
612 converted = [x * cf.cst_ADCconv for x in rawdata]
613 formatstr = '{:2.3f}'
614 unitstr = 'V'
615 elif itemname.lower() == s_ADC_CH09.lower():
616 converted = [x * cf.cst_ADCconv for x in rawdata]
617 formatstr = '{:2.3f}'
618 unitstr = 'V'
619 elif itemname.lower() == s_ADC_CH10.lower():
620 converted = [x * cf.cst_ADCconv for x in rawdata]
621 formatstr = '{:2.3f}'
622 unitstr = 'V'
623 elif itemname.lower() == s_ADC_CH14.lower():
624 converted = [x * cf.cst_ADCconv for x in rawdata]
625 formatstr = '{:2.3f}'
626 unitstr = 'V'
627 elif itemname.lower() == 'PSU_E3631A_CH1_Voltage'.lower():
628 converted = [float(x) for x in rawdata]
629 elif itemname.lower() == 'PSU_E3631A_CH1_Current'.lower():
630 converted = [float(x) for x in rawdata]
631 elif itemname.lower() == 'PSU_E3631A_CH2_Voltage'.lower():
632 converted = [float(x) for x in rawdata]
633 elif itemname.lower() == 'PSU_E3631A_CH2_Current'.lower():
634 converted = [float(x) for x in rawdata]
635 elif itemname.lower() == 'PSU_E3631A_CH3_Voltage'.lower():
636 converted = [float(x) for x in rawdata]
637 elif itemname.lower() == 'PSU_E3631A_CH3_Current'.lower():
638 converted = [float(x) for x in rawdata]
639 elif itemname.lower() == 'PSU_HMP4040_CH1_Voltage'.lower():
640 converted = [float(x) for x in rawdata]
641 elif itemname.lower() == 'PSU_HMP4040_CH1_Current'.lower():
642 converted = [float(x) for x in rawdata]
643 elif itemname.lower() == 'PSU_HMP4040_CH2_Voltage'.lower():
644 converted = [float(x) for x in rawdata]
645 elif itemname.lower() == 'PSU_HMP4040_CH2_Current'.lower():
646 converted = [float(x) for x in rawdata]
647 elif itemname.lower() == 'PSU_HMP4040_CH3_Voltage'.lower():
648 converted = [float(x) for x in rawdata]
649 elif itemname.lower() == 'PSU_HMP4040_CH3_Current'.lower():
650 converted = [float(x) for x in rawdata]
651 elif itemname.lower() == 'PSU_HMP4040_CH4_Voltage'.lower():
652 converted = [float(x) for x in rawdata]
653 elif itemname.lower() == 'PSU_HMP4040_CH4_Current'.lower():
654 converted = [float(x) for x in rawdata]
655 elif 'DAC'.lower() in itemname.lower():
656 converted = convDACtoBiasV(itemname, rawdata, cf)
657 formatstr = '{:3.2f}'
658 unitstr = 'V'
659 elif 'PMU'.lower() in itemname.lower():
660 voltagevalue = [x * (5 / 4095) for x in rawdata]
661 if itemname == s_PMU_HK7: # read current -12V
662 # -100mA = 5V
663 converted = [float(-0.02 * x) for x in voltagevalue]
664 formatstr = '{:3.2f}'
665 unitstr = 'A'
666 elif itemname == s_PMU_HK6: # read current +12V
667 # 100mA = 5V
668 converted = [float(0.02 * x) for x in voltagevalue]
669 formatstr = '{:3.2f}'
670 unitstr = 'A'
671 elif itemname == s_PMU_HK5: # read current +5V
672 # 1A = 5V
673 converted = [float(0.2 * x) for x in voltagevalue]
674 formatstr = '{:3.2f}'
675 unitstr = 'A'
676 elif itemname == s_PMU_HK4: # PMUS Temp
677 # 423K / 5V
678 converted = [float((423 / 5 * x) - 273.15) for x in voltagevalue]
679 formatstr = '{:3.2f}'
680 unitstr = 'degC'
681 elif s_PMU_HK3.lower() in itemname.lower(): # PMU Temp
682 converted = [__convert_voltvalue(x) for x in voltagevalue]
683 formatstr = '{:3.2f}'
684 unitstr = 'degC'
685 elif s_PMU_HK2.lower() in itemname.lower(): # PMU ANG Err
686 converted = [float((x - 2.5) / 0.3255) for x in voltagevalue]
687 formatstr = '{:3.2f}'
688 unitstr = 'deg'
689 elif s_PMU_HK1.lower() in itemname.lower(): # PMU ANG
690 converted = [float(x / 0.0138890) for x in voltagevalue]
691 formatstr = '{:3.2f}'
692 unitstr = 'deg'
693 elif s_PMU_HK0.lower() in itemname.lower(): # PMU Current
694 converted = [float(x / 5) for x in voltagevalue]
695 formatstr = '{:3.2f}'
696 unitstr = 'A'
697 else:
698 logger.warning("unrecognised PMU SYNC data") # this should not occur, only in for bug testing.#######
699 elif s_Integration_time.lower() in itemname.lower():
700 converted = []
701 for i in range(len(rawdata)):
702 val = calcExpSTD(int(rawdata[i]), 513)
703 formatstr = '{:3.2e}'
704 unitstr = 's'
705 converted.append(val)
706 elif itemname.lower() == s_Timestamp_us.lower():
707 unitstr = 'us'
708 elif itemname.lower() == s_Timestamp_ms.lower():
709 unitstr = 'ms'
710 except Exception as e:
711 logger.error("{:} - {:}".format(sys._getframe().f_code.co_name, e))
713 return converted, formatstr, unitstr
716def full_hk(file_name):
717 hk = ImageHousekeeping(file_name)
718 image_hk = hk.get_image_hk()
719 user_hk = hk.get_user_hk()
720 image_array = np.fromfile(file_name, dtype="<u2", count=-1)
721 if len(image_array) == 2048:
722 image_array_withhk = None # it was just a HK line of 2048 bytes
723 else:
724 image_array_withhk = np.reshape(image_array, (2049, 2048))
725 return image_hk, user_hk, image_array_withhk
728def camera_hk(image_array):
729 """
730 Returns the image housekeeping information from row 2049 of image_array
731 """
732 hk = ImageHousekeeping(raw_file_name=None, image_array=image_array)
733 image_hk = hk.get_image_hk()
734 return image_hk
737def __convert_voltvalue(val):
738 # changed by Francisco on 20210609 due to a K. Herline recommendation (email)
739 denom = (0.0014708 + 0.00023783 * np.log(-10000 / (-5 + val)) + 1.03 * 10 ** -7 * np.log(-10000 / (-5 + val)) ** 3)
740 return -273.15 + 1 / denom