legend-daq2lh5 1.3.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- daq2lh5/_version.py +2 -2
- daq2lh5/buffer_processor/lh5_buffer_processor.py +7 -5
- daq2lh5/build_raw.py +17 -13
- daq2lh5/raw_buffer.py +78 -82
- daq2lh5/utils.py +35 -0
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/METADATA +1 -1
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/RECORD +11 -10
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/LICENSE +0 -0
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/WHEEL +0 -0
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/entry_points.txt +0 -0
- {legend_daq2lh5-1.3.0.dist-info → legend_daq2lh5-1.4.0.dist-info}/top_level.txt +0 -0
daq2lh5/_version.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import json
|
4
3
|
import logging
|
5
4
|
import os
|
6
5
|
|
@@ -8,6 +7,7 @@ import h5py
|
|
8
7
|
import lgdo
|
9
8
|
from lgdo import lh5
|
10
9
|
|
10
|
+
from .. import utils
|
11
11
|
from ..buffer_processor.buffer_processor import buffer_processor
|
12
12
|
from ..raw_buffer import RawBuffer, RawBufferLibrary
|
13
13
|
|
@@ -104,11 +104,13 @@ def lh5_buffer_processor(
|
|
104
104
|
raw_store.gimme_file(proc_file_name, "a")
|
105
105
|
|
106
106
|
# Do key expansion on the out_spec
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
allowed_exts = [ext for exts in utils.__file_extensions__.values() for ext in exts]
|
108
|
+
if isinstance(out_spec, str) and any(
|
109
|
+
[out_spec.endswith(ext) for ext in allowed_exts]
|
110
|
+
):
|
111
|
+
out_spec = utils.load_dict(out_spec)
|
110
112
|
if isinstance(out_spec, dict):
|
111
|
-
RawBufferLibrary(
|
113
|
+
RawBufferLibrary(config=out_spec)
|
112
114
|
|
113
115
|
# Write everything in the raw file to the new file, check for proc_spec under either the group name, out_name, or the name
|
114
116
|
for tb in lh5_tables:
|
daq2lh5/build_raw.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import glob
|
4
|
-
import json
|
5
4
|
import logging
|
6
5
|
import os
|
7
6
|
import time
|
@@ -10,6 +9,7 @@ import numpy as np
|
|
10
9
|
from lgdo import lh5
|
11
10
|
from tqdm.auto import tqdm
|
12
11
|
|
12
|
+
from . import utils
|
13
13
|
from .compass.compass_streamer import CompassStreamer
|
14
14
|
from .fc.fc_streamer import FCStreamer
|
15
15
|
from .llama.llama_streamer import LLAMAStreamer
|
@@ -49,12 +49,14 @@ def build_raw(
|
|
49
49
|
Specification for the output stream.
|
50
50
|
|
51
51
|
- if None, uses ``{in_stream}.lh5`` as the output filename.
|
52
|
-
- if a str not ending
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
- if a str not ending with a config file extension, interpreted as the
|
53
|
+
output filename.
|
54
|
+
- if a str ending with a config file extension, interpreted as a
|
55
|
+
filename containing shorthand for the output specification (see
|
56
|
+
:mod:`.raw_buffer`).
|
57
|
+
- if a dict, should be a dict loaded from the shorthand notation for
|
58
|
+
RawBufferLibraries (see :mod:`.raw_buffer`), which is then used to
|
59
|
+
build a :class:`.RawBufferLibrary`.
|
58
60
|
- if a :class:`.RawBufferLibrary`, the mapping of data to output file /
|
59
61
|
group is taken from that.
|
60
62
|
|
@@ -72,8 +74,8 @@ def build_raw(
|
|
72
74
|
|
73
75
|
- if None, CompassDecoder will sacrifice the first packet to determine
|
74
76
|
waveform length
|
75
|
-
- if a str ending
|
76
|
-
|
77
|
+
- if a str ending with a config file extension, interpreted as a
|
78
|
+
filename containing shorthand for the output specification (see
|
77
79
|
:mod:`.compass.compass_event_decoder`).
|
78
80
|
|
79
81
|
hdf5_settings
|
@@ -120,11 +122,13 @@ def build_raw(
|
|
120
122
|
|
121
123
|
# process out_spec and setup rb_lib if specified
|
122
124
|
rb_lib = None
|
123
|
-
|
124
|
-
|
125
|
-
|
125
|
+
allowed_exts = [ext for exts in utils.__file_extensions__.values() for ext in exts]
|
126
|
+
if isinstance(out_spec, str) and any(
|
127
|
+
[out_spec.endswith(ext) for ext in allowed_exts]
|
128
|
+
):
|
129
|
+
out_spec = utils.load_dict(out_spec)
|
126
130
|
if isinstance(out_spec, dict):
|
127
|
-
out_spec = RawBufferLibrary(
|
131
|
+
out_spec = RawBufferLibrary(config=out_spec, kw_dict=kwargs)
|
128
132
|
if isinstance(out_spec, RawBufferLibrary):
|
129
133
|
rb_lib = out_spec
|
130
134
|
# if no rb_lib, write all data to file
|
daq2lh5/raw_buffer.py
CHANGED
@@ -19,48 +19,49 @@ output to a :class:`.RawBufferList`.
|
|
19
19
|
:class:`.RawBufferLibrary`: a dictionary of :class:`RawBufferList`\ s, e.g. one
|
20
20
|
for each :class:`~.data_decoder.DataDecoder`. Keyed by the decoder name.
|
21
21
|
|
22
|
-
:class:`.RawBuffer` supports a
|
23
|
-
:meth:`.RawBufferLibrary.
|
24
|
-
|
25
|
-
Example
|
26
|
-
example, the user would call
|
27
|
-
kw_dict)`` with ``kw_dict``
|
28
|
-
|
29
|
-
|
22
|
+
:class:`.RawBuffer` supports a config file short-hand notation, see
|
23
|
+
:meth:`.RawBufferLibrary.set_from_dict` for full specification.
|
24
|
+
|
25
|
+
Example YAML yielding a valid :class:`.RawBufferLibrary` is below (other
|
26
|
+
formats like JSON are also supported). In the example, the user would call
|
27
|
+
``RawBufferLibrary.set_from_dict(config, kw_dict)`` with ``kw_dict``
|
28
|
+
containing an entry for ``'file_key'``. The other keywords ``{key}`` and
|
29
|
+
``{name}`` are understood by and filled in during
|
30
|
+
:meth:`.RawBufferLibrary.set_from_dict` unless overloaded in ``kw_dict``.
|
30
31
|
Note the use of the wildcard ``*``: this will match all other decoder names /
|
31
32
|
keys.
|
32
33
|
|
33
|
-
.. code-block ::
|
34
|
-
|
35
|
-
|
36
|
-
"
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
"{
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
34
|
+
.. code-block :: yaml
|
35
|
+
|
36
|
+
FCEventDecoder:
|
37
|
+
"g{key:0>3d}":
|
38
|
+
key_list:
|
39
|
+
- [24, 64]
|
40
|
+
out_stream: "$DATADIR/{file_key}_geds.lh5:/geds"
|
41
|
+
proc_spec:
|
42
|
+
window:
|
43
|
+
- waveform
|
44
|
+
- 10
|
45
|
+
- 100
|
46
|
+
- windowed_waveform
|
47
|
+
spms:
|
48
|
+
key_list:
|
49
|
+
- [6, 23]
|
50
|
+
out_stream: "$DATADIR/{file_key}_spms.lh5:/spms"
|
51
|
+
puls:
|
52
|
+
key_list:
|
53
|
+
- 0
|
54
|
+
out_stream: "$DATADIR/{file_key}_auxs.lh5:/auxs"
|
55
|
+
muvt:
|
56
|
+
key_list:
|
57
|
+
- 1
|
58
|
+
- 5
|
59
|
+
out_stream: "$DATADIR/{file_key}_auxs.lh5:/auxs"
|
60
|
+
|
61
|
+
"*":
|
62
|
+
"{name}":
|
63
|
+
key_list: ["*"]
|
64
|
+
out_stream: "$DATADIR/{file_key}_{name}.lh5"
|
64
65
|
"""
|
65
66
|
|
66
67
|
from __future__ import annotations
|
@@ -105,7 +106,7 @@ class RawBuffer:
|
|
105
106
|
the name or identifier of the object in the output stream.
|
106
107
|
proc_spec
|
107
108
|
a dictionary containing the following:
|
108
|
-
- a DSP config file, passed as a dictionary, or as a path to a
|
109
|
+
- a DSP config file, passed as a dictionary, or as a path to a config file
|
109
110
|
- an array containing: the name of an LGDO object stored in the :class:`.RawBuffer` to be sliced,
|
110
111
|
the start and end indices of the slice, and the new name for the sliced object
|
111
112
|
- a dictionary of fields to drop
|
@@ -185,29 +186,27 @@ class RawBufferList(list):
|
|
185
186
|
self.keyed_dict[key] = rb
|
186
187
|
return self.keyed_dict
|
187
188
|
|
188
|
-
def
|
189
|
-
|
190
|
-
|
191
|
-
"""Set up a :class:`.RawBufferList` from a dictionary written in JSON
|
192
|
-
shorthand. See :meth:`.RawBufferLibrary.set_from_json_dict` for details.
|
189
|
+
def set_from_dict(self, config: dict, kw_dict: dict[str, str] = None) -> None:
|
190
|
+
"""Set up a :class:`.RawBufferList` from a dictionary. See
|
191
|
+
:meth:`.RawBufferLibrary.set_from_dict` for details.
|
193
192
|
|
194
193
|
Notes
|
195
194
|
-----
|
196
|
-
`
|
195
|
+
`config` is changed by this function.
|
197
196
|
"""
|
198
|
-
|
199
|
-
for name in
|
197
|
+
expand_rblist_dict(config, {} if kw_dict is None else kw_dict)
|
198
|
+
for name in config:
|
200
199
|
rb = RawBuffer()
|
201
|
-
if "key_list" in
|
202
|
-
rb.key_list =
|
203
|
-
if "out_stream" in
|
204
|
-
rb.out_stream =
|
205
|
-
if "proc_spec" in
|
206
|
-
rb.proc_spec =
|
200
|
+
if "key_list" in config[name]:
|
201
|
+
rb.key_list = config[name]["key_list"]
|
202
|
+
if "out_stream" in config[name]:
|
203
|
+
rb.out_stream = config[name]["out_stream"]
|
204
|
+
if "proc_spec" in config[name]:
|
205
|
+
rb.proc_spec = config[name][
|
207
206
|
"proc_spec"
|
208
207
|
] # If you swap this with the next line, then key expansion doesn't work
|
209
|
-
if "out_name" in
|
210
|
-
rb.out_name =
|
208
|
+
if "out_name" in config[name]:
|
209
|
+
rb.out_name = config[name]["out_name"]
|
211
210
|
else:
|
212
211
|
rb.out_name = name
|
213
212
|
self.append(rb)
|
@@ -250,15 +249,12 @@ class RawBufferLibrary(dict):
|
|
250
249
|
write to them.
|
251
250
|
"""
|
252
251
|
|
253
|
-
def __init__(self,
|
254
|
-
if
|
255
|
-
self.
|
252
|
+
def __init__(self, config: dict = None, kw_dict: dict[str, str] = None) -> None:
|
253
|
+
if config is not None:
|
254
|
+
self.set_from_dict(config, kw_dict)
|
256
255
|
|
257
|
-
def
|
258
|
-
|
259
|
-
) -> None:
|
260
|
-
r"""Set up a :class:`.RawBufferLibrary` from a dictionary written in
|
261
|
-
JSON shorthand.
|
256
|
+
def set_from_dict(self, config: dict, kw_dict: dict[str, str] = None) -> None:
|
257
|
+
r"""Set up a :class:`.RawBufferLibrary` from a dictionary.
|
262
258
|
|
263
259
|
Basic structure:
|
264
260
|
|
@@ -288,7 +284,7 @@ class RawBufferLibrary(dict):
|
|
288
284
|
to the first and last integer keys in a contiguous range (e.g. of
|
289
285
|
channels) that get stored to the same buffer. These simply get
|
290
286
|
replaced with the explicit list of integers in the range. We use
|
291
|
-
lists not tuples for
|
287
|
+
lists not tuples for config file format compliance.
|
292
288
|
* The ``name`` can include ``{key:xxx}`` format specifiers, indicating
|
293
289
|
that each key in ``key_list`` should be given its own buffer with the
|
294
290
|
corresponding name. The same specifier can appear in ``out_path`` to
|
@@ -307,18 +303,18 @@ class RawBufferLibrary(dict):
|
|
307
303
|
|
308
304
|
Parameters
|
309
305
|
----------
|
310
|
-
|
311
|
-
loaded from a
|
312
|
-
`
|
306
|
+
config
|
307
|
+
loaded from a config file written in the allowed shorthand.
|
308
|
+
`config` is changed by this function.
|
313
309
|
kw_dict
|
314
310
|
dictionary of keyword-value pairs for substitutions into the
|
315
311
|
``out_stream`` and ``out_name`` fields.
|
316
312
|
"""
|
317
|
-
for list_name in
|
313
|
+
for list_name in config:
|
318
314
|
if list_name not in self:
|
319
315
|
self[list_name] = RawBufferList()
|
320
|
-
self[list_name].
|
321
|
-
|
316
|
+
self[list_name].set_from_dict(
|
317
|
+
config[list_name], {} if kw_dict is None else kw_dict
|
322
318
|
)
|
323
319
|
|
324
320
|
def get_list_of(self, attribute: str, unique: bool = True) -> list:
|
@@ -352,26 +348,26 @@ class RawBufferLibrary(dict):
|
|
352
348
|
rb_list.clear_full()
|
353
349
|
|
354
350
|
|
355
|
-
def
|
356
|
-
"""Expand shorthands in a
|
351
|
+
def expand_rblist_dict(config: dict, kw_dict: dict[str, str]) -> None:
|
352
|
+
"""Expand shorthands in a dictionary representing a
|
357
353
|
:class:`.RawBufferList`.
|
358
354
|
|
359
|
-
See :meth:`.RawBufferLibrary.
|
355
|
+
See :meth:`.RawBufferLibrary.set_from_dict` for details.
|
360
356
|
|
361
357
|
Notes
|
362
358
|
-----
|
363
|
-
The input
|
359
|
+
The input dictionary is changed by this function.
|
364
360
|
"""
|
365
361
|
# get the original list of groups because we are going to change the
|
366
|
-
# dict.keys() of
|
362
|
+
# dict.keys() of config inside the next list. Note: we have to convert
|
367
363
|
# from dict_keys to list here otherwise the loop complains about changing
|
368
364
|
# the dictionary during iteration
|
369
|
-
buffer_names = list(
|
365
|
+
buffer_names = list(config.keys())
|
370
366
|
for name in buffer_names:
|
371
367
|
if name == "":
|
372
368
|
raise ValueError("buffer name can't be empty")
|
373
369
|
|
374
|
-
info =
|
370
|
+
info = config[name] # changes to info will change config[name]
|
375
371
|
# make sure we have a key list
|
376
372
|
if "key_list" not in info:
|
377
373
|
raise ValueError(f"'{name}' is missing key_list")
|
@@ -399,12 +395,12 @@ def expand_rblist_json_dict(json_dict: dict, kw_dict: dict[str, str]) -> None:
|
|
399
395
|
continue # will be handled later, once the key_list is known
|
400
396
|
for key in info["key_list"]:
|
401
397
|
expanded_name = name.format(key=key)
|
402
|
-
|
403
|
-
|
404
|
-
|
398
|
+
config[expanded_name] = info.copy()
|
399
|
+
config[expanded_name]["key_list"] = [key]
|
400
|
+
config.pop(name)
|
405
401
|
|
406
402
|
# now re-iterate and expand out_paths
|
407
|
-
for name, info in
|
403
|
+
for name, info in config.items():
|
408
404
|
if len(info["key_list"]) == 1 and not (
|
409
405
|
isinstance(info["key_list"][0], str) and "*" in info["key_list"][0]
|
410
406
|
):
|
daq2lh5/utils.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import json
|
4
|
+
import logging
|
5
|
+
from pathlib import Path
|
6
|
+
|
7
|
+
import yaml
|
8
|
+
|
9
|
+
log = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
__file_extensions__ = {"json": [".json"], "yaml": [".yaml", ".yml"]}
|
13
|
+
|
14
|
+
|
15
|
+
def load_dict(fname: str, ftype: str | None = None) -> dict:
|
16
|
+
"""Load a text file as a Python dict."""
|
17
|
+
fname = Path(fname)
|
18
|
+
|
19
|
+
# determine file type from extension
|
20
|
+
if ftype is None:
|
21
|
+
for _ftype, exts in __file_extensions__.items():
|
22
|
+
if fname.suffix in exts:
|
23
|
+
ftype = _ftype
|
24
|
+
|
25
|
+
msg = f"loading {ftype} dict from: {fname}"
|
26
|
+
log.debug(msg)
|
27
|
+
|
28
|
+
with fname.open() as f:
|
29
|
+
if ftype == "json":
|
30
|
+
return json.load(f)
|
31
|
+
if ftype == "yaml":
|
32
|
+
return yaml.safe_load(f)
|
33
|
+
|
34
|
+
msg = f"unsupported file format {ftype}"
|
35
|
+
raise NotImplementedError(msg)
|
@@ -1,14 +1,15 @@
|
|
1
1
|
daq2lh5/__init__.py,sha256=VPmwKuZSA0icpce05ojhnsKWhR4_QUgD0oVXUoN9wks,975
|
2
|
-
daq2lh5/_version.py,sha256=
|
3
|
-
daq2lh5/build_raw.py,sha256=
|
2
|
+
daq2lh5/_version.py,sha256=R8-T9fmURjcuoxYpHTAjyNAhgJPDtI2jogCjqYYkfCU,411
|
3
|
+
daq2lh5/build_raw.py,sha256=SDpdOU8qpfzMtx8gtFu-RZYqxutQo1smJSkv-LrH9YE,10672
|
4
4
|
daq2lh5/cli.py,sha256=7bPfH1XbyAS48wZn_0unj4Y5MD5kF7V34Q5srn4jKVM,2913
|
5
5
|
daq2lh5/data_decoder.py,sha256=Cn40fodfKs7pKa2odzG1j806iw9IyQVfbbWObNGmof8,10677
|
6
6
|
daq2lh5/data_streamer.py,sha256=WuyqneVg8Kf7V072aUWYT5q3vmPZoobjAZ7oSw0sC9k,14187
|
7
7
|
daq2lh5/logging.py,sha256=rYNeToaZBTCaIiC42a4CUroAo1PCOreTXbpEZyMO8Fo,987
|
8
|
-
daq2lh5/raw_buffer.py,sha256=
|
8
|
+
daq2lh5/raw_buffer.py,sha256=LfkVAOZa4cWz227Ef22rKi57Shk7GbENoxUEkxC6IgU,17403
|
9
|
+
daq2lh5/utils.py,sha256=Pc8Oh0ZVBqwwVehyhSJttHnX5tWbOyEZPk-rVg8mb0c,839
|
9
10
|
daq2lh5/buffer_processor/__init__.py,sha256=7k6v_KPximtv7805QnX4-xp_S3vqvqwDfdV3q95oZJo,84
|
10
11
|
daq2lh5/buffer_processor/buffer_processor.py,sha256=GUxpNDbqGLuUEZmXjeratipbzmki12RFNYZkxgMtesg,14483
|
11
|
-
daq2lh5/buffer_processor/lh5_buffer_processor.py,sha256=
|
12
|
+
daq2lh5/buffer_processor/lh5_buffer_processor.py,sha256=einRDLI6EVR-U_TT2GdCZPctFnosJ774eMiUj-ahn6c,8316
|
12
13
|
daq2lh5/compass/__init__.py,sha256=mOXHWp7kRDgNTPQty3E8k2KPSy_vAzjneKfAcCVaPyE,132
|
13
14
|
daq2lh5/compass/compass_config_parser.py,sha256=zeAsOo1dOJPGLL8-zkAcdYRkqt8BodtOPi96n7fWsl4,12300
|
14
15
|
daq2lh5/compass/compass_event_decoder.py,sha256=kiPOaEu8SgLD2wbSPbBahcbTBBRAIw35wtVLBcwPcXY,7386
|
@@ -32,9 +33,9 @@ daq2lh5/orca/orca_header_decoder.py,sha256=ORIIyfx22ybyKc-uyWy5ER49-dl3BGpHdfV8O
|
|
32
33
|
daq2lh5/orca/orca_packet.py,sha256=nOHuBXsTI1SzTjHZtff0txSQYvkwo4XGx3fpk7XfYj8,2489
|
33
34
|
daq2lh5/orca/orca_run_decoder.py,sha256=3atKXC6mDi8_PK6ICUBBJ-LyaTM8OU31kKWIpmttRr4,2065
|
34
35
|
daq2lh5/orca/orca_streamer.py,sha256=VbD9PF-rx_Rk-rEy7XECPmgxr6kZSUf0tC7Qbol3Qeg,15693
|
35
|
-
legend_daq2lh5-1.
|
36
|
-
legend_daq2lh5-1.
|
37
|
-
legend_daq2lh5-1.
|
38
|
-
legend_daq2lh5-1.
|
39
|
-
legend_daq2lh5-1.
|
40
|
-
legend_daq2lh5-1.
|
36
|
+
legend_daq2lh5-1.4.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
37
|
+
legend_daq2lh5-1.4.0.dist-info/METADATA,sha256=SKEW8u7wRrCK5zTY01iMGDYGPmrmg1ED5g9fsbwLVVA,3956
|
38
|
+
legend_daq2lh5-1.4.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
39
|
+
legend_daq2lh5-1.4.0.dist-info/entry_points.txt,sha256=R08R4NrHi0ab5MJN_qKqzePVzrLSsw5WpmbiwwduYjw,59
|
40
|
+
legend_daq2lh5-1.4.0.dist-info/top_level.txt,sha256=MJQVLyLqMgMKBdVfNXFaCKCjHKakAs19VLbC9ctXZ7A,8
|
41
|
+
legend_daq2lh5-1.4.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|