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