def test_hashing(): """" check that hashes are correctly computed """ camera_name = "Unknown" sampling_rate = u.Quantity(2, u.GHz) reference_pulse_shape = np.ones((2, 20)).astype(np.float) reference_pulse_sample_width = u.Quantity(0.5, u.ns) readout1 = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) readout2 = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) readout3 = CameraReadout( camera_name=4, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) assert len({readout1, readout2, readout3}) == 2
def ctapipe_subarray(self): from ctapipe.instrument import TelescopeDescription, SubarrayDescription, \ CameraGeometry, CameraReadout, CameraDescription, OpticsDescription import astropy.units as u geom = CameraGeometry("sstcam", self.mapping.pixel.i, u.Quantity(self.mapping.pixel.x, 'm'), u.Quantity(self.mapping.pixel.y, 'm'), u.Quantity(self.mapping.pixel.size, 'm')**2, 'square') readout = CameraReadout( "sstcam", u.Quantity(1 / self.waveform_sample_width, "GHz"), self.photoelectron_pulse.amplitude[None, :], u.Quantity(self.photoelectron_pulse.sample_width, "ns")) camera = CameraDescription("sstcam", geom, readout) optics = OpticsDescription.from_name('SST-ASTRI') telescope = TelescopeDescription("SST", "SST", optics, camera) subarray = SubarrayDescription( 'toy', tel_positions={1: [0, 0, 0] * u.m}, tel_descriptions={1: telescope}, ) return subarray
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()
def test_camera_from_name(camera_name): """ check we can construct all cameras from name""" try: camera = CameraReadout.from_name(camera_name) assert str(camera) == camera_name except FileNotFoundError: # these don't have readout definitions on the dataserver if camera_name not in ["MAGICCam", "Whipple109", "FACT"]: raise
def readout(): camera_name = "Unknown" sampling_rate = u.Quantity(2, u.GHz) reference_pulse_shape = np.ones((2, 20)).astype(np.float) reference_pulse_sample_width = u.Quantity(0.5, u.ns) return CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, )
def test_equals(): """ check we can use the == operator """ camera_name = "Unknown" sampling_rate = u.Quantity(2, u.GHz) reference_pulse_shape = np.ones((2, 20)).astype(np.float) reference_pulse_sample_width = u.Quantity(0.5, u.ns) readout1 = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) readout2 = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) readout3 = CameraReadout( camera_name=4, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) readout4 = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=u.Quantity(1, u.ns), ) assert readout1 is not readout2 assert readout2 is not readout3 assert readout3 is not readout4 assert readout1 == readout2 assert readout1 != readout3 assert readout1 != readout4
def test_camera_from_name(camera_geometry): """ check we can construct all cameras from name""" try: camera = CameraReadout.from_name(camera_geometry.camera_name) assert str(camera) == camera_geometry.camera_name except FileNotFoundError: # Most non-cta cameras don't have readout provided on the data server if camera_geometry.camera_name in [ "LSTCam", "NectarCam", "FlashCam", "CHEC" ]: raise
def read_single_camera_readout(filename, camera_name): """ Read a specific camera readout from a DL1 file Parameters ---------- filename: str camera_name: str Returns ------- `ctapipe.instrument.camera.readout.CameraReadout` """ camera_readout_path = f"/configuration/instrument/telescope/camera/readout_{camera_name}" return CameraReadout.from_table( Table.read(filename, path=camera_readout_path))
def test_construct(): """ Check we can make a CameraReadout from scratch """ camera_name = "Unknown" sampling_rate = u.Quantity(2, u.GHz) reference_pulse_shape = np.ones((2, 20)).astype(np.float) reference_pulse_sample_width = u.Quantity(0.5, u.ns) readout = CameraReadout( camera_name=camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) assert readout.camera_name == camera_name assert readout.sampling_rate == sampling_rate assert (readout.reference_pulse_shape == reference_pulse_shape).all() assert readout.reference_pulse_sample_width == reference_pulse_sample_width
def create_subarray(geometry_version, tel_id=1): """ Obtain the subarray from the EventSource Returns ------- ctapipe.instrument.SubarrayDescription """ # camera info from LSTCam-[geometry_version].camgeom.fits.gz file camera_geom = load_camera_geometry(version=geometry_version) # get info on the camera readout: daq_time_per_sample, pulse_shape_time_step, pulse_shapes = read_pulse_shapes( ) camera_readout = CameraReadout( 'LSTCam', 1 / daq_time_per_sample, pulse_shapes, pulse_shape_time_step, ) camera = CameraDescription('LSTCam', camera_geom, camera_readout) lst_tel_descr = TelescopeDescription(name='LST', tel_type='LST', optics=OPTICS, camera=camera) tel_descriptions = {tel_id: lst_tel_descr} # LSTs telescope position taken from MC from the moment tel_positions = {tel_id: [50., 50., 16] * u.m} subarray = SubarrayDescription( name=f"LST-{tel_id} subarray", tel_descriptions=tel_descriptions, tel_positions=tel_positions, ) return subarray
def build_camera(cam_settings, pixel_settings, telescope): pixel_shape = cam_settings['pixel_shape'][0] try: pix_type, pix_rotation = CameraGeometry.simtel_shape_to_type( pixel_shape) except ValueError: warnings.warn( f'Unkown pixel_shape {pixel_shape} for camera_type {telescope.camera_name}', UnknownPixelShapeWarning, ) pix_type = 'hexagon' pix_rotation = '0d' geometry = CameraGeometry( telescope.camera_name, pix_id=np.arange(cam_settings['n_pixels']), pix_x=u.Quantity(cam_settings['pixel_x'], u.m), pix_y=u.Quantity(cam_settings['pixel_y'], u.m), pix_area=u.Quantity(cam_settings['pixel_area'], u.m**2), pix_type=pix_type, pix_rotation=pix_rotation, cam_rotation=-Angle(cam_settings['cam_rot'], u.rad), apply_derotation=True, ) readout = CameraReadout( telescope.camera_name, sampling_rate=u.Quantity(1 / pixel_settings['time_slice'], u.GHz), reference_pulse_shape=pixel_settings['ref_shape'].astype('float64', copy=False), reference_pulse_sample_width=u.Quantity(pixel_settings['ref_step'], u.ns), ) return CameraDescription(camera_name=telescope.camera_name, geometry=geometry, readout=readout)
def build_camera(cam_settings, pixel_settings, telescope): pixel_shape = cam_settings["pixel_shape"][0] try: pix_type, pix_rotation = CameraGeometry.simtel_shape_to_type( pixel_shape) except ValueError: warnings.warn( f"Unkown pixel_shape {pixel_shape} for camera_type {telescope.camera_name}", UnknownPixelShapeWarning, ) pix_type = "hexagon" pix_rotation = "0d" geometry = CameraGeometry( telescope.camera_name, pix_id=np.arange(cam_settings["n_pixels"]), pix_x=u.Quantity(cam_settings["pixel_x"], u.m), pix_y=u.Quantity(cam_settings["pixel_y"], u.m), pix_area=u.Quantity(cam_settings["pixel_area"], u.m**2), pix_type=pix_type, pix_rotation=pix_rotation, cam_rotation=-Angle(cam_settings["cam_rot"], u.rad), apply_derotation=True, ) readout = CameraReadout( telescope.camera_name, sampling_rate=u.Quantity(1 / pixel_settings["time_slice"], u.GHz), reference_pulse_shape=pixel_settings["ref_shape"].astype("float64", copy=False), reference_pulse_sample_width=u.Quantity(pixel_settings["ref_step"], u.ns), ) return CameraDescription(camera_name=telescope.camera_name, geometry=geometry, readout=readout)
def __init__(self, **kwargs): """ Constructor Parameters ---------- kwargs: dict Parameters to be passed. NOTE: The file mask of the data to read can be passed with the 'input_url' parameter. """ try: import uproot except ImportError: raise ImportError( "The 'uproot' package is required for the DLMAGICEventSource class." ) self.file_list = glob.glob(kwargs['input_url']) self.file_list.sort() # Since EventSource can not handle file wild cards as input_url # We substitute the input_url with first file matching # the specified file mask. del kwargs['input_url'] super().__init__(input_url=self.file_list[0], **kwargs) # get run number mask = r".*_za\d+to\d+_\d_(\d+)_([A-Z]+)_.*" parsed_info = re.findall(mask, self.file_list[0]) self.run_number = parsed_info[0][0] # MAGIC telescope positions in m wrt. to the center of CTA simulations self.magic_tel_positions = { 1: [-27.24, -146.66, 50.00] * u.m, 2: [-96.44, -96.77, 51.00] * u.m } self.magic_tel_positions = self.magic_tel_positions # MAGIC telescope description optics = OpticsDescription.from_name('MAGIC') geom = CameraGeometry.from_name('MAGICCam') # Camera Readout for NectarCam used as a placeholder readout = CameraReadout( 'MAGICCam', sampling_rate=u.Quantity(1, u.GHz), reference_pulse_shape=np.array([norm.pdf(np.arange(96), 48, 6)]), reference_pulse_sample_width=u.Quantity(1, u.ns)) camera = CameraDescription('MAGICCam', geom, readout) self.magic_tel_description = TelescopeDescription(name='MAGIC', tel_type='LST', optics=optics, camera=camera) self.magic_tel_descriptions = { 1: self.magic_tel_description, 2: self.magic_tel_description } self.magic_subarray = SubarrayDescription('MAGIC', self.magic_tel_positions, self.magic_tel_descriptions) # Open ROOT files self.calib_M1, self.calib_M2, self.star_M1, self.star_M2, self.superstar = None, None, None, None, None for file in self.file_list: uproot_file = uproot.open(file) if "_Y_" in file: if "_M1_" in file: self.calib_M1 = uproot_file["Events"] self.meta = uproot_file["RunHeaders"] elif "_M2_" in file: self.calib_M2 = uproot_file["Events"] if "_I_" in file: if "_M1_" in file: self.star_M1 = uproot_file["Events"] elif "_M2_" in file: self.star_M2 = uproot_file["Events"] if "_S_" in file: self.superstar = uproot_file["Events"] self.meta = uproot_file["RunHeaders"] self._mc_header = self._parse_mc_header()
def test_camera_from_name(camera_name): """ check we can construct all cameras from name""" camera = CameraReadout.from_name(camera_name) assert str(camera) == camera_name
def __init__(self, **kwargs): """ Constructor Parameters ---------- kwargs: dict Parameters to be passed. NOTE: The file mask of the data to read can be passed with the 'input_url' parameter. """ try: import uproot except ImportError: raise ImportError( "The 'uproot' package is required for the DLMAGICEventSource class." ) self.file_list = glob.glob(kwargs["input_url"]) self.file_list.sort() # Since EventSource can not handle file wild cards as input_url # We substitute the input_url with first file matching # the specified file mask. del kwargs["input_url"] super().__init__(input_url=self.file_list[0], **kwargs) # Translate MAGIC shower primary id to CTA convention self.magic_to_cta_shower_primary_id = { 1: 0, # gamma 14: 101, # MAGIC proton 3: 1, # MAGIC electron } # MAGIC telescope positions in m wrt. to the center of CTA simulations self.magic_tel_positions = { 1: [-27.24, -146.66, 50.00] * u.m, 2: [-96.44, -96.77, 51.00] * u.m, } self.magic_tel_positions = self.magic_tel_positions # MAGIC telescope description optics = OpticsDescription.from_name("MAGIC") geom = CameraGeometry.from_name("MAGICCam") # Camera Readout for NectarCam used as a placeholder readout = CameraReadout( "MAGICCam", sampling_rate=u.Quantity(1, u.GHz), reference_pulse_shape=np.array([norm.pdf(np.arange(96), 48, 6)]), reference_pulse_sample_width=u.Quantity(1, u.ns), ) camera = CameraDescription("MAGICCam", geom, readout) self.magic_tel_description = TelescopeDescription(name="MAGIC", tel_type="LST", optics=optics, camera=camera) self.magic_tel_descriptions = { 1: self.magic_tel_description, 2: self.magic_tel_description, } self.magic_subarray = SubarrayDescription("MAGIC", self.magic_tel_positions, self.magic_tel_descriptions) # Open ROOT files self.calib_M1, self.calib_M2, self.star_M1, self.star_M2, self.superstar = ( None, None, None, None, None, ) for file in self.file_list: uproot_file = uproot.open(file) if "_Y_" in file: if "_M1_" in file: self.calib_M1 = uproot_file["Events"] self.meta = uproot_file["RunHeaders"] elif "_M2_" in file: self.calib_M2 = uproot_file["Events"] if "_I_" in file: if "_M1_" in file: self.star_M1 = uproot_file["Events"] elif "_M2_" in file: self.star_M2 = uproot_file["Events"] if "_S_" in file: self.superstar = uproot_file["Events"] self.meta = uproot_file["RunHeaders"] # figure out if MC or Data run self.mc = "MMcCorsikaRunHeader." in self.meta.keys() # get the run number directly from the root file if self.mc: self.run_number = int( uproot_file["RunHeaders"]["MMcCorsikaRunHeader."] ["MMcCorsikaRunHeader.fRunNumber"].array()[0]) else: self.run_number = int(uproot_file["RunHeaders"]["MRawRunHeader_1."] ["MRawRunHeader_1.fRunNumber"].array()[0]) self._header = self._parse_header()
def _build_telescope_description(self, file, tel_id): pix_x, pix_y = u.Quantity(file.get_pixel_position(tel_id), u.m) focal_length = u.Quantity(file.get_optical_foclen(tel_id), u.m) n_pixels = len(pix_x) try: telescope = guess_telescope(n_pixels, focal_length) except ValueError: telescope = UNKNOWN_TELESCOPE pixel_shape = file.get_pixel_shape(tel_id)[0] try: pix_type, pix_rot = CameraGeometry.simtel_shape_to_type( pixel_shape) except ValueError: warnings.warn( f'Unkown pixel_shape {pixel_shape} for tel_id {tel_id}', UnknownPixelShapeWarning, ) pix_type = 'hexagon' pix_rot = '0d' pix_area = u.Quantity(file.get_pixel_area(tel_id), u.m**2) mirror_area = u.Quantity(file.get_mirror_area(tel_id), u.m**2) num_tiles = file.get_mirror_number(tel_id) cam_rot = file.get_camera_rotation_angle(tel_id) num_mirrors = file.get_mirror_number(tel_id) sampling_rate = u.Quantity(1 / file.get_time_slice(tel_id), u.GHz) reference_pulse_shape = file.get_ref_shapes(tel_id) reference_pulse_sample_width = u.Quantity(file.get_ref_step(tel_id), u.ns) geometry = CameraGeometry( telescope.camera_name, pix_id=np.arange(n_pixels), pix_x=pix_x, pix_y=pix_y, pix_area=pix_area, pix_type=pix_type, pix_rotation=pix_rot, cam_rotation=-Angle(cam_rot, u.rad), apply_derotation=True, ) readout = CameraReadout( telescope.camera_name, sampling_rate=sampling_rate, reference_pulse_shape=reference_pulse_shape, reference_pulse_sample_width=reference_pulse_sample_width, ) camera = CameraDescription(camera_name=telescope.camera_name, geometry=geometry, readout=readout) optics = OpticsDescription( name=telescope.name, num_mirrors=num_mirrors, equivalent_focal_length=focal_length, mirror_area=mirror_area, num_mirror_tiles=num_tiles, ) return TelescopeDescription(name=telescope.name, tel_type=telescope.type, optics=optics, camera=camera)