def image_cleaning_filter(reader, images, **opts): """ Filter images according to a cleaning operation. Parameters ---------- reader: `DL1DataReader` images options for image cleaning Returns ------- mask (Array of bool) """ try: from ctapipe.image import cleaning except ImportError: raise ImportError( "The `ctapipe.image.cleaning` python module is required to perform cleaning operation" ) try: from ctapipe.instrument.camera import CameraGeometry except ImportError: raise ImportError( "The `ctapipe.instrument.CameraGeometry` python module is required to perform cleaning operation" ) geom = CameraGeometry.from_name(reader.tel_type.split("_")[-1]) def clean(img): return cleaning.tailcuts_clean(geom, img, **opts) clean_mask = np.apply_along_axis(clean, 1, images) return clean_mask.any(axis=1)
def leakage_filter(reader, images, leakage_value=1.0, leakage_number=2, **opts): """ Filter images on leakage Comment: An image cleaning filter is applied by default. Parameters ---------- reader: `DL1DataReader` images options for image cleaning leakage_value leakage_number Returns ------- mask (Array of bool) """ try: from ctapipe.image import cleaning, leakage except ImportError: raise ImportError( "The `ctapipe.image.cleaning` and/or `ctapipe.image.leakage` python module is required to perform leakage operation" ) try: from ctapipe.instrument.camera import CameraGeometry except ImportError: raise ImportError( "The `ctapipe.instrument.CameraGeometry` python module is required to perform leakage operation" ) if leakage_number not in [1, 2]: raise ValueError( "The leakage_number is {}. Valid options are 1 or 2.".format( leakage_number)) geom = CameraGeometry.from_name(reader.tel_type.split("_")[-1]) def leak(img): cleanmask = cleaning.tailcuts_clean(geom, img, **opts) mask = False if any(cleanmask): leakage_values = leakage(geom, img, cleanmask) if hasattr(leakage_values, "leakage{}_intensity".format(leakage_number)): mask = (leakage_values["leakage{}_intensity".format( leakage_number)] <= leakage_value) elif hasattr(leakage_values, "intensity_width_{}".format(leakage_number)): mask = ( leakage_values["intensity_width_{}".format(leakage_number)] <= leakage_value) return mask leakage_mask = np.apply_along_axis(leak, 1, images) return leakage_mask
def test_psi_20(): from ctapipe.image import timing_parameters # Then try a different rotation angle grad = 2 intercept = 1 deviation = 0.1 geom = CameraGeometry.from_name("LSTCam") psi = 20 * u.deg hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=psi) random = np.random.RandomState(1) peak_time = intercept + grad * (np.cos(psi) * geom.pix_x.value + np.sin(psi) * geom.pix_y.value) peak_time += random.normal(0, deviation, geom.n_pixels) timing = timing_parameters( geom, image=np.ones(geom.n_pixels), peak_time=peak_time, hillas_parameters=hillas, cleaning_mask=np.ones(geom.n_pixels, dtype=bool) ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit, rtol=1e-2) assert_allclose(timing.intercept, intercept, rtol=1e-2) assert_allclose(timing.deviation, deviation, rtol=1e-2)
def test_ignore_negative(): from ctapipe.image import timing_parameters grad = 2.0 intercept = 1.0 deviation = 0.1 geom = CameraGeometry.from_name("LSTCam") hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=0 * u.deg) random = np.random.RandomState(1) peak_time = intercept + grad * geom.pix_x.value peak_time += random.normal(0, deviation, geom.n_pixels) image = np.ones(geom.n_pixels) image[5:10] = -1.0 cleaning_mask = image >= 0 timing = timing_parameters( geom, image, peak_time=peak_time, hillas_parameters=hillas, cleaning_mask=cleaning_mask, ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit, rtol=1e-2) assert_allclose(timing.intercept, intercept, rtol=1e-2) assert_allclose(timing.deviation, deviation, rtol=1e-2)
def test_psi_0(): from ctapipe.image import timing_parameters """ Simple test that gradient fitting gives expected answers for perfect gradient """ grad = 2.0 intercept = 1.0 deviation = 0.1 geom = CameraGeometry.from_name("LSTCam") hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=0 * u.deg) random = np.random.RandomState(1) peak_time = intercept + grad * geom.pix_x.value peak_time += random.normal(0, deviation, geom.n_pixels) timing = timing_parameters( geom, image=np.ones(geom.n_pixels), peak_time=peak_time, hillas_parameters=hillas, cleaning_mask=np.ones(geom.n_pixels, dtype=bool) ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit, rtol=1e-2) assert_allclose(timing.intercept, intercept, rtol=1e-2) assert_allclose(timing.deviation, deviation, rtol=1e-2)
def generate_geometry_from_camera(camera, source_x=0. * u.mm, source_y=0. * u.mm): """ Generate the SST-1M geometry from the CTS configuration :param camera: a CTS instance :param source_x: x coord :param source_y: y coord :return: the geometry for visualisation and the list of "good" pixels """ pix_x = [] pix_y = [] pix_id = [] for pix in camera.Pixels: pix_x.append(pix.center[0]) pix_y.append(pix.center[1]) pix_id.append(pix.ID) neighbors_pix = _find_neighbor_pixels(pix_x, pix_y, 30.) geom = CameraGeometry(0, pix_id, pix_x * u.mm - source_x, pix_y * u.mm - source_y, np.ones(1296) * 400., pix_type='hexagonal', neighbors=neighbors_pix) return geom
def test_leakage(): from ctapipe.image.leakage import leakage geom = CameraGeometry.from_name('LSTCam') img = np.ones(geom.n_pixels) mask = np.ones(len(geom), dtype=bool) l = leakage(geom, img, mask) ratio1 = np.sum(geom.get_border_pixel_mask(1)) / geom.n_pixels ratio2 = np.sum(geom.get_border_pixel_mask(2)) / geom.n_pixels assert l.intensity_width_1 == ratio1 assert l.intensity_width_2 == ratio2 assert l.pixels_width_1 == ratio1 assert l.pixels_width_2 == ratio2
def test_leakage(): from ctapipe.image.leakage import leakage geom = CameraGeometry.from_name('LSTCam') img = np.ones(geom.n_pixels) mask = np.ones(len(geom), dtype=bool) l = leakage(geom, img, mask) ratio1 = np.sum(geom.get_border_pixel_mask(1)) / geom.n_pixels ratio2 = np.sum(geom.get_border_pixel_mask(2)) / geom.n_pixels assert l.leakage1_intensity == ratio1 assert l.leakage2_intensity == ratio2 assert l.leakage1_pixel == ratio1 assert l.leakage2_pixel == ratio2
def image_intensity_after_cleaning_filter(reader, images, i_min=-np.inf, i_max=np.inf, **opts): """ Filter images on intensity (in pe) after cleaning Parameters ---------- reader: `DL1DataReader` images options for image cleaning i_min i_max Returns ------- mask (Array of bool) """ try: from ctapipe.image import cleaning except ImportError: raise ImportError( "The `ctapipe.image.cleaning` python module is required to perform cleaning operation" ) try: from ctapipe.instrument.camera import CameraGeometry except ImportError: raise ImportError( "The `ctapipe.instrument.CameraGeometry` python module is required to perform cleaning operation" ) geom = CameraGeometry.from_name(reader.tel_type.split("_")[-1]) def int_after_clean(img): cleanmask = cleaning.tailcuts_clean(geom, img, **opts) clean = img.copy() clean[~cleanmask] = 0.0 amps = np.sum(clean) return (i_min < amps) & (amps < i_max) int_mask = np.apply_along_axis(int_after_clean, 1, images) return int_mask
def test_hash(): types = ["LST", "MST", "SST"] names = ["LST", "MST", "SST-1M"] cameras = ["LSTCam", "FlashCam", "DigiCam"] telescopes = [] for name, type, camera in zip(names, types, cameras): for i in range(3): telescopes.append( TelescopeDescription(name=name, tel_type=type, optics=OpticsDescription.from_name(name), camera=CameraGeometry.from_name(camera))) assert len(telescopes) == 9 assert len(set(telescopes)) == 3
def initialise_plots(self): # first load in a very nasty way the camera geometry pix_x, pix_y, pix_id = [], [], [] pixels = self.cts.camera.Pixels pixelspresent = list(self.cts.pixel_to_led['DC'].keys()) for pix in pixels: if pix.ID in pixelspresent: pix_x.append(pix.center[0]) pix_y.append(pix.center[1]) pix_id.append(pix.ID) else: pix_x.append(-200.) pix_y.append(-200.) pix_id.append(pix.ID) pix_x = list(pix_x) pix_y = list(pix_y) pix_id = list(pix_id) neighbors_pix = find_neighbor_pixels(pix_x, pix_y, 30.) geom = CameraGeometry(0, pix_id, pix_x * u.mm, pix_y * u.mm, np.ones((1296)) * 400., 'hexagonal', neighbors=neighbors_pix) plt.figure(0, figsize=(20, 6)) self.plots = [] plt.subplot(1, 2, 1) self.plots.append( visualization.CameraDisplay(geom, title='AC status', norm='lin', cmap='coolwarm')) self.plots[-1].add_colorbar() self.plots[-1].image = np.multiply(self.ac_status, self.ac_level) plt.subplot(1, 2, 2) self.plots.append( visualization.CameraDisplay(geom, title='DC status', norm='lin', cmap='coolwarm')) self.plots[-1].add_colorbar() self.plots[-1].image = np.multiply(self.dc_status, self.dc_level)
def test_ignore_negative(): grad = 2.0 intercept = 1.0 geom = CameraGeometry.from_name("LSTCam") hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=0 * u.deg) image = np.ones(geom.n_pixels) image[5:10] = -1.0 timing = timing_parameters( geom, image, peakpos=intercept + grad * geom.pix_x.value, hillas_parameters=hillas, ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit) assert_allclose(timing.intercept, intercept)
def test_psi_20(): # Then try a different rotation angle grad = 2 intercept = 1 geom = CameraGeometry.from_name("LSTCam") psi = 20 * u.deg hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=psi) timing = timing_parameters( geom, image=np.ones(geom.n_pixels), peakpos=intercept + grad * (np.cos(psi) * geom.pix_x.value + np.sin(psi) * geom.pix_y.value), hillas_parameters=hillas, ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit) assert_allclose(timing.intercept, intercept)
def test_psi_0(): """ Simple test that gradient fitting gives expected answers for perfect gradient """ grad = 2.0 intercept = 1.0 geom = CameraGeometry.from_name("LSTCam") hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=0 * u.deg) timing = timing_parameters( geom, image=np.ones(geom.n_pixels), peakpos=intercept + grad * geom.pix_x.value, hillas_parameters=hillas, ) # Test we get the values we put in back out again assert_allclose(timing.slope, grad / geom.pix_x.unit) assert_allclose(timing.intercept, intercept)
def generate_geometry(camera): """ Generate the SST-1M geometry from the CTS configuration :param cts: a CTS instance :param available_board: which board per sector are available (dict) :return: the geometry for visualisation and the list of "good" pixels """ pix_x = [] pix_y = [] pix_id = [] for pix in camera.Pixels: pix_x.append(pix.center[0]) pix_y.append(pix.center[1]) pix_id.append(pix.ID) neighbors_pix = _find_neighbor_pixels(pix_x, pix_y, 30.) geom = CameraGeometry(cam_id=0, pix_id=pix_id, pix_x=pix_x * u.mm, pix_y=pix_y * u.mm, pix_area=np.ones(1296) * 482.41, neighbors=neighbors_pix, pix_type='hexagonal') return geom, pix_id
def test_hash(): from ctapipe.instrument.telescope import TelescopeDescription from ctapipe.instrument.optics import OpticsDescription from ctapipe.instrument.camera import CameraGeometry types = ['LST', 'MST', 'SST'] names = ['LST', 'MST', 'SST-1M'] cameras = ['LSTCam', 'FlashCam', 'DigiCam'] telescopes = [] for name, type, camera in zip(names, types, cameras): for i in range(3): telescopes.append( TelescopeDescription(name=name, type=type, optics=OpticsDescription.from_name(name), camera=CameraGeometry.from_name(camera))) assert len(telescopes) == 9 assert len(set(telescopes)) == 3
def _build_subarray_info(self, run): """ constructs a SubarrayDescription object from the info in an MCRun Parameters ---------- run: MCRun object Returns ------- SubarrayDescription : instrumental information """ subarray = SubarrayDescription("MonteCarloArray") runHeader = run.root.RunHeader tabFocalTel = runHeader.tabFocalTel.read() tabPosTelX = runHeader.tabPosTelX.read() tabPosTelY = runHeader.tabPosTelY.read() tabPosTelZ = runHeader.tabPosTelZ.read() tabPoslXYZ = np.ascontiguousarray( np.vstack((tabPosTelX, tabPosTelY, tabPosTelZ)).T) ''' # Correspance HiPeData.Telscope.Type and camera name # 0 LSTCam, 1 NectarCam, 2 FlashCam, 3 SCTCam, # 4 ASTRICam, 5 DigiCam, 6 CHEC ''' mapping_camera = { 0: 'LSTCam', 1: 'NectarCam', 2: 'FlashCam', 3: 'SCTCam', 4: 'ASTRICam', 5: 'DigiCam', 6: 'CHEC' } mapping_telName = { 0: 'LST', 1: 'MST', 2: 'MST', 3: 'MST', 4: 'SST-ASTRI', 5: 'SST-1M', 6: 'SST-2M' } for telNode in self.run.walk_nodes('/Tel', 'Group'): try: telType = uint64(telNode.telType.read()) telIndex = uint64(telNode.telIndex.read()) telId = uint64(telNode.telId.read()) cameraName = mapping_camera[telType] telName = mapping_telName[telType] camera = CameraGeometry.from_name(cameraName) camera.cam_id = cameraName foclen = tabFocalTel[telIndex] * u.m tel_pos = tabPoslXYZ[telIndex] * u.m camera.pix_x = telNode.tabPixelX.read() * u.m camera.pix_y = telNode.tabPixelY.read() * u.m #camera.rotate(-90.0*u.deg) optic = OpticsDescription.from_name(telName) optic.equivalent_focal_length = foclen telescope_description = TelescopeDescription(telName, telName, optics=optic, camera=camera) #tel.optics.mirror_area = mirror_area #tel.optics.num_mirror_tiles = num_tiles subarray.tels[telId] = telescope_description subarray.positions[telId] = tel_pos except tables.exceptions.NoSuchNodeError as e: pass return subarray
calib.calibrate(event) hillas_params = {} subarray = event.inst.subarray for tel_id in event.dl0.tels_with_data: # telescope pointing direction point_azimuth[tel_id] = event.mc.tel[tel_id].azimuth_raw * u.rad point_altitude[tel_id] = (np.pi / 2 - event.mc.tel[tel_id].altitude_raw) * u.rad # print(point_azimuth,point_altitude) # Camera Geometry required for hillas parametrization pix_x = subarray.tel[tel_id].camera.pix_x pix_y = subarray.tel[tel_id].camera.pix_y foclen = subarray.tel[tel_id].optics.equivalent_focal_length camgeom = CameraGeometry.guess(pix_x, pix_y, foclen) # note the [0] is for channel 0 which is high-gain channel image = event.dl1.tel[tel_id].image[0] # Cleaning of the image cleaned_image = image # create a clean mask of pixels above the threshold cleanmask = tailcuts_clean(camgeom, image, picture_thresh=10, boundary_thresh=5) # set all rejected pixels to zero cleaned_image[~cleanmask] = 0 # Calulate hillas parameters # It fails for empty pixels try: hillas_params[tel_id] = hillas_parameters(camgeom, cleaned_image)
cameras = ["LSTCam", "FlashCam", "DigiCam"] telescopes = [] for name, type, camera in zip(names, types, cameras): for i in range(3): telescopes.append( TelescopeDescription(name=name, tel_type=type, optics=OpticsDescription.from_name(name), camera=CameraGeometry.from_name(camera))) assert len(telescopes) == 9 assert len(set(telescopes)) == 3 OPTICS_NAMES = OpticsDescription.get_known_optics_names() CAMERA_NAMES = CameraGeometry.get_known_camera_names() @pytest.mark.parametrize("camera_name", CAMERA_NAMES) @pytest.mark.parametrize("optics_name", OPTICS_NAMES) def test_telescope_from_name(optics_name, camera_name): """ Check we can construct all telescopes from their names """ tel = TelescopeDescription.from_name(optics_name, camera_name) assert optics_name in str(tel) assert camera_name in str(tel) assert tel.camera.pix_x.shape[0] > 0 assert tel.optics.equivalent_focal_length.to("m") > 0 assert tel.type in ["MST", "SST", "LST", "UNKNOWN"]