Пример #1
0
def main():
    std_config = get_standard_config()

    if args.config_file is not None:
        config = replace_config(std_config, read_configuration_file(args.config_file))
    else:
        config = std_config

    print(config['tailcut'])

    geom = CameraGeometry.from_name('LSTCam-002')
    foclen = OpticsDescription.from_name('LST').equivalent_focal_length
    dl1_container = DL1ParametersContainer()
    parameters_to_update = list(HillasParametersContainer().keys())
    parameters_to_update.extend(['wl', 'r', 'leakage', 'n_islands', 'intercept', 'time_gradient'])

    nodes_keys = get_dataset_keys(args.input_file)
    if args.noimage:
        nodes_keys.remove(dl1_images_lstcam_key)

    auto_merge_h5files([args.input_file], args.output_file, nodes_keys=nodes_keys)

    with tables.open_file(args.input_file, mode='r') as input:
        image_table = input.root[dl1_images_lstcam_key]
        with tables.open_file(args.output_file, mode='a') as output:

            params = output.root[dl1_params_lstcam_key].read()

            for ii, row in enumerate(image_table):
                if ii%10000 == 0:
                    print(ii)
                image = row['image']
                pulse_time = row['pulse_time']
                signal_pixels = tailcuts_clean(geom, image, **config['tailcut'])
                if image[signal_pixels].shape[0] > 0:
                    num_islands, island_labels = number_of_islands(geom, signal_pixels)
                    hillas = hillas_parameters(geom[signal_pixels], image[signal_pixels])

                    dl1_container.fill_hillas(hillas)
                    dl1_container.set_timing_features(geom[signal_pixels],
                                                      image[signal_pixels],
                                                      pulse_time[signal_pixels],
                                                      hillas)
                    dl1_container.set_leakage(geom, image, signal_pixels)
                    dl1_container.n_islands = num_islands
                    dl1_container.wl = dl1_container.width / dl1_container.length
                    width = np.rad2deg(np.arctan2(dl1_container.width, foclen))
                    length = np.rad2deg(np.arctan2(dl1_container.length, foclen))
                    dl1_container.width = width.value
                    dl1_container.length = length.value
                    dl1_container.r = np.sqrt(dl1_container.x**2 + dl1_container.y**2)

                    for p in parameters_to_update:
                        params[ii][p] = Quantity(dl1_container[p]).value
                else:
                    for p in parameters_to_update:
                        params[ii][p] = 0

            output.root[dl1_params_lstcam_key][:] = params
Пример #2
0
def test_largest_island():
    """Test selection of largest island in imagea with given cleaning masks."""

    # Create a simple rectangular camera made of 17 pixels
    camera = CameraGeometry.make_rectangular(17, 1)

    # Assume a simple image (flattened array) made of 0, 1 or 2 photoelectrons
    # [2, 1, 1, 1, 1, 2, 2, 1, 0, 2, 1, 1, 1, 0, 2, 2, 2]
    # Assume a virtual tailcut cleaning that requires:
    # - picture_threshold = 2 photoelectrons,
    # - boundary_threshold = 1 photoelectron,
    # - min_number_picture_neighbors = 0
    # There will be 4 islands left after cleaning:
    clean_mask = np.zeros(camera.n_pixels).astype("bool")  # initialization
    clean_mask[[0, 1]] = 1
    clean_mask[[4, 5, 6, 7]] = 2  # this is the biggest
    clean_mask[[9, 10]] = 3
    clean_mask[[14, 15, 16]] = 4
    # Label islands (their number is not important here)
    _, islands_labels = cleaning.number_of_islands(camera, clean_mask)
    # Create the true mask which takes into account only the biggest island
    # Pixels with no signal are labelled with a 0
    true_mask_largest = np.zeros(camera.n_pixels).astype("bool")
    true_mask_largest[[4, 5, 6, 7]] = 1
    # Apply the function to test
    mask_largest = cleaning.largest_island(islands_labels)

    # Now the degenerate case of only one island surviving
    # Same process as before
    clean_mask_one = np.zeros(camera.n_pixels).astype("bool")
    clean_mask_one[[0, 1]] = 1
    _, islands_labels_one = cleaning.number_of_islands(camera, clean_mask_one)
    true_mask_largest_one = np.zeros(camera.n_pixels).astype("bool")
    true_mask_largest_one[[0, 1]] = 1
    mask_largest_one = cleaning.largest_island(islands_labels_one)

    # Last the case of no islands surviving
    clean_mask_0 = np.zeros(camera.n_pixels).astype("bool")
    _, islands_labels_0 = cleaning.number_of_islands(camera, clean_mask_0)
    true_mask_largest_0 = np.zeros(camera.n_pixels).astype("bool")
    mask_largest_0 = cleaning.largest_island(islands_labels_0)

    # Check if the function recovers the ground truth in all of the three cases
    assert (mask_largest_one == true_mask_largest_one).all()
    assert (mask_largest_0 == true_mask_largest_0).all()
    assert_allclose(mask_largest, true_mask_largest)
Пример #3
0
def test_number_of_islands():
    # test with LST geometry (1855 pixels)
    geom = CameraGeometry.from_name("LSTCam")

    # create 18 triggered pixels grouped to 5 clusters
    island_mask_true = np.zeros(geom.n_pixels)
    mask = np.zeros(geom.n_pixels).astype('bool')
    triggered_pixels = np.array(
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 37, 38, 111, 222])
    island_mask_true[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]] = 1
    island_mask_true[14] = 2
    island_mask_true[[37, 38]] = 3
    island_mask_true[111] = 4
    island_mask_true[222] = 5
    mask[triggered_pixels] = 1

    n_islands, island_mask = cleaning.number_of_islands(geom, mask)
    n_islands_true = 5
    assert n_islands == n_islands_true
    assert_allclose(island_mask, island_mask_true)
Пример #4
0
def test_number_of_islands():
    # test with LST geometry (1855 pixels)
    geom = CameraGeometry.from_name("LSTCam")

    # create 18 triggered pixels grouped to 5 clusters
    island_mask_true = np.zeros(geom.n_pixels)
    mask = np.zeros(geom.n_pixels).astype('bool')
    triggered_pixels = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
                                 14,
                                 37, 38,
                                 111,
                                 222])
    island_mask_true[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]] = 1
    island_mask_true[14] = 2
    island_mask_true[[37, 38]] = 3
    island_mask_true[111] = 4
    island_mask_true[222] = 5
    mask[triggered_pixels] = 1

    n_islands, island_mask = cleaning.number_of_islands(geom, mask)
    n_islands_true = 5
    assert n_islands == n_islands_true
    assert_allclose(island_mask, island_mask_true)
Пример #5
0
 def set_n_islands(self, geom, clean):
     n_islands, islands_mask = number_of_islands(geom, clean)
     self.n_islands = n_islands
Пример #6
0
def get_dl1(
    calibrated_event,
    telescope_id,
    dl1_container=None,
    custom_config={},
    use_main_island=True,
):
    """
    Return a DL1ParametersContainer of extracted features from a calibrated event.
    The DL1ParametersContainer can be passed to be filled if created outside the function
    (faster for multiple event processing)

    Parameters
    ----------
    calibrated_event: ctapipe event container
    telescope_id: `int`
    dl1_container: DL1ParametersContainer
    custom_config: path to a configuration file
        configuration used for tailcut cleaning
        superseeds the standard configuration
    use_main_island: `bool` Use only the main island
        to calculate DL1 parameters

    Returns
    -------
    DL1ParametersContainer
    """

    config = replace_config(standard_config, custom_config)
    cleaning_parameters = config["tailcut"]

    dl1_container = DL1ParametersContainer() if dl1_container is None else dl1_container

    tel = calibrated_event.inst.subarray.tels[telescope_id]
    dl1 = calibrated_event.dl1.tel[telescope_id]
    camera = tel.camera

    image = dl1.image
    pulse_time = dl1.pulse_time

    signal_pixels = cleaning_method(camera, image, **cleaning_parameters)
    n_pixels = np.count_nonzero(signal_pixels)

    if n_pixels > 0:
        # check the number of islands
        num_islands, island_labels = number_of_islands(camera, signal_pixels)

        if use_main_island:
            n_pixels_on_island = np.bincount(island_labels.astype(np.int))
            n_pixels_on_island[0] = 0  # first island is no-island and should not be considered
            max_island_label = np.argmax(n_pixels_on_island)
            signal_pixels[island_labels != max_island_label] = False

        hillas = hillas_parameters(camera[signal_pixels], image[signal_pixels])

        # Fill container
        dl1_container.fill_hillas(hillas)
        dl1_container.fill_event_info(calibrated_event)
        dl1_container.set_mc_core_distance(calibrated_event, telescope_id)
        dl1_container.set_mc_type(calibrated_event)
        dl1_container.set_timing_features(camera[signal_pixels],
                                          image[signal_pixels],
                                          pulse_time[signal_pixels],
                                          hillas)
        dl1_container.set_leakage(camera, image, signal_pixels)
        dl1_container.set_concentration(camera, image, hillas)
        dl1_container.n_pixels = n_pixels
        dl1_container.n_islands = num_islands
        dl1_container.set_telescope_info(calibrated_event, telescope_id)


        return dl1_container

    else:
        return None
def process_event(event, config):
    '''
    Processes
    '''

    reco_algorithm = config.reco_algorithm
    features = {}
    params = {}

    pointing_azimuth = {}
    pointing_altitude = {}

    tel_x = {}
    tel_y = {}
    tel_focal_lengths = {}
    cleaning_method = config.cleaning_method
    valid_cleaning_methods = ['tailcuts_clean', 'fact_image_cleaning']
    if cleaning_method not in valid_cleaning_methods:
        print('Cleaning Method not implemented')
        print('Please use one of ', valid_cleaning_methods)
        return None

    for telescope_id, dl1 in event.dl1.tel.items():
        camera = event.inst.subarray.tels[telescope_id].camera
        if camera.cam_id not in config.allowed_cameras:
            continue

        telescope_type_name = event.inst.subarray.tels[
            telescope_id].optics.tel_type

        if cleaning_method == 'tailcuts_clean':
            boundary_thresh, picture_thresh, min_number_picture_neighbors = config.cleaning_level[
                camera.cam_id]
            mask = tailcuts_clean(camera, dl1.image[0],
                                  *config.cleaning_level[camera.cam_id])

        elif cleaning_method == 'fact_image_cleaning':
            mask = fact_image_cleaning(
                camera, dl1.image[0],
                *config.cleaning_level_fact[camera.cam_id])

        try:
            cleaned = dl1.image[0].copy()
            cleaned[~mask] = 0
            hillas_container = hillas_parameters(
                camera,
                cleaned,
            )
            params[telescope_id] = hillas_container
        except HillasParameterizationError:
            continue
        # probably wise to add try...except blocks here as well
        # Add more Features here (look what ctapipe can do, timing?)
        num_islands, island_labels = number_of_islands(camera, mask)
        island_dict = {
            'num_islands': num_islands,
            'island_labels': island_labels
        }
        leakage_container = leakage(camera, dl1.image[0], mask)
        timing_container = timing_parameters(camera, dl1.image[0],
                                             dl1.peakpos[0], hillas_container)

        pointing_azimuth[
            telescope_id] = event.mc.tel[telescope_id].azimuth_raw * u.rad
        pointing_altitude[
            telescope_id] = event.mc.tel[telescope_id].altitude_raw * u.rad
        tel_x[telescope_id] = event.inst.subarray.positions[telescope_id][0]
        tel_y[telescope_id] = event.inst.subarray.positions[telescope_id][1]

        telescope_description = event.inst.subarray.tel[telescope_id]
        tel_focal_lengths[
            telescope_id] = telescope_description.optics.equivalent_focal_length

        d = {
            'array_event_id': event.dl0.event_id,
            'telescope_id': int(telescope_id),
            'camera_name': camera.cam_id,
            'camera_id': config.names_to_id[camera.cam_id],
            'run_id': event.r0.obs_id,
            'telescope_type_name': telescope_type_name,
            'telescope_type_id': config.types_to_id[telescope_type_name],
            'pointing_azimuth': event.mc.tel[telescope_id].azimuth_raw,
            'pointing_altitude': event.mc.tel[telescope_id].altitude_raw,
            'mirror_area': telescope_description.optics.mirror_area,
            'focal_length':
            telescope_description.optics.equivalent_focal_length,
        }

        d.update(hillas_container.as_dict())
        d.update(leakage_container.as_dict())
        d.update(island_dict)
        d.update(timing_container.as_dict())

        features[telescope_id] = ({k: strip_unit(v) for k, v in d.items()})

    if reco_algorithm == 'intersection':
        reco = HillasIntersection()
        array_direction = SkyCoord(alt=event.mcheader.run_array_direction[1],
                                   az=event.mcheader.run_array_direction[0],
                                   frame='altaz')
        reconstruction = reco.predict(params, tel_x, tel_y, tel_focal_lengths,
                                      array_direction)
    elif reco_algorithm == 'planes':
        reco = HillasReconstructor()
        reconstruction = reco.predict(params, event.inst, pointing_altitude,
                                      pointing_azimuth)

    for telescope_id in event.dl1.tel.keys():
        if telescope_id not in params:
            continue
        camera = event.inst.subarray.tels[telescope_id].camera
        if camera.cam_id not in config.allowed_cameras:
            continue

        pos = event.inst.subarray.positions[telescope_id]
        x, y = pos[0], pos[1]
        core_x = reconstruction.core_x
        core_y = reconstruction.core_y
        d = np.sqrt((core_x - x)**2 + (core_y - y)**2)
        features[telescope_id]['distance_to_core'] = d.value

    return pd.DataFrame(list(features.values())), reconstruction, params
Пример #8
0
        # cleaning
        boundary, picture, min_neighbors = cleaning_level[geom.camera_name]
        clean = tailcuts_clean(geom,
                               image,
                               boundary_thresh=boundary,
                               picture_thresh=picture,
                               min_number_picture_neighbors=min_neighbors)

        # ignore images with less than 5 pixels after cleaning
        if clean.sum() < 5:
            continue

        # image parameters
        hillas_c = hillas_parameters(geom[clean], image[clean])
        leakage_c = leakage(geom, image, clean)
        n_islands, island_ids = number_of_islands(geom, clean)

        timing_c = timing_parameters(
            geom[clean],
            image[clean],
            peakpos[clean],
            hillas_c,
        )

        # store parameters for stereo reconstruction
        hillas_containers[telescope_id] = hillas_c

        # store timegradients for plotting
        # ASTRI has no timing in PROD3b, so we use skewness instead
        if geom.camera_name != 'ASTRICam':
            time_gradients[telescope_id] = timing_c.slope.value
Пример #9
0
def main():
    std_config = get_standard_config()

    if args.config_file is not None:
        config = replace_config(std_config,
                                read_configuration_file(args.config_file))
    else:
        config = std_config

    print(config['tailcut'])

    foclen = OpticsDescription.from_name('LST').equivalent_focal_length
    cam_table = Table.read(args.input_file,
                           path="instrument/telescope/camera/LSTCam")
    camera_geom = CameraGeometry.from_table(cam_table)

    dl1_container = DL1ParametersContainer()
    parameters_to_update = list(HillasParametersContainer().keys())
    parameters_to_update.extend([
        'wl', 'r', 'leakage1_intensity', 'leakage2_intensity',
        'leakage1_pixel', 'leakage2_pixel', 'concentration_cog',
        'concentration_core', 'concentration_pixel', 'n_pixels', 'n_islands',
        'intercept', 'time_gradient'
    ])

    nodes_keys = get_dataset_keys(args.input_file)
    if args.noimage:
        nodes_keys.remove(dl1_images_lstcam_key)

    auto_merge_h5files([args.input_file],
                       args.output_file,
                       nodes_keys=nodes_keys)

    with tables.open_file(args.input_file, mode='r') as input:
        image_table = input.root[dl1_images_lstcam_key]
        with tables.open_file(args.output_file, mode='a') as output:

            params = output.root[dl1_params_lstcam_key].read()

            for ii, row in enumerate(image_table):
                if ii % 10000 == 0:
                    print(ii)
                image = row['image']
                pulse_time = row['pulse_time']

                signal_pixels = tailcuts_clean(camera_geom, image,
                                               **config['tailcut'])
                n_pixels = np.count_nonzero(signal_pixels)
                if n_pixels > 0:
                    num_islands, island_labels = number_of_islands(
                        camera_geom, signal_pixels)
                    n_pixels_on_island = np.bincount(
                        island_labels.astype(np.int))
                    n_pixels_on_island[
                        0] = 0  # first island is no-island and should not be considered
                    max_island_label = np.argmax(n_pixels_on_island)
                    signal_pixels[island_labels != max_island_label] = False

                    hillas = hillas_parameters(camera_geom[signal_pixels],
                                               image[signal_pixels])

                    dl1_container.fill_hillas(hillas)
                    dl1_container.set_timing_features(
                        camera_geom[signal_pixels], image[signal_pixels],
                        pulse_time[signal_pixels], hillas)

                    dl1_container.set_leakage(camera_geom, image,
                                              signal_pixels)
                    dl1_container.set_concentration(camera_geom, image, hillas)
                    dl1_container.n_islands = num_islands
                    dl1_container.wl = dl1_container.width / dl1_container.length
                    dl1_container.n_pixels = n_pixels
                    width = np.rad2deg(np.arctan2(dl1_container.width, foclen))
                    length = np.rad2deg(
                        np.arctan2(dl1_container.length, foclen))
                    dl1_container.width = width.value
                    dl1_container.length = length.value
                    dl1_container.r = np.sqrt(dl1_container.x**2 +
                                              dl1_container.y**2)

                    for p in parameters_to_update:
                        params[ii][p] = Quantity(dl1_container[p]).value
                else:
                    for p in parameters_to_update:
                        params[ii][p] = 0

            output.root[dl1_params_lstcam_key][:] = params
Пример #10
0
        clean = tailcuts_clean(
            camera,
            image,
            boundary_thresh=boundary,
            picture_thresh=picture,
            min_number_picture_neighbors=min_neighbors
        )

        # ignore images with less than 5 pixels after cleaning
        if clean.sum() < 5:
            continue

        # image parameters
        hillas_c = hillas_parameters(camera[clean], image[clean])
        leakage_c = leakage(camera, image, clean)
        n_islands, island_ids = number_of_islands(camera, clean)

        timing_c = timing_parameters(
            camera[clean], image[clean], peakpos[clean], hillas_c
        )

        # store parameters for stereo reconstruction
        hillas_containers[telescope_id] = hillas_c
        pointing_azimuth[telescope_id] = event.mc.tel[telescope_id].azimuth_raw * u.rad
        pointing_altitude[telescope_id] = event.mc.tel[telescope_id].altitude_raw * u.rad

        # store timegradients for plotting
        # ASTRI has no timing in PROD3b, so we use skewness instead
        if camera.cam_id != 'ASTRICam':
            time_gradients[telescope_id] = timing_c.slope.value
        else:
Пример #11
0
def main_pipeline(
    files,
    aux_basepath,
    max_events,
    dark_filename,
    integral_width,
    debug,
    hillas_filename,
    parameters_filename,
    picture_threshold,
    boundary_threshold,
    template_filename,
    saturation_threshold,
    threshold_pulse,
    nevent_plot=12,
    event_plot_filename=None,
    bad_pixels=None,
    disable_bar=False,
    wdw_number=1,
    apply_corr_factor=False,
):
    # get configuration
    with open(parameters_filename) as file:
        calibration_parameters = yaml.load(file)
    if bad_pixels is None:
        bad_pixels = get_bad_pixels(calib_file=parameters_filename,
                                    dark_histo=dark_filename,
                                    plot=None)
    pulse_template = NormalizedPulseTemplate.load(template_filename)
    pulse_area = pulse_template.integral() * u.ns
    ratio = pulse_template.compute_charge_amplitude_ratio(
        integral_width=integral_width, dt_sampling=4)  # ~ 0.24
    gain = np.array(calibration_parameters['gain'])  # ~ 20 LSB / p.e.
    gain_amplitude = gain * ratio
    crosstalk = np.array(calibration_parameters['mu_xt'])
    bias_resistance = 10 * 1E3 * u.Ohm  # 10 kOhm
    cell_capacitance = 50 * 1E-15 * u.Farad  # 50 fF
    geom = DigiCam.geometry
    dark_histo = Histogram1D.load(dark_filename)
    dark_baseline = dark_histo.mean()

    # define pipeline
    events = calibration_event_stream(files,
                                      max_events=max_events,
                                      disable_bar=disable_bar)
    if aux_basepath is not None:
        events = add_slow_data_calibration(
            events,
            basepath=aux_basepath,
            aux_services=('DriveSystem', 'DigicamSlowControl', 'MasterSST1M',
                          'SafetyPLC', 'PDPSlowControl'))
    events = baseline.fill_dark_baseline(events, dark_baseline)
    events = baseline.fill_digicam_baseline(events)
    events = tagging.tag_burst_from_moving_average_baseline(events)
    events = baseline.compute_baseline_shift(events)
    events = baseline.subtract_baseline(events)
    events = filters.filter_clocked_trigger(events)
    events = baseline.compute_nsb_rate(events, gain_amplitude, pulse_area,
                                       crosstalk, bias_resistance,
                                       cell_capacitance)
    events = baseline.compute_gain_drop(events, bias_resistance,
                                        cell_capacitance)
    events = peak.find_pulse_with_max(events)
    events = charge.compute_dynamic_charge(
        events,
        integral_width=integral_width,
        saturation_threshold=saturation_threshold,
        threshold_pulse=threshold_pulse,
        debug=debug,
        pulse_tail=False,
    )
    events = charge.compute_photo_electron(events, gains=gain)
    events = charge.apply_wdw_transmittance_correction_factor(
        events, wdw_number, apply_corr_factor)
    events = charge.interpolate_bad_pixels(events, geom, bad_pixels)
    events = cleaning.compute_tailcuts_clean(
        events,
        geom=geom,
        overwrite=True,
        picture_thresh=picture_threshold,
        boundary_thresh=boundary_threshold,
        keep_isolated_pixels=False)
    events = cleaning.compute_boarder_cleaning(events, geom,
                                               boundary_threshold)
    events = cleaning.compute_dilate(events, geom)
    events = image.compute_hillas_parameters(events, geom)
    if event_plot_filename is not None:
        events = plot_nevent(events,
                             nevent_plot,
                             filename=event_plot_filename,
                             bad_pixels=bad_pixels,
                             norm="lin")
    events = charge.compute_sample_photo_electron(events, gain_amplitude)
    events = cleaning.compute_3d_cleaning(events,
                                          geom,
                                          n_sample=50,
                                          threshold_sample_pe=20,
                                          threshold_time=2.1 * u.ns,
                                          threshold_size=0.005 * u.mm)
    # create pipeline output file
    output_file = Serializer(hillas_filename, mode='w', format='fits')
    data_to_store = PipelineOutputContainer()
    for event in events:
        if debug:
            print(event.hillas)
            print(event.data.nsb_rate)
            print(event.data.gain_drop)
            print(event.data.baseline_shift)
            print(event.data.border)
            plot_array_camera(np.max(event.data.adc_samples, axis=-1))
            plot_array_camera(event.data.reconstructed_charge)
            plot_array_camera(event.data.cleaning_mask.astype(float))
            plot_array_camera(event.data.reconstructed_number_of_pe)
            plt.show()
        # fill container
        data_to_store.local_time = event.data.local_time
        data_to_store.event_type = event.event_type
        data_to_store.event_id = event.event_id
        r = event.hillas.r
        phi = event.hillas.phi
        psi = event.hillas.psi
        alpha = compute_alpha(phi.value, psi.value) * u.rad
        data_to_store.alpha = alpha
        data_to_store.miss = compute_miss(r=r.value, alpha=alpha.value)
        data_to_store.miss = data_to_store.miss * r.unit
        data_to_store.baseline = np.mean(event.data.digicam_baseline)
        data_to_store.nsb_rate = np.mean(event.data.nsb_rate)
        data_to_store.shower = bool(event.data.shower)
        data_to_store.border = bool(event.data.border)
        data_to_store.burst = bool(event.data.burst)
        data_to_store.saturated = bool(event.data.saturated)
        num_islands, island_labels = number_of_islands(
            geom, event.data.cleaning_mask)
        data_to_store.number_of_island = num_islands
        if aux_basepath is not None:
            data_to_store.az = event.slow_data.DriveSystem.current_position_az
            data_to_store.el = event.slow_data.DriveSystem.current_position_el
            temp_crate1 = event.slow_data.DigicamSlowControl.Crate1_T
            temp_crate2 = event.slow_data.DigicamSlowControl.Crate2_T
            temp_crate3 = event.slow_data.DigicamSlowControl.Crate3_T
            temp_digicam = np.array(
                np.hstack([temp_crate1, temp_crate2, temp_crate3]))
            temp_digicam_mean = np.mean(temp_digicam[np.logical_and(
                temp_digicam > 0, temp_digicam < 60)])
            data_to_store.digicam_temperature = temp_digicam_mean
            temp_sector1 = event.slow_data.PDPSlowControl.Sector1_T
            temp_sector2 = event.slow_data.PDPSlowControl.Sector2_T
            temp_sector3 = event.slow_data.PDPSlowControl.Sector3_T
            temp_pdp = np.array(
                np.hstack([temp_sector1, temp_sector2, temp_sector3]))
            temp_pdp_mean = np.mean(temp_pdp[np.logical_and(
                temp_pdp > 0, temp_pdp < 60)])
            data_to_store.pdp_temperature = temp_pdp_mean
            target_radec = event.slow_data.MasterSST1M.target_radec
            data_to_store.target_ra = target_radec[0]
            data_to_store.target_dec = target_radec[1]
            status_leds = event.slow_data.SafetyPLC.SPLC_CAM_Status
            # bit 8 of status_LEDs is about on/off, bit 9 about blinking
            data_to_store.pointing_leds_on = bool((status_leds & 1 << 8) >> 8)
            pointing_leds_blink = bool((status_leds & 1 << 9) >> 9)
            data_to_store.pointing_leds_blink = pointing_leds_blink
            hv_sector1 = event.slow_data.PDPSlowControl.Sector1_HV
            hv_sector2 = event.slow_data.PDPSlowControl.Sector2_HV
            hv_sector3 = event.slow_data.PDPSlowControl.Sector3_HV
            hv_pdp = np.array(np.hstack([hv_sector1, hv_sector2, hv_sector3]),
                              dtype=bool)
            data_to_store.all_hv_on = np.all(hv_pdp)
            ghv_sector1 = event.slow_data.PDPSlowControl.Sector1_GHV
            ghv_sector2 = event.slow_data.PDPSlowControl.Sector2_GHV
            ghv_sector3 = event.slow_data.PDPSlowControl.Sector3_GHV
            ghv_pdp = np.array(np.hstack(
                [ghv_sector1, ghv_sector2, ghv_sector3]),
                               dtype=bool)
            data_to_store.all_ghv_on = np.all(ghv_pdp)
            is_on_source = bool(event.slow_data.DriveSystem.is_on_source)
            data_to_store.is_on_source = is_on_source
            is_tracking = bool(event.slow_data.DriveSystem.is_tracking)
            data_to_store.is_tracking = is_tracking
        for key, val in event.hillas.items():
            data_to_store[key] = val
        output_file.add_container(data_to_store)
    try:
        output_file.close()
        print(hillas_filename, 'created.')
    except ValueError:
        print('WARNING: no data to save,', hillas_filename, 'not created.')
def calculate_image_features(telescope_id, event, dl1, config):
    ''' Performs cleaning and adds the following image parameters:
    - hillas
    - leakage
    - concentration
    - timing
    - number of islands

    Make sure to adapt cleaning levels to the used algorithm (-> config)
    - tailcuts:
        picture_thresh, picture_thresh, min_number_picture_neighbors
    - fact_image_cleaning:
        picture_threshold, boundary_threshold, min_number_neighbors, time_limit
    
    Returns:
    --------
    TelescopeParameterContainer
    '''
    array_event_id = event.dl0.event_id
    run_id = event.r0.obs_id
    telescope = event.inst.subarray.tels[telescope_id]
    image = dl1.image

    # might want to make the parameter names more consistent between methods
    if config.cleaning_method == 'tailcuts_clean':
        boundary_thresh, picture_thresh, min_number_picture_neighbors = config.cleaning_level[
            telescope.camera.cam_id
        ]
        mask = tailcuts_clean(
            telescope.camera,
            image,
            boundary_thresh=boundary_thresh,
            picture_thresh=picture_thresh,
            min_number_picture_neighbors=min_number_picture_neighbors,
        )
    elif config.cleaning_method == 'fact_image_cleaning':
        boundary_threshold, picture_threshold, time_limit, min_number_neighbors = config.cleaning_level[
            telescope.camera.cam_id
        ]
        mask = fact_image_cleaning(
            telescope.camera,
            image,
            dl1.pulse_time,
            boundary_threshhold=boundary_threshold,
            picture_threshold=picture_threshold,
            min_number_neighbors=min_number_neighbors,
            time_limit=time_limit,
        )

    cleaned = image.copy()
    cleaned[~mask] = 0
    logging.debug(f'calculating hillas for event {array_event_id, telescope_id}')
    hillas_container = hillas_parameters(telescope.camera, cleaned)
    hillas_container.prefix = ''
    logging.debug(f'calculating leakage for event {array_event_id, telescope_id}')
    leakage_container = leakage(telescope.camera, image, mask)
    leakage_container.prefix = ''
    logging.debug(f'calculating concentration for event {array_event_id, telescope_id}')
    concentration_container = concentration(telescope.camera, image, hillas_container)
    concentration_container.prefix = ''
    logging.debug(f'getting timing information for event {array_event_id, telescope_id}')
    timing_container = timing_parameters(telescope.camera, image, dl1.pulse_time, hillas_container)
    timing_container.prefix = ''

    # membership missing for now as it causes problems with the hdf5tablewriter
    # right now i dont need this anyway
    logging.debug(f'calculating num_islands for event {array_event_id, telescope_id}')
    num_islands, membership = number_of_islands(telescope.camera, mask)
    island_container = IslandContainer(num_islands=num_islands)
    island_container.prefix = ''
    num_pixel_in_shower = mask.sum()

    logging.debug(f'getting pointing container for event {array_event_id, telescope_id}')

    # ctapipe requires this to be rad
    pointing_container = TelescopePointingContainer(
        azimuth=event.mc.tel[telescope_id].azimuth_raw * u.rad,
        altitude=event.mc.tel[telescope_id].altitude_raw * u.rad,
        prefix='pointing',
    )

    return TelescopeParameterContainer(
        telescope_id=telescope_id,
        run_id=run_id,
        array_event_id=array_event_id,
        leakage=leakage_container,
        hillas=hillas_container,
        concentration=concentration_container,
        pointing=pointing_container,
        timing=timing_container,
        islands=island_container,
        telescope_type_id=config.types_to_id[telescope.type],
        camera_type_id=config.names_to_id[telescope.camera.cam_id],
        focal_length=telescope.optics.equivalent_focal_length,
        mirror_area=telescope.optics.mirror_area,
        num_pixel_in_shower=num_pixel_in_shower,
    )
Пример #13
0
def get_dl1(calibrated_event,
            telescope_id,
            dl1_container=None,
            custom_config={},
            use_main_island=True):
    """
    Return a DL1ParametersContainer of extracted features from a calibrated event.
    The DL1ParametersContainer can be passed to be filled if created outside the function
    (faster for multiple event processing)

    Parameters
    ----------
    calibrated_event: ctapipe event container
    telescope_id: int
    dl1_container: DL1ParametersContainer
    config_file: path to a configuration file
        configuration used for tailcut cleaning
        superseeds the standard configuration

    Returns
    -------
    DL1ParametersContainer
    """

    config = replace_config(standard_config, custom_config)
    cleaning_parameters = config["tailcut"]

    dl1_container = DL1ParametersContainer(
    ) if dl1_container is None else dl1_container

    tel = calibrated_event.inst.subarray.tels[telescope_id]
    dl1 = calibrated_event.dl1.tel[telescope_id]
    camera = tel.camera

    image = dl1.image
    pulse_time = dl1.pulse_time

    signal_pixels = cleaning_method(camera, image, **cleaning_parameters)

    if image[signal_pixels].sum() > 0:

        # check the number of islands
        num_islands, island_labels = number_of_islands(camera, signal_pixels)

        if use_main_island:
            n_pixels_on_island = np.zeros(num_islands + 1)

            for iisland in range(1, num_islands + 1):
                n_pixels_on_island[iisland] = np.sum(island_labels == iisland)

            max_island_label = np.argmax(n_pixels_on_island)
            signal_pixels[island_labels != max_island_label] = False

        hillas = hillas_parameters(camera[signal_pixels], image[signal_pixels])

        # Fill container
        dl1_container.fill_hillas(hillas)
        dl1_container.fill_event_info(calibrated_event)
        dl1_container.set_mc_core_distance(calibrated_event, telescope_id)
        dl1_container.set_mc_type(calibrated_event)
        dl1_container.set_timing_features(camera[signal_pixels],
                                          image[signal_pixels],
                                          pulse_time[signal_pixels], hillas)
        dl1_container.set_leakage(camera, image, signal_pixels)
        dl1_container.n_islands = num_islands
        dl1_container.set_telescope_info(calibrated_event, telescope_id)

        return dl1_container

    else:
        return None