def subarray(): subarray = SubarrayDescription( "test array", tel_positions={ 1: np.zeros(3) * u.m, 2: np.zeros(3) * u.m }, tel_descriptions={ 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), 2: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), }, ) # Create reference pulse sample_width = 0.5 reference_pulse_sample_width = sample_width / 10 reference_pulse_duration = 100 pulse_sigma = 6 ref_time = np.arange(0, reference_pulse_duration, reference_pulse_sample_width) reference_pulse = norm.pdf(ref_time, reference_pulse_duration / 2, pulse_sigma) readout = subarray.tel[1].camera.readout readout.reference_pulse_shape = np.array([reference_pulse]) readout.reference_pulse_sample_width = u.Quantity( reference_pulse_sample_width, u.ns) readout.sampling_rate = u.Quantity(1 / sample_width, u.GHz) return subarray
def camera_waveforms(): subarray = SubarrayDescription( "test array", tel_positions={ 1: np.zeros(3) * u.m, 2: np.ones(3) * u.m }, tel_descriptions={ 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), 2: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), }) n_pixels = subarray.tel[1].camera.n_pixels n_samples = 96 mid = n_samples // 2 pulse_sigma = 6 random = np.random.RandomState(1) x = np.arange(n_samples) # Randomize times t_pulse = random.uniform(mid - 10, mid + 10, n_pixels)[:, np.newaxis] # Create pulses y = norm.pdf(x, t_pulse, pulse_sigma) # Randomize amplitudes y *= random.uniform(100, 1000, n_pixels)[:, np.newaxis] return y, subarray
def test_hdf(example_subarray): import tables with tempfile.NamedTemporaryFile(suffix=".hdf5") as f: example_subarray.to_hdf(f.name) read = SubarrayDescription.from_hdf(f.name) assert example_subarray == read # test that subarrays without name (v0.8.0) work: with tables.open_file(f.name, "r+") as hdf: del hdf.root.configuration.instrument.subarray._v_attrs.name no_name = SubarrayDescription.from_hdf(f.name) assert no_name.name == "Unknown" # test with a subarray that has two different telescopes with the same # camera tel = { 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), 2: TelescopeDescription.from_name(optics_name="SST-GCT", camera_name="CHEC"), } pos = {1: [0, 0, 0] * u.m, 2: [50, 0, 0] * u.m} array = SubarrayDescription("test array", tel_positions=pos, tel_descriptions=tel) with tempfile.NamedTemporaryFile(suffix=".hdf5") as f: array.to_hdf(f.name) read = SubarrayDescription.from_hdf(f.name) assert array == read
def test_hdf(example_subarray): import tables with tempfile.NamedTemporaryFile(suffix=".hdf5") as f: example_subarray.to_hdf(f.name) read = SubarrayDescription.from_hdf(f.name) assert example_subarray == read # test we can write the read subarray read.to_hdf(f.name, overwrite=True) for tel_id, tel in read.tel.items(): assert (tel.camera.geometry.frame.focal_length == tel.optics.equivalent_focal_length) # test if transforming works tel.camera.geometry.transform_to(TelescopeFrame()) # test that subarrays without name (v0.8.0) work: with tables.open_file(f.name, "r+") as hdf: del hdf.root.configuration.instrument.subarray._v_attrs.name no_name = SubarrayDescription.from_hdf(f.name) assert no_name.name == "Unknown" # test with a subarray that has two different telescopes with the same # camera tel = { 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), 2: TelescopeDescription.from_name(optics_name="SST-GCT", camera_name="CHEC"), } pos = {1: [0, 0, 0] * u.m, 2: [50, 0, 0] * u.m} array = SubarrayDescription("test array", tel_positions=pos, tel_descriptions=tel) with tempfile.NamedTemporaryFile(suffix=".hdf5") as f: array.to_hdf(f.name) read = SubarrayDescription.from_hdf(f.name) assert array == read
def plot_telescope_layout(tel_layout_file_name): layout_file = "/Users/alicedonini/PycharmProjects/Pointing_tool/layout-3AL4-BN15-MST.txt" grd_coords = pd.read_csv(layout_file, header=None, delimiter=" ", names=["x", "y", "z"], engine='python') # convert to m grd_coords = grd_coords / 100 # create a dictionary with the tel position on the ground by tel_id and the tel description tel_descr = {} G_coords = {} for tel_id, coord in enumerate(grd_coords.values, 1): G_coords[tel_id] = coord * u.m tel_descr[tel_id] = TelescopeDescription.from_name( optics_name='MST', camera_name='NectarCam') # create the subarray sub = SubarrayDescription(name="Baseline only MST", tel_positions=G_coords, tel_descriptions=tel_descr) #sub.info() #sub.to_table(kind='optics') # display the array plt.figure(num=None, figsize=(7, 7), facecolor='w', edgecolor='k') disp = ArrayDisplay(sub, tel_scale=3.0) return sub
def test_hdf_duplicate_string_repr(tmp_path): """Test writing and reading of a subarray with two telescopes that are different but have the same name. """ # test with a subarray that has two different telescopes with the same # camera tel1 = TelescopeDescription.from_name(optics_name="LST", camera_name="LSTCam") # second telescope is almost the same and as the same str repr tel2 = deepcopy(tel1) # e.g. one mirror fell off tel2.optics.num_mirror_tiles = tel1.optics.num_mirror_tiles - 1 array = SubarrayDescription( "test array", tel_positions={1: [0, 0, 0] * u.m, 2: [50, 0, 0] * u.m}, tel_descriptions={1: tel1, 2: tel2}, ) # defensive checks to make sure we are actually testing this assert len(array.telescope_types) == 2 assert str(tel1) == str(tel2) assert tel1 != tel2 path = tmp_path / "subarray.h5" array.to_hdf(path) read = SubarrayDescription.from_hdf(path) assert array == read assert ( read.tel[1].optics.num_mirror_tiles == read.tel[2].optics.num_mirror_tiles + 1 )
def test_hdf_same_camera(tmp_path): """Test writing / reading subarray to hdf5 with a subarray that has two different telescopes with the same camera """ tel = { 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), 2: TelescopeDescription.from_name(optics_name="SST-GCT", camera_name="CHEC"), } pos = {1: [0, 0, 0] * u.m, 2: [50, 0, 0] * u.m} array = SubarrayDescription("test array", tel_positions=pos, tel_descriptions=tel) path = tmp_path / "subarray.h5" array.to_hdf(path) read = SubarrayDescription.from_hdf(path) assert array == read
def subarray_lst(): telid = 1 subarray = SubarrayDescription( "test array lst", tel_positions={1: np.zeros(3) * u.m, 2: np.ones(3) * u.m}, tel_descriptions={ 1: TelescopeDescription.from_name(optics_name="LST", camera_name="LSTCam"), 2: TelescopeDescription.from_name(optics_name="LST", camera_name="LSTCam"), }, ) n_pixels = subarray.tel[telid].camera.geometry.n_pixels n_samples = 30 selected_gain_channel = np.zeros(n_pixels, dtype=np.int) return subarray, telid, selected_gain_channel, n_pixels, n_samples
def test_array_display(): from ctapipe.visualization.mpl_array import ArrayDisplay # build a test subarray: tels = dict() tel_pos = dict() for ii, pos in enumerate([[0, 0, 0], [100, 0, 0], [-100, 0, 0]] * u.m): tels[ii + 1] = TelescopeDescription.from_name("MST", "NectarCam") tel_pos[ii + 1] = pos sub = SubarrayDescription(name="TestSubarray", tel_positions=tel_pos, tel_descriptions=tels) ad = ArrayDisplay(sub) ad.set_vector_rho_phi(1 * u.m, 90 * u.deg) # try setting a value vals = ones(sub.num_tels) ad.values = vals assert (vals == ad.values).all() # test using hillas params: hillas_dict = { 1: HillasParametersContainer(length=1.0 * u.m, phi=90 * u.deg), 2: HillasParametersContainer(length=200 * u.cm, phi="95deg"), } ad.set_vector_hillas(hillas_dict) ad.add_labels() ad.remove_labels()
def test_muon_efficiency_fit(): from ctapipe.instrument import TelescopeDescription, SubarrayDescription from ctapipe.coordinates import TelescopeFrame, CameraFrame from ctapipe.image.muon.intensity_fitter import image_prediction, MuonIntensityFitter telescope = TelescopeDescription.from_name('LST', 'LSTCam') subarray = SubarrayDescription( 'LSTMono', {0: [0, 0, 0] * u.m}, {0: telescope}, ) center_x = 0.8 * u.deg center_y = 0.4 * u.deg radius = 1.2 * u.deg ring_width = 0.05 * u.deg impact_parameter = 5 * u.m phi = 0 * u.rad efficiency = 0.5 focal_length = telescope.optics.equivalent_focal_length geom = telescope.camera.geometry mirror_radius = np.sqrt(telescope.optics.mirror_area / np.pi) pixel_diameter = 2 * u.rad * (np.sqrt(geom.pix_area / np.pi) / focal_length).to_value(u.dimensionless_unscaled) tel = CameraFrame( x=geom.pix_x, y=geom.pix_y, focal_length=focal_length, rotation=geom.cam_rotation, ).transform_to(TelescopeFrame()) x = tel.fov_lon y = tel.fov_lat image = image_prediction( mirror_radius, hole_radius=0 * u.m, impact_parameter=impact_parameter, phi=phi, center_x=center_x, center_y=center_y, radius=radius, ring_width=ring_width, pixel_x=x, pixel_y=y, pixel_diameter=pixel_diameter[0] ) fitter = MuonIntensityFitter(subarray=subarray) result = fitter( tel_id=0, center_x=center_x, center_y=center_y, radius=radius, image=image * efficiency, pedestal=np.full_like(image, 1.1) ) assert u.isclose(result.impact, impact_parameter, rtol=0.05) assert u.isclose(result.width, ring_width, rtol=0.05) assert u.isclose(result.optical_efficiency, efficiency, rtol=0.05)
def test_array_display(): """ check that we can do basic array display functionality """ from ctapipe.visualization.mpl_array import ArrayDisplay from ctapipe.image import timing_parameters # build a test subarray: tels = dict() tel_pos = dict() for ii, pos in enumerate([[0, 0, 0], [100, 0, 0], [-100, 0, 0]] * u.m): tels[ii + 1] = TelescopeDescription.from_name("MST", "NectarCam") tel_pos[ii + 1] = pos sub = SubarrayDescription(name="TestSubarray", tel_positions=tel_pos, tel_descriptions=tels) ad = ArrayDisplay(sub) ad.set_vector_rho_phi(1 * u.m, 90 * u.deg) # try setting a value vals = ones(sub.num_tels) ad.values = vals assert (vals == ad.values).all() # test using hillas params: hillas_dict = { 1: HillasParametersContainer(length=100.0 * u.m, psi=90 * u.deg), 2: HillasParametersContainer(length=20000 * u.cm, psi="95deg"), } grad = 2 intercept = 1 geom = CameraGeometry.from_name("LSTCam") rot_angle = 20 * u.deg hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=rot_angle) timing_rot20 = timing_parameters( geom, image=ones(geom.n_pixels), peak_time=intercept + grad * geom.pix_x.value, hillas_parameters=hillas, cleaning_mask=ones(geom.n_pixels, dtype=bool), ) gradient_dict = { 1: timing_rot20.slope.value, 2: timing_rot20.slope.value, } ad.set_vector_hillas( hillas_dict=hillas_dict, length=500, time_gradient=gradient_dict, angle_offset=0 * u.deg, ) ad.set_line_hillas(hillas_dict, range=300) ad.add_labels() ad.remove_labels()
def get_telescope_description(optics_name: str, cam_name: str) -> TelescopeDescription: if telescope_descriptions.get(optics_name) is None: telescope_descriptions[optics_name] = dict() if telescope_descriptions[optics_name].get(cam_name) is None: telescope_descriptions[optics_name][ cam_name] = TelescopeDescription.from_name(optics_name, cam_name) return telescope_descriptions[optics_name][cam_name]
def __init__(self, config=None, tool=None, **kwargs): super().__init__(config=config, tool=tool, **kwargs) from protozfits import File self.file = File(self.input_url) # TODO: Correct pixel ordering self._tel_desc = TelescopeDescription.from_name( optics_name='SST-1M', camera_name='DigiCam' )
def subarray_1_LST(): subarray = SubarrayDescription( "One LST", tel_positions={1: np.zeros(3) * u.m}, tel_descriptions={ 1: TelescopeDescription.from_name(optics_name="LST", camera_name="LSTCam") }, ) return subarray
def test_tel_ids_to_mask(example_subarray): lst = TelescopeDescription.from_name("LST", "LSTCam") subarray = SubarrayDescription( "someone_counted_in_binary", tel_positions={1: [0, 0, 0] * u.m, 10: [50, 0, 0] * u.m}, tel_descriptions={1: lst, 10: lst}, ) assert np.all(subarray.tel_ids_to_mask([]) == [False, False]) assert np.all(subarray.tel_ids_to_mask([1]) == [True, False]) assert np.all(subarray.tel_ids_to_mask([10]) == [False, True]) assert np.all(subarray.tel_ids_to_mask([1, 10]) == [True, True])
def example_subarray(n_tels=10): """ generate a simple subarray for testing purposes """ pos = {} tel = {} for tel_id in range(1, n_tels + 1): tel[tel_id] = TelescopeDescription.from_name( optics_name="MST", camera_name="NectarCam" ) pos[tel_id] = np.random.uniform(-100, 100, size=3) * u.m return SubarrayDescription("test array", tel_positions=pos, tel_descriptions=tel)
def test_array_display(): from ctapipe.visualization.mpl_array import ArrayDisplay from ctapipe.image.timing_parameters import timing_parameters # build a test subarray: tels = dict() tel_pos = dict() for ii, pos in enumerate([[0, 0, 0], [100, 0, 0], [-100, 0, 0]] * u.m): tels[ii + 1] = TelescopeDescription.from_name("MST", "NectarCam") tel_pos[ii + 1] = pos sub = SubarrayDescription(name="TestSubarray", tel_positions=tel_pos, tel_descriptions=tels) ad = ArrayDisplay(sub) ad.set_vector_rho_phi(1 * u.m, 90 * u.deg) # try setting a value vals = ones(sub.num_tels) ad.values = vals assert (vals == ad.values).all() # test using hillas params: hillas_dict = { 1: HillasParametersContainer(length=100.0 * u.m, psi=90 * u.deg), 2: HillasParametersContainer(length=20000 * u.cm, psi="95deg"), } grad = 2 intercept = 1 rot_angle = 20 * u.deg timing_rot20 = timing_parameters(pix_x=arange(4) * u.deg, pix_y=zeros(4) * u.deg, image=ones(4), peak_time=intercept * u.ns + grad * arange(4) * u.ns, rotation_angle=rot_angle) gradient_dict = { 1: timing_rot20.gradient.value, 2: timing_rot20.gradient.value, } ad.set_vector_hillas(hillas_dict=hillas_dict, length=500, time_gradient=gradient_dict, angle_offset=0 * u.deg) ad.set_line_hillas(hillas_dict, range=300) ad.add_labels() ad.remove_labels()
def subarray(): lst = TelescopeDescription.from_name("LST", "LSTCam") tels = [lst] * 4 positions = { 1: [0, 0, 0] * u.m, 2: [50, 0, 0] * u.m, 3: [0, 50, 0] * u.m, 4: [50, 50, 0] * u.m, } descriptions = {i: t for i, t in enumerate(tels, start=1)} return SubarrayDescription("test", positions, descriptions)
def test_pedestal_calculator(): """ test of PedestalIntegrator """ from lstchain.calib.camera.pedestals import PedestalIntegrator tel_id = 0 n_events = 10 n_gain = 2 n_pixels = 1855 ped_level = 300 subarray = SubarrayDescription( "test array", tel_positions={0: np.zeros(3) * u.m}, tel_descriptions={ 0: TelescopeDescription.from_name( optics_name="SST-ASTRI", camera_name="CHEC" ), }, ) subarray.tel[0].camera.readout.reference_pulse_shape = np.ones((1, 2)) subarray.tel[0].camera.readout.reference_pulse_sample_width = u.Quantity(1, u.ns) config = Config({ "FixedWindowSum": { "apply_integration_correction": False, } }) ped_calculator = PedestalIntegrator(charge_product="FixedWindowSum", config=config, sample_size=n_events, tel_id=tel_id, subarray=subarray) # create one event data = ArrayEventContainer() data.meta['origin'] = 'test' # fill the values necessary for the pedestal calculation data.mon.tel[tel_id].pixel_status.hardware_failing_pixels = np.zeros( (n_gain, n_pixels), dtype=bool ) data.r1.tel[tel_id].waveform = np.full((2, n_pixels, 40), ped_level) data.trigger.time = Time(0, format='mjd', scale='tai') while ped_calculator.num_events_seen < n_events: if ped_calculator.calculate_pedestals(data): assert data.mon.tel[tel_id].pedestal assert np.mean(data.mon.tel[tel_id].pedestal.charge_median) == ( ped_calculator.extractor.window_width.tel[tel_id] * ped_level ) assert np.mean(data.mon.tel[tel_id].pedestal.charge_std) == 0
def test_get_tel_ids(example_subarray): """Test for SubarrayDescription.get_tel_ids""" subarray = example_subarray sst = TelescopeDescription.from_name("SST-ASTRI", "CHEC") telescopes = [1, 2, "MST_MST_FlashCam", sst] tel_ids = subarray.get_tel_ids(telescopes) true_tel_ids = (subarray.get_tel_ids_for_type("MST_MST_FlashCam") + subarray.get_tel_ids_for_type(sst) + [1, 2]) assert sorted(tel_ids) == sorted(true_tel_ids) # test invalid telescope type with pytest.raises(Exception): tel_ids = subarray.get_tel_ids(["It's a-me, Mario!"])
def test_telescope_component(): from ctapipe.core import TelescopeComponent from ctapipe.instrument import SubarrayDescription, TelescopeDescription subarray = SubarrayDescription( "test", tel_positions={1: [0, 0, 0] * u.m}, tel_descriptions={1: TelescopeDescription.from_name("LST", "LSTCam")}, ) class Base(TelescopeComponent): pass class Sub(Base): pass assert isinstance(Base.from_name("Sub", subarray=subarray), Sub)
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
def test_pedestal_calculator(): """ test of PedestalIntegrator """ tel_id = 0 n_events = 10 n_gain = 2 n_pixels = 1855 ped_level = 300 subarray = SubarrayDescription( "test array", tel_positions={0: np.zeros(3) * u.m}, tel_descriptions={ 0: TelescopeDescription.from_name( optics_name="SST-ASTRI", camera_name="CHEC" ), }, ) subarray.tel[0].camera.readout.reference_pulse_shape = np.ones((1, 2)) subarray.tel[0].camera.readout.reference_pulse_sample_width = u.Quantity(1, u.ns) ped_calculator = PedestalIntegrator( subarray=subarray, charge_product="FixedWindowSum", sample_size=n_events, tel_id=tel_id, ) # create one event data = EventAndMonDataContainer() data.meta["origin"] = "test" # fill the values necessary for the pedestal calculation data.mon.tel[tel_id].pixel_status.hardware_failing_pixels = np.zeros( (n_gain, n_pixels), dtype=bool ) data.r1.tel[tel_id].waveform = np.full((2, n_pixels, 40), ped_level) data.r1.tel[tel_id].trigger_time = 1000 while ped_calculator.num_events_seen < n_events: if ped_calculator.calculate_pedestals(data): assert data.mon.tel[tel_id].pedestal assert np.mean(data.mon.tel[tel_id].pedestal.charge_median) == ( ped_calculator.extractor.window_width.tel[0] * ped_level ) assert np.mean(data.mon.tel[tel_id].pedestal.charge_std) == 0
def test_subarray_description(): pos = {} tel = {} n_tels = 10 for tel_id in range(1, n_tels + 1): tel[tel_id] = TelescopeDescription.from_name( optics_name="MST", camera_name="NectarCam", ) pos[tel_id] = np.random.uniform(-100, 100, size=3) * u.m sub = SubarrayDescription( "test array", tel_positions=pos, tel_descriptions=tel ) sub.peek() assert len(sub.telescope_types) == 1 assert str(sub) == "test array" assert sub.num_tels == n_tels assert len(sub.tel_ids) == n_tels assert sub.tel_ids[0] == 1 assert sub.tel[1].camera is not None assert 0 not in sub.tel # check that there is no tel 0 (1 is first above) assert len(sub.to_table()) == n_tels assert len(sub.camera_types) == 1 # only 1 camera type assert sub.camera_types[0] == 'NectarCam' assert sub.optics_types[0].equivalent_focal_length.to_value(u.m) == 16.0 assert sub.telescope_types[0] == 'MST:NectarCam' assert sub.tel_coords assert isinstance(sub.tel_coords, SkyCoord) assert len(sub.tel_coords) == n_tels subsub = sub.select_subarray("newsub", [2, 3, 4, 6]) assert subsub.num_tels == 4 assert set(subsub.tels.keys()) == {2, 3, 4, 6} assert subsub.tel_indices[6] == 3 assert subsub.tel_ids[3] == 6 assert len(sub.to_table(kind='optics')) == 1
def test_scts(): from ctapipe.instrument import TelescopeDescription, SubarrayDescription from ctapipe.image.muon.intensity_fitter import MuonIntensityFitter telescope = TelescopeDescription.from_name('SST-ASTRI', 'CHEC') subarray = SubarrayDescription( 'ssts', {0: [0, 0, 0] * u.m}, {0: telescope}, ) fitter = MuonIntensityFitter(subarray=subarray) with pytest.raises(NotImplementedError): fitter( tel_id=0, center_x=0 * u.deg, center_y=2 * u.deg, radius=1.3 * u.deg, image=np.zeros(telescope.camera.geometry.n_pixels), pedestal=np.zeros(telescope.camera.geometry.n_pixels) )
def test_estimator_results(): """ creating some planes pointing in different directions (two north-south, two east-west) and that have a slight position errors (+- 0.1 m in one of the four cardinal directions """ horizon_frame = AltAz() p1 = SkyCoord(alt=43 * u.deg, az=45 * u.deg, frame=horizon_frame) p2 = SkyCoord(alt=47 * u.deg, az=45 * u.deg, frame=horizon_frame) circle1 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, 1, 0] * u.m) p1 = SkyCoord(alt=44 * u.deg, az=90 * u.deg, frame=horizon_frame) p2 = SkyCoord(alt=46 * u.deg, az=90 * u.deg, frame=horizon_frame) circle2 = HillasPlane(p1=p1, p2=p2, telescope_position=[1, 0, 0] * u.m) p1 = SkyCoord(alt=44.5 * u.deg, az=45 * u.deg, frame=horizon_frame) p2 = SkyCoord(alt=46.5 * u.deg, az=45 * u.deg, frame=horizon_frame) circle3 = HillasPlane(p1=p1, p2=p2, telescope_position=[0, -1, 0] * u.m) p1 = SkyCoord(alt=43.5 * u.deg, az=90 * u.deg, frame=horizon_frame) p2 = SkyCoord(alt=45.5 * u.deg, az=90 * u.deg, frame=horizon_frame) circle4 = HillasPlane(p1=p1, p2=p2, telescope_position=[-1, 0, 0] * u.m) # Create a dummy subarray # (not used here, but required to initialize the reconstructor) subarray = SubarrayDescription( "test array", tel_positions={1: np.zeros(3) * u.m}, tel_descriptions={ 1: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC") }, ) # creating the fit class and setting the the great circle member fit = HillasReconstructor(subarray) hillas_planes = {1: circle1, 2: circle2, 3: circle3, 4: circle4} # performing the direction fit with the minimisation algorithm # and a seed that is perpendicular to the up direction dir_fit_minimise, _ = fit.estimate_direction(hillas_planes) print("direction fit test minimise:", dir_fit_minimise)
def test_subarray_description(): pos = {} tel = {} n_tels = 10 for tel_id in range(1, n_tels + 1): tel[tel_id] = TelescopeDescription.from_name( optics_name="MST", camera_name="NectarCam", ) pos[tel_id] = np.random.uniform(-100, 100, size=3) * u.m sub = SubarrayDescription( "test array", tel_positions=pos, tel_descriptions=tel ) assert len(sub.telescope_types) == 1 assert str(sub) == "test array" assert sub.num_tels == n_tels assert len(sub.tel_ids) == n_tels assert sub.tel_ids[0] == 1 assert sub.tel[1].camera is not None assert 0 not in sub.tel # check that there is no tel 0 (1 is first above) assert len(sub.to_table()) == n_tels assert len(sub.camera_types) == 1 # only 1 camera type assert sub.camera_types[0] == 'NectarCam' assert sub.optics_types[0].equivalent_focal_length.to_value(u.m) == 16.0 assert sub.telescope_types[0] == 'MST:NectarCam' assert sub.tel_coords assert isinstance(sub.tel_coords, SkyCoord) assert len(sub.tel_coords) == n_tels subsub = sub.select_subarray("newsub", [2, 3, 4, 6]) assert subsub.num_tels == 4 assert set(subsub.tels.keys()) == {2, 3, 4, 6} assert subsub.tel_indices[6] == 3 assert subsub.tel_ids[3] == 6 assert len(sub.to_table(kind='optics')) == 1
def test_image_cleaner(method): """ Test that we can construct and use a component-based ImageCleaner""" config = Config({ "TailcutsImageCleaner": { "boundary_threshold_pe": 5.0, "picture_threshold_pe": 10.0, }, "MARSImageCleaner": { "boundary_threshold_pe": 5.0, "picture_threshold_pe": 10.0, }, "FACTImageCleaner": { "boundary_threshold_pe": 5.0, "picture_threshold_pe": 10.0, "time_limit_ns": 6.0, }, }) tel = TelescopeDescription.from_name("MST", "NectarCam") subarray = SubarrayDescription(name="test", tel_positions={1: None}, tel_descriptions={1: tel}) clean = ImageCleaner.from_name(method, config=config, subarray=subarray) image = np.zeros_like(tel.camera.geometry.pix_x.value, dtype=np.float) image[10:30] = 20.0 image[31:40] = 8.0 times = np.linspace(-5, 10, image.shape[0]) mask = clean(tel_id=1, image=image, arrival_times=times) # we're not testing the algorithm here, just that it does something (for the # algorithm tests, see test_cleaning.py assert np.count_nonzero(mask) > 0
import matplotlib.pylab as plt import numpy as np from astropy import units as u from ctapipe.instrument import CameraGeometry from ctapipe.visualization import CameraDisplay from ctapipe.image import toymodel from matplotlib.animation import FuncAnimation from ctapipe.instrument import TelescopeDescription if __name__ == '__main__': plt.style.use("ggplot") fig, ax = plt.subplots() # load the camera tel = TelescopeDescription.from_name("SST-1M", "DigiCam") print(tel, tel.optics.effective_focal_length) geom = tel.camera # poor-man's coordinate transform from telscope to camera frame (it's # better to use ctapipe.coordiantes when they are stable) scale = tel.optics.effective_focal_length.to(geom.pix_x.unit).value fov = np.deg2rad(4.0) maxwid = np.deg2rad(0.01) maxlen = np.deg2rad(0.03) disp = CameraDisplay(geom, ax=ax) disp.cmap = plt.cm.terrain disp.add_colorbar(ax=ax) def update(frame):
def test_flasherflatfieldcalculator(): """test of flasherFlatFieldCalculator""" tel_id = 0 n_gain = 2 n_events = 10 n_pixels = 1855 ff_level = 10000 subarray = SubarrayDescription( "test array", tel_positions={0: np.zeros(3) * u.m}, tel_descriptions={ 0: TelescopeDescription.from_name(optics_name="SST-ASTRI", camera_name="CHEC"), }, ) subarray.tel[0].camera.readout.reference_pulse_shape = np.ones((1, 2)) subarray.tel[0].camera.readout.reference_pulse_sample_width = u.Quantity( 1, u.ns) config = Config({ "FixedWindowSum": { "window_shift": 5, "window_width": 10, "peak_index": 20, "apply_integration_correction": False, } }) ff_calculator = FlasherFlatFieldCalculator(subarray=subarray, charge_product="FixedWindowSum", sample_size=n_events, tel_id=tel_id, config=config) # create one event data = ArrayEventContainer() data.meta['origin'] = 'test' data.trigger.time = Time(0, format='mjd', scale='tai') # initialize mon and r1 data data.mon.tel[tel_id].pixel_status.hardware_failing_pixels = np.zeros( (n_gain, n_pixels), dtype=bool) data.mon.tel[tel_id].pixel_status.pedestal_failing_pixels = np.zeros( (n_gain, n_pixels), dtype=bool) data.mon.tel[tel_id].pixel_status.flatfield_failing_pixels = np.zeros( (n_gain, n_pixels), dtype=bool) data.r1.tel[tel_id].waveform = np.zeros((n_gain, n_pixels, 40), dtype=np.float32) # data.r1.tel[tel_id].trigger_time = 1000 # flat-field signal put == delta function of height ff_level at sample 20 data.r1.tel[tel_id].waveform[:, :, 20] = ff_level print(data.r1.tel[tel_id].waveform[0, 0, 20]) # First test: good event while ff_calculator.num_events_seen < n_events: if ff_calculator.calculate_relative_gain(data): assert data.mon.tel[tel_id].flatfield print(data.mon.tel[tel_id].flatfield) assert np.mean( data.mon.tel[tel_id].flatfield.charge_median) == ff_level assert np.mean( data.mon.tel[tel_id].flatfield.relative_gain_median) == 1 assert np.mean( data.mon.tel[tel_id].flatfield.relative_gain_std) == 0 # Second test: introduce some failing pixels failing_pixels_id = np.array([10, 20, 30, 40]) data.r1.tel[tel_id].waveform[:, failing_pixels_id, :] = 0 data.mon.tel[ tel_id].pixel_status.pedestal_failing_pixels[:, failing_pixels_id] = True while ff_calculator.num_events_seen < n_events: if ff_calculator.calculate_relative_gain(data): # working pixel have good gain assert ( data.mon.tel[tel_id].flatfield.relative_gain_median[0, 0] == 1) # bad pixels do non influence the gain assert np.mean( data.mon.tel[tel_id].flatfield.relative_gain_std) == 0
def _display_camera_animation(self): # plt.style.use("ggplot") fig = plt.figure(num="ctapipe Camera Demo", figsize=(7, 7)) ax = plt.subplot(111) # load the camera tel = TelescopeDescription.from_name(optics_name=self.optics, camera_name=self.camera) geom = tel.camera # poor-man's coordinate transform from telscope to camera frame (it's # better to use ctapipe.coordiantes when they are stable) scale = tel.optics.effective_focal_length.to(geom.pix_x.unit).value fov = np.deg2rad(4.0) maxwid = np.deg2rad(0.01) maxlen = np.deg2rad(0.03) disp = CameraDisplay(geom, ax=ax, autoupdate=True, title="{}, f={}".format( tel, tel.optics.effective_focal_length)) disp.cmap = plt.cm.terrain def update(frame): centroid = np.random.uniform(-fov, fov, size=2) * scale width = np.random.uniform(0, maxwid) * scale length = np.random.uniform(0, maxlen) * scale + width angle = np.random.uniform(0, 360) intens = np.random.exponential(2) * 50 model = toymodel.generate_2d_shower_model(centroid=centroid, width=width, length=length, psi=angle * u.deg) image, sig, bg = toymodel.make_toymodel_shower_image( geom, model.pdf, intensity=intens, nsb_level_pe=5000) # alternate between cleaned and raw images if self._counter == self.cleanframes: plt.suptitle("Image Cleaning ON") self.imclean = True if self._counter == self.cleanframes * 2: plt.suptitle("Image Cleaning OFF") self.imclean = False self._counter = 0 if self.imclean: cleanmask = tailcuts_clean(geom, image / 80.0) for ii in range(3): dilate(geom, cleanmask) image[cleanmask == 0] = 0 # zero noise pixels self.log.debug("count = {}, image sum={} max={}".format( self._counter, image.sum(), image.max())) disp.image = image if self.autoscale: disp.set_limits_percent(95) else: disp.set_limits_minmax(-100, 4000) disp.axes.figure.canvas.draw() self._counter += 1 return [ ax, ] self.anim = FuncAnimation(fig, update, interval=self.delay, blit=self.blit) plt.show()
import matplotlib.pylab as plt import numpy as np from astropy import units as u from matplotlib.animation import FuncAnimation from ctapipe.image import toymodel from ctapipe.instrument import TelescopeDescription from ctapipe.visualization import CameraDisplay if __name__ == '__main__': plt.style.use("ggplot") fig, ax = plt.subplots() # load the camera tel = TelescopeDescription.from_name("SST-1M", "DigiCam") geom = tel.camera fov = 0.3 maxwid = 0.05 maxlen = 0.1 disp = CameraDisplay(geom, ax=ax) disp.cmap = 'inferno' disp.add_colorbar(ax=ax) def update(frame): x, y = np.random.uniform(-fov, fov, size=2) width = np.random.uniform(0.01, maxwid) length = np.random.uniform(width, maxlen) angle = np.random.uniform(0, 180)
def _display_camera_animation(self): # plt.style.use("ggplot") fig = plt.figure(num="ctapipe Camera Demo", figsize=(7, 7)) ax = plt.subplot(111) # load the camera tel = TelescopeDescription.from_name(optics_name=self.optics, camera_name=self.camera) geom = tel.camera # poor-man's coordinate transform from telscope to camera frame (it's # better to use ctapipe.coordiantes when they are stable) foclen = tel.optics.equivalent_focal_length.to(geom.pix_x.unit).value fov = np.deg2rad(4.0) scale = foclen minwid = np.deg2rad(0.1) maxwid = np.deg2rad(0.3) maxlen = np.deg2rad(0.5) self.log.debug("scale={} m, wid=({}-{})".format(scale, minwid, maxwid)) disp = CameraDisplay( geom, ax=ax, autoupdate=True, title="{}, f={}".format(tel, tel.optics.equivalent_focal_length) ) disp.cmap = plt.cm.terrain def update(frame): centroid = np.random.uniform(-fov, fov, size=2) * scale width = np.random.uniform(0, maxwid-minwid) * scale + minwid length = np.random.uniform(0, maxlen) * scale + width angle = np.random.uniform(0, 360) intens = np.random.exponential(2) * 500 model = toymodel.generate_2d_shower_model(centroid=centroid, width=width, length=length, psi=angle * u.deg) self.log.debug( "Frame=%d width=%03f length=%03f intens=%03d", frame, width, length, intens ) image, sig, bg = toymodel.make_toymodel_shower_image( geom, model.pdf, intensity=intens, nsb_level_pe=3, ) # alternate between cleaned and raw images if self._counter == self.cleanframes: plt.suptitle("Image Cleaning ON") self.imclean = True if self._counter == self.cleanframes * 2: plt.suptitle("Image Cleaning OFF") self.imclean = False self._counter = 0 disp.clear_overlays() if self.imclean: cleanmask = tailcuts_clean(geom, image, picture_thresh=10.0, boundary_thresh=5.0) for ii in range(2): dilate(geom, cleanmask) image[cleanmask == 0] = 0 # zero noise pixels try: hillas = hillas_parameters(geom, image) disp.overlay_moments(hillas, with_label=False, color='red', alpha=0.7, linewidth=2, linestyle='dashed') except HillasParameterizationError: disp.clear_overlays() pass self.log.debug("Frame=%d image_sum=%.3f max=%.3f", self._counter, image.sum(), image.max()) disp.image = image if self.autoscale: disp.set_limits_percent(95) else: disp.set_limits_minmax(-5, 200) disp.axes.figure.canvas.draw() self._counter += 1 return [ax, ] frames = None if self.num_events == 0 else self.num_events repeat = True if self.num_events == 0 else False self.log.info("Running for {} frames".format(frames)) self.anim = FuncAnimation(fig, update, interval=self.delay, frames=frames, repeat=repeat, blit=self.blit) if self.display: plt.show()