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.
- daq2lh5/_version.py +2 -2
- daq2lh5/buffer_processor/buffer_processor.py +8 -5
- daq2lh5/buffer_processor/lh5_buffer_processor.py +8 -5
- daq2lh5/build_raw.py +4 -3
- daq2lh5/data_decoder.py +1 -3
- daq2lh5/data_streamer.py +73 -28
- daq2lh5/fc/fc_config_decoder.py +99 -28
- daq2lh5/fc/fc_event_decoder.py +127 -137
- daq2lh5/fc/fc_eventheader_decoder.py +311 -0
- daq2lh5/fc/fc_fsp_decoder.py +885 -0
- daq2lh5/fc/fc_status_decoder.py +231 -63
- daq2lh5/fc/fc_streamer.py +153 -76
- daq2lh5/llama/llama_header_decoder.py +1 -2
- daq2lh5/orca/orca_digitizers.py +1 -1
- daq2lh5/orca/orca_fcio.py +405 -0
- daq2lh5/orca/orca_flashcam.py +7 -4
- daq2lh5/orca/orca_header.py +7 -2
- daq2lh5/orca/orca_packet.py +10 -0
- daq2lh5/orca/orca_run_decoder.py +6 -6
- daq2lh5/orca/orca_streamer.py +28 -10
- daq2lh5/orca/skim_orca_file.py +54 -0
- daq2lh5/raw_buffer.py +15 -2
- {legend_daq2lh5-1.5.0.dist-info → legend_daq2lh5-1.6.1.dist-info}/METADATA +13 -14
- legend_daq2lh5-1.6.1.dist-info/RECORD +46 -0
- {legend_daq2lh5-1.5.0.dist-info → legend_daq2lh5-1.6.1.dist-info}/WHEEL +1 -1
- legend_daq2lh5-1.6.1.dist-info/entry_points.txt +3 -0
- legend_daq2lh5-1.5.0.dist-info/RECORD +0 -42
- legend_daq2lh5-1.5.0.dist-info/entry_points.txt +0 -2
- {legend_daq2lh5-1.5.0.dist-info → legend_daq2lh5-1.6.1.dist-info}/licenses/LICENSE +0 -0
- {legend_daq2lh5-1.5.0.dist-info → legend_daq2lh5-1.6.1.dist-info}/top_level.txt +0 -0
daq2lh5/fc/fc_status_decoder.py
CHANGED
@@ -1,52 +1,145 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import
|
3
|
+
import copy
|
4
|
+
import logging
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
import lgdo
|
8
|
+
from fcio import FCIO
|
4
9
|
|
5
10
|
from ..data_decoder import DataDecoder
|
6
|
-
|
11
|
+
|
12
|
+
log = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
# status.data[i].reqid contains the card type in 0xff00 and the index within
|
15
|
+
# a type group in 0xff
|
16
|
+
# 0 is readout master
|
17
|
+
# if bit 0x1000 is set: trigger card
|
18
|
+
# if bit 0x2000 is set: adc card
|
19
|
+
# if bit 0x4000 is set: submaster card
|
20
|
+
|
21
|
+
fc_status_decoded_values = {
|
22
|
+
"packet_id": {"dtype": "uint32", "description": "Packet index in file."},
|
23
|
+
"status": {
|
24
|
+
"dtype": "bool",
|
25
|
+
"description": "True: Ok, False: Errors occurred, check card-wise status.",
|
26
|
+
},
|
27
|
+
"fpga_time": {
|
28
|
+
"dtype": "float32",
|
29
|
+
"units": "s",
|
30
|
+
"description": "The clock in the fpga of the highest-level card.",
|
31
|
+
},
|
32
|
+
"server_time": {
|
33
|
+
"dtype": "float64",
|
34
|
+
"units": "s",
|
35
|
+
"description": "The server time when the status was checked.",
|
36
|
+
},
|
37
|
+
"fpga_start_time": {
|
38
|
+
"dtype": "float64",
|
39
|
+
"units": "s",
|
40
|
+
"description": "The start time of the run.",
|
41
|
+
},
|
42
|
+
# FC card-wise list DAQ errors during data taking
|
43
|
+
"id": {
|
44
|
+
"dtype": "uint32",
|
45
|
+
"description": "The card id (reqid) when checking the status. Don't confuse with the card address.",
|
46
|
+
},
|
47
|
+
"eventnumber": {
|
48
|
+
"dtype": "uint32",
|
49
|
+
"description": "The eventcounter when the status was requested.",
|
50
|
+
},
|
51
|
+
"fpga_time_nsec": {
|
52
|
+
"dtype": "uint32",
|
53
|
+
"units": "ns",
|
54
|
+
"description": "The clock in the fpga of the highest-level card.",
|
55
|
+
},
|
56
|
+
"n_total_errors": {
|
57
|
+
"dtype": "uint32",
|
58
|
+
"description": "The sum of all error counter of all cards.",
|
59
|
+
},
|
60
|
+
"n_environment_errors": {
|
61
|
+
"dtype": "uint32",
|
62
|
+
"description": "The sum of all environment sensor errors.",
|
63
|
+
},
|
64
|
+
"n_cti_errors": {
|
65
|
+
"dtype": "uint32",
|
66
|
+
"description": "The sum of all CTI connection errors.",
|
67
|
+
},
|
68
|
+
"n_link_errors": {
|
69
|
+
"dtype": "uint32",
|
70
|
+
"description": "The sum of all trigger link errors.",
|
71
|
+
},
|
72
|
+
"n_other_errors": {
|
73
|
+
"dtype": "uint32",
|
74
|
+
"datatype": "array_of_equalsized_arrays<1,1>{real}",
|
75
|
+
"length": 5,
|
76
|
+
"description": "The sum of other errors.",
|
77
|
+
},
|
78
|
+
"mb_temps": {
|
79
|
+
"dtype": "int32",
|
80
|
+
"units": "mC",
|
81
|
+
"datatype": "array_of_equalsized_arrays<1,1>{real}",
|
82
|
+
"length": 5,
|
83
|
+
"description": "The temperatures measured by sensors on the motherboard.",
|
84
|
+
},
|
85
|
+
"mb_voltages": {
|
86
|
+
"dtype": "int32",
|
87
|
+
"units": "mV",
|
88
|
+
"datatype": "array_of_equalsized_arrays<1,1>{real}",
|
89
|
+
"length": 6,
|
90
|
+
"description": "The supply voltages of the motherboard.",
|
91
|
+
},
|
92
|
+
"mb_current": {
|
93
|
+
"dtype": "int32",
|
94
|
+
"units": "mA",
|
95
|
+
"description": "The current draw of the motherboard.",
|
96
|
+
},
|
97
|
+
"mb_humidity": {
|
98
|
+
"dtype": "int32",
|
99
|
+
"units": "o/oo",
|
100
|
+
"description": "The humidity in permille measured on the motherboard.",
|
101
|
+
},
|
102
|
+
"adc_temps": {
|
103
|
+
"dtype": "int32",
|
104
|
+
"units": "mC",
|
105
|
+
"datatype": "array<1>{array<1>{real}}",
|
106
|
+
"length_guess": 2, # max number of daughter cards - only for adc cards
|
107
|
+
"description": "If the card has adc daughter (piggy) boards mounted, each daughter has a temperature sensor.",
|
108
|
+
},
|
109
|
+
"cti_links": {
|
110
|
+
"dtype": "uint32",
|
111
|
+
"datatype": "array<1>{array<1>{real}}", # vector of vectors
|
112
|
+
"length_guess": 4,
|
113
|
+
"description": "CTI debugging values, for experts only.",
|
114
|
+
},
|
115
|
+
"link_states": {
|
116
|
+
"dtype": "uint32",
|
117
|
+
"datatype": "array<1>{array<1>{real}}", # vector of vectors
|
118
|
+
"length_guess": 256, # 256*max number of boards
|
119
|
+
"description": "Trigger link debugging values, for experts only.",
|
120
|
+
},
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
def get_key(streamid, reqid):
|
125
|
+
return (streamid & 0xFFFF) * 1000000 + (reqid & 0xFFFF)
|
126
|
+
|
127
|
+
|
128
|
+
def get_fcid(key: int) -> int:
|
129
|
+
return int(key // 10000000)
|
130
|
+
|
131
|
+
|
132
|
+
def get_reqid(key: int) -> int:
|
133
|
+
return int(key % 1000000)
|
7
134
|
|
8
135
|
|
9
136
|
class FCStatusDecoder(DataDecoder):
|
10
137
|
"""Decode FlashCam digitizer status data."""
|
11
138
|
|
12
139
|
def __init__(self, *args, **kwargs) -> None:
|
13
|
-
self.
|
14
|
-
|
15
|
-
|
16
|
-
# fc250 seconds, microseconds, dummy, startsec startusec
|
17
|
-
"statustime": {"dtype": "float32", "units": "s"},
|
18
|
-
# CPU seconds, microseconds, dummy, startsec startusec
|
19
|
-
"cputime": {"dtype": "float64", "units": "s"},
|
20
|
-
# fc250 seconds, microseconds, dummy, startsec startusec
|
21
|
-
"startoffset": {"dtype": "float32", "units": "s"},
|
22
|
-
# Total number of cards (number of status data to follow)
|
23
|
-
"cards": {"dtype": "int32"},
|
24
|
-
# Size of each status data
|
25
|
-
"size": {"dtype": "int32"},
|
26
|
-
# FC card-wise environment status
|
27
|
-
"environment": {
|
28
|
-
# Array contents:
|
29
|
-
# [0-4] Temps in mDeg
|
30
|
-
# [5-10] Voltages in mV
|
31
|
-
# 11 main current in mA
|
32
|
-
# 12 humidity in o/oo
|
33
|
-
# [13-14] Temps from adc cards in mDeg
|
34
|
-
# FIXME: change to a table?
|
35
|
-
"dtype": "uint32",
|
36
|
-
"datatype": "array_of_equalsized_arrays<1,1>{real}",
|
37
|
-
"length": 16,
|
38
|
-
},
|
39
|
-
# FC card-wise list DAQ errors during data taking
|
40
|
-
"totalerrors": {"dtype": "uint32"},
|
41
|
-
"enverrors": {"dtype": "uint32"},
|
42
|
-
"ctierrors": {"dtype": "uint32"},
|
43
|
-
"linkerrors": {"dtype": "uint32"},
|
44
|
-
"othererrors": {
|
45
|
-
"dtype": "uint32",
|
46
|
-
"datatype": "array_of_equalsized_arrays<1,1>{real}",
|
47
|
-
"length": 5,
|
48
|
-
},
|
49
|
-
}
|
140
|
+
self.key_list = []
|
141
|
+
self.max_rows_in_packet = 0
|
142
|
+
self.decoded_values = copy.deepcopy(fc_status_decoded_values)
|
50
143
|
"""Default FlashCam status decoded values.
|
51
144
|
|
52
145
|
Warning
|
@@ -55,37 +148,112 @@ class FCStatusDecoder(DataDecoder):
|
|
55
148
|
"""
|
56
149
|
super().__init__(*args, **kwargs)
|
57
150
|
|
151
|
+
def set_fcio_stream(self, fcio_stream: FCIO) -> None:
|
152
|
+
"""Access ``FCIOConfig`` members once when each file is opened.
|
153
|
+
|
154
|
+
Parameters
|
155
|
+
----------
|
156
|
+
fcio_stream
|
157
|
+
extracted via :meth:`~.fc_config_decoder.FCConfigDecoder.decode_config`.
|
158
|
+
"""
|
159
|
+
|
160
|
+
n_cards = (
|
161
|
+
fcio_stream.config.mastercards
|
162
|
+
+ fcio_stream.config.triggercards
|
163
|
+
+ fcio_stream.config.adccards
|
164
|
+
)
|
165
|
+
self.max_rows_in_packet = n_cards
|
166
|
+
|
167
|
+
# the number of master cards is the sum of top and sub masters,
|
168
|
+
# if there is more than one, the first is the top master
|
169
|
+
# the rest is a sub master card.
|
170
|
+
for i in range(fcio_stream.config.mastercards):
|
171
|
+
if i == 0:
|
172
|
+
key = get_key(fcio_stream.config.streamid, 0)
|
173
|
+
else:
|
174
|
+
key = get_key(fcio_stream.config.streamid, 0x4000 + i - 1)
|
175
|
+
self.key_list.append(key)
|
176
|
+
|
177
|
+
for i in range(fcio_stream.config.triggercards):
|
178
|
+
key = get_key(fcio_stream.config.streamid, 0x1000 + i)
|
179
|
+
self.key_list.append(key)
|
180
|
+
|
181
|
+
for i in range(fcio_stream.config.adccards):
|
182
|
+
key = get_key(fcio_stream.config.streamid, 0x2000 + i)
|
183
|
+
self.key_list.append(key)
|
184
|
+
|
185
|
+
def get_key_lists(self) -> list[list[int | str]]:
|
186
|
+
return [copy.deepcopy(self.key_list)]
|
187
|
+
|
188
|
+
def get_decoded_values(self, key: int | str = None) -> dict[str, dict[str, Any]]:
|
189
|
+
# FC uses the same values for all channels
|
190
|
+
return self.decoded_values
|
191
|
+
|
192
|
+
def get_max_rows_in_packet(self) -> int:
|
193
|
+
return self.max_rows_in_packet
|
194
|
+
|
58
195
|
def decode_packet(
|
59
|
-
self,
|
196
|
+
self,
|
197
|
+
fcio: FCIO,
|
198
|
+
status_rbkd: lgdo.Table | dict[int, lgdo.Table],
|
199
|
+
packet_id: int,
|
60
200
|
) -> bool:
|
61
|
-
|
62
|
-
tbl = status_rb.lgdo
|
63
|
-
ii = status_rb.loc
|
201
|
+
"""Access ``FCIOStatus`` members for each status packet in the DAQ file.
|
64
202
|
|
65
|
-
|
66
|
-
|
203
|
+
Parameters
|
204
|
+
----------
|
205
|
+
fcio
|
206
|
+
The interface to the ``fcio`` data. Enters this function after a
|
207
|
+
call to ``fcio.get_record()`` so that data for `packet_id` ready to
|
208
|
+
be read out.
|
209
|
+
status_rbkd
|
210
|
+
A single table for reading out all data, or a dictionary of tables
|
211
|
+
keyed by card number.
|
212
|
+
packet_id
|
213
|
+
The index of the packet in the `fcio` stream. Incremented by
|
214
|
+
:class:`~.fc.fc_streamer.FCStreamer`.
|
67
215
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
216
|
+
Returns
|
217
|
+
-------
|
218
|
+
any_full
|
219
|
+
TODO
|
220
|
+
"""
|
221
|
+
any_full = False
|
222
|
+
for card_data in fcio.status.data:
|
223
|
+
key = get_key(fcio.config.streamid, card_data.reqid)
|
224
|
+
if key not in status_rbkd:
|
225
|
+
continue
|
72
226
|
|
73
|
-
|
74
|
-
|
227
|
+
tbl = status_rbkd[key].lgdo
|
228
|
+
loc = status_rbkd[key].loc
|
75
229
|
|
76
|
-
|
77
|
-
|
230
|
+
tbl["packet_id"].nda[loc] = packet_id
|
231
|
+
tbl["status"].nda[loc] = fcio.status.status
|
78
232
|
|
79
|
-
|
80
|
-
|
233
|
+
# times
|
234
|
+
tbl["fpga_time"].nda[loc] = fcio.status.fpga_time_sec
|
235
|
+
tbl["server_time"].nda[loc] = fcio.status.unix_time_utc_sec
|
236
|
+
tbl["fpga_start_time"].nda[loc] = fcio.status.fpga_start_time_sec
|
81
237
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
238
|
+
# per card information
|
239
|
+
tbl["id"].nda[loc] = card_data.reqid
|
240
|
+
tbl["eventnumber"].nda[loc] = card_data.eventno
|
241
|
+
tbl["fpga_time_nsec"].nda[loc] = card_data.fpga_time_nsec
|
242
|
+
tbl["n_total_errors"].nda[loc] = card_data.totalerrors
|
243
|
+
tbl["n_environment_errors"].nda[loc] = card_data.enverrors
|
244
|
+
tbl["n_cti_errors"].nda[loc] = card_data.ctierrors
|
245
|
+
tbl["n_other_errors"].nda[loc][:] = card_data.othererrors
|
246
|
+
tbl["mb_temps"].nda[loc][:] = card_data.mainboard_temperatures_mC
|
247
|
+
tbl["mb_voltages"].nda[loc][:] = card_data.mainboard_voltages_mV
|
248
|
+
tbl["mb_current"].nda[loc] = card_data.mainboard_current_mA
|
249
|
+
tbl["mb_humidity"].nda[loc] = card_data.mainboard_humiditiy_permille
|
250
|
+
tbl["adc_temps"]._set_vector_unsafe(
|
251
|
+
loc, card_data.daughterboard_temperatures_mC
|
252
|
+
)
|
253
|
+
tbl["cti_links"]._set_vector_unsafe(loc, card_data.ctilinks)
|
254
|
+
tbl["link_states"]._set_vector_unsafe(loc, card_data.linkstates)
|
88
255
|
|
89
|
-
|
256
|
+
status_rbkd[key].loc += 1
|
257
|
+
any_full |= status_rbkd[key].is_full()
|
90
258
|
|
91
|
-
return
|
259
|
+
return bool(any_full)
|
daq2lh5/fc/fc_streamer.py
CHANGED
@@ -2,13 +2,16 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import logging
|
4
4
|
|
5
|
-
import
|
5
|
+
import lgdo
|
6
|
+
from fcio import FCIO, Tags
|
6
7
|
|
7
8
|
from ..data_decoder import DataDecoder
|
8
9
|
from ..data_streamer import DataStreamer
|
9
10
|
from ..raw_buffer import RawBuffer, RawBufferLibrary
|
10
11
|
from .fc_config_decoder import FCConfigDecoder
|
11
12
|
from .fc_event_decoder import FCEventDecoder
|
13
|
+
from .fc_eventheader_decoder import FCEventHeaderDecoder
|
14
|
+
from .fc_fsp_decoder import FSPConfigDecoder, FSPEventDecoder, FSPStatusDecoder
|
12
15
|
from .fc_status_decoder import FCStatusDecoder
|
13
16
|
|
14
17
|
log = logging.getLogger(__name__)
|
@@ -16,30 +19,49 @@ log = logging.getLogger(__name__)
|
|
16
19
|
|
17
20
|
class FCStreamer(DataStreamer):
|
18
21
|
"""
|
19
|
-
Decode FlashCam data, using the ``
|
22
|
+
Decode FlashCam data, using the ``fcio`` package to handle file access,
|
20
23
|
and the FlashCam data decoders to save the results and write to output.
|
21
24
|
"""
|
22
25
|
|
23
26
|
def __init__(self) -> None:
|
24
27
|
super().__init__()
|
25
|
-
self.fcio =
|
28
|
+
self.fcio = FCIO()
|
26
29
|
self.config_decoder = FCConfigDecoder()
|
27
30
|
self.status_decoder = FCStatusDecoder()
|
28
31
|
self.event_decoder = FCEventDecoder()
|
29
|
-
self.
|
32
|
+
self.eventheader_decoder = FCEventHeaderDecoder()
|
33
|
+
|
34
|
+
self.fsp_config_decoder = FSPConfigDecoder()
|
35
|
+
self.fsp_event_decoder = FSPEventDecoder()
|
36
|
+
self.fsp_status_decoder = FSPStatusDecoder()
|
37
|
+
|
30
38
|
self.event_rbkd = None
|
31
|
-
self.
|
39
|
+
self.eventheader_rbkd = None
|
40
|
+
self.status_rbkd = None
|
41
|
+
|
42
|
+
self.fsp_config_rbkd = None
|
43
|
+
self.fsp_event_rbkd = None
|
44
|
+
self.fsp_status_rbkd = None
|
45
|
+
|
46
|
+
self.fcio_bytes_read = 0
|
47
|
+
self.fcio_bytes_skipped = 0
|
32
48
|
|
33
49
|
def get_decoder_list(self) -> list[DataDecoder]:
|
34
50
|
dec_list = []
|
35
51
|
dec_list.append(self.config_decoder)
|
36
52
|
dec_list.append(self.status_decoder)
|
37
53
|
dec_list.append(self.event_decoder)
|
54
|
+
dec_list.append(self.eventheader_decoder)
|
55
|
+
|
56
|
+
dec_list.append(self.fsp_config_decoder)
|
57
|
+
dec_list.append(self.fsp_event_decoder)
|
58
|
+
dec_list.append(self.fsp_status_decoder)
|
59
|
+
|
38
60
|
return dec_list
|
39
61
|
|
40
62
|
def open_stream(
|
41
63
|
self,
|
42
|
-
|
64
|
+
fcio_peer: str,
|
43
65
|
rb_lib: RawBufferLibrary = None,
|
44
66
|
buffer_size: int = 8192,
|
45
67
|
chunk_mode: str = "any_full",
|
@@ -54,22 +76,28 @@ class FCStreamer(DataStreamer):
|
|
54
76
|
Returns
|
55
77
|
-------
|
56
78
|
header_data
|
57
|
-
a list of length
|
58
|
-
:class:`~.fc_config_decoder.FCConfig` table
|
79
|
+
a list of length 2 containing the raw buffer holding the
|
80
|
+
:class:`~.fc_config_decoder.FCConfig` table and
|
81
|
+
optionally the :class:`~.fsp_decoder.FSPConfig` table.
|
59
82
|
"""
|
60
|
-
self.fcio
|
61
|
-
self.n_bytes_read =
|
83
|
+
self.fcio.open(fcio_peer) # using defaults
|
84
|
+
self.n_bytes_read = self.fcio.read_bytes() + self.fcio.skipped_bytes()
|
85
|
+
|
86
|
+
# read in file header (config) info, returns an lgdo.Struct
|
87
|
+
fc_config = self.config_decoder.decode_config(self.fcio)
|
88
|
+
config_lgdos = [fc_config]
|
89
|
+
if self.fcio.fsp:
|
90
|
+
config_lgdos.append(self.fsp_config_decoder.decode_config(self.fcio))
|
62
91
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
)
|
67
|
-
self.
|
68
|
-
self.n_bytes_read += 11 * 4 # there are 11 ints in the fcio_config struct
|
92
|
+
self.status_decoder.set_fcio_stream(self.fcio)
|
93
|
+
self.event_decoder.set_fcio_stream(self.fcio)
|
94
|
+
self.eventheader_decoder.set_fcio_stream(self.fcio)
|
95
|
+
self.fsp_event_decoder.set_fcio_stream(self.fcio)
|
96
|
+
self.fsp_status_decoder.set_fcio_stream(self.fcio)
|
69
97
|
|
70
98
|
# initialize the buffers in rb_lib. Store them for fast lookup
|
71
99
|
super().open_stream(
|
72
|
-
|
100
|
+
fcio_peer,
|
73
101
|
rb_lib,
|
74
102
|
buffer_size=buffer_size,
|
75
103
|
chunk_mode=chunk_mode,
|
@@ -78,91 +106,140 @@ class FCStreamer(DataStreamer):
|
|
78
106
|
if rb_lib is None:
|
79
107
|
rb_lib = self.rb_lib
|
80
108
|
|
81
|
-
#
|
82
|
-
|
83
|
-
rb_lib["FCStatusDecoder"]
|
109
|
+
# event and status allow offer key_lists
|
110
|
+
self.status_rbkd = (
|
111
|
+
rb_lib["FCStatusDecoder"].get_keyed_dict()
|
112
|
+
if "FCStatusDecoder" in rb_lib
|
113
|
+
else None
|
84
114
|
)
|
85
|
-
|
86
|
-
if len(status_rb_list) != 1:
|
87
|
-
log.warning(
|
88
|
-
f"status_rb_list had length {len(status_rb_list)}, ignoring all but the first"
|
89
|
-
)
|
90
|
-
if len(status_rb_list) == 0:
|
91
|
-
self.status_rb = None
|
92
|
-
else:
|
93
|
-
self.status_rb = status_rb_list[0]
|
115
|
+
|
94
116
|
self.event_rbkd = (
|
95
117
|
rb_lib["FCEventDecoder"].get_keyed_dict()
|
96
118
|
if "FCEventDecoder" in rb_lib
|
97
119
|
else None
|
98
120
|
)
|
99
121
|
|
122
|
+
self.eventheader_rbkd = (
|
123
|
+
rb_lib["FCEventHeaderDecoder"].get_keyed_dict()
|
124
|
+
if "FCEventHeaderDecoder" in rb_lib
|
125
|
+
else None
|
126
|
+
)
|
127
|
+
|
128
|
+
self.fsp_event_rbkd = (
|
129
|
+
rb_lib["FSPEventDecoder"].get_keyed_dict()
|
130
|
+
if "FSPEventDecoder" in rb_lib
|
131
|
+
else None
|
132
|
+
)
|
133
|
+
|
134
|
+
self.fsp_status_rbkd = (
|
135
|
+
rb_lib["FSPStatusDecoder"].get_keyed_dict()
|
136
|
+
if "FSPStatusDecoder" in rb_lib
|
137
|
+
else None
|
138
|
+
)
|
100
139
|
# set up data loop variables
|
101
140
|
self.packet_id = 0 # for storing packet order in output tables
|
102
141
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
142
|
+
rbs = []
|
143
|
+
for config_decoder, config_lgdo in zip(
|
144
|
+
["FCConfigDecoder", "FSPConfigDecoder"], config_lgdos
|
145
|
+
):
|
146
|
+
if config_decoder in rb_lib:
|
147
|
+
config_rb_list = rb_lib[config_decoder]
|
148
|
+
if len(config_rb_list) != 1:
|
149
|
+
log.warning(
|
150
|
+
f"config_rb_list for {config_decoder} had length {len(config_rb_list)}, "
|
151
|
+
"ignoring all but the first"
|
152
|
+
)
|
153
|
+
rb = config_rb_list[0]
|
154
|
+
else:
|
155
|
+
rb = RawBuffer(lgdo=config_lgdo)
|
156
|
+
|
157
|
+
# TODO: not clear if this workaround is needed, or a bug:
|
158
|
+
# It seems like the `loc` of the RawBuffer is used as `len`
|
159
|
+
# for individual elements in a `lgdo.Struct` while writing.
|
160
|
+
# Search for longest and use as `loc` attr.
|
161
|
+
if isinstance(config_lgdo, lgdo.Struct):
|
162
|
+
max_length = max(
|
163
|
+
[
|
164
|
+
len(entry) if hasattr(entry, "__len__") else 1
|
165
|
+
for entry in config_lgdo.values()
|
166
|
+
]
|
108
167
|
)
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
rb.loc = 1 # we have filled this buffer
|
113
|
-
return [rb]
|
168
|
+
rb.loc = max_length
|
169
|
+
rbs.append(rb)
|
170
|
+
return rbs
|
114
171
|
|
115
172
|
def close_stream(self) -> None:
|
116
|
-
self.fcio
|
173
|
+
self.fcio.close()
|
117
174
|
|
118
175
|
def read_packet(self) -> bool:
|
119
|
-
rc = self.fcio.get_record()
|
120
|
-
if rc == 0:
|
121
|
-
return False # no more data
|
122
|
-
|
123
|
-
self.packet_id += 1
|
124
176
|
|
125
|
-
if
|
126
|
-
|
127
|
-
f"got a header after start of run? n_bytes_read = {self.n_bytes_read}"
|
128
|
-
)
|
129
|
-
self.n_bytes_read += 11 * 4 # there are 11 ints in the fcio_config struct
|
130
|
-
return True
|
177
|
+
if not self.fcio.get_record():
|
178
|
+
return False # no more data
|
131
179
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
180
|
+
# The fcio stream processor (FSP) prepends records to the corresponding
|
181
|
+
# FCIO records. The fcio library parses these separate records,
|
182
|
+
# which requires an additional call to get_record().
|
183
|
+
# Both records are treated as one packet, so their packet_id is shared.
|
184
|
+
if self.fcio.tag in [Tags.FSPConfig, Tags.FSPEvent, Tags.FSPStatus]:
|
185
|
+
if not self.fcio.get_record():
|
186
|
+
self.n_bytes_read = self.fcio.read_bytes() + self.fcio.skipped_bytes()
|
187
|
+
log.error(
|
188
|
+
f"FCIO stream ended early with a {Tags.str(self.fcio.tag)} and n_bytes_read = {self.n_bytes_read}"
|
189
|
+
)
|
190
|
+
return False
|
137
191
|
|
138
|
-
|
139
|
-
#
|
140
|
-
|
192
|
+
self.packet_id += 1
|
193
|
+
# records or fields in records unknown to fcio are read but not parsed,
|
194
|
+
# and tracked in skipped_bytes
|
195
|
+
self.n_bytes_read = self.fcio.read_bytes() + self.fcio.skipped_bytes()
|
196
|
+
|
197
|
+
# FCIOConfigs contains header data (lengths) required to access
|
198
|
+
# (Sparse)Event(Header) records.
|
199
|
+
# The protocol allows updates of these settings within a datastream.
|
200
|
+
# Concatenating of FCIO streams is supported here only if the FCIOConfig
|
201
|
+
# is the same.
|
202
|
+
if self.fcio.tag == Tags.Config or self.fcio.tag == Tags.FSPConfig:
|
141
203
|
log.warning(
|
142
|
-
f"got
|
204
|
+
f"got an {Tags.str(self.fcio.tag)} after start of run? "
|
205
|
+
f"n_bytes_read = {self.n_bytes_read}"
|
143
206
|
)
|
144
|
-
# sizeof(fcio_recevent): (6 + 3*10 + 1*2304 + 3*4000)*4
|
145
|
-
self.n_bytes_read += 57360
|
146
|
-
return True
|
147
207
|
|
148
|
-
|
149
|
-
|
150
|
-
if self.status_rb is not None:
|
208
|
+
elif self.fcio.tag == Tags.Status:
|
209
|
+
if self.status_rbkd is not None:
|
151
210
|
self.any_full |= self.status_decoder.decode_packet(
|
152
|
-
self.fcio, self.
|
211
|
+
self.fcio, self.status_rbkd, self.packet_id
|
212
|
+
)
|
213
|
+
if self.fcio.fsp and self.fsp_status_rbkd is not None:
|
214
|
+
self.any_full |= self.fsp_status_decoder.decode_packet(
|
215
|
+
self.fcio, self.fsp_status_rbkd, self.packet_id
|
153
216
|
)
|
154
|
-
# sizeof(fcio_status): (3 + 10 + 256*(10 + 9 + 16 + 4 + 256))*4
|
155
|
-
self.n_bytes_read += 302132
|
156
|
-
return True
|
157
217
|
|
158
|
-
|
159
|
-
elif rc == 3 or rc == 6:
|
218
|
+
elif self.fcio.tag == Tags.Event or self.fcio.tag == Tags.SparseEvent:
|
160
219
|
if self.event_rbkd is not None:
|
161
220
|
self.any_full |= self.event_decoder.decode_packet(
|
162
221
|
self.fcio, self.event_rbkd, self.packet_id
|
163
222
|
)
|
164
|
-
|
165
|
-
|
166
|
-
|
223
|
+
if self.fcio.fsp and self.fsp_event_rbkd is not None:
|
224
|
+
self.any_full |= self.fsp_event_decoder.decode_packet(
|
225
|
+
self.fcio, self.fsp_event_rbkd, self.packet_id, False
|
226
|
+
)
|
227
|
+
|
228
|
+
elif self.fcio.tag == Tags.EventHeader:
|
229
|
+
if self.eventheader_rbkd is not None:
|
230
|
+
self.any_full |= self.eventheader_decoder.decode_packet(
|
231
|
+
self.fcio, self.eventheader_rbkd, self.packet_id
|
232
|
+
)
|
233
|
+
if self.fcio.fsp and self.fsp_event_rbkd is not None:
|
234
|
+
self.any_full |= self.fsp_event_decoder.decode_packet(
|
235
|
+
self.fcio, self.fsp_event_rbkd, self.packet_id, True
|
236
|
+
)
|
237
|
+
|
238
|
+
# FIXME: push to a buffer of skipped packets?
|
239
|
+
else: # unknown record
|
240
|
+
log.warning(
|
241
|
+
f"skipping unsupported record {Tags.str(self.fcio.tag)}. "
|
242
|
+
f"n_bytes_read = {self.n_bytes_read}"
|
167
243
|
)
|
168
|
-
|
244
|
+
|
245
|
+
return True
|
@@ -92,7 +92,6 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
|
|
92
92
|
log.debug(
|
93
93
|
f"{self.number_chOpen} channels open, each config {self.length_econf} bytes long"
|
94
94
|
)
|
95
|
-
|
96
95
|
n_bytes_read += self.__decode_channel_configs(f_in)
|
97
96
|
|
98
97
|
# print(self.channel_configs[0]["maw3_offset"])
|
@@ -151,7 +150,7 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
|
|
151
150
|
# print("reading in channel config {}".format(i))
|
152
151
|
|
153
152
|
channel = f_in.read(self.length_econf)
|
154
|
-
n_bytes_read += self.length_econf
|
153
|
+
n_bytes_read += int(self.length_econf)
|
155
154
|
ch_dpf = channel[16:32]
|
156
155
|
evt_data_32 = np.frombuffer(channel, dtype=np.uint32)
|
157
156
|
evt_data_dpf = np.frombuffer(ch_dpf, dtype=np.float64)
|
daq2lh5/orca/orca_digitizers.py
CHANGED
@@ -295,7 +295,7 @@ class ORSIS3316WaveformDecoder(OrcaDecoder):
|
|
295
295
|
key_lists = []
|
296
296
|
for key in self.decoded_values.keys():
|
297
297
|
key_lists.append([key])
|
298
|
-
return
|
298
|
+
return key_lists
|
299
299
|
|
300
300
|
def get_decoded_values(self, key: int = None) -> dict[str, Any]:
|
301
301
|
if key is None:
|