legend-daq2lh5 1.4.3__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.
@@ -1,7 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import datetime
3
4
  import io
4
5
  import logging
6
+ import os
7
+ import re
5
8
  from typing import Any, Dict
6
9
 
7
10
  import lgdo
@@ -15,6 +18,25 @@ log = logging.getLogger(__name__)
15
18
  LLAMA_Channel_Configs_t = Dict[int, Dict[str, Any]]
16
19
 
17
20
 
21
+ def parse_filename_for_timestamp(f_in_name: str) -> float:
22
+ """take a filename; return the unixtime parsed from the filename; 0 if impossible."""
23
+ filename = os.path.basename(f_in_name)
24
+ if match := re.fullmatch(r".*(\d{8})[-T](\d{6})(Z?).*", filename):
25
+ tsymd = match.group(1)
26
+ tshms = match.group(2)
27
+ utc: bool = True if match.group(3) == "Z" else False
28
+ when_file: datetime.datetime = datetime.datetime.strptime(
29
+ tsymd + tshms, "%Y%m%d%H%M%S"
30
+ ) # naive datetime object
31
+ if utc:
32
+ when_file = when_file.replace(
33
+ tzinfo=datetime.timezone.utc
34
+ ) # make it aware; UTC. Naive is treated as local
35
+ return when_file.timestamp()
36
+ else:
37
+ return 0
38
+
39
+
18
40
  class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
19
41
  """Decode llamaDAQ header data.
20
42
 
@@ -31,7 +53,7 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
31
53
  self.config = lgdo.Struct()
32
54
  self.channel_configs = None
33
55
 
34
- def decode_header(self, f_in: io.BufferedReader) -> lgdo.Struct:
56
+ def decode_header(self, f_in: io.BufferedReader, f_in_name: str) -> lgdo.Struct:
35
57
  n_bytes_read = 0
36
58
 
37
59
  f_in.seek(0) # should be there anyhow, but re-set if not
@@ -55,13 +77,21 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
55
77
  self.length_econf = evt_data_16[5]
56
78
  self.number_chOpen = evt_data_32[3]
57
79
 
80
+ self.global_configs = {}
81
+
82
+ # currently pulled from filename with 1s precision.
83
+ # change if we have it in the llamaDAQ file's header
84
+ self.global_configs["initial_timestamp"] = parse_filename_for_timestamp(
85
+ f_in_name
86
+ )
87
+ self.global_configs["initial_timestamp_accuracy"] = 1.0 # in seconds
88
+
58
89
  log.debug(
59
90
  f"File version: {self.version_major}.{self.version_minor}.{self.version_patch}"
60
91
  )
61
92
  log.debug(
62
93
  f"{self.number_chOpen} channels open, each config {self.length_econf} bytes long"
63
94
  )
64
-
65
95
  n_bytes_read += self.__decode_channel_configs(f_in)
66
96
 
67
97
  # print(self.channel_configs[0]["maw3_offset"])
@@ -72,6 +102,13 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
72
102
  self.config.add_field("version_patch", lgdo.Scalar(self.version_patch))
73
103
  self.config.add_field("length_econf", lgdo.Scalar(self.length_econf))
74
104
  self.config.add_field("number_chOpen", lgdo.Scalar(self.number_chOpen))
105
+ self.config.add_field(
106
+ "initial_timestamp", lgdo.Scalar(self.global_configs["initial_timestamp"])
107
+ )
108
+ self.config.add_field(
109
+ "initial_timestamp_accuracy",
110
+ lgdo.Scalar(self.global_configs["initial_timestamp_accuracy"]),
111
+ )
75
112
 
76
113
  for fch_id, fch_content in self.channel_configs.items():
77
114
  fch_lgdo = lgdo.Struct()
@@ -88,6 +125,9 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
88
125
  def get_channel_configs(self) -> LLAMA_Channel_Configs_t:
89
126
  return self.channel_configs
90
127
 
128
+ def get_global_configs(self) -> dict[str, Any]:
129
+ return self.global_configs
130
+
91
131
  def __decode_channel_configs(self, f_in: io.BufferedReader) -> int:
92
132
  """Reads the metadata.
93
133
 
@@ -110,7 +150,7 @@ class LLAMAHeaderDecoder(DataDecoder): # DataDecoder currently unused
110
150
  # print("reading in channel config {}".format(i))
111
151
 
112
152
  channel = f_in.read(self.length_econf)
113
- n_bytes_read += self.length_econf
153
+ n_bytes_read += int(self.length_econf)
114
154
  ch_dpf = channel[16:32]
115
155
  evt_data_32 = np.frombuffer(channel, dtype=np.uint32)
116
156
  evt_data_dpf = np.frombuffer(ch_dpf, dtype=np.float64)
@@ -53,12 +53,15 @@ class LLAMAStreamer(DataStreamer):
53
53
  self.packet_id = 0
54
54
 
55
55
  # read header info here
56
- header, n_bytes_hdr = self.header_decoder.decode_header(self.in_stream)
56
+ header, n_bytes_hdr = self.header_decoder.decode_header(
57
+ self.in_stream, llama_filename
58
+ )
57
59
  self.n_bytes_read += n_bytes_hdr
58
60
 
59
61
  self.event_decoder.set_channel_configs(
60
62
  self.header_decoder.get_channel_configs()
61
63
  )
64
+ self.event_decoder.set_global_configs(self.header_decoder.get_global_configs())
62
65
 
63
66
  # as far as I can tell, this happens if a user does not specify output.
64
67
  # Then I can still get a rb_lib, but that misses keys entirely, which I need since channels can have different setups.
@@ -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 [key_lists]
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:
@@ -0,0 +1,405 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import logging
5
+ from typing import Any
6
+
7
+ from fcio import FCIO, Tags
8
+
9
+ from daq2lh5.fc.fc_config_decoder import FCConfigDecoder
10
+ from daq2lh5.fc.fc_event_decoder import FCEventDecoder
11
+ from daq2lh5.fc.fc_eventheader_decoder import FCEventHeaderDecoder, get_fcid, get_key
12
+ from daq2lh5.fc.fc_fsp_decoder import (
13
+ FSPConfigDecoder,
14
+ FSPEventDecoder,
15
+ FSPStatusDecoder,
16
+ )
17
+ from daq2lh5.fc.fc_status_decoder import FCStatusDecoder
18
+ from daq2lh5.fc.fc_status_decoder import get_key as get_status_key
19
+
20
+ from ..raw_buffer import RawBufferList
21
+ from .orca_base import OrcaDecoder
22
+ from .orca_header import OrcaHeader
23
+ from .orca_packet import OrcaPacket
24
+
25
+ log = logging.getLogger(__name__)
26
+
27
+
28
+ # FCIO streams are stateful and need to be accessible for all decoders.
29
+ fcio_stream_library = dict()
30
+
31
+
32
+ def get_fcio_stream(streamid):
33
+ if streamid in fcio_stream_library:
34
+ return fcio_stream_library[streamid]
35
+ else:
36
+ fcio_stream_library[streamid] = FCIO()
37
+ return fcio_stream_library[streamid]
38
+
39
+
40
+ def extract_header_information(header: OrcaHeader):
41
+
42
+ fc_hdr_info = {
43
+ "key_list": {},
44
+ "n_adc": {},
45
+ "adc_card_layout": {},
46
+ "wf_len": {},
47
+ "fsp_enabled": {},
48
+ "n_card": {},
49
+ }
50
+
51
+ fc_card_info_dict = header.get_object_info(
52
+ [
53
+ "ORFlashCamGlobalTriggerModel",
54
+ "ORFlashCamTriggerModel",
55
+ "ORFlashCamADCModel",
56
+ "ORFlashCamADCStdModel",
57
+ ]
58
+ )
59
+
60
+ fc_listener_info_list = header.get_readout_info("ORFlashCamListenerModel")
61
+ for fc_listener_info in fc_listener_info_list:
62
+ fcid = fc_listener_info["uniqueID"] # it should be called listener_id
63
+ if fcid == 0:
64
+ raise ValueError("got fcid=0 unexpectedly!")
65
+ aux_hw_info = header.get_auxhw_info("ORFlashCamListenerModel", fcid)
66
+ if "fspEnabled" in aux_hw_info:
67
+ fc_hdr_info["fsp_enabled"][fcid] = aux_hw_info["fspEnabled"]
68
+ else:
69
+ fc_hdr_info["fsp_enabled"][fcid] = False
70
+
71
+ fc_hdr_info["wf_len"][fcid] = header.get_auxhw_info(
72
+ "ORFlashCamListenerModel", fcid
73
+ )["eventSamples"]
74
+ fc_hdr_info["n_adc"][fcid] = 0
75
+ fc_hdr_info["n_card"][fcid] = 0
76
+ fc_hdr_info["key_list"][fcid] = []
77
+ fc_hdr_info["adc_card_layout"][fcid] = {}
78
+ for child in fc_listener_info["children"]:
79
+
80
+ crate = child["crate"]
81
+ card = child["station"]
82
+ card_address = fc_card_info_dict[crate][card]["CardAddress"]
83
+ fc_hdr_info["adc_card_layout"][fcid][card_address] = (
84
+ crate,
85
+ card,
86
+ card_address,
87
+ )
88
+ fc_hdr_info["n_card"][fcid] += 1
89
+
90
+ if crate not in fc_card_info_dict:
91
+ raise RuntimeError(f"no crate {crate} in fc_card_info_dict")
92
+ if card not in fc_card_info_dict[crate]:
93
+ raise RuntimeError(f"no card {card} in fc_card_info_dict[{crate}]")
94
+
95
+ for fc_input in range(len(fc_card_info_dict[crate][card]["Enabled"])):
96
+ if not fc_card_info_dict[crate][card]["Enabled"][fc_input]:
97
+ continue
98
+
99
+ fc_hdr_info["n_adc"][fcid] += 1
100
+ key = get_key(fcid, card_address, fc_input)
101
+
102
+ if key in fc_hdr_info["key_list"][fcid]:
103
+ log.warning(f"key {key} already in key_list...")
104
+ else:
105
+ fc_hdr_info["key_list"][fcid].append(key)
106
+
107
+ return fc_hdr_info
108
+
109
+
110
+ class ORFCIOConfigDecoder(OrcaDecoder):
111
+ def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
112
+
113
+ self.decoder = FCConfigDecoder()
114
+ self.fsp_decoder = None
115
+ self.decoded_values = {}
116
+ self.key_list = {"fc_config": [], "fsp_config": []}
117
+ self.max_rows_in_packet = 0
118
+
119
+ super().__init__(header=header, **kwargs)
120
+
121
+ # The ConfigDecoder is always required for decoding fcio data.
122
+ # When OrcaStreamer.open_stream is called, we close any open fcio stream
123
+ for fcio_stream in fcio_stream_library.values():
124
+ fcio_stream.close()
125
+
126
+ def set_header(self, header: OrcaHeader) -> None:
127
+ self.header = header
128
+ self.fc_hdr_info = extract_header_information(header)
129
+ self.decoded_values = copy.deepcopy(self.decoder.get_decoded_values())
130
+
131
+ for fcid in self.fc_hdr_info["fsp_enabled"]:
132
+ key = get_key(fcid, 0, 0)
133
+ self.key_list["fc_config"].append(key)
134
+ if self.fc_hdr_info["fsp_enabled"][fcid]:
135
+ self.fsp_decoder = FSPConfigDecoder()
136
+ self.key_list["fsp_config"].append(f"fsp_config_{key}")
137
+ self.max_rows_in_packet = 1
138
+
139
+ def get_key_lists(self) -> list[list[int, str]]:
140
+ return list(self.key_list.values())
141
+
142
+ def get_decoded_values(self, key: int | str = None) -> dict[str, Any]:
143
+ if isinstance(key, str) and key.startswith("fsp_config"):
144
+ return copy.deepcopy(self.fsp_decoder.get_decoded_values())
145
+ return self.decoded_values
146
+ raise KeyError(f"no decoded values for key {key}")
147
+
148
+ def decode_packet(
149
+ self, packet: OrcaPacket, packet_id: int, rbl: RawBufferList
150
+ ) -> bool:
151
+
152
+ fcio_stream = get_fcio_stream(packet[2])
153
+ if fcio_stream.is_open():
154
+ raise NotImplementedError(
155
+ f"FCIO stream with stream id {packet[2]} already opened. Update of FCIOConfig is not supported."
156
+ )
157
+ else:
158
+ fcio_stream.open(memoryview(packet[3:]))
159
+
160
+ if fcio_stream.config.streamid != packet[2]:
161
+ log.warning(
162
+ f"The expected stream id {packet[2]} does not match the contained stream id {fcio_stream.config.streamid}"
163
+ )
164
+
165
+ config_rbkd = rbl.get_keyed_dict()
166
+
167
+ # TODO: the decoders could fetch lgdo's using it's key_list
168
+ fc_key = get_key(fcio_stream.config.streamid, 0, 0)
169
+ any_full = self.decoder.decode_packet(
170
+ fcio_stream, config_rbkd[fc_key], packet_id
171
+ )
172
+ if self.fsp_decoder is not None:
173
+ fsp_key = f"fsp_config_{get_key(fcio_stream.config.streamid, 0, 0)}"
174
+ any_full |= self.fsp_decoder.decode_packet(
175
+ fcio_stream, config_rbkd[fsp_key], packet_id
176
+ )
177
+
178
+ return bool(any_full)
179
+
180
+
181
+ class ORFCIOStatusDecoder(OrcaDecoder):
182
+ def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
183
+
184
+ self.decoder = FCStatusDecoder()
185
+ self.fsp_decoder = None
186
+ self.decoded_values = {}
187
+ self.key_list = {"fc_status": [], "fsp_status": []}
188
+ self.max_rows_in_packet = 0
189
+ super().__init__(header=header, **kwargs)
190
+
191
+ def set_header(self, header: OrcaHeader) -> None:
192
+ """Setter for headers. Overload to set card parameters, etc."""
193
+ self.header = header
194
+ self.fc_hdr_info = extract_header_information(header)
195
+ self.decoded_values = copy.deepcopy(self.decoder.get_decoded_values())
196
+
197
+ for fcid in self.fc_hdr_info["n_card"]:
198
+ # If the data was taken without a master distribution module,
199
+ # i.e. only one ADC Module the decoder will just not write to the buffer.
200
+
201
+ # MDB key
202
+ self.key_list["fc_status"] = [get_status_key(fcid, 0)]
203
+ # ADC module keys
204
+ self.key_list["fc_status"] += [
205
+ get_status_key(fcid, 0x2000 + i)
206
+ for i in range(self.fc_hdr_info["n_card"][fcid])
207
+ ]
208
+
209
+ if self.fc_hdr_info["fsp_enabled"][fcid]:
210
+ key = get_key(fcid, 0, 0)
211
+ self.key_list["fsp_status"].append(f"fsp_status_{key}")
212
+ self.fsp_decoder = FSPStatusDecoder()
213
+ self.max_rows_in_packet = max(self.fc_hdr_info["n_card"].values()) + 1
214
+
215
+ def get_key_lists(self) -> list[list[int | str]]:
216
+ return list(self.key_list.values())
217
+
218
+ def get_decoded_values(self, key: int | str = None) -> dict[str, Any]:
219
+ if key is None:
220
+ dec_vals_list = list(self.decoded_values)
221
+ if len(dec_vals_list) > 0:
222
+ return {dec_vals_list[0]: self.decoded_values[dec_vals_list[0]]}
223
+ raise RuntimeError("decoded_values not built")
224
+
225
+ if (
226
+ isinstance(key, str)
227
+ and key.startswith("fsp_status")
228
+ and self.fsp_decoder is not None
229
+ ):
230
+ return copy.deepcopy(self.fsp_decoder.get_decoded_values())
231
+ elif isinstance(key, int):
232
+ return copy.deepcopy(self.decoder.get_decoded_values())
233
+ else:
234
+ raise KeyError(f"no decoded values for key {key}")
235
+
236
+ def get_max_rows_in_packet(self) -> int:
237
+ return self.max_rows_in_packet
238
+
239
+ def decode_packet(
240
+ self, packet: OrcaPacket, packet_id: int, rbl: RawBufferList
241
+ ) -> bool:
242
+ status_rbkd = rbl.get_keyed_dict()
243
+
244
+ fcio_stream = get_fcio_stream(packet[2])
245
+ fcio_stream.set_mem_field(memoryview(packet[3:]))
246
+
247
+ any_full = False
248
+ while fcio_stream.get_record():
249
+ if fcio_stream.tag == Tags.Status:
250
+ any_full |= self.decoder.decode_packet(
251
+ fcio_stream, status_rbkd, packet_id
252
+ )
253
+ if self.fsp_decoder is not None:
254
+ any_full |= self.fsp_decoder.decode_packet(
255
+ fcio_stream, status_rbkd, packet_id
256
+ )
257
+
258
+ return bool(any_full)
259
+
260
+
261
+ class ORFCIOEventHeaderDecoder(OrcaDecoder):
262
+ def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
263
+
264
+ self.decoder = FCEventHeaderDecoder()
265
+ self.fsp_decoder = None
266
+ self.decoded_values = {}
267
+ self.key_list = {"fc_eventheader": [], "fsp_eventheader": []}
268
+
269
+ super().__init__(header=header, **kwargs)
270
+
271
+ def set_header(self, header: OrcaHeader) -> None:
272
+ """Setter for headers. Overload to set card parameters, etc."""
273
+ self.header = header
274
+
275
+ self.fc_hdr_info = extract_header_information(header)
276
+
277
+ key_list = self.fc_hdr_info["key_list"]
278
+ for fcid in key_list:
279
+ key = get_key(fcid, 0, 0)
280
+ self.key_list["fc_eventheader"].append(key)
281
+ self.decoded_values[fcid] = copy.deepcopy(self.decoder.get_decoded_values())
282
+ if self.fc_hdr_info["fsp_enabled"][fcid]:
283
+ self.fsp_decoder = FSPEventDecoder()
284
+ self.key_list["fsp_eventheader"].append(f"fsp_eventheader_{key}")
285
+
286
+ self.max_rows_in_packet = 1
287
+
288
+ def get_key_lists(self) -> list[list[int | str]]:
289
+ return list(self.key_list.values())
290
+
291
+ def get_decoded_values(self, key: int | str = None) -> dict[str, Any]:
292
+ if (
293
+ isinstance(key, str)
294
+ and key.startswith("fsp_eventheader_")
295
+ and self.fsp_decoder is not None
296
+ ):
297
+ return copy.deepcopy(self.fsp_decoder.get_decoded_values())
298
+ elif isinstance(key, int):
299
+ fcid = get_fcid(key)
300
+ if fcid in self.decoded_values:
301
+ return self.decoded_values[fcid]
302
+ elif key is None and self.fsp_decoder is None:
303
+ dec_vals_list = list(self.decoded_values.values())
304
+ if len(dec_vals_list) > 0:
305
+ return dec_vals_list[0]
306
+ raise RuntimeError("decoded_values not built")
307
+
308
+ raise KeyError(f"no decoded values for key {key}")
309
+
310
+ def decode_packet(
311
+ self, packet: OrcaPacket, packet_id: int, rbl: RawBufferList
312
+ ) -> bool:
313
+ evthdr_rbkd = rbl.get_keyed_dict()
314
+ fcio_stream = get_fcio_stream(packet[2])
315
+ fcio_stream.set_mem_field(memoryview(packet[3:]))
316
+
317
+ any_full = False
318
+ while fcio_stream.get_record():
319
+ if fcio_stream.tag == Tags.EventHeader:
320
+ any_full |= self.decoder.decode_packet(
321
+ fcio_stream, evthdr_rbkd, packet_id
322
+ )
323
+ if self.fsp_decoder is not None:
324
+ any_full |= self.fsp_decoder.decode_packet(
325
+ fcio_stream, evthdr_rbkd, packet_id, True
326
+ )
327
+
328
+ return bool(any_full)
329
+
330
+
331
+ class ORFCIOEventDecoder(OrcaDecoder):
332
+ """Decoder for FlashCam FCIO stream data written by ORCA."""
333
+
334
+ def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
335
+ self.decoder = FCEventDecoder()
336
+ self.fsp_decoder = None
337
+
338
+ self.key_list = {"event": [], "fsp_event": []}
339
+ self.decoded_values = {}
340
+ self.max_rows_in_packet = 0
341
+
342
+ super().__init__(header=header, **kwargs)
343
+
344
+ def set_header(self, header: OrcaHeader) -> None:
345
+ """Setter for headers. Overload to set card parameters, etc."""
346
+ self.header = header
347
+ self.fc_hdr_info = extract_header_information(header)
348
+ key_list = self.fc_hdr_info["key_list"]
349
+ for fcid in key_list:
350
+ self.key_list["event"] += key_list[fcid]
351
+ self.decoded_values[fcid] = copy.deepcopy(self.decoder.get_decoded_values())
352
+ self.decoded_values[fcid]["waveform"]["wf_len"] = self.fc_hdr_info[
353
+ "wf_len"
354
+ ][fcid]
355
+ if self.fc_hdr_info["fsp_enabled"][fcid]:
356
+ key = get_key(fcid, 0, 0)
357
+ self.key_list["fsp_event"].append(f"fsp_event_{key}")
358
+ self.fsp_decoder = FSPEventDecoder()
359
+ self.max_rows_in_packet = max(self.fc_hdr_info["n_adc"].values())
360
+
361
+ def get_key_lists(self) -> list[list[int]]:
362
+ return list(self.key_list.values())
363
+
364
+ def get_max_rows_in_packet(self) -> int:
365
+ return self.max_rows_in_packet
366
+
367
+ def get_decoded_values(self, key: int = None) -> dict[str, Any]:
368
+ if key is None:
369
+ dec_vals_list = list(self.decoded_values.values())
370
+ if len(dec_vals_list) > 0:
371
+ return dec_vals_list[0]
372
+ raise RuntimeError("decoded_values not built")
373
+
374
+ if (
375
+ isinstance(key, str)
376
+ and key.startswith("fsp_event_")
377
+ and self.fsp_decoder is not None
378
+ ):
379
+ return copy.deepcopy(self.fsp_decoder.get_decoded_values())
380
+ elif isinstance(key, int):
381
+ fcid = get_fcid(key)
382
+ if fcid in self.decoded_values:
383
+ return self.decoded_values[fcid]
384
+
385
+ raise KeyError(f"no decoded values for key {key}")
386
+
387
+ def decode_packet(
388
+ self, packet: OrcaPacket, packet_id: int, rbl: RawBufferList
389
+ ) -> bool:
390
+ """Decode the ORCA FlashCam ADC packet."""
391
+ evt_rbkd = rbl.get_keyed_dict()
392
+
393
+ fcio_stream = get_fcio_stream(packet[2])
394
+ fcio_stream.set_mem_field(memoryview(packet[3:]))
395
+
396
+ any_full = False
397
+ while fcio_stream.get_record():
398
+ if fcio_stream.tag == Tags.Event or fcio_stream.tag == Tags.SparseEvent:
399
+ any_full |= self.decoder.decode_packet(fcio_stream, evt_rbkd, packet_id)
400
+ if self.fsp_decoder is not None:
401
+ any_full |= self.fsp_decoder.decode_packet(
402
+ fcio_stream, evt_rbkd, packet_id, False
403
+ )
404
+
405
+ return bool(any_full)
@@ -5,7 +5,7 @@ from typing import Any
5
5
 
6
6
  import numpy as np
7
7
 
8
- from ..fc.fc_event_decoder import fc_decoded_values
8
+ from ..fc.fc_event_decoder import fc_event_decoded_values
9
9
  from ..raw_buffer import RawBufferLibrary
10
10
  from .orca_base import OrcaDecoder
11
11
  from .orca_header import OrcaHeader
@@ -43,7 +43,7 @@ class ORFlashCamListenerConfigDecoder(OrcaDecoder):
43
43
  "packet_len": {"dtype": "uint32"},
44
44
  "readout_id": {"dtype": "uint16"},
45
45
  "fcid": {"dtype": "uint16"},
46
- "telid": {"dtype": "int32"},
46
+ "streamid": {"dtype": "int32"},
47
47
  "nadcs": {"dtype": "int32"},
48
48
  "ntriggers": {"dtype": "int32"},
49
49
  "nsamples": {"dtype": "int32"},
@@ -458,8 +458,8 @@ class ORFlashCamWaveformDecoder(OrcaDecoder):
458
458
 
459
459
  def __init__(self, header: OrcaHeader = None, **kwargs) -> None:
460
460
  # start with the values defined in fcdaq
461
- self.decoded_values_template = copy.deepcopy(fc_decoded_values)
462
- """A custom copy of :obj:`.fc.fc_event_decoder.fc_decoded_values`."""
461
+ self.decoded_values_template = copy.deepcopy(fc_event_decoded_values)
462
+ """A custom copy of :obj:`.fc.fc_event_decoder.fc_event_decoded_values`."""
463
463
  # add header values from Orca
464
464
  self.decoded_values_template.update(
465
465
  {
@@ -737,6 +737,9 @@ class ORFlashCamWaveformDecoder(OrcaDecoder):
737
737
  tbl["waveform"]["values"].nda[ii][:wf_samples] = wf
738
738
 
739
739
  evt_rbkd[key].loc += 1
740
+ log.info(
741
+ f"-> {tbl['eventnumber'].nda[ii]} {channel} .. {evt_rbkd[key].loc}/{len(evt_rbkd[key])} {id(evt_rbkd[key])} {id(evt_rbkd[key].lgdo)}"
742
+ )
740
743
  return evt_rbkd[key].is_full()
741
744
 
742
745
 
@@ -46,16 +46,21 @@ class OrcaHeader(dict):
46
46
  return d["Run Control"]["RunNumber"]
47
47
  raise ValueError("No run number found in header!")
48
48
 
49
- def get_object_info(self, orca_class_name: str) -> dict[int, dict[int, dict]]:
49
+ def get_object_info(
50
+ self, orca_class_name: str | list[str]
51
+ ) -> dict[int, dict[int, dict]]:
50
52
  """Returns a ``dict[crate][card]`` with all info from the header for
51
53
  each card with name `orca_class_name`.
52
54
  """
53
55
  object_info_dict = {}
54
56
 
57
+ if isinstance(orca_class_name, str):
58
+ orca_class_name = [orca_class_name]
59
+
55
60
  crates = self["ObjectInfo"]["Crates"]
56
61
  for crate in crates:
57
62
  for card in crate["Cards"]:
58
- if card["Class Name"] == orca_class_name:
63
+ if card["Class Name"] in orca_class_name:
59
64
  if crate["CrateNumber"] not in object_info_dict:
60
65
  object_info_dict[crate["CrateNumber"]] = {}
61
66
  object_info_dict[crate["CrateNumber"]][card["Card"]] = card
@@ -20,9 +20,19 @@ def is_short(packet: OrcaPacket) -> bool:
20
20
  return bool(packet[0] >> 31)
21
21
 
22
22
 
23
+ def is_extended(packet: OrcaPacket) -> bool:
24
+ # if the packet is 0 size in default format
25
+ # the length if the packet is stored in the next uint32
26
+ return bool((packet[0] & 0x3FFFF) == 0)
27
+
28
+
23
29
  def get_n_words(packet: OrcaPacket) -> int:
24
30
  if is_short(packet):
25
31
  return 1
32
+ if is_extended(packet):
33
+ # we could check here if packet is actually long enough
34
+ # to return packet[1]
35
+ return packet[1]
26
36
  return packet[0] & 0x3FFFF
27
37
 
28
38
 
@@ -18,12 +18,12 @@ class ORRunDecoderForRun(OrcaDecoder):
18
18
  # bit in data packet
19
19
  self.decoded_values = {
20
20
  "subrun_number": {"dtype": "uint16"},
21
- "runstartorstop": {"dtype": "bool8"},
22
- "quickstartrun": {"dtype": "bool8"},
23
- "remotecontrolrun": {"dtype": "bool8"},
24
- "heartbeatrecord": {"dtype": "bool8"},
25
- "endsubrunrecord": {"dtype": "bool8"},
26
- "startsubrunrecord": {"dtype": "bool8"},
21
+ "runstartorstop": {"dtype": "bool"},
22
+ "quickstartrun": {"dtype": "bool"},
23
+ "remotecontrolrun": {"dtype": "bool"},
24
+ "heartbeatrecord": {"dtype": "bool"},
25
+ "endsubrunrecord": {"dtype": "bool"},
26
+ "startsubrunrecord": {"dtype": "bool"},
27
27
  "run_number": {"dtype": "int32"},
28
28
  "time": {"dtype": "int32"},
29
29
  }