legend-daq2lh5 1.5.0__py3-none-any.whl → 1.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,885 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ from typing import Any
5
+
6
+ import lgdo
7
+ import numpy as np
8
+ from fcio import FCIO, Limits
9
+
10
+ from ..data_decoder import DataDecoder
11
+ from .fc_eventheader_decoder import get_key
12
+
13
+ fsp_config_decoded_values = {
14
+ "packet_id": {
15
+ "dtype": "uint32",
16
+ "description": "The index of this decoded packet in the file.",
17
+ },
18
+ "buffer_max_states": {"dtype": "int32", "description": ""},
19
+ "buffer_window_nsec": {"dtype": "int64", "description": ""},
20
+ "trg_hwm_min_multiplicity": {"dtype": "int32", "description": ""},
21
+ "trg_hwm_prescale_ratio": {
22
+ "dtype": "int32",
23
+ "datatype": "array<1>{array<1>{real}}",
24
+ "length_guess": Limits.MaxChannels,
25
+ "description": "",
26
+ },
27
+ "trg_wps_prescale_ratio": {"dtype": "int32", "description": ""},
28
+ "trg_wps_coincident_sum_threshold": {"dtype": "float32", "description": ""},
29
+ "trg_wps_sum_threshold": {"dtype": "float32", "description": ""},
30
+ "trg_wps_prescale_rate": {"dtype": "float32", "description": ""},
31
+ "trg_hwm_prescale_rate": {
32
+ "dtype": "float32",
33
+ "datatype": "array<1>{array<1>{real}}",
34
+ "length_guess": Limits.MaxChannels,
35
+ "description": "",
36
+ },
37
+ "trg_wps_ref_flags_hwm": {"dtype": "int64", "description": ""},
38
+ "trg_wps_ref_flags_ct": {"dtype": "int64", "description": ""},
39
+ "trg_wps_ref_flags_wps": {"dtype": "int64", "description": ""},
40
+ "trg_wps_ref_map_idx": {
41
+ "dtype": "int32",
42
+ "datatype": "array<1>{array<1>{real}}",
43
+ "length_guess": Limits.MaxChannels,
44
+ "description": "",
45
+ },
46
+ "trg_enabled_write_flags_trigger": {"dtype": "int64", "description": ""},
47
+ "trg_enabled_write_flags_event": {"dtype": "int64", "description": ""},
48
+ "trg_pre_trigger_window_nsec": {"dtype": "int64", "description": ""},
49
+ "trg_post_trigger_window_nsec": {"dtype": "int64", "description": ""},
50
+ "dsp_wps_tracemap_format": {"dtype": "int32", "description": ""},
51
+ "dsp_wps_tracemap_indices": {
52
+ "dtype": "int32",
53
+ "datatype": "array<1>{array<1>{real}}",
54
+ "length_guess": Limits.MaxChannels,
55
+ "description": "",
56
+ },
57
+ "dsp_wps_tracemap_enabled": {
58
+ "dtype": "int32",
59
+ "datatype": "array<1>{array<1>{real}}",
60
+ "length_guess": Limits.MaxChannels,
61
+ "description": "",
62
+ },
63
+ "dsp_wps_tracemap_label": {
64
+ "dtype": "|S7",
65
+ "datatype": "array_of_equalsized_arrays<1,1>{string}",
66
+ "length": Limits.MaxChannels,
67
+ "description": "",
68
+ },
69
+ "dsp_wps_gains": {
70
+ "dtype": "float32",
71
+ "datatype": "array<1>{array<1>{real}}",
72
+ "length_guess": Limits.MaxChannels,
73
+ "description": "",
74
+ },
75
+ "dsp_wps_thresholds": {
76
+ "dtype": "float32",
77
+ "datatype": "array<1>{array<1>{real}}",
78
+ "length_guess": Limits.MaxChannels,
79
+ "description": "",
80
+ },
81
+ "dsp_wps_lowpass": {
82
+ "dtype": "float32",
83
+ "datatype": "array<1>{array<1>{real}}",
84
+ "length_guess": Limits.MaxChannels,
85
+ "description": "",
86
+ },
87
+ "dsp_wps_shaping_widths": {
88
+ "dtype": "int32",
89
+ "datatype": "array<1>{array<1>{real}}",
90
+ "length_guess": Limits.MaxChannels,
91
+ "description": "",
92
+ },
93
+ "dsp_wps_margin_front": {
94
+ "dtype": "int32",
95
+ "datatype": "array<1>{array<1>{real}}",
96
+ "length_guess": Limits.MaxChannels,
97
+ "description": "",
98
+ },
99
+ "dsp_wps_margin_back": {
100
+ "dtype": "int32",
101
+ "datatype": "array<1>{array<1>{real}}",
102
+ "length_guess": Limits.MaxChannels,
103
+ "description": "",
104
+ },
105
+ "dsp_wps_start_sample": {
106
+ "dtype": "int32",
107
+ "datatype": "array<1>{array<1>{real}}",
108
+ "length_guess": Limits.MaxChannels,
109
+ "description": "",
110
+ },
111
+ "dsp_wps_stop_sample": {
112
+ "dtype": "int32",
113
+ "datatype": "array<1>{array<1>{real}}",
114
+ "length_guess": Limits.MaxChannels,
115
+ "description": "",
116
+ },
117
+ "dsp_wps_dsp_max_margin_front": {"dtype": "int32", "description": ""},
118
+ "dsp_wps_dsp_max_margin_back": {"dtype": "int32", "description": ""},
119
+ "dsp_wps_apply_gain_scaling": {"dtype": "int32", "description": ""},
120
+ "dsp_wps_sum_window_size": {"dtype": "int32", "description": ""},
121
+ "dsp_wps_sum_window_start_sample": {"dtype": "int32", "description": ""},
122
+ "dsp_wps_sum_window_stop_sample": {"dtype": "int32", "description": ""},
123
+ "dsp_wps_sub_event_sum_threshold": {"dtype": "float32", "description": ""},
124
+ "dsp_hwm_tracemap_format": {"dtype": "int32", "description": ""},
125
+ "dsp_hwm_tracemap_indices": {
126
+ "dtype": "int32",
127
+ "datatype": "array<1>{array<1>{real}}",
128
+ "length_guess": Limits.MaxChannels,
129
+ "description": "",
130
+ },
131
+ "dsp_hwm_tracemap_enabled": {
132
+ "dtype": "int32",
133
+ "datatype": "array<1>{array<1>{real}}",
134
+ "length_guess": Limits.MaxChannels,
135
+ "description": "",
136
+ },
137
+ "dsp_hwm_tracemap_label": {
138
+ "dtype": "|S7",
139
+ "datatype": "array_of_equalsized_arrays<1,1>{string}",
140
+ "length": Limits.MaxChannels,
141
+ "description": "",
142
+ },
143
+ "dsp_hwm_fpga_energy_threshold_adc": {
144
+ "dtype": "uint16",
145
+ "datatype": "array<1>{array<1>{real}}",
146
+ "length_guess": Limits.MaxChannels,
147
+ "description": "",
148
+ },
149
+ "dsp_ct_tracemap_format": {"dtype": "int32", "description": ""},
150
+ "dsp_ct_tracemap_indices": {
151
+ "dtype": "int32",
152
+ "datatype": "array<1>{array<1>{real}}",
153
+ "length_guess": Limits.MaxChannels,
154
+ "description": "",
155
+ },
156
+ "dsp_ct_tracemap_enabled": {
157
+ "dtype": "int32",
158
+ "datatype": "array<1>{array<1>{real}}",
159
+ "length_guess": Limits.MaxChannels,
160
+ "description": "",
161
+ },
162
+ "dsp_ct_tracemap_label": {
163
+ "dtype": "|S7",
164
+ "datatype": "array_of_equalsized_arrays<1,1>{string}",
165
+ "length": Limits.MaxChannels,
166
+ "description": "",
167
+ },
168
+ "dsp_ct_thresholds": {
169
+ "dtype": "uint16",
170
+ "datatype": "array<1>{array<1>{real}}",
171
+ "length_guess": Limits.MaxChannels,
172
+ "description": "",
173
+ },
174
+ }
175
+
176
+
177
+ class FSPConfigDecoder(DataDecoder):
178
+ def __init__(self, *args, **kwargs) -> None:
179
+ super().__init__(*args, **kwargs)
180
+ self.fsp_config = lgdo.Struct()
181
+
182
+ self.decoded_values = copy.deepcopy(fsp_config_decoded_values)
183
+ self.key_list = []
184
+
185
+ def set_fcio_stream(self, fcio_stream: FCIO) -> None:
186
+ self.key_list = [f"fsp_config_{get_key(fcio_stream.config.streamid, 0, 0)}"]
187
+ if fcio_stream.fsp is not None:
188
+ wps_n_traces = fcio_stream.fsp.config.wps["tracemap"]["n_mapped"]
189
+ hwm_n_traces = fcio_stream.fsp.config.hwm["tracemap"]["n_mapped"]
190
+ ct_n_traces = fcio_stream.fsp.config.ct["tracemap"]["n_mapped"]
191
+ self.decoded_values["dsp_wps_tracemap_label"]["length"] = wps_n_traces
192
+ self.decoded_values["dsp_hwm_tracemap_label"]["length"] = hwm_n_traces
193
+ self.decoded_values["dsp_ct_tracemap_label"]["length"] = ct_n_traces
194
+
195
+ self.decoded_values["trg_wps_ref_map_idx"]["length_guess"] = (
196
+ fcio_stream.fsp.config.triggerconfig["n_wps_ref_map_idx"]
197
+ )
198
+ self.decoded_values["trg_hwm_prescale_ratio"]["length"] = hwm_n_traces
199
+ self.decoded_values["trg_hwm_prescale_rate"]["length"] = hwm_n_traces
200
+ self.decoded_values["dsp_wps_tracemap_indices"][
201
+ "length_guess"
202
+ ] = wps_n_traces
203
+ self.decoded_values["dsp_wps_tracemap_enabled"]["length_guess"] = (
204
+ fcio_stream.fsp.config.wps["tracemap"]["n_enabled"]
205
+ )
206
+ self.decoded_values["dsp_wps_gains"]["length_guess"] = wps_n_traces
207
+ self.decoded_values["dsp_wps_thresholds"]["length_guess"] = wps_n_traces
208
+ self.decoded_values["dsp_wps_lowpass"]["length_guess"] = wps_n_traces
209
+ self.decoded_values["dsp_wps_shaping_widths"]["length_guess"] = wps_n_traces
210
+ self.decoded_values["dsp_wps_margin_front"]["length_guess"] = wps_n_traces
211
+ self.decoded_values["dsp_wps_margin_back"]["length_guess"] = wps_n_traces
212
+ self.decoded_values["dsp_wps_start_sample"]["length_guess"] = wps_n_traces
213
+ self.decoded_values["dsp_wps_stop_sample"]["length_guess"] = wps_n_traces
214
+ self.decoded_values["dsp_hwm_tracemap_indices"][
215
+ "length_guess"
216
+ ] = hwm_n_traces
217
+ self.decoded_values["dsp_hwm_tracemap_enabled"]["length_guess"] = (
218
+ fcio_stream.fsp.config.hwm["tracemap"]["n_enabled"]
219
+ )
220
+ self.decoded_values["dsp_hwm_fpga_energy_threshold_adc"][
221
+ "length_guess"
222
+ ] = hwm_n_traces
223
+ self.decoded_values["dsp_ct_tracemap_indices"]["length_guess"] = ct_n_traces
224
+ self.decoded_values["dsp_ct_tracemap_enabled"]["length_guess"] = (
225
+ fcio_stream.fsp.config.ct["tracemap"]["n_enabled"]
226
+ )
227
+ self.decoded_values["dsp_ct_thresholds"]["length_guess"] = ct_n_traces
228
+
229
+ def get_decoded_values(self, key: int = None) -> dict[str, dict[str, Any]]:
230
+ return self.decoded_values
231
+
232
+ def decode_packet(
233
+ self,
234
+ fcio: FCIO,
235
+ fsp_config_rb: lgdo.Table,
236
+ packet_id: int,
237
+ ) -> bool:
238
+
239
+ tbl = fsp_config_rb.lgdo
240
+ loc = fsp_config_rb.loc
241
+
242
+ # FSP: Buffer
243
+ buffer = fcio.fsp.config.buffer
244
+ # TriggerConfig
245
+ triggerconfig = fcio.fsp.config.triggerconfig
246
+ # DSPWindowedPeakSum:
247
+ wps = fcio.fsp.config.wps
248
+ wps_n_traces = wps["tracemap"]["n_mapped"]
249
+ # DSPHardwareMajority:
250
+ hwm = fcio.fsp.config.hwm
251
+ hwm_n_traces = hwm["tracemap"]["n_mapped"]
252
+ # DSPChannelThreshold:
253
+ ct = fcio.fsp.config.ct
254
+ ct_n_traces = ct["tracemap"]["n_mapped"]
255
+
256
+ tbl["packet_id"].nda[loc] = packet_id
257
+
258
+ tbl["buffer_max_states"].nda[loc] = np.int32(buffer["max_states"])
259
+ tbl["buffer_window_nsec"].nda[loc] = np.int64(
260
+ buffer["buffer_window"]["seconds"] * 1e9
261
+ + buffer["buffer_window"]["nanoseconds"]
262
+ )
263
+ tbl["trg_hwm_min_multiplicity"].nda[loc] = np.int32(
264
+ triggerconfig["hwm_min_multiplicity"]
265
+ )
266
+ tbl["trg_hwm_prescale_ratio"]._set_vector_unsafe(
267
+ loc,
268
+ np.array(triggerconfig["hwm_prescale_ratio"], dtype="int32")[:hwm_n_traces],
269
+ )
270
+ tbl["trg_wps_prescale_ratio"].nda[loc] = np.int32(
271
+ triggerconfig["wps_prescale_ratio"]
272
+ )
273
+ tbl["trg_wps_coincident_sum_threshold"].nda[loc] = np.float32(
274
+ triggerconfig["wps_coincident_sum_threshold"]
275
+ )
276
+ tbl["trg_wps_sum_threshold"].nda[loc] = np.float32(
277
+ triggerconfig["wps_sum_threshold"]
278
+ )
279
+ tbl["trg_wps_prescale_rate"].nda[loc] = np.float32(
280
+ triggerconfig["wps_prescale_rate"]
281
+ )
282
+ tbl["trg_hwm_prescale_rate"]._set_vector_unsafe(
283
+ loc,
284
+ np.array(triggerconfig["hwm_prescale_rate"], dtype="float32")[
285
+ :hwm_n_traces
286
+ ],
287
+ )
288
+ tbl["trg_wps_ref_flags_hwm"].nda[loc] = np.int64(
289
+ triggerconfig["wps_ref_flags_hwm"]["is_flagged"]
290
+ )
291
+ tbl["trg_wps_ref_flags_ct"].nda[loc] = np.int64(
292
+ triggerconfig["wps_ref_flags_ct"]["is_flagged"]
293
+ )
294
+ tbl["trg_wps_ref_flags_wps"].nda[loc] = np.int64(
295
+ triggerconfig["wps_ref_flags_wps"]["is_flagged"]
296
+ )
297
+ wps_ref_map_idx = np.array(triggerconfig["wps_ref_map_idx"], dtype="int32")[
298
+ : triggerconfig["n_wps_ref_map_idx"]
299
+ ]
300
+ tbl["trg_wps_ref_map_idx"]._set_vector_unsafe(loc, wps_ref_map_idx)
301
+
302
+ tbl["trg_enabled_write_flags_trigger"].nda[loc] = np.int64(
303
+ triggerconfig["enabled_flags"]["trigger"]["is_flagged"]
304
+ )
305
+ tbl["trg_enabled_write_flags_event"].nda[loc] = np.int64(
306
+ triggerconfig["enabled_flags"]["event"]["is_flagged"]
307
+ )
308
+ tbl["trg_pre_trigger_window_nsec"].nda[loc] = np.int64(
309
+ triggerconfig["pre_trigger_window"]["seconds"] * 1e9
310
+ + triggerconfig["pre_trigger_window"]["nanoseconds"]
311
+ )
312
+ tbl["trg_post_trigger_window_nsec"].nda[loc] = np.int64(
313
+ triggerconfig["post_trigger_window"]["seconds"] * 1e9
314
+ + triggerconfig["post_trigger_window"]["nanoseconds"]
315
+ )
316
+ tbl["dsp_wps_tracemap_format"].nda[loc] = np.int32(wps["tracemap"]["format"])
317
+ tbl["dsp_wps_tracemap_indices"]._set_vector_unsafe(
318
+ loc, np.array(wps["tracemap"]["map"], dtype="int32")[:wps_n_traces]
319
+ )
320
+ tbl["dsp_wps_tracemap_enabled"]._set_vector_unsafe(
321
+ loc,
322
+ np.array(wps["tracemap"]["enabled"], dtype="int32")[
323
+ : wps["tracemap"]["n_enabled"]
324
+ ],
325
+ )
326
+
327
+ tbl["dsp_wps_tracemap_label"].nda[loc][:] = np.array(
328
+ wps["tracemap"]["label"], dtype="|S7"
329
+ )
330
+
331
+ tbl["dsp_wps_gains"]._set_vector_unsafe(
332
+ loc, np.array(wps["gains"], dtype="float32")[:wps_n_traces]
333
+ )
334
+ tbl["dsp_wps_thresholds"]._set_vector_unsafe(
335
+ loc, np.array(wps["thresholds"], dtype="float32")[:wps_n_traces]
336
+ )
337
+ tbl["dsp_wps_lowpass"]._set_vector_unsafe(
338
+ loc, np.array(wps["lowpass"], dtype="float32")[:wps_n_traces]
339
+ )
340
+ tbl["dsp_wps_shaping_widths"]._set_vector_unsafe(
341
+ loc, np.array(wps["shaping_widths"], dtype="int32")[:wps_n_traces]
342
+ )
343
+ tbl["dsp_wps_margin_front"]._set_vector_unsafe(
344
+ loc, np.array(wps["dsp_margin_front"], dtype="int32")[:wps_n_traces]
345
+ )
346
+ tbl["dsp_wps_margin_back"]._set_vector_unsafe(
347
+ loc, np.array(wps["dsp_margin_back"], dtype="int32")[:wps_n_traces]
348
+ )
349
+ tbl["dsp_wps_start_sample"]._set_vector_unsafe(
350
+ loc, np.array(wps["dsp_start_sample"], dtype="int32")[:wps_n_traces]
351
+ )
352
+ tbl["dsp_wps_stop_sample"]._set_vector_unsafe(
353
+ loc, np.array(wps["dsp_stop_sample"], dtype="int32")[:wps_n_traces]
354
+ )
355
+ tbl["dsp_wps_dsp_max_margin_front"].nda[loc] = np.int32(
356
+ wps["dsp_max_margin_front"]
357
+ )
358
+ tbl["dsp_wps_dsp_max_margin_back"].nda[loc] = np.int32(
359
+ wps["dsp_max_margin_back"]
360
+ )
361
+ tbl["dsp_wps_apply_gain_scaling"].nda[loc] = np.int32(wps["apply_gain_scaling"])
362
+ tbl["dsp_wps_sum_window_size"].nda[loc] = np.int32(wps["sum_window_size"])
363
+ tbl["dsp_wps_sum_window_start_sample"].nda[loc] = np.int32(
364
+ wps["sum_window_start_sample"]
365
+ )
366
+ tbl["dsp_wps_sum_window_stop_sample"].nda[loc] = np.int32(
367
+ wps["sum_window_stop_sample"]
368
+ )
369
+ tbl["dsp_wps_sub_event_sum_threshold"].nda[loc] = np.float32(
370
+ wps["sub_event_sum_threshold"]
371
+ )
372
+ tbl["dsp_hwm_tracemap_format"].nda[loc] = np.int32(hwm["tracemap"]["format"])
373
+ tbl["dsp_hwm_tracemap_indices"]._set_vector_unsafe(
374
+ loc, np.array(hwm["tracemap"]["map"], dtype="int32")[:hwm_n_traces]
375
+ )
376
+ tbl["dsp_hwm_tracemap_enabled"]._set_vector_unsafe(
377
+ loc,
378
+ np.array(hwm["tracemap"]["enabled"], dtype="int32")[
379
+ : hwm["tracemap"]["n_enabled"]
380
+ ],
381
+ )
382
+
383
+ tbl["dsp_hwm_tracemap_label"].nda[loc][:] = np.array(
384
+ hwm["tracemap"]["label"], dtype="|S7"
385
+ )
386
+
387
+ tbl["dsp_hwm_fpga_energy_threshold_adc"]._set_vector_unsafe(
388
+ loc,
389
+ np.array(hwm["fpga_energy_threshold_adc"], dtype="uint16")[:hwm_n_traces],
390
+ )
391
+ tbl["dsp_ct_tracemap_format"].nda[loc] = np.int32(ct["tracemap"]["format"])
392
+ tbl["dsp_ct_tracemap_indices"]._set_vector_unsafe(
393
+ loc, np.array(ct["tracemap"]["map"], dtype="int32")[:ct_n_traces]
394
+ )
395
+ tbl["dsp_ct_tracemap_enabled"]._set_vector_unsafe(
396
+ loc,
397
+ np.array(ct["tracemap"]["enabled"], dtype="int32")[
398
+ : ct["tracemap"]["n_enabled"]
399
+ ],
400
+ )
401
+
402
+ tbl["dsp_ct_tracemap_label"].nda[loc][:] = np.array(
403
+ ct["tracemap"]["label"], dtype="|S7"
404
+ )
405
+
406
+ tbl["dsp_ct_thresholds"]._set_vector_unsafe(
407
+ loc, np.array(ct["thresholds"], dtype="uint16")[:ct_n_traces]
408
+ )
409
+
410
+ fsp_config_rb.loc += 1
411
+
412
+ return fsp_config_rb.is_full()
413
+
414
+ def decode_config(self, fcio: FCIO) -> lgdo.Struct:
415
+ # FSP: Buffer
416
+ buffer = fcio.fsp.config.buffer
417
+ self.fsp_config.add_field(
418
+ "buffer_max_states", lgdo.Scalar(np.int32(buffer["max_states"]))
419
+ )
420
+ self.fsp_config.add_field(
421
+ "buffer_window_nsec",
422
+ lgdo.Scalar(
423
+ np.int64(
424
+ buffer["buffer_window"]["seconds"] * 1e9
425
+ + buffer["buffer_window"]["nanoseconds"]
426
+ )
427
+ ),
428
+ )
429
+
430
+ # TriggerConfig
431
+ triggerconfig = fcio.fsp.config.triggerconfig
432
+ hwm = fcio.fsp.config.hwm
433
+ hwm_n_traces = hwm["tracemap"]["n_mapped"]
434
+ self.fsp_config.add_field(
435
+ "trg_hwm_min_multiplicity",
436
+ lgdo.Scalar(np.int32(triggerconfig["hwm_min_multiplicity"])),
437
+ )
438
+ self.fsp_config.add_field(
439
+ "trg_hwm_prescale_ratio",
440
+ lgdo.Array(
441
+ np.array(triggerconfig["hwm_prescale_ratio"], dtype="int32")[
442
+ :hwm_n_traces
443
+ ]
444
+ ),
445
+ )
446
+ self.fsp_config.add_field(
447
+ "trg_wps_prescale_ratio",
448
+ lgdo.Scalar(np.int32(triggerconfig["wps_prescale_ratio"])),
449
+ )
450
+ self.fsp_config.add_field(
451
+ "trg_wps_coincident_sum_threshold",
452
+ lgdo.Scalar(np.float32(triggerconfig["wps_coincident_sum_threshold"])),
453
+ )
454
+ self.fsp_config.add_field(
455
+ "trg_wps_sum_threshold",
456
+ lgdo.Scalar(np.float32(triggerconfig["wps_sum_threshold"])),
457
+ )
458
+ self.fsp_config.add_field(
459
+ "trg_wps_prescale_rate",
460
+ lgdo.Scalar(np.float32(triggerconfig["wps_prescale_rate"])),
461
+ )
462
+ self.fsp_config.add_field(
463
+ "trg_hwm_prescale_rate",
464
+ lgdo.Array(
465
+ np.array(triggerconfig["hwm_prescale_rate"], dtype="float32")[
466
+ :hwm_n_traces
467
+ ]
468
+ ),
469
+ )
470
+
471
+ self.fsp_config.add_field(
472
+ "trg_wps_ref_flags_hwm",
473
+ lgdo.Scalar(np.int64(triggerconfig["wps_ref_flags_hwm"]["is_flagged"])),
474
+ )
475
+ self.fsp_config.add_field(
476
+ "trg_wps_ref_flags_ct",
477
+ lgdo.Scalar(np.int64(triggerconfig["wps_ref_flags_ct"]["is_flagged"])),
478
+ )
479
+ self.fsp_config.add_field(
480
+ "trg_wps_ref_flags_wps",
481
+ lgdo.Scalar(np.int64(triggerconfig["wps_ref_flags_wps"]["is_flagged"])),
482
+ )
483
+
484
+ wps_ref_map_idx = np.array(triggerconfig["wps_ref_map_idx"], dtype="int32")[
485
+ : triggerconfig["n_wps_ref_map_idx"]
486
+ ]
487
+ self.fsp_config.add_field("trg_wps_ref_map_idx", lgdo.Array(wps_ref_map_idx))
488
+ self.fsp_config.add_field(
489
+ "trg_enabled_write_flags_trigger",
490
+ lgdo.Scalar(
491
+ np.int64(triggerconfig["enabled_flags"]["trigger"]["is_flagged"])
492
+ ),
493
+ )
494
+ self.fsp_config.add_field(
495
+ "trg_enabled_write_flags_event",
496
+ lgdo.Scalar(
497
+ np.int64(triggerconfig["enabled_flags"]["event"]["is_flagged"])
498
+ ),
499
+ )
500
+ self.fsp_config.add_field(
501
+ "trg_pre_trigger_window_nsec",
502
+ lgdo.Scalar(
503
+ np.int64(
504
+ triggerconfig["pre_trigger_window"]["seconds"] * 1e9
505
+ + triggerconfig["pre_trigger_window"]["nanoseconds"]
506
+ )
507
+ ),
508
+ )
509
+ self.fsp_config.add_field(
510
+ "trg_post_trigger_window_nsec",
511
+ lgdo.Scalar(
512
+ np.int64(
513
+ triggerconfig["post_trigger_window"]["seconds"] * 1e9
514
+ + triggerconfig["post_trigger_window"]["nanoseconds"]
515
+ )
516
+ ),
517
+ )
518
+
519
+ # DSPWindowedPeakSum:
520
+ wps = fcio.fsp.config.wps
521
+ wps_n_traces = wps["tracemap"]["n_mapped"]
522
+ self.fsp_config.add_field(
523
+ "dsp_wps_tracemap_format", lgdo.Scalar(np.int32(wps["tracemap"]["format"]))
524
+ )
525
+ self.fsp_config.add_field(
526
+ "dsp_wps_tracemap_indices",
527
+ lgdo.Array(np.array(wps["tracemap"]["map"], dtype="int32")[:wps_n_traces]),
528
+ )
529
+ self.fsp_config.add_field(
530
+ "dsp_wps_tracemap_enabled",
531
+ lgdo.Array(
532
+ np.array(wps["tracemap"]["enabled"], dtype="int32")[
533
+ : wps["tracemap"]["n_enabled"]
534
+ ]
535
+ ),
536
+ )
537
+ self.fsp_config.add_field(
538
+ "dsp_wps_tracemap_label",
539
+ lgdo.Array(np.array(wps["tracemap"]["label"], dtype="|S7")[:wps_n_traces]),
540
+ )
541
+
542
+ self.fsp_config.add_field(
543
+ "dsp_wps_gains",
544
+ lgdo.Array(np.array(wps["gains"], dtype="float32")[:wps_n_traces]),
545
+ )
546
+ self.fsp_config.add_field(
547
+ "dsp_wps_thresholds",
548
+ lgdo.Array(np.array(wps["thresholds"], dtype="float32")[:wps_n_traces]),
549
+ )
550
+ self.fsp_config.add_field(
551
+ "dsp_wps_lowpass",
552
+ lgdo.Array(np.array(wps["lowpass"], dtype="float32")[:wps_n_traces]),
553
+ )
554
+ self.fsp_config.add_field(
555
+ "dsp_wps_shaping_widths",
556
+ lgdo.Array(np.array(wps["shaping_widths"], dtype="int32")[:wps_n_traces]),
557
+ )
558
+ self.fsp_config.add_field(
559
+ "dsp_wps_margin_front",
560
+ lgdo.Array(np.array(wps["dsp_margin_front"], dtype="int32")[:wps_n_traces]),
561
+ )
562
+ self.fsp_config.add_field(
563
+ "dsp_wps_margin_back",
564
+ lgdo.Array(np.array(wps["dsp_margin_back"], dtype="int32")[:wps_n_traces]),
565
+ )
566
+ self.fsp_config.add_field(
567
+ "dsp_wps_start_sample",
568
+ lgdo.Array(np.array(wps["dsp_start_sample"], dtype="int32")[:wps_n_traces]),
569
+ )
570
+ self.fsp_config.add_field(
571
+ "dsp_wps_stop_sample",
572
+ lgdo.Array(np.array(wps["dsp_stop_sample"], dtype="int32")[:wps_n_traces]),
573
+ )
574
+
575
+ self.fsp_config.add_field(
576
+ "dsp_wps_dsp_max_margin_front",
577
+ lgdo.Scalar(np.int32(wps["dsp_max_margin_front"])),
578
+ )
579
+ self.fsp_config.add_field(
580
+ "dsp_wps_dsp_max_margin_back",
581
+ lgdo.Scalar(np.int32(wps["dsp_max_margin_back"])),
582
+ )
583
+ self.fsp_config.add_field(
584
+ "dsp_wps_apply_gain_scaling",
585
+ lgdo.Scalar(np.int32(wps["apply_gain_scaling"])),
586
+ )
587
+ self.fsp_config.add_field(
588
+ "dsp_wps_sum_window_size", lgdo.Scalar(np.int32(wps["sum_window_size"]))
589
+ )
590
+ self.fsp_config.add_field(
591
+ "dsp_wps_sum_window_start_sample",
592
+ lgdo.Scalar(np.int32(wps["sum_window_start_sample"])),
593
+ )
594
+ self.fsp_config.add_field(
595
+ "dsp_wps_sum_window_stop_sample",
596
+ lgdo.Scalar(np.int32(wps["sum_window_stop_sample"])),
597
+ )
598
+ self.fsp_config.add_field(
599
+ "dsp_wps_sub_event_sum_threshold",
600
+ lgdo.Scalar(np.float32(wps["sub_event_sum_threshold"])),
601
+ )
602
+
603
+ # DSPHardwareMajority:
604
+ hwm = fcio.fsp.config.hwm
605
+ hwm_n_traces = hwm["tracemap"]["n_mapped"]
606
+ self.fsp_config.add_field(
607
+ "dsp_hwm_tracemap_format", lgdo.Scalar(np.int32(hwm["tracemap"]["format"]))
608
+ )
609
+ self.fsp_config.add_field(
610
+ "dsp_hwm_tracemap_indices",
611
+ lgdo.Array(np.array(hwm["tracemap"]["map"], dtype="int32")[:hwm_n_traces]),
612
+ )
613
+ self.fsp_config.add_field(
614
+ "dsp_hwm_tracemap_enabled",
615
+ lgdo.Array(
616
+ np.array(hwm["tracemap"]["enabled"], dtype="int32")[
617
+ : hwm["tracemap"]["n_enabled"]
618
+ ]
619
+ ),
620
+ )
621
+ self.fsp_config.add_field(
622
+ "dsp_hwm_tracemap_label",
623
+ lgdo.Array(np.array(hwm["tracemap"]["label"], dtype="|S7")[:hwm_n_traces]),
624
+ )
625
+
626
+ self.fsp_config.add_field(
627
+ "dsp_hwm_fpga_energy_threshold_adc",
628
+ lgdo.Array(
629
+ np.array(hwm["fpga_energy_threshold_adc"], dtype="uint16")[
630
+ :hwm_n_traces
631
+ ]
632
+ ),
633
+ )
634
+
635
+ # DSPChannelThreshold:
636
+ ct = fcio.fsp.config.ct
637
+ ct_n_traces = ct["tracemap"]["n_mapped"]
638
+ self.fsp_config.add_field(
639
+ "dsp_ct_tracemap_format", lgdo.Scalar(np.int32(ct["tracemap"]["format"]))
640
+ )
641
+ self.fsp_config.add_field(
642
+ "dsp_ct_tracemap_indices",
643
+ lgdo.Array(np.array(ct["tracemap"]["map"], dtype="int32")[:ct_n_traces]),
644
+ )
645
+ self.fsp_config.add_field(
646
+ "dsp_ct_tracemap_enabled",
647
+ lgdo.Array(
648
+ np.array(ct["tracemap"]["enabled"], dtype="int32")[
649
+ : ct["tracemap"]["n_enabled"]
650
+ ]
651
+ ),
652
+ )
653
+ self.fsp_config.add_field(
654
+ "dsp_ct_tracemap_label",
655
+ lgdo.Array(np.array(ct["tracemap"]["label"], dtype="|S7")[:ct_n_traces]),
656
+ )
657
+
658
+ self.fsp_config.add_field(
659
+ "dsp_ct_thresholds",
660
+ lgdo.Array(np.array(ct["thresholds"], dtype="uint16")[:ct_n_traces]),
661
+ )
662
+ return self.fsp_config
663
+
664
+ def make_lgdo(self, key: int | str = None, size: int = None) -> lgdo.Struct:
665
+ return self.fsp_config
666
+
667
+
668
+ fsp_status_decoded_values = {
669
+ "packet_id": {"dtype": "uint32"},
670
+ "start_time": {"dtype": "float64"},
671
+ "log_time": {"dtype": "float64"},
672
+ "dt_logtime": {"dtype": "float64"},
673
+ "runtime": {"dtype": "float64"},
674
+ "n_read_events": {"dtype": "int32"},
675
+ "n_written_events": {"dtype": "int32"},
676
+ "n_discarded_events": {"dtype": "int32"},
677
+ "dt_n_read_events": {"dtype": "int32"},
678
+ "dt_n_written_events": {"dtype": "int32"},
679
+ "dt_n_discarded_events": {"dtype": "int32"},
680
+ "dt": {"dtype": "float64"},
681
+ "dt_rate_read_events": {"dtype": "float64"},
682
+ "dt_rate_write_events": {"dtype": "float64"},
683
+ "dt_rate_discard_events": {"dtype": "float64"},
684
+ "avg_rate_read_events": {"dtype": "float64"},
685
+ "avg_rate_write_events": {"dtype": "float64"},
686
+ "avg_rate_discard_events": {"dtype": "float64"},
687
+ }
688
+
689
+
690
+ class FSPStatusDecoder(DataDecoder):
691
+ def __init__(self, *args, **kwargs) -> None:
692
+ super().__init__(*args, **kwargs)
693
+ self.decoded_values = copy.deepcopy(fsp_status_decoded_values)
694
+ self.key_list = []
695
+
696
+ def set_fcio_stream(self, fcio_stream: FCIO) -> None:
697
+ self.key_list = [f"fsp_status_{get_key(fcio_stream.config.streamid, 0, 0)}"]
698
+
699
+ def get_key_lists(self) -> list[list[int | str]]:
700
+ return [copy.deepcopy(self.key_list)]
701
+
702
+ def get_decoded_values(self, key: int = None) -> dict[str, dict[str, Any]]:
703
+ return self.decoded_values
704
+
705
+ def decode_packet(
706
+ self,
707
+ fcio: FCIO,
708
+ fsp_status_rbkd: dict[int, lgdo.Table],
709
+ packet_id: int,
710
+ ) -> bool:
711
+
712
+ key = f"fsp_status_{get_key(fcio.config.streamid, 0, 0)}"
713
+ if key not in fsp_status_rbkd:
714
+ return False
715
+ fsp_status_rb = fsp_status_rbkd[key]
716
+
717
+ tbl = fsp_status_rb.lgdo
718
+ loc = fsp_status_rb.loc
719
+
720
+ tbl["packet_id"].nda[loc] = packet_id
721
+ tbl["start_time"].nda[loc] = fcio.fsp.status.start_time
722
+ tbl["log_time"].nda[loc] = fcio.fsp.status.log_time
723
+ tbl["dt_logtime"].nda[loc] = fcio.fsp.status.dt_logtime
724
+ tbl["runtime"].nda[loc] = fcio.fsp.status.runtime
725
+ tbl["n_read_events"].nda[loc] = fcio.fsp.status.n_read_events
726
+ tbl["n_written_events"].nda[loc] = fcio.fsp.status.n_written_events
727
+ tbl["n_discarded_events"].nda[loc] = fcio.fsp.status.n_discarded_events
728
+ tbl["dt_n_read_events"].nda[loc] = fcio.fsp.status.dt_n_read_events
729
+ tbl["dt_n_written_events"].nda[loc] = fcio.fsp.status.dt_n_written_events
730
+ tbl["dt_n_discarded_events"].nda[loc] = fcio.fsp.status.dt_n_discarded_events
731
+ tbl["dt"].nda[loc] = fcio.fsp.status.dt
732
+ tbl["dt_rate_read_events"].nda[loc] = fcio.fsp.status.dt_rate_read_events
733
+ tbl["dt_rate_write_events"].nda[loc] = fcio.fsp.status.dt_rate_write_events
734
+ tbl["dt_rate_discard_events"].nda[loc] = fcio.fsp.status.dt_rate_discard_events
735
+ tbl["avg_rate_read_events"].nda[loc] = fcio.fsp.status.avg_rate_read_events
736
+ tbl["avg_rate_write_events"].nda[loc] = fcio.fsp.status.avg_rate_write_events
737
+ tbl["avg_rate_discard_events"].nda[
738
+ loc
739
+ ] = fcio.fsp.status.avg_rate_discard_events
740
+
741
+ fsp_status_rb.loc += 1
742
+
743
+ return fsp_status_rb.is_full()
744
+
745
+
746
+ fsp_event_decoded_values = {
747
+ "packet_id": {"dtype": "uint32", "description": ""},
748
+ "is_written": {"dtype": "bool", "description": ""},
749
+ "is_extended": {"dtype": "bool", "description": ""},
750
+ "is_consecutive": {"dtype": "bool", "description": ""},
751
+ "is_hwm_prescaled": {"dtype": "bool", "description": ""},
752
+ "is_hwm_multiplicity": {"dtype": "bool", "description": ""},
753
+ "is_wps_sum": {"dtype": "bool", "description": ""},
754
+ "is_wps_coincident_sum": {"dtype": "bool", "description": ""},
755
+ "is_wps_prescaled": {"dtype": "bool", "description": ""},
756
+ "is_ct_multiplicity": {"dtype": "bool", "description": ""},
757
+ "obs_wps_sum_value": {"dtype": "float32", "description": ""},
758
+ "obs_wps_sum_offset": {"dtype": "int32", "description": ""},
759
+ "obs_wps_sum_multiplicity": {"dtype": "int32", "description": ""},
760
+ "obs_wps_max_peak_value": {"dtype": "float32", "description": ""},
761
+ "obs_wps_max_peak_offset": {"dtype": "int32", "description": ""},
762
+ "obs_hwm_hw_multiplicity": {"dtype": "int32", "description": ""},
763
+ "obs_hwm_sw_multiplicity": {"dtype": "int32", "description": ""},
764
+ "obs_hwm_max_value": {"dtype": "uint16", "description": ""},
765
+ "obs_hwm_min_value": {"dtype": "uint16", "description": ""},
766
+ "obs_ct_multiplicity": {"dtype": "int32", "description": ""},
767
+ "obs_ct_trace_idx": {
768
+ "dtype": "int32",
769
+ "datatype": "array<1>{array<1>{real}}",
770
+ "length_guess": Limits.MaxChannels,
771
+ "description": "",
772
+ },
773
+ "obs_ct_max": {
774
+ "dtype": "uint16",
775
+ "datatype": "array<1>{array<1>{real}}",
776
+ "length_guess": Limits.MaxChannels,
777
+ "description": "",
778
+ },
779
+ "obs_ps_hwm_prescaled_trace_idx": {
780
+ "dtype": "uint16",
781
+ "datatype": "array<1>{array<1>{real}}",
782
+ "length_guess": Limits.MaxChannels,
783
+ "description": "",
784
+ },
785
+ "obs_evt_nconsecutive": {"dtype": "int32", "description": ""},
786
+ }
787
+
788
+
789
+ class FSPEventDecoder(DataDecoder):
790
+
791
+ def __init__(self, *args, **kwargs) -> None:
792
+ super().__init__(*args, **kwargs)
793
+ self.decoded_values = copy.deepcopy(fsp_event_decoded_values)
794
+ self.key_list = []
795
+
796
+ def set_fcio_stream(self, fcio_stream: FCIO) -> None:
797
+
798
+ self.key_list = [
799
+ f"fsp_event_{get_key(fcio_stream.config.streamid, 0, 0)}",
800
+ f"fsp_eventheader_{get_key(fcio_stream.config.streamid, 0, 0)}",
801
+ ]
802
+
803
+ def get_decoded_values(self, key: int = None) -> dict[str, dict[str, Any]]:
804
+ return self.decoded_values
805
+
806
+ def get_key_lists(self) -> list[list[int | str]]:
807
+ return [copy.deepcopy(self.key_list)]
808
+
809
+ def decode_packet(
810
+ self,
811
+ fcio: FCIO,
812
+ fsp_evt_rbkd: dict[int, lgdo.Table],
813
+ packet_id: int,
814
+ is_header: bool = False,
815
+ ) -> bool:
816
+
817
+ if is_header:
818
+ key = f"fsp_eventheader_{get_key(fcio.config.streamid, 0, 0)}"
819
+ else:
820
+ key = f"fsp_event_{get_key(fcio.config.streamid, 0, 0)}"
821
+
822
+ if key not in fsp_evt_rbkd:
823
+ return False
824
+ fsp_evt_rb = fsp_evt_rbkd[key]
825
+
826
+ tbl = fsp_evt_rb.lgdo
827
+ loc = fsp_evt_rb.loc
828
+
829
+ tbl["packet_id"].nda[loc] = packet_id
830
+ tbl["is_written"].nda[loc] = fcio.fsp.event.is_written
831
+ tbl["is_extended"].nda[loc] = fcio.fsp.event.is_extended
832
+ tbl["is_consecutive"].nda[loc] = fcio.fsp.event.is_consecutive
833
+ tbl["is_hwm_prescaled"].nda[loc] = fcio.fsp.event.is_hwm_prescaled
834
+ tbl["is_hwm_multiplicity"].nda[loc] = fcio.fsp.event.is_hwm_multiplicity
835
+ tbl["is_wps_sum"].nda[loc] = fcio.fsp.event.is_wps_sum
836
+ tbl["is_wps_coincident_sum"].nda[loc] = fcio.fsp.event.is_wps_coincident_sum
837
+ tbl["is_wps_prescaled"].nda[loc] = fcio.fsp.event.is_wps_prescaled
838
+ tbl["is_ct_multiplicity"].nda[loc] = fcio.fsp.event.is_ct_multiplicity
839
+
840
+ tbl["obs_wps_sum_value"].nda[loc] = fcio.fsp.event.obs_wps_sum_value
841
+ tbl["obs_wps_sum_offset"].nda[loc] = fcio.fsp.event.obs_wps_sum_offset
842
+ tbl["obs_wps_sum_multiplicity"].nda[
843
+ loc
844
+ ] = fcio.fsp.event.obs_wps_sum_multiplicity
845
+ tbl["obs_wps_max_peak_value"].nda[
846
+ loc
847
+ ] = fcio.fsp.event.obs_wps_max_single_peak_value
848
+ tbl["obs_wps_max_peak_offset"].nda[
849
+ loc
850
+ ] = fcio.fsp.event.obs_wps_max_single_peak_offset
851
+ tbl["obs_hwm_hw_multiplicity"].nda[loc] = fcio.fsp.event.obs_hwm_hw_multiplicity
852
+ tbl["obs_hwm_sw_multiplicity"].nda[loc] = fcio.fsp.event.obs_hwm_sw_multiplicity
853
+ tbl["obs_hwm_max_value"].nda[loc] = fcio.fsp.event.obs_hwm_max_value
854
+ tbl["obs_hwm_min_value"].nda[loc] = fcio.fsp.event.obs_hwm_min_value
855
+ tbl["obs_evt_nconsecutive"].nda[loc] = fcio.fsp.event.obs_evt_nconsecutive
856
+ tbl["obs_ct_multiplicity"].nda[loc] = fcio.fsp.event.obs_ct_multiplicity
857
+
858
+ lens = fcio.fsp.event.obs_ct_multiplicity
859
+ start = 0 if loc == 0 else tbl["obs_ct_trace_idx"].cumulative_length[loc - 1]
860
+ end = start + lens
861
+ if lens > 0:
862
+ tbl["obs_ct_trace_idx"].flattened_data.nda[
863
+ start:end
864
+ ] = fcio.fsp.event.obs_ct_trace_idx
865
+ tbl["obs_ct_max"].flattened_data.nda[start:end] = fcio.fsp.event.obs_ct_max
866
+
867
+ tbl["obs_ct_trace_idx"].cumulative_length[loc] = end
868
+ tbl["obs_ct_max"].cumulative_length[loc] = end
869
+
870
+ lens = len(fcio.fsp.event.obs_ps_hwm_prescaled_trace_idx)
871
+ start = (
872
+ 0
873
+ if loc == 0
874
+ else tbl["obs_ps_hwm_prescaled_trace_idx"].cumulative_length[loc - 1]
875
+ )
876
+ end = start + lens
877
+ if lens > 0:
878
+ tbl["obs_ps_hwm_prescaled_trace_idx"].flattened_data.nda[
879
+ start:end
880
+ ] = fcio.fsp.event.obs_ps_hwm_prescaled_trace_ix
881
+ tbl["obs_ps_hwm_prescaled_trace_idx"].cumulative_length[loc] = end
882
+
883
+ fsp_evt_rb.loc += 1
884
+
885
+ return fsp_evt_rb.is_full()