def test_global_peak_window_sum(camera_waveforms): waveforms, _ = camera_waveforms extractor = GlobalPeakWindowSum() charge, pulse_time = extractor(waveforms) assert_allclose(charge[0][0], 232.559, rtol=1e-3) assert_allclose(charge[1][0], 425.406, rtol=1e-3) assert_allclose(pulse_time[0][0], 47.823488, rtol=1e-3) assert_allclose(pulse_time[1][0], 62.931829, rtol=1e-3)
def test_global_peak_window_sum_with_pixel_fraction(subarray): from ctapipe.image.extractor import GlobalPeakWindowSum tel_id = 1 camera = subarray.tel[tel_id].camera sample_rate = camera.readout.sampling_rate.to_value(u.ns**-1) n_pixels = camera.geometry.n_pixels selected_gain_channel = np.zeros(n_pixels, dtype=np.uint8) bright_pixels = np.zeros(n_pixels, dtype=bool) bright_pixels[np.random.choice(n_pixels, size=int(0.1 * n_pixels))] = True # signal in dim pixels is in slice 10, signal in bright pixels is in slice 30 waveforms = np.zeros((n_pixels, 50), dtype="float64") waveforms[~bright_pixels, 9] = 3 waveforms[~bright_pixels, 10] = 5 waveforms[~bright_pixels, 11] = 2 waveforms[bright_pixels, 29] = 5 waveforms[bright_pixels, 30] = 10 waveforms[bright_pixels, 31] = 3 extractor = GlobalPeakWindowSum( subarray=subarray, window_width=8, window_shift=4, pixel_fraction=0.05, apply_integration_correction=False, ) dl1 = extractor(waveforms=waveforms, telid=tel_id, selected_gain_channel=selected_gain_channel) assert np.allclose(dl1.image[bright_pixels], 18) assert np.allclose(dl1.image[~bright_pixels], 0) expected = np.average([29, 30, 31], weights=[5, 10, 3]) assert np.allclose(dl1.peak_time[bright_pixels], expected / sample_rate)
def test_dl1_charge_calib(example_subarray): # copy because we mutate the camera, should not affect other tests subarray = deepcopy(example_subarray) camera = subarray.tel[1].camera # test with a sampling_rate different than 1 to # test if we handle time vs. slices correctly sampling_rate = 2 camera.readout.sampling_rate = sampling_rate * u.GHz n_pixels = camera.geometry.n_pixels n_samples = 96 mid = n_samples // 2 pulse_sigma = 6 random = np.random.RandomState(1) x = np.arange(n_samples) # Randomize times and create pulses time_offset = random.uniform(-10, +10, n_pixels) y = norm.pdf(x, mid + time_offset[:, np.newaxis], pulse_sigma).astype("float32") camera.readout.reference_pulse_shape = norm.pdf(x, mid, pulse_sigma)[np.newaxis, :] camera.readout.reference_pulse_sample_width = 1 / camera.readout.sampling_rate # Define absolute calibration coefficients absolute = random.uniform(100, 1000, n_pixels).astype("float32") y *= absolute[:, np.newaxis] # Define relative coefficients relative = random.normal(1, 0.01, n_pixels) y /= relative[:, np.newaxis] # Define pedestal pedestal = random.uniform(-4, 4, n_pixels) y += pedestal[:, np.newaxis] event = ArrayEventContainer() telid = list(subarray.tel.keys())[0] event.dl0.tel[telid].waveform = y event.dl0.tel[telid].selected_gain_channel = np.zeros(len(y), dtype=int) event.r1.tel[telid].selected_gain_channel = np.zeros(len(y), dtype=int) # Test default calibrator = CameraCalibrator( subarray=subarray, image_extractor=FullWaveformSum(subarray=subarray)) calibrator(event) np.testing.assert_allclose(event.dl1.tel[telid].image, y.sum(1), rtol=1e-4) event.calibration.tel[telid].dl1.pedestal_offset = pedestal event.calibration.tel[telid].dl1.absolute_factor = absolute event.calibration.tel[telid].dl1.relative_factor = relative # Test without timing corrections calibrator(event) dl1 = event.dl1.tel[telid] np.testing.assert_allclose(dl1.image, 1, rtol=1e-5) expected_peak_time = (mid + time_offset) / sampling_rate np.testing.assert_allclose(dl1.peak_time, expected_peak_time, rtol=1e-5) # test with timing corrections event.calibration.tel[telid].dl1.time_shift = time_offset / sampling_rate calibrator(event) # more rtol since shifting might lead to reduced integral np.testing.assert_allclose(event.dl1.tel[telid].image, 1, rtol=1e-5) np.testing.assert_allclose(event.dl1.tel[telid].peak_time, mid / sampling_rate, atol=1) # test not applying time shifts # now we should be back to the result without setting time shift calibrator.apply_peak_time_shift = False calibrator.apply_waveform_time_shift = False calibrator(event) np.testing.assert_allclose(event.dl1.tel[telid].image, 1, rtol=1e-4) np.testing.assert_allclose(event.dl1.tel[telid].peak_time, expected_peak_time, atol=1) # We now use GlobalPeakWindowSum to see the effect of missing charge # due to not correcting time offsets. calibrator = CameraCalibrator( subarray=subarray, image_extractor=GlobalPeakWindowSum(subarray=subarray)) calibrator(event) # test with timing corrections, should work # higher rtol because we cannot shift perfectly np.testing.assert_allclose(event.dl1.tel[telid].image, 1, rtol=0.01) np.testing.assert_allclose(event.dl1.tel[telid].peak_time, mid / sampling_rate, atol=1) # test deactivating timing corrections calibrator.apply_waveform_time_shift = False calibrator(event) # make sure we chose an example where the time shifts matter # charges should be quite off due to summing around global shift assert not np.allclose(event.dl1.tel[telid].image, 1, rtol=0.1) assert not np.allclose( event.dl1.tel[telid].peak_time, mid / sampling_rate, atol=1)