Beispiel #1
0
def test_waveform_model():
    from ctapipe.image.toymodel import Gaussian

    geom = CameraGeometry.from_name("CHEC")
    readout = CameraReadout.from_name("CHEC")

    ref_duration = 67
    n_ref_samples = 100
    pulse_sigma = 3
    ref_x_norm = np.linspace(0, ref_duration, n_ref_samples)
    ref_y_norm = norm.pdf(ref_x_norm, ref_duration / 2, pulse_sigma)

    readout.reference_pulse_shape = ref_y_norm[np.newaxis, :]
    readout.reference_pulse_sample_width = u.Quantity(
        ref_x_norm[1] - ref_x_norm[0], u.ns)
    readout.sampling_rate = u.Quantity(2, u.GHz)

    centroid_x = u.Quantity(0.05, u.m)
    centroid_y = u.Quantity(0.05, u.m)
    length = u.Quantity(0.03, u.m)
    width = u.Quantity(0.008, u.m)
    psi = u.Quantity(70, u.deg)
    time_gradient = u.Quantity(50, u.ns / u.m)
    time_intercept = u.Quantity(20, u.ns)

    _, charge, _ = Gaussian(x=centroid_x,
                            y=centroid_y,
                            width=width,
                            length=length,
                            psi=psi).generate_image(geom, 10000)
    time = obtain_time_image(
        geom.pix_x,
        geom.pix_y,
        centroid_x,
        centroid_y,
        psi,
        time_gradient,
        time_intercept,
    )
    time[charge == 0] = 0

    waveform_model = WaveformModel.from_camera_readout(readout)
    waveform = waveform_model.get_waveform(charge, time, 96)
    np.testing.assert_allclose(waveform.sum(axis=1), charge, rtol=1e-3)
    np.testing.assert_allclose(waveform.argmax(axis=1) /
                               readout.sampling_rate.to_value(u.GHz),
                               time,
                               rtol=1e-1)

    time_2 = time + 1
    time_2[charge == 0] = 0
    waveform_2 = waveform_model.get_waveform(charge, time_2, 96)
    np.testing.assert_allclose(waveform_2.sum(axis=1), charge, rtol=1e-3)
    np.testing.assert_allclose(
        waveform_2.argmax(axis=1) / readout.sampling_rate.to_value(u.GHz),
        time_2,
        rtol=1e-1,
    )
    assert (waveform_2.argmax(axis=1)[charge != 0] >
            waveform.argmax(axis=1)[charge != 0]).all()
Beispiel #2
0
def test_sw_pulse_lst():
    """
    Test function of sliding window extractor for LST camera pulse shape with
    the correction for the integration window completeness
    """

    # prepare array with 1 LST
    subarray = SubarrayDescription(
        "LST1",
        tel_positions={1: np.zeros(3) * u.m},
        tel_descriptions={
            1:
            TelescopeDescription.from_name(optics_name="LST",
                                           camera_name="LSTCam")
        },
    )

    telid = list(subarray.tel.keys())[0]

    n_pixels = subarray.tel[telid].camera.geometry.n_pixels
    n_samples = 40
    readout = subarray.tel[telid].camera.readout

    random = np.random.RandomState(1)
    min_charge = 100
    max_charge = 1000
    charge_true = random.uniform(min_charge, max_charge, n_pixels)
    time_true = random.uniform(n_samples // 2 - 1, n_samples // 2 + 1,
                               n_pixels) / readout.sampling_rate.to_value(
                                   u.GHz)

    waveform_model = WaveformModel.from_camera_readout(readout)
    waveform = waveform_model.get_waveform(charge_true, time_true, n_samples)
    selected_gain_channel = np.zeros(charge_true.size, dtype=np.int8)

    # define extractor
    config = Config({"SlidingWindowMaxSum": {"window_width": 8}})
    extractor = SlidingWindowMaxSum(subarray=subarray)
    extractor = ImageExtractor.from_name("SlidingWindowMaxSum",
                                         subarray=subarray,
                                         config=config)

    dl1: DL1CameraContainer = extractor(waveform, telid, selected_gain_channel)
    print(dl1.image / charge_true)
    assert_allclose(dl1.image, charge_true, rtol=0.02)
    assert dl1.is_valid
Beispiel #3
0
def toymodel(subarray):
    telid = list(subarray.tel.keys())[0]
    n_pixels = subarray.tel[telid].camera.geometry.n_pixels
    n_samples = 96
    readout = subarray.tel[telid].camera.readout

    random = np.random.RandomState(1)
    charge = random.uniform(100, 1000, n_pixels)
    mid = (n_samples // 2) / readout.sampling_rate.to_value(u.GHz)
    time = random.uniform(mid - 1, mid + 1, n_pixels)

    waveform_model = WaveformModel.from_camera_readout(readout)
    waveform = waveform_model.get_waveform(charge, time, n_samples)

    selected_gain_channel = np.zeros(charge.size, dtype=np.int)

    return waveform, subarray, telid, selected_gain_channel, charge, time
Beispiel #4
0
def test_Two_pass_window_sum_no_noise(subarray_1_LST):

    rng = np.random.default_rng(0)

    subarray = subarray_1_LST

    camera = subarray.tel[1].camera
    geometry = camera.geometry
    readout = camera.readout
    sampling_rate = readout.sampling_rate.to_value("GHz")
    n_samples = 30  # LSTCam & NectarCam specific
    max_time_readout = (n_samples / sampling_rate) * u.ns

    # True image settings
    x = 0.0 * u.m
    y = 0.0 * u.m
    length = 0.2 * u.m
    width = 0.05 * u.m
    psi = 45.0 * u.deg
    skewness = 0.0
    # build the true time evolution in a way that
    # the whole image is about the readout window
    time_gradient = u.Quantity(max_time_readout.value / length.value,
                               u.ns / u.m)
    time_intercept = u.Quantity(max_time_readout.value / 2, u.ns)
    intensity = 600
    nsb_level_pe = 0

    # create the image
    m = SkewedGaussian(x, y, length, width, psi, skewness)
    true_charge, true_signal, true_noise = m.generate_image(
        geometry, intensity=intensity, nsb_level_pe=nsb_level_pe, rng=rng)
    signal_pixels = true_signal > 2
    # create a pulse-times image without noise
    # we can make new functions later
    time_noise = rng.uniform(0, 0, geometry.n_pixels)
    time_signal = obtain_time_image(geometry.pix_x, geometry.pix_y, x, y, psi,
                                    time_gradient, time_intercept)

    true_charge[(time_signal < 0) | (time_signal >
                                     (n_samples / sampling_rate))] = 0

    true_time = np.average(
        np.column_stack([time_noise, time_signal]),
        weights=np.column_stack([true_noise, true_signal]) + 1,
        axis=1,
    )

    # Define the model for the waveforms to fill with the information from
    # the simulated image
    waveform_model = WaveformModel.from_camera_readout(readout)
    waveforms = waveform_model.get_waveform(true_charge, true_time, n_samples)
    selected_gain_channel = np.zeros(true_charge.size, dtype=np.int64)

    # Define the extractor
    extractor = TwoPassWindowSum(subarray=subarray)

    # Select the signal pixels for which the integration window is well inside
    # the readout window (in this case we should require more accuracy)
    true_peaks = np.rint(true_time * sampling_rate).astype(np.int64)

    # integration of 5 samples centered on peak + 1 sample of error
    # to not be really on the edge
    min_good_sample = 2 + 1
    max_good_sample = n_samples - 1 - min_good_sample
    integration_window_inside = (true_peaks >= min_good_sample) & (
        true_peaks < max_good_sample)

    # Test only the 1st pass
    extractor.disable_second_pass = True
    dl1_pass1 = extractor(waveforms, 1, selected_gain_channel)
    assert_allclose(
        dl1_pass1.image[signal_pixels & integration_window_inside],
        true_charge[signal_pixels & integration_window_inside],
        rtol=0.15,
    )
    assert_allclose(
        dl1_pass1.peak_time[signal_pixels & integration_window_inside],
        true_time[signal_pixels & integration_window_inside],
        rtol=0.15,
    )

    # Test also the 2nd pass
    extractor.disable_second_pass = False
    dl1_pass2 = extractor(waveforms, 1, selected_gain_channel)

    # Check that we have gained signal charge by using the 2nd pass
    # This also checks that the test image has triggered the 2nd pass
    # (i.e. it is not so bad to have <3 pixels in the preliminary cleaned image)
    reco_charge1 = np.sum(dl1_pass1.image[signal_pixels
                                          & integration_window_inside])
    reco_charge2 = np.sum(dl1_pass2.image[signal_pixels
                                          & integration_window_inside])
    # since there is no noise in this test, 1st pass will find the peak and 2nd
    # can at most to the same
    assert (reco_charge2 / reco_charge1) < 1
    assert dl1_pass1.is_valid == True

    # Test only signal pixels for which it is expected to find most of the
    # charge well inside the readout window
    assert_allclose(
        dl1_pass2.image[signal_pixels & integration_window_inside],
        true_charge[signal_pixels & integration_window_inside],
        rtol=0.3,
        atol=2.0,
    )
    assert_allclose(
        dl1_pass2.peak_time[signal_pixels & integration_window_inside],
        true_time[signal_pixels & integration_window_inside],
        rtol=0.3,
        atol=2.0,
    )