reboost 0.4.3__tar.gz → 0.5.1__tar.gz

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.
Files changed (76) hide show
  1. {reboost-0.4.3 → reboost-0.5.1}/PKG-INFO +2 -2
  2. {reboost-0.4.3 → reboost-0.5.1}/pyproject.toml +1 -1
  3. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/__init__.py +4 -0
  4. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/_version.py +2 -2
  5. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/build_evt.py +2 -2
  6. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/build_glm.py +4 -3
  7. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/build_hit.py +6 -9
  8. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/cli.py +0 -3
  9. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/iterator.py +6 -2
  10. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/convolve.py +3 -3
  11. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/create.py +2 -3
  12. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/evt.py +4 -5
  13. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/utils.py +3 -1
  14. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/PKG-INFO +2 -2
  15. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/SOURCES.txt +1 -3
  16. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/requires.txt +1 -1
  17. {reboost-0.4.3 → reboost-0.5.1}/tests/conftest.py +2 -0
  18. {reboost-0.4.3 → reboost-0.5.1}/tests/hit/configs/basic.yaml +0 -2
  19. {reboost-0.4.3 → reboost-0.5.1}/tests/hit/configs/hit_config.yaml +8 -4
  20. {reboost-0.4.3 → reboost-0.5.1}/tests/hit/configs/pars.yaml +2 -2
  21. reboost-0.5.1/tests/hit/configs/reshape.yaml +11 -0
  22. reboost-0.5.1/tests/hit/test_build_hit.py +219 -0
  23. reboost-0.5.1/tests/test_cli.py +81 -0
  24. {reboost-0.4.3 → reboost-0.5.1}/tests/test_utils.py +4 -4
  25. reboost-0.4.3/src/reboost/build_tcm.py +0 -111
  26. reboost-0.4.3/tests/hit/test_build_hit.py +0 -126
  27. reboost-0.4.3/tests/hit/test_files/beta_small.lh5 +0 -0
  28. reboost-0.4.3/tests/hit/test_files/beta_small_hit.lh5 +0 -0
  29. reboost-0.4.3/tests/test_cli.py +0 -49
  30. {reboost-0.4.3 → reboost-0.5.1}/LICENSE +0 -0
  31. {reboost-0.4.3 → reboost-0.5.1}/README.md +0 -0
  32. {reboost-0.4.3 → reboost-0.5.1}/setup.cfg +0 -0
  33. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/core.py +0 -0
  34. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/hpge/__init__.py +0 -0
  35. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/hpge/psd.py +0 -0
  36. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/hpge/surface.py +0 -0
  37. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/hpge/utils.py +0 -0
  38. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/log_utils.py +0 -0
  39. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/math/__init__.py +0 -0
  40. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/math/functions.py +0 -0
  41. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/math/stats.py +0 -0
  42. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/__init__.py +0 -0
  43. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/cli.py +0 -0
  44. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/mapview.py +0 -0
  45. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/numba_pdg.py +0 -0
  46. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/optmap/optmap.py +0 -0
  47. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/profile.py +0 -0
  48. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/shape/__init__.py +0 -0
  49. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/shape/cluster.py +0 -0
  50. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/shape/group.py +0 -0
  51. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/shape/reduction.py +0 -0
  52. {reboost-0.4.3 → reboost-0.5.1}/src/reboost/units.py +0 -0
  53. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/dependency_links.txt +0 -0
  54. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/entry_points.txt +0 -0
  55. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/not-zip-safe +0 -0
  56. {reboost-0.4.3 → reboost-0.5.1}/src/reboost.egg-info/top_level.txt +0 -0
  57. {reboost-0.4.3 → reboost-0.5.1}/tests/glm/test_build_glm.py +0 -0
  58. {reboost-0.4.3 → reboost-0.5.1}/tests/hit/configs/args.yaml +0 -0
  59. {reboost-0.4.3 → reboost-0.5.1}/tests/hit/configs/geom.gdml +0 -0
  60. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/simulation/gammas.mac +0 -0
  61. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/simulation/geometry.gdml +0 -0
  62. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/simulation/make_dt_map.jl +0 -0
  63. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/simulation/make_geom.py +0 -0
  64. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_current.py +0 -0
  65. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_dt_heuristic.py +0 -0
  66. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_files/drift_time_maps.lh5 +0 -0
  67. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_files/internal_electron.lh5 +0 -0
  68. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_hpge_map.py +0 -0
  69. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_r90.py +0 -0
  70. {reboost-0.4.3 → reboost-0.5.1}/tests/hpge/test_surface.py +0 -0
  71. {reboost-0.4.3 → reboost-0.5.1}/tests/test_core.py +0 -0
  72. {reboost-0.4.3 → reboost-0.5.1}/tests/test_math.py +0 -0
  73. {reboost-0.4.3 → reboost-0.5.1}/tests/test_optmap.py +0 -0
  74. {reboost-0.4.3 → reboost-0.5.1}/tests/test_profile.py +0 -0
  75. {reboost-0.4.3 → reboost-0.5.1}/tests/test_shape.py +0 -0
  76. {reboost-0.4.3 → reboost-0.5.1}/tests/test_units.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reboost
3
- Version: 0.4.3
3
+ Version: 0.5.1
4
4
  Summary: New LEGEND Monte-Carlo simulation post-processing
5
5
  Author-email: Manuel Huber <info@manuelhu.de>, Toby Dixon <toby.dixon.23@ucl.ac.uk>, Luigi Pertoldi <gipert@pm.me>
6
6
  Maintainer: The LEGEND Collaboration
@@ -700,7 +700,7 @@ Requires-Dist: colorlog
700
700
  Requires-Dist: numpy
701
701
  Requires-Dist: scipy
702
702
  Requires-Dist: numba
703
- Requires-Dist: legend-pydataobj>=1.11.10
703
+ Requires-Dist: legend-pydataobj>=1.12.0
704
704
  Requires-Dist: legend-pygeom-optics>=0.6.5
705
705
  Requires-Dist: hist
706
706
  Requires-Dist: dbetto
@@ -36,7 +36,7 @@ dependencies = [
36
36
  "numpy",
37
37
  "scipy",
38
38
  "numba",
39
- "legend-pydataobj>=1.11.10",
39
+ "legend-pydataobj>=1.12.0",
40
40
  "legend-pygeom-optics>=0.6.5",
41
41
  "hist",
42
42
  "dbetto",
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from lgdo import lh5
4
+
3
5
  from . import build_hit, core, iterator, math, shape
4
6
  from ._version import version as __version__
5
7
 
@@ -15,3 +17,5 @@ __all__ = [
15
17
  "optmap",
16
18
  "shape",
17
19
  ]
20
+
21
+ lh5.settings.DEFAULT_HDF5_SETTINGS = {"shuffle": True, "compression": "lzf"}
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.4.3'
21
- __version_tuple__ = version_tuple = (0, 4, 3)
20
+ __version__ = version = '0.5.1'
21
+ __version_tuple__ = version_tuple = (0, 5, 1)
@@ -102,9 +102,9 @@ def build_evt(
102
102
  elif isinstance(info, list):
103
103
  channels[group] = info
104
104
 
105
- for tcm_lh5, _, n_rows_read in LH5Iterator(tcm_file, "tcm", buffer_len=buffer):
105
+ for tcm_lh5 in LH5Iterator(tcm_file, "tcm", buffer_len=buffer):
106
106
  tcm_lh5_sel = tcm_lh5
107
- tcm_ak = tcm_lh5_sel.view_as("ak")[:n_rows_read]
107
+ tcm_ak = tcm_lh5_sel.view_as("ak")
108
108
 
109
109
  tcm = TCMData(
110
110
  id=np.array(ak.flatten(tcm_ak.array_id)),
@@ -146,13 +146,14 @@ def get_stp_evtids(
146
146
 
147
147
  while start_row < n_rows_tot:
148
148
  # read the file
149
- lh5_obj, n_read = store.read(
149
+ lh5_obj = store.read(
150
150
  f"{lh5_table}/{id_name}",
151
151
  stp_file,
152
152
  start_row=start_row,
153
153
  n_rows=stp_buffer,
154
154
  )
155
155
  evtids = lh5_obj.view_as("ak")
156
+ n_read = len(evtids)
156
157
 
157
158
  # pick the first evtid
158
159
  if evtids.ndim > 1:
@@ -247,9 +248,9 @@ def build_glm(
247
248
  vfield = f"vtx/{id_name}"
248
249
 
249
250
  # iterate over the vertex table
250
- for vert_obj, vidx, n_evtid in LH5Iterator(stp_file, vfield, buffer_len=evtid_buffer):
251
+ for vidx, vert_obj in enumerate(LH5Iterator(stp_file, vfield, buffer_len=evtid_buffer)):
251
252
  # range of vertices
252
- vert_ak = vert_obj.view_as("ak")[:n_evtid]
253
+ vert_ak = vert_obj.view_as("ak")
253
254
 
254
255
  msg = f"... read chunk {vidx}"
255
256
  log.debug(msg)
@@ -41,10 +41,6 @@ A :func:`build_hit` to parse the following configuration file:
41
41
  phyvol: OBJECTS.geometry.physical_volume_dict[DETECTOR]
42
42
  drift_time_map: lgdo.lh5.read(DETECTOR, ARGS.dtmap_file)
43
43
 
44
- # this defines "hits", i.e. layout of the output hit table
45
- # group steps by time and evtid with 10us window
46
- hit_table_layout: reboost.shape.group_by_time(STEPS, window=10)
47
-
48
44
  # finally, the processing chain
49
45
  operations:
50
46
 
@@ -190,7 +186,6 @@ def build_hit(
190
186
  *,
191
187
  start_evtid: int = 0,
192
188
  n_evtid: int | None = None,
193
- in_field: str = "stp",
194
189
  out_field: str = "hit",
195
190
  buffer: int = int(5e6),
196
191
  overwrite: bool = False,
@@ -214,8 +209,6 @@ def build_hit(
214
209
  first evtid to read.
215
210
  n_evtid
216
211
  number of evtid to read, if `None` read all.
217
- in_field
218
- name of the input field in the remage output.
219
212
  out_field
220
213
  name of the output field
221
214
  buffer
@@ -280,13 +273,17 @@ def build_hit(
280
273
  time_dict=time_dict[proc_name],
281
274
  )
282
275
 
276
+ lh5_group = proc_group.get("lh5_group", "stp")
277
+ if lh5_group is None:
278
+ lh5_group = "/"
279
+
283
280
  # begin iterating over the glm
284
281
  iterator = GLMIterator(
285
282
  glm_file,
286
283
  stp_file,
287
284
  lh5_group=in_detector,
288
285
  start_row=start_evtid,
289
- stp_field=in_field,
286
+ stp_field=lh5_group,
290
287
  n_rows=n_evtid,
291
288
  buffer=buffer,
292
289
  time_dict=time_dict[proc_name],
@@ -396,7 +393,7 @@ def build_hit(
396
393
  lh5.read(obj, stp_file),
397
394
  obj,
398
395
  files.hit[file_idx],
399
- wo_mode="write_safe",
396
+ wo_mode="write_safe" if file_idx == 0 else "append",
400
397
  )
401
398
  except LH5EncodeError as e:
402
399
  msg = f"cannot forward object {obj} as it has been already processed by reboost"
@@ -103,7 +103,6 @@ def cli(args=None) -> None:
103
103
  hit_parser.add_argument(
104
104
  "--n-evtid", type=int, default=None, help="Number of event id to process."
105
105
  )
106
- hit_parser.add_argument("--in-field", type=str, default="stp", help="Input field name.")
107
106
  hit_parser.add_argument("--out-field", type=str, default="hit", help="Output field name.")
108
107
  hit_parser.add_argument("--buffer", type=int, default=int(5e6), help="Buffer size.")
109
108
 
@@ -174,7 +173,6 @@ def cli(args=None) -> None:
174
173
  msg += f" hit files: {hit_files}\n"
175
174
  msg += f" start_evtid: {args.start_evtid}\n"
176
175
  msg += f" n_evtid: {args.n_evtid}\n"
177
- msg += f" in_field: {args.in_field}\n"
178
176
  msg += f" out_field: {args.out_field}\n"
179
177
  msg += f" buffer: {args.buffer} \n"
180
178
  msg += f" overwrite: {args.overwrite} \n"
@@ -189,7 +187,6 @@ def cli(args=None) -> None:
189
187
  hit_files=hit_files,
190
188
  start_evtid=args.start_evtid,
191
189
  n_evtid=args.n_evtid,
192
- in_field=args.in_field,
193
190
  out_field=args.out_field,
194
191
  buffer=args.buffer,
195
192
  overwrite=args.overwrite,
@@ -139,12 +139,14 @@ class GLMIterator:
139
139
 
140
140
  if self.use_glm:
141
141
  if self.glm_file is not None:
142
- glm_rows, n_rows_read = self.sto.read(
142
+ glm_rows = self.sto.read(
143
143
  f"glm/{self.lh5_group}",
144
144
  self.glm_file,
145
145
  start_row=self.start_row_tmp,
146
146
  n_rows=n_rows,
147
147
  )
148
+ n_rows_read = len(glm_rows.view_as("ak"))
149
+
148
150
  else:
149
151
  # get the maximum row to read
150
152
  max_row = self.start_row_tmp + n_rows
@@ -198,12 +200,14 @@ class GLMIterator:
198
200
  time_start = time.time()
199
201
 
200
202
  try:
201
- stp_rows, n_steps = self.sto.read(
203
+ stp_rows = self.sto.read(
202
204
  f"{self.stp_field}/{self.lh5_group}",
203
205
  self.stp_file,
204
206
  start_row=int(start),
205
207
  n_rows=int(n),
206
208
  )
209
+ n_steps = len(stp_rows.view_as("ak"))
210
+
207
211
  except OverflowError:
208
212
  raise StopIteration from None
209
213
 
@@ -356,9 +356,9 @@ def convolve(
356
356
 
357
357
  log.info("opening energy deposition hit output %s", edep_file)
358
358
  it = LH5Iterator(edep_file, edep_path, buffer_len=buffer_len)
359
- for it_count, (edep_lgdo, edep_events, edep_n_rows) in enumerate(it):
360
- assert (it_count == 0) == (edep_events == 0)
361
- edep_df = edep_lgdo.view_as("pd").iloc[0:edep_n_rows].to_records()
359
+
360
+ for it_count, edep_lgdo in enumerate(it):
361
+ edep_df = edep_lgdo.view_as("pd").iloc.to_records()
362
362
 
363
363
  log.info("start event processing (%d)", it_count)
364
364
  output_map = iterate_stepwise_depositions(
@@ -130,9 +130,8 @@ def _create_optical_maps_chunk(
130
130
 
131
131
  hits_per_primary = np.zeros(10, dtype=np.int64)
132
132
  hits_per_primary_len = 0
133
- for it_count, (events_lgdo, events_entry, event_n_rows) in enumerate(optmap_events_it):
134
- assert (it_count == 0) == (events_entry == 0)
135
- optmap_events = events_lgdo.view_as("pd").iloc[0:event_n_rows]
133
+ for it_count, events_lgdo in enumerate(optmap_events_it):
134
+ optmap_events = events_lgdo.view_as("pd").iloc
136
135
  hitcounts = optmap_events[all_det_ids].to_numpy()
137
136
  loc = optmap_events[["xloc", "yloc", "zloc"]].to_numpy()
138
137
 
@@ -80,8 +80,8 @@ def build_optmap_evt(
80
80
  _store_vert_df()
81
81
 
82
82
  # read the next vertex chunk into memory.
83
- (vert_lgdo, vert_entry, vert_n_rows) = next(vert_it)
84
- vert_df = vert_lgdo.view_as("pd").iloc[0:vert_n_rows]
83
+ (vert_lgdo, vert_entry) = next(vert_it)
84
+ vert_df = vert_lgdo.view_as("pd").iloc
85
85
 
86
86
  # prepare vertex coordinates.
87
87
  vert_df = vert_df.set_index("evtid", drop=True).drop(["n_part", "time"], axis=1)
@@ -94,9 +94,8 @@ def build_optmap_evt(
94
94
  log.info("prepare evt table")
95
95
  # use smaller integer type uint8 to spare RAM when storing types.
96
96
  hit_count_type = np.uint8
97
- for opti_it_count, (opti_lgdo, opti_entry, opti_n_rows) in enumerate(opti_it):
98
- assert (opti_it_count == 0) == (opti_entry == 0)
99
- opti_df = opti_lgdo.view_as("pd").iloc[0:opti_n_rows]
97
+ for opti_it_count, opti_lgdo in enumerate(opti_it):
98
+ opti_df = opti_lgdo.view_as("pd").iloc
100
99
 
101
100
  log.info("build evt table (%d)", opti_it_count)
102
101
  for t in opti_df[["evtid", "det_uid"]].itertuples(name=None, index=False):
@@ -30,7 +30,9 @@ def get_wo_mode(
30
30
  return "overwrite_file" if overwrite else "write_safe"
31
31
 
32
32
  # if we have a detector not the first and chunk 0 append column
33
- if ((in_det > 0) or (out_det > 0)) & (chunk == 0):
33
+ is_append = ((in_det > 0) or (out_det > 0)) & (chunk == 0)
34
+ is_append = is_append or (in_det == 0 and out_det == 0 and chunk == 0 and group > 0)
35
+ if is_append:
34
36
  return "append_column"
35
37
  return "append"
36
38
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reboost
3
- Version: 0.4.3
3
+ Version: 0.5.1
4
4
  Summary: New LEGEND Monte-Carlo simulation post-processing
5
5
  Author-email: Manuel Huber <info@manuelhu.de>, Toby Dixon <toby.dixon.23@ucl.ac.uk>, Luigi Pertoldi <gipert@pm.me>
6
6
  Maintainer: The LEGEND Collaboration
@@ -700,7 +700,7 @@ Requires-Dist: colorlog
700
700
  Requires-Dist: numpy
701
701
  Requires-Dist: scipy
702
702
  Requires-Dist: numba
703
- Requires-Dist: legend-pydataobj>=1.11.10
703
+ Requires-Dist: legend-pydataobj>=1.12.0
704
704
  Requires-Dist: legend-pygeom-optics>=0.6.5
705
705
  Requires-Dist: hist
706
706
  Requires-Dist: dbetto
@@ -6,7 +6,6 @@ src/reboost/_version.py
6
6
  src/reboost/build_evt.py
7
7
  src/reboost/build_glm.py
8
8
  src/reboost/build_hit.py
9
- src/reboost/build_tcm.py
10
9
  src/reboost/cli.py
11
10
  src/reboost/core.py
12
11
  src/reboost/iterator.py
@@ -56,8 +55,7 @@ tests/hit/configs/basic.yaml
56
55
  tests/hit/configs/geom.gdml
57
56
  tests/hit/configs/hit_config.yaml
58
57
  tests/hit/configs/pars.yaml
59
- tests/hit/test_files/beta_small.lh5
60
- tests/hit/test_files/beta_small_hit.lh5
58
+ tests/hit/configs/reshape.yaml
61
59
  tests/hpge/test_current.py
62
60
  tests/hpge/test_dt_heuristic.py
63
61
  tests/hpge/test_hpge_map.py
@@ -2,7 +2,7 @@ colorlog
2
2
  numpy
3
3
  scipy
4
4
  numba
5
- legend-pydataobj>=1.11.10
5
+ legend-pydataobj>=1.12.0
6
6
  legend-pygeom-optics>=0.6.5
7
7
  hist
8
8
  dbetto
@@ -12,6 +12,8 @@ from legendtestdata import LegendTestData
12
12
 
13
13
  _tmptestdir = Path(gettempdir()) / f"reboost-tests-{getuser()}-{uuid.uuid4()!s}"
14
14
 
15
+ collect_ignore = ["test_optmap.py"]
16
+
15
17
 
16
18
  @pytest.fixture(scope="session")
17
19
  def tmptestdir_global():
@@ -9,8 +9,6 @@ processing_groups:
9
9
  - evtid
10
10
  - energy
11
11
 
12
- hit_table_layout: reboost.shape.group.group_by_time(STEPS, window=10)
13
-
14
12
  operations:
15
13
  t0: ak.fill_none(ak.firsts(HITS.time, axis=-1), np.nan)
16
14
  first_evtid: ak.fill_none(ak.firsts(HITS.evtid, axis=-1), np.nan)
@@ -7,8 +7,8 @@ processing_groups:
7
7
  - name: geds
8
8
 
9
9
  detector_mapping:
10
- - output: det001
11
- - output: det002
10
+ - output: det1
11
+ - output: det2
12
12
  detector_objects:
13
13
  meta: dbetto.AttrsDict(pygeomtools.get_sensvol_metadata(OBJECTS.geometry,
14
14
  OBJECTS.user_pars[DETECTOR].name ))
@@ -24,8 +24,6 @@ processing_groups:
24
24
  - active_energy
25
25
  - smeared_energy
26
26
 
27
- hit_table_layout: reboost.shape.group.group_by_evtid(STEPS)
28
-
29
27
  operations:
30
28
  t0: ak.fill_none(ak.firsts(HITS.time, axis=-1), np.nan)
31
29
  first_evtid: ak.fill_none(ak.firsts(HITS.evtid, axis=-1), np.nan)
@@ -44,3 +42,9 @@ processing_groups:
44
42
 
45
43
  active_energy: ak.sum(HITS.edep*HITS.activeness, axis=-1)
46
44
  smeared_energy: reboost.math.stats.gaussian_sample(HITS.active_energy,DETECTOR_OBJECTS.det_pars.reso_in_sigma)
45
+
46
+ - name: vtx
47
+ detector_mapping:
48
+ - output: vtx
49
+
50
+ lh5_group: null
@@ -1,9 +1,9 @@
1
- det001:
1
+ det1:
2
2
  fccd_in_mm: 0.71
3
3
  dlf: 0.7
4
4
  reso_in_sigma: 1.1
5
5
  name: BEGe
6
- det002:
6
+ det2:
7
7
  fccd_in_mm: 2.2
8
8
  dlf: 0.4
9
9
  reso_in_sigma: 2.32
@@ -0,0 +1,11 @@
1
+ processing_groups:
2
+ - name: all
3
+
4
+ detector_mapping:
5
+ - output: det1
6
+ - output: det2
7
+
8
+ hit_table_layout: "reboost.shape.group.group_by_time(STEPS, 10)"
9
+
10
+ forward:
11
+ - /vtx
@@ -0,0 +1,219 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ from pathlib import Path
5
+
6
+ import awkward as ak
7
+ import dbetto
8
+ import h5py
9
+ import pytest
10
+ from lgdo import Array, Struct, Table, VectorOfVectors, lh5
11
+
12
+ import reboost
13
+
14
+
15
+ @pytest.fixture(scope="module")
16
+ def test_gen_lh5(tmptestdir):
17
+ # write a basic lh5 file
18
+
19
+ stp_path = str(tmptestdir / "basic.lh5")
20
+
21
+ data = {}
22
+ data["evtid"] = VectorOfVectors([[0, 0], [1, 1, 1]])
23
+ data["edep"] = VectorOfVectors([[100, 200], [10, 20, 300]]) # keV
24
+ data["time"] = VectorOfVectors([[0, 1.5], [0.1, 2.1, 3.7]]) # ns
25
+
26
+ data["xloc"] = VectorOfVectors([[0.01, 0.02], [0.001, 0.003, 0.005]]) # m
27
+ data["yloc"] = VectorOfVectors([[0.01, 0.02], [0.001, 0.003, 0.005]]) # m
28
+ data["zloc"] = VectorOfVectors([[0.04, 0.02], [0.001, 0.023, 0.005]]) # m
29
+ data["dist_to_surf"] = VectorOfVectors([[0.04, 0.02], [0.011, 0.003, 0.051]]) # m
30
+
31
+ vertices = [0, 1]
32
+ tab = Table(data)
33
+ tab2 = copy.deepcopy(tab)
34
+
35
+ lh5.write(tab, "stp/det1", stp_path, wo_mode="of")
36
+ lh5.write(tab2, "stp/det2", stp_path, wo_mode="append")
37
+ lh5.write(
38
+ Table({"evtid": Array(vertices)}),
39
+ "vtx",
40
+ stp_path,
41
+ wo_mode="append",
42
+ )
43
+
44
+ return stp_path
45
+
46
+
47
+ @pytest.fixture(scope="module")
48
+ def test_gen_lh5_flat(tmptestdir):
49
+ # write a basic lh5 file
50
+
51
+ stp_path = str(tmptestdir / "basic_flat.lh5")
52
+
53
+ data = {}
54
+ data["evtid"] = Array([0, 0, 1, 1, 1])
55
+ data["edep"] = Array([100, 200, 10, 20, 300]) # keV
56
+ data["time"] = Array([0, 1.5, 0.1, 2.1, 3.7]) # ns
57
+
58
+ data["xloc"] = Array([0.01, 0.02, 0.001, 0.003, 0.005]) # m
59
+ data["yloc"] = Array([0.01, 0.02, 0.001, 0.003, 0.005]) # m
60
+ data["zloc"] = Array([0.04, 0.02, 0.001, 0.023, 0.005]) # m
61
+ data["dist_to_surf"] = Array([0.04, 0.02, 0.011, 0.003, 0.051]) # m
62
+
63
+ vertices = [0, 1]
64
+ tab = Table(data)
65
+ tab2 = copy.deepcopy(tab)
66
+
67
+ lh5.write(tab, "stp/det1", stp_path, wo_mode="of")
68
+ lh5.write(tab2, "stp/det2", stp_path, wo_mode="append")
69
+ lh5.write(
70
+ Table({"evtid": Array(vertices)}),
71
+ "vtx",
72
+ stp_path,
73
+ wo_mode="append",
74
+ )
75
+
76
+ return stp_path
77
+
78
+
79
+ def test_reshape(test_gen_lh5_flat, tmptestdir):
80
+ outfile = f"{tmptestdir}/basic_hit_reshaped.lh5"
81
+
82
+ reboost.build_hit.build_hit(
83
+ f"{Path(__file__).parent}/configs/reshape.yaml",
84
+ args={},
85
+ stp_files=test_gen_lh5_flat,
86
+ glm_files=None,
87
+ hit_files=outfile,
88
+ out_field="stp",
89
+ overwrite=True,
90
+ )
91
+
92
+ data = {}
93
+ data["evtid"] = VectorOfVectors([[0, 0], [1, 1, 1]])
94
+ data["edep"] = VectorOfVectors([[100, 200], [10, 20, 300]]) # keV
95
+ data["time"] = VectorOfVectors([[0, 1.5], [0.1, 2.1, 3.7]]) # ns
96
+
97
+ data["xloc"] = VectorOfVectors([[0.01, 0.02], [0.001, 0.003, 0.005]]) # m
98
+ data["yloc"] = VectorOfVectors([[0.01, 0.02], [0.001, 0.003, 0.005]]) # m
99
+ data["zloc"] = VectorOfVectors([[0.04, 0.02], [0.001, 0.023, 0.005]]) # m
100
+ data["dist_to_surf"] = VectorOfVectors([[0.04, 0.02], [0.011, 0.003, 0.051]]) # m
101
+ tab = Table(data)
102
+
103
+ output = lh5.read("stp/det1", outfile)
104
+
105
+ # check the outputs
106
+ assert output == tab
107
+ assert lh5.read("vtx", outfile) == Table({"evtid": Array([0, 1])})
108
+
109
+
110
+ def test_basic(test_gen_lh5, tmptestdir):
111
+ outfile = f"{tmptestdir}/basic_hit.lh5"
112
+
113
+ reboost.build_hit.build_hit(
114
+ f"{Path(__file__).parent}/configs/basic.yaml",
115
+ args={},
116
+ stp_files=test_gen_lh5,
117
+ glm_files=None,
118
+ hit_files=outfile,
119
+ overwrite=True,
120
+ )
121
+
122
+ assert lh5.ls(outfile) == ["hit", "vtx"]
123
+
124
+ with h5py.File(outfile) as h5f:
125
+ assert h5f["/hit/det1/energy"].shuffle is True
126
+ assert h5f["/hit/det1/energy"].compression == "lzf"
127
+
128
+ hits = lh5.read("hit/det1", outfile).view_as("ak")
129
+
130
+ assert ak.all(hits.energy == [300, 330])
131
+ assert ak.all(hits.t0 == [0, 0.1])
132
+ assert ak.all(hits.evtid[0] == [0, 0])
133
+ assert ak.all(hits.evtid[1] == [1, 1, 1])
134
+
135
+ assert len(hits) == 2
136
+
137
+ # test in memory
138
+
139
+ hits, time_dict = reboost.build_hit.build_hit(
140
+ f"{Path(__file__).parent}/configs/basic.yaml",
141
+ args={},
142
+ stp_files=test_gen_lh5,
143
+ glm_files=None,
144
+ hit_files=None,
145
+ )
146
+
147
+ assert ak.all(hits["det1"].energy == [300, 330])
148
+ assert ak.all(hits["det1"].t0 == [0, 0.1])
149
+ assert ak.all(hits["det1"].evtid[0] == [0, 0])
150
+ assert ak.all(hits["det1"].evtid[1] == [1, 1, 1])
151
+
152
+ assert set(time_dict.keys()) == {"global_objects", "geds"}
153
+ assert set(time_dict["geds"].keys()) == {
154
+ "detector_objects",
155
+ "read",
156
+ "conv",
157
+ "expressions",
158
+ }
159
+ assert set(time_dict["geds"]["read"].keys()) == {"stp"}
160
+ assert set(time_dict["geds"]["expressions"].keys()) == {"t0", "first_evtid", "energy"}
161
+
162
+
163
+ def test_file_merging(test_gen_lh5, tmptestdir):
164
+ outfile = f"{tmptestdir}/basic_hit_merged.lh5"
165
+
166
+ reboost.build_hit.build_hit(
167
+ f"{Path(__file__).parent}/configs/basic.yaml",
168
+ args={},
169
+ stp_files=[test_gen_lh5, test_gen_lh5],
170
+ glm_files=None,
171
+ hit_files=outfile,
172
+ overwrite=True,
173
+ )
174
+
175
+ assert lh5.ls(outfile) == ["hit", "vtx"]
176
+
177
+ hits = lh5.read("hit/det1", outfile).view_as("ak")
178
+
179
+ assert len(hits) == 4
180
+
181
+
182
+ def test_full_chain(test_gen_lh5, tmptestdir):
183
+ args = dbetto.AttrsDict(
184
+ {
185
+ "gdml": f"{Path(__file__).parent}/configs/geom.gdml",
186
+ "pars": f"{Path(__file__).parent}/configs/pars.yaml",
187
+ }
188
+ )
189
+
190
+ _, time_dict = reboost.build_hit.build_hit(
191
+ f"{Path(__file__).parent}/configs/hit_config.yaml",
192
+ args=args,
193
+ stp_files=test_gen_lh5,
194
+ glm_files=None,
195
+ hit_files=str(tmptestdir / "beta_small_hit.lh5"),
196
+ overwrite=True,
197
+ )
198
+ hits = lh5.read("hit", str(tmptestdir / "beta_small_hit.lh5"))
199
+
200
+ assert isinstance(hits, Struct)
201
+
202
+ assert set(hits["det1"].view_as("ak").fields) == {
203
+ "evtid",
204
+ "t0",
205
+ "truth_energy",
206
+ "active_energy",
207
+ "smeared_energy",
208
+ }
209
+ assert set(hits["det2"].view_as("ak").fields) == {
210
+ "evtid",
211
+ "t0",
212
+ "truth_energy",
213
+ "active_energy",
214
+ "smeared_energy",
215
+ }
216
+
217
+ # also check the processing of the vtx table
218
+
219
+ assert hits["vtx"] == Table({"evtid": Array([0, 1])})
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+ from lgdo import Array, Table, lh5
8
+
9
+ from reboost.cli import cli
10
+
11
+
12
+ @pytest.fixture(scope="module")
13
+ def test_gen_lh5_flat(tmptestdir):
14
+ # write a basic lh5 file
15
+
16
+ stp_path = str(tmptestdir / "basic_flat.lh5")
17
+
18
+ data = {}
19
+ data["evtid"] = Array([0, 0, 1, 1, 1])
20
+ data["edep"] = Array([100, 200, 10, 20, 300]) # keV
21
+ data["time"] = Array([0, 1.5, 0.1, 2.1, 3.7]) # ns
22
+
23
+ data["xloc"] = Array([0.01, 0.02, 0.001, 0.003, 0.005]) # m
24
+ data["yloc"] = Array([0.01, 0.02, 0.001, 0.003, 0.005]) # m
25
+ data["zloc"] = Array([0.04, 0.02, 0.001, 0.023, 0.005]) # m
26
+ data["dist_to_surf"] = Array([0.04, 0.02, 0.011, 0.003, 0.051]) # m
27
+
28
+ vertices = [0, 1]
29
+ tab = Table(data)
30
+ tab2 = copy.deepcopy(tab)
31
+
32
+ lh5.write(tab, "stp/det1", stp_path, wo_mode="of")
33
+ lh5.write(tab2, "stp/det2", stp_path, wo_mode="append")
34
+ lh5.write(
35
+ Table({"evtid": Array(vertices)}),
36
+ "vtx",
37
+ stp_path,
38
+ wo_mode="append",
39
+ )
40
+
41
+ return stp_path
42
+
43
+
44
+ def test_cli(tmptestdir, test_gen_lh5_flat):
45
+ test_file_dir = Path(__file__).parent / "hit"
46
+
47
+ # test cli for build_glm
48
+ cli(
49
+ [
50
+ "build-glm",
51
+ "--id-name",
52
+ "evtid",
53
+ "-w",
54
+ "--glm-file",
55
+ f"{tmptestdir}/glm.lh5",
56
+ "--stp-file",
57
+ test_gen_lh5_flat,
58
+ ]
59
+ )
60
+
61
+ glm = lh5.read("glm/det1", f"{tmptestdir}/glm.lh5").view_as("ak")
62
+ assert glm.fields == ["evtid", "n_rows", "start_row"]
63
+
64
+ # test cli for build_hit
65
+ cli(
66
+ [
67
+ "build-hit",
68
+ "--config",
69
+ f"{test_file_dir}/configs/reshape.yaml",
70
+ "-w",
71
+ "--stp-file",
72
+ test_gen_lh5_flat,
73
+ "--hit-file",
74
+ f"{tmptestdir}/hit.lh5",
75
+ "--args",
76
+ f"{test_file_dir}/configs/args.yaml",
77
+ ]
78
+ )
79
+
80
+ hit1 = lh5.read("hit/det1", f"{tmptestdir}/hit.lh5").view_as("ak")
81
+ assert set(hit1.fields) == {"xloc", "yloc", "zloc", "dist_to_surf", "time", "edep", "evtid"}
@@ -118,10 +118,10 @@ def test_save_dict(tmp_path):
118
118
 
119
119
 
120
120
  def test_wo_mode():
121
- assert get_wo_mode(0, 0, 0, 0, True, overwrite=True) == "of"
122
- assert get_wo_mode(0, 0, 0, 0, True, overwrite=False) == "w"
123
- assert get_wo_mode(0, 0, 1, 0, True, overwrite=False) == "ac"
124
- assert get_wo_mode(0, 0, 1, 1, True, overwrite=False) == "a"
121
+ assert get_wo_mode(0, 0, 0, 0, True, overwrite=True) == "overwrite_file"
122
+ assert get_wo_mode(0, 0, 0, 0, True, overwrite=False) == "write_safe"
123
+ assert get_wo_mode(0, 0, 1, 0, True, overwrite=False) == "append_column"
124
+ assert get_wo_mode(0, 0, 1, 1, True, overwrite=False) == "append"
125
125
 
126
126
 
127
127
  def test_get_files_dict():
@@ -1,111 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import logging
4
- import re
5
-
6
- import awkward as ak
7
- from lgdo import Table, lh5
8
-
9
- from .shape import group
10
-
11
- log = logging.getLogger(__name__)
12
-
13
-
14
- def build_tcm(
15
- hit_file: str,
16
- out_file: str,
17
- channels: list[str],
18
- time_name: str = "t0",
19
- idx_name: str = "global_evtid",
20
- time_window_in_us: float = 10,
21
- ) -> None:
22
- """Build the (Time Coincidence Map) TCM from the hit tier.
23
-
24
- Parameters
25
- ----------
26
- hit_file
27
- path to hit tier file.
28
- out_file
29
- output path for tcm.
30
- channels
31
- list of channel names to include.
32
- time_name
33
- name of the hit tier field used for time grouping.
34
- idx_name
35
- name of the hit tier field used for index grouping.
36
- time_window_in_us
37
- time window used to define the grouping.
38
- """
39
- hash_func = r"\d+"
40
-
41
- msg = "start building time-coincidence map"
42
- log.info(msg)
43
-
44
- chan_ids = [re.search(hash_func, channel).group() for channel in channels]
45
-
46
- hit_data = []
47
- for channel in channels:
48
- hit_data.append(
49
- lh5.read(f"{channel}/hit", hit_file, field_mask=[idx_name, time_name]).view_as("ak")
50
- )
51
- tcm = get_tcm_from_ak(
52
- hit_data, chan_ids, window=time_window_in_us, time_name=time_name, idx_name=idx_name
53
- )
54
-
55
- if tcm is not None:
56
- lh5.write(tcm, "tcm", out_file, wo_mode="overwrite_file")
57
-
58
-
59
- def get_tcm_from_ak(
60
- hit_data: list[ak.Array],
61
- channels: list[int],
62
- *,
63
- window: float = 10,
64
- time_name: str = "t0",
65
- idx_name: str = "global_evtid",
66
- ) -> Table:
67
- """Builds a time-coincidence map from a hit of hit data Tables.
68
-
69
- - build an ak.Array of the data merging channels with fields base on "time_name", and "idx_name" and adding a field `rawid` from the channel idx, also add the row (`hit_idx`)
70
- - sorts this array by "idx_name" then "time_name" fields
71
- - group by "idx_name" and "time_name" based on the window parameter
72
-
73
- Parameters
74
- ----------
75
- hit_data
76
- list of hit tier data for each channel
77
- channels
78
- list of channel indices
79
- window
80
- time window for selecting coincidences (in us)
81
- time_name
82
- name of the field for time information
83
- idx_name
84
- name of the decay index field
85
-
86
- Returns
87
- -------
88
- an LGDO.VectorOfVectors containing the time-coincidence map
89
- """
90
- # build ak_obj for sorting
91
- sort_objs = []
92
-
93
- for ch_idx, data_tmp in zip(channels, hit_data):
94
- obj_tmp = ak.copy(data_tmp)
95
- obj_tmp = obj_tmp[[time_name, idx_name]]
96
- hit_idx = ak.local_index(obj_tmp)
97
-
98
- obj_tmp = ak.with_field(obj_tmp, hit_idx, "array_idx")
99
-
100
- obj_tmp["array_id"] = int(ch_idx)
101
- sort_objs.append(obj_tmp)
102
-
103
- obj_tot = ak.concatenate(sort_objs)
104
-
105
- return group.group_by_time(
106
- obj_tot,
107
- time_name=time_name,
108
- evtid_name=idx_name,
109
- window=window,
110
- fields=["array_id", "array_idx"],
111
- )
@@ -1,126 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
-
5
- import awkward as ak
6
- import dbetto
7
- import pytest
8
- from lgdo import Array, Struct, Table, lh5
9
-
10
- import reboost
11
- from reboost.build_glm import build_glm
12
-
13
-
14
- @pytest.fixture(scope="module")
15
- def test_gen_lh5(tmptestdir):
16
- # write a basic lh5 file
17
-
18
- stp_path = str(tmptestdir / "basic.lh5")
19
- glm_path = str(tmptestdir / "basic_glm.lh5")
20
-
21
- evtid = [0, 0, 1, 1, 1]
22
- edep = [100, 200, 10, 20, 300] # keV
23
- time = [0, 1.5, 0.1, 2.1, 3.7] # ns
24
- vertices = [0, 1]
25
- tab = Table({"evtid": Array(evtid), "edep": Array(edep), "time": Array(time)})
26
- lh5.write(tab, "stp/det1", stp_path, wo_mode="of")
27
- lh5.write(
28
- Table({"evtid": Array(vertices)}),
29
- "vtx",
30
- stp_path,
31
- wo_mode="append",
32
- )
33
-
34
- build_glm(stp_path, glm_path, id_name="evtid")
35
-
36
- return stp_path, glm_path
37
-
38
-
39
- def test_basic(test_gen_lh5, tmptestdir):
40
- stp_path, glm_path = test_gen_lh5
41
-
42
- reboost.build_hit.build_hit(
43
- f"{Path(__file__).parent}/configs/basic.yaml",
44
- args={},
45
- stp_files=stp_path,
46
- glm_files=glm_path,
47
- hit_files=f"{tmptestdir}/basic_hit.lh5",
48
- overwrite=True,
49
- )
50
-
51
- assert lh5.ls(f"{tmptestdir}/basic_hit.lh5") == ["hit", "vtx"]
52
-
53
- hits = lh5.read("hit/det1", f"{tmptestdir}/basic_hit.lh5").view_as("ak")
54
-
55
- assert ak.all(hits.energy == [300, 330])
56
- assert ak.all(hits.t0 == [0, 0.1])
57
- assert ak.all(hits.evtid[0] == [0, 0])
58
- assert ak.all(hits.evtid[1] == [1, 1, 1])
59
-
60
- # test in memory
61
-
62
- hits, time_dict = reboost.build_hit.build_hit(
63
- f"{Path(__file__).parent}/configs/basic.yaml",
64
- args={},
65
- stp_files=stp_path,
66
- glm_files=glm_path,
67
- hit_files=None,
68
- )
69
-
70
- assert ak.all(hits["det1"].energy == [300, 330])
71
- assert ak.all(hits["det1"].t0 == [0, 0.1])
72
- assert ak.all(hits["det1"].evtid[0] == [0, 0])
73
- assert ak.all(hits["det1"].evtid[1] == [1, 1, 1])
74
-
75
- assert list(time_dict.keys()) == ["global_objects", "geds"]
76
- assert list(time_dict["geds"].keys()) == [
77
- "detector_objects",
78
- "read",
79
- "conv",
80
- "hit_layout",
81
- "expressions",
82
- ]
83
- assert list(time_dict["geds"]["read"].keys()) == ["glm", "stp"]
84
- assert list(time_dict["geds"]["expressions"].keys()) == ["t0", "first_evtid", "energy"]
85
-
86
-
87
- def test_full_chain(tmptestdir):
88
- build_glm(
89
- f"{Path(__file__).parent}/test_files/beta_small.lh5",
90
- str(tmptestdir / "beta_small_glm.lh5"),
91
- id_name="evtid",
92
- )
93
-
94
- args = dbetto.AttrsDict(
95
- {
96
- "gdml": f"{Path(__file__).parent}/configs/geom.gdml",
97
- "pars": f"{Path(__file__).parent}/configs/pars.yaml",
98
- }
99
- )
100
-
101
- _, time_dict = reboost.build_hit.build_hit(
102
- f"{Path(__file__).parent}/configs/hit_config.yaml",
103
- args=args,
104
- stp_files=f"{Path(__file__).parent}/test_files/beta_small.lh5",
105
- glm_files=str(tmptestdir / "beta_small_glm.lh5"),
106
- hit_files=str(tmptestdir / "beta_small_hit.lh5"),
107
- overwrite=True,
108
- )
109
- hits = lh5.read("hit", str(tmptestdir / "beta_small_hit.lh5"))
110
-
111
- assert isinstance(hits, Struct)
112
-
113
- assert set(hits["det001"].view_as("ak").fields) == {
114
- "evtid",
115
- "t0",
116
- "truth_energy",
117
- "active_energy",
118
- "smeared_energy",
119
- }
120
- assert set(hits["det002"].view_as("ak").fields) == {
121
- "evtid",
122
- "t0",
123
- "truth_energy",
124
- "active_energy",
125
- "smeared_energy",
126
- }
@@ -1,49 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from pathlib import Path
4
-
5
- from lgdo import lh5
6
-
7
- from reboost.cli import cli
8
-
9
-
10
- def test_cli(tmptestdir):
11
- test_file_dir = Path(__file__).parent / "hit"
12
-
13
- # test cli for build_glm
14
- cli(
15
- [
16
- "build-glm",
17
- "--id-name",
18
- "evtid",
19
- "-w",
20
- "--glm-file",
21
- f"{tmptestdir}/glm.lh5",
22
- "--stp-file",
23
- f"{test_file_dir}/test_files/beta_small.lh5",
24
- ]
25
- )
26
-
27
- glm = lh5.read("glm/det001", f"{tmptestdir}/glm.lh5").view_as("ak")
28
- assert glm.fields == ["evtid", "n_rows", "start_row"]
29
-
30
- # test cli for build_hit
31
- cli(
32
- [
33
- "build-hit",
34
- "--config",
35
- f"{test_file_dir}/configs/hit_config.yaml",
36
- "-w",
37
- "--glm-file",
38
- f"{tmptestdir}/glm.lh5",
39
- "--stp-file",
40
- f"{test_file_dir}/test_files/beta_small.lh5",
41
- "--hit-file",
42
- f"{tmptestdir}/hit.lh5",
43
- "--args",
44
- f"{test_file_dir}/configs/args.yaml",
45
- ]
46
- )
47
-
48
- hit1 = lh5.read("hit/det001", f"{tmptestdir}/hit.lh5").view_as("ak")
49
- assert set(hit1.fields) == {"evtid", "t0", "truth_energy", "active_energy", "smeared_energy"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes