def test_fact_image_cleaning(): # use LST pixel geometry geom = CameraGeometry.from_name("LSTCam") # create some signal pixels values = np.zeros(len(geom)) timing = np.zeros(len(geom)) signal_pixels = np.array( [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 37, 38, 111, 222]) values[signal_pixels] = 5 timing[signal_pixels] = 10 # manipulate some of those values[[1, 2]] = 3 values[7] = 1 timing[[5, 6, 13, 111]] = 20 mask = cleaning.fact_image_cleaning( geom, values, timing, boundary_threshold=2, picture_threshold=4, min_number_neighbors=2, time_limit=5, ) expected_pixels = np.array([0, 1, 2, 3, 4, 8, 9, 10, 11]) expected_mask = np.zeros(len(geom)).astype(bool) expected_mask[expected_pixels] = 1 assert_allclose(mask, expected_mask)
def test_fact_image_cleaning(): # use LST pixel geometry geom = CameraGeometry.from_name("LSTCam") # create some signal pixels values = np.zeros(len(geom)) timing = np.zeros(len(geom)) signal_pixels = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 37, 38, 111, 222]) values[signal_pixels] = 5 timing[signal_pixels] = 10 # manipulate some of those values[[1, 2]] = 3 values[7] = 1 timing[[5, 6, 13, 111]] = 20 mask = cleaning.fact_image_cleaning(geom, values, timing, boundary_threshold=2, picture_threshold=4, min_number_neighbors=2, time_limit=5) expected_pixels = np.array([0, 1, 2, 3, 4, 8, 9, 10, 11]) expected_mask = np.zeros(len(geom)).astype(bool) expected_mask[expected_pixels] = 1 assert_allclose(mask, expected_mask)
d1 = CameraDisplay(camera, ax=axs) axs.set_title('Image ' + camera.cam_id) d1.image = dl1.image plt.show() plt.close(fig) # cleaning boundary, picture, min_neighbors = cleaning_level[camera.cam_id] start = datetime.datetime.now() clean1 = fact_image_cleaning(camera, image, peakpos, boundary_threshold=boundary, picture_threshold=picture, min_number_neighbors=min_neighbors) finish = datetime.datetime.now() # display dl1 cleaned images cleaned1 = dl1.image.copy() cleaned1[~clean1] = 0.0 """ fig, axs = plt.subplots(1, 1, figsize=(6, 3)) d1 = CameraDisplay(camera, ax=axs) axs.set_title('Cleaned_Image(fact_cleaning) ' + camera.cam_id) d1.image = cleaned1 plt.show()
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
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, )