Skip to content

Commit a44ec2b

Browse files
committed
Add a component to reduce waveform readout window
1 parent 4e55c3e commit a44ec2b

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

src/ctapipe/image/reducer.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from abc import abstractmethod
6+
from copy import deepcopy
67

78
import numpy as np
89

@@ -214,3 +215,39 @@ def select_pixels(self, waveforms, tel_id=None, selected_gain_channel=None):
214215
mask = dilate(camera_geom, mask)
215216

216217
return mask
218+
219+
220+
class ReadoutWindowReducer(TelescopeComponent):
221+
"""
222+
Reduce the readout window size of telescope using a fixed window.
223+
"""
224+
225+
window_start = IntTelescopeParameter(
226+
default_value=None,
227+
allow_none=True,
228+
help="Start sample of readout window",
229+
).tag(config=True)
230+
231+
window_end = IntTelescopeParameter(
232+
default_value=None,
233+
allow_none=True,
234+
help="Last sample of readout window (non-inclusive)",
235+
).tag(config=True)
236+
237+
def __init__(self, subarray, **kwargs):
238+
# we mutate the subarray, make sure we do not modify it for someone else
239+
super().__init__(deepcopy(subarray), **kwargs)
240+
241+
for tel_id, tel in self.subarray.tel.items():
242+
start = self.window_start.tel[tel_id]
243+
end = self.window_end.tel[tel_id]
244+
n_samples = len(np.arange(tel.camera.readout.n_samples)[start:end])
245+
tel.camera.readout.n_samples = n_samples
246+
247+
def __call__(self, event):
248+
for container in (event.r0, event.r1, event.dl0):
249+
for tel_id, tel_container in container.tel.items():
250+
if tel_container.waveform is not None:
251+
start = self.window_start.tel[tel_id]
252+
end = self.window_end.tel[tel_id]
253+
tel_container.waveform = tel_container.waveform[start:end]

src/ctapipe/image/tests/test_reducer.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from copy import deepcopy
2+
13
import astropy.units as u
24
import numpy as np
35
import pytest
@@ -6,6 +8,7 @@
68

79
from ctapipe.image.reducer import NullDataVolumeReducer, TailCutsDataVolumeReducer
810
from ctapipe.instrument import SubarrayDescription
11+
from ctapipe.io import EventSource
912

1013

1114
@pytest.fixture(scope="module")
@@ -92,3 +95,67 @@ def test_tailcuts_data_volume_reducer(subarray_lst):
9295

9396
assert (reduced_waveforms != 0).sum() == (1 + 4 + 14) * n_samples
9497
assert_array_equal(expected_waveforms, reduced_waveforms)
98+
99+
100+
def test_readout_window_reducer(prod5_gamma_simtel_path):
101+
from ctapipe.image.reducer import ReadoutWindowReducer
102+
103+
def check(subarray, event, event_reduced, event_no_op):
104+
checked = 0
105+
for dl in ("r0", "r1", "dl0"):
106+
for tel_id in getattr(event, dl).tel.keys():
107+
if str(subarray.tel[tel_id]).startswith("LST"):
108+
start = 10
109+
end = 20
110+
elif str(subarray.tel[tel_id]).startswith("MST"):
111+
start = 15
112+
end = 40
113+
else:
114+
start = None
115+
end = None
116+
117+
original_waveform = getattr(event, dl).tel[tel_id].waveform
118+
reduced_waveform = getattr(event_reduced, dl).tel[tel_id].waveform
119+
no_op_waveform = getattr(event_no_op, dl).tel[tel_id].waveform
120+
121+
np.testing.assert_array_equal(original_waveform, no_op_waveform)
122+
np.testing.assert_array_equal(
123+
original_waveform[start:end], reduced_waveform
124+
)
125+
126+
checked += 1
127+
return checked
128+
129+
with EventSource(prod5_gamma_simtel_path) as source:
130+
reducer_no_op = ReadoutWindowReducer(source.subarray)
131+
reducer = ReadoutWindowReducer(
132+
source.subarray,
133+
window_start=[
134+
("type", "*", None),
135+
("type", "LST*", 10),
136+
("type", "MST*", 15),
137+
],
138+
window_end=[
139+
("type", "*", None),
140+
("type", "LST*", 20),
141+
("type", "MST*", 40),
142+
],
143+
)
144+
145+
# make sure we didn't modify the original subarray
146+
assert source.subarray.tel[1].camera.readout.n_samples == 40
147+
assert reducer_no_op.subarray.tel[1].camera.readout.n_samples == 40
148+
# new subarray should have reduced window
149+
assert reducer.subarray.tel[1].camera.readout.n_samples == 10
150+
151+
n_checked = 0
152+
for event in source:
153+
event_no_op = deepcopy(event)
154+
event_reduced = deepcopy(event)
155+
156+
reducer(event_reduced)
157+
reducer_no_op(event_no_op)
158+
159+
n_checked += check(source.subarray, event, event_reduced, event_no_op)
160+
161+
assert n_checked > 0

0 commit comments

Comments
 (0)