Skip to content

Commit b0c171d

Browse files
authored
Merge pull request #216 from cta-observatory/ctar1_missing_module
Add support for data with missing pixels (offline DVR or missing modules) in EVBv6 / R1v1 format
2 parents 3a4deee + 13e92f0 commit b0c171d

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

src/ctapipe_io_lst/__init__.py

+20-16
Original file line numberDiff line numberDiff line change
@@ -479,27 +479,30 @@ def fill_from_cta_r1(self, array_event, zfits_event):
479479
offset = self.data_stream.waveform_offset
480480
pixel_id_map = self.camera_config.pixel_id_map
481481

482-
# FIXME: missing modules / pixels
483-
# FIXME: DVR? should not happen in r1 but dl0, but our own converter uses the old R1
484-
485482
# reorder to nominal pixel order
486483
pixel_status = _reorder_pixel_status(
487-
zfits_event.pixel_status, pixel_id_map, set_dvr_bits=True
484+
zfits_event.pixel_status, pixel_id_map, set_dvr_bits=not self.dvr_applied,
488485
)
489486

490487
n_channels = zfits_event.num_channels
491-
n_pixels = zfits_event.num_pixels
492488
n_samples = zfits_event.num_samples
493489

490+
if self.dvr_applied:
491+
stored_pixels = (zfits_event.pixel_status & PixelStatus.DVR_STATUS) > 0
492+
n_pixels = np.count_nonzero(stored_pixels)
493+
else:
494+
stored_pixels = slice(None) # all pixels stored
495+
n_pixels = zfits_event.num_pixels
496+
494497
readout_shape = (n_channels, n_pixels, n_samples)
495498
raw_waveform = zfits_event.waveform.reshape(readout_shape)
496499
waveform = raw_waveform.astype(np.float32) / scale - offset
497500

498501
reordered_waveform = np.full((n_channels, N_PIXELS, n_samples), 0.0, dtype=np.float32)
499-
reordered_waveform[:, pixel_id_map] = waveform
502+
reordered_waveform[:, pixel_id_map[stored_pixels]] = waveform
500503
waveform = reordered_waveform
501504

502-
# FIXME, check using evb_preprocessing and make ctapipe support 2 gains
505+
503506
if zfits_event.num_channels == 2:
504507
selected_gain_channel = None
505508
else:
@@ -529,22 +532,23 @@ def fill_from_cta_r1(self, array_event, zfits_event):
529532

530533
if DataLevel.R0 in self.datalevels:
531534
reordered_raw_waveform = np.full((n_channels, N_PIXELS, n_samples), 0, dtype=np.uint16)
532-
reordered_raw_waveform[:, pixel_id_map] = raw_waveform
535+
reordered_raw_waveform[:, pixel_id_map[stored_pixels]] = raw_waveform
533536
array_event.r0.tel[self.tel_id] = R0CameraContainer(
534537
waveform=reordered_raw_waveform,
535538
)
536539

537540
def fill_lst_from_ctar1(self, zfits_event):
541+
pixel_status = _reorder_pixel_status(
542+
zfits_event.pixel_status,
543+
self.pixel_id_map,
544+
set_dvr_bits=not self.dvr_applied,
545+
)
538546
evt = LSTEventContainer(
539-
pixel_status=zfits_event.pixel_status.copy(),
547+
pixel_status=pixel_status,
540548
first_capacitor_id=zfits_event.first_cell_id,
541549
calibration_monitoring_id=zfits_event.calibration_monitoring_id,
542550
local_clock_counter=zfits_event.module_hires_local_clock_counter,
543551
)
544-
# set bits for dvr if not already set
545-
if not self.dvr_applied:
546-
not_broken = get_channel_info(evt.pixel_status) != 0
547-
evt.pixel_status[not_broken] |= PixelStatus.DVR_STATUS_0
548552

549553
if zfits_event.debug is not None:
550554
debug = zfits_event.debug
@@ -971,7 +975,7 @@ def tag_flatfield_events(self, array_event):
971975
'''
972976
tel_id = self.tel_id
973977
waveform = array_event.r1.tel[tel_id].waveform
974-
978+
975979
if waveform.ndim == 3:
976980
image = waveform[HIGH_GAIN].sum(axis=1)
977981
else:
@@ -981,7 +985,7 @@ def tag_flatfield_events(self, array_event):
981985
n_in_range = np.count_nonzero(in_range)
982986

983987
looks_like_ff = n_in_range >= self.min_flatfield_pixel_fraction * image.size
984-
988+
985989
if looks_like_ff:
986990
# Tag as FF only events with 2-gains waveforms: both gains are needed for calibration
987991
if waveform.ndim == 3:
@@ -1091,7 +1095,7 @@ def fill_r0r1_camera_container(self, zfits_event):
10911095
if CTAPIPE_0_20:
10921096
# reorder to nominal pixel order
10931097
pixel_status = _reorder_pixel_status(
1094-
zfits_event.pixel_status, pixel_id_map, set_dvr_bits=True
1098+
zfits_event.pixel_status, pixel_id_map, set_dvr_bits=not self.dvr_applied
10951099
)
10961100
r1.pixel_status = pixel_status
10971101
r1.event_time = cta_high_res_to_time(

src/ctapipe_io_lst/tests/test_lsteventsource.py

+30
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
test_r0_path_all_streams = test_r0_dir / 'LST-1.1.Run02008.0000_first50.fits.fz'
2222

2323
test_missing_module_path = test_data / 'real/R0/20210215/LST-1.1.Run03669.0000_first50.fits.fz'
24+
test_missing_module_r1v1_path = test_data / 'real/R0/20240310/LST-1.1.Run17016.0000_first10.fits.fz'
2425

2526
test_drive_report = test_data / 'real/monitoring/DrivePositioning/DrivePosition_log_20200218.txt'
2627

@@ -142,6 +143,35 @@ def test_missing_modules():
142143
assert np.all(event.r0.tel[1].waveform[:, 514] == fill)
143144

144145

146+
def test_missing_modules_r1v1():
147+
from ctapipe_io_lst import LSTEventSource
148+
source = LSTEventSource(
149+
test_missing_module_r1v1_path,
150+
apply_drs4_corrections=False,
151+
pointing_information=False,
152+
)
153+
154+
assert source.lst_service.telescope_id == 1
155+
assert source.lst_service.num_modules == 264
156+
157+
n_events = 0
158+
for event in source:
159+
n_events += 1
160+
# one module missing, so 7 pixels
161+
assert np.count_nonzero(event.mon.tel[1].pixel_status.hardware_failing_pixels) == N_PIXELS_MODULE * N_GAINS
162+
assert np.count_nonzero(event.r0.tel[1].waveform == 0.0) == N_PIXELS_MODULE * N_SAMPLES * N_GAINS
163+
164+
missing_gain, missing_pixel = np.nonzero(event.mon.tel[1].pixel_status.hardware_failing_pixels)
165+
# 514 is one of the missing pixels
166+
for gain, pixel in zip(missing_gain, missing_pixel):
167+
np.testing.assert_equal(event.r0.tel[1].waveform[gain, pixel], 0.0)
168+
169+
if CTAPIPE_0_20:
170+
np.testing.assert_equal(event.lst.tel[1].evt.pixel_status, event.r1.tel[1].pixel_status)
171+
172+
assert n_events == 40
173+
174+
145175
def test_gain_selected():
146176
from ctapipe_io_lst import LSTEventSource
147177

0 commit comments

Comments
 (0)