def test_reconstruction_works(subarray_and_event_gamma_off_axis_500_gev): subarray, event = subarray_and_event_gamma_off_axis_500_gev reconstructor = HillasIntersection() array_pointing = SkyCoord( az=event.pointing.array_azimuth, alt=event.pointing.array_altitude, frame=AltAz(), ) hillas_dict = { tel_id: dl1.parameters.hillas for tel_id, dl1 in event.dl1.tel.items() if dl1.parameters.hillas.width.value > 0 } telescope_pointings = { tel_id: SkyCoord(alt=pointing.altitude, az=pointing.azimuth, frame=AltAz()) for tel_id, pointing in event.pointing.tel.items() if tel_id in hillas_dict } result = reconstructor.predict(hillas_dict, subarray, array_pointing, telescope_pointings) reco_coord = SkyCoord(alt=result.alt, az=result.az, frame=AltAz()) true_coord = SkyCoord(alt=event.simulation.shower.alt, az=event.simulation.shower.az, frame=AltAz()) assert reco_coord.separation(true_coord) < 0.1 * u.deg
def test_selected_subarray(subarray_and_event_gamma_off_axis_500_gev): """test that reconstructor also works with "missing" ids""" subarray, event = subarray_and_event_gamma_off_axis_500_gev # remove telescopes 2 and 3 to see that HillasIntersection can work # with arbirary telescope ids subarray = subarray.select_subarray([1, 4]) reconstructor = HillasIntersection() array_pointing = SkyCoord( az=event.pointing.array_azimuth, alt=event.pointing.array_altitude, frame=AltAz(), ) # again, only use telescopes 1 and 4 hillas_dict = { tel_id: dl1.parameters.hillas for tel_id, dl1 in event.dl1.tel.items() if dl1.parameters.hillas.width.value > 0 and tel_id in {1, 4} } telescope_pointings = { tel_id: SkyCoord(alt=pointing.altitude, az=pointing.azimuth, frame=AltAz()) for tel_id, pointing in event.pointing.tel.items() if tel_id in hillas_dict } reconstructor.predict(hillas_dict, subarray, array_pointing, telescope_pointings)
def nominal_to_altaz(): nom = SkyCoord( x=0 * u.deg, y=0 * u.deg, frame=NominalFrame(origin=AltAz(alt=75 * u.deg, az=180 * u.deg))) alt_az = nom.transform_to(AltAz()) print("HorizonCoordinate", alt_az)
def test_reconstruction_works(subarray_and_event_gamma_off_axis_500_gev): subarray, event = subarray_and_event_gamma_off_axis_500_gev reconstructor = HillasIntersection(subarray) true_coord = SkyCoord( alt=event.simulation.shower.alt, az=event.simulation.shower.az, frame=AltAz() ) result = reconstructor(event) reco_coord = SkyCoord(alt=result.alt, az=result.az, frame=AltAz()) assert reco_coord.separation(true_coord) < 0.1 * u.deg
def grd_to_tilt(): grd_coord = GroundFrame(x=1 * u.m, y=2 * u.m, z=0 * u.m) tilt_coord = grd_coord.transform_to( TiltedGroundFrame( pointing_direction=AltAz(alt=90 * u.deg, az=180 * u.deg))) print(project_to_ground(tilt_coord)) print("Tilted Coordinate", tilt_coord)
def to_nominal_frame(self, alt, az): alt_LST = 70 # deg if self.plike: alt_LST = 69.6 # deg az_LST = 180 # deg point = AltAz(alt=alt_LST * u.deg, az=az_LST * u.deg) # alt = np.array(indexes['alt']) # altitude # az = np.array(indexes['az']) # azimuth # print("\nalt shape: {}, az shape: {}".format(indexes['alt'].shape, indexes['az'].shape)) src = AltAz(alt=alt * u.deg, az=az * u.deg) source_direction = src.transform_to(NominalFrame(origin=point)) delta_alt = source_direction.delta_alt.deg delta_az = source_direction.delta_az.deg return delta_alt, delta_az
def configure(self, config): config["pix_pos"] = self.pix_pos config["fov"] = self.fov td = config["time_step"] n_frames = config["n_frames"] # precomputing transformations # Will need to do this smarter (in chunks) when the number of frames reaches 10k-100k self.obstimes = np.array( [config["start_time"] + td * i for i in range(n_frames)]) self.precomp_hf = AltAz(location=self.location, obstime=self.obstimes) if isinstance(self.target, SkyCoord): self.precomp_point = self.target.transform_to(self.precomp_hf) else: alt, az = self.target n = len(self.obstimes) self.precomp_point = SkyCoord( alt=alt * np.ones(n), az=az * np.ones(n), frame=self.precomp_hf, ) self.precomp_camf = EngineeringCameraFrame( n_mirrors=2, telescope_pointing=self.precomp_point, focal_length=u.Quantity(self.focal_length, u.m), # 28 for LST obstime=self.obstimes, location=self.location, ) config["start_pointing"] = self.precomp_point[0]
def test_intersection_nominal_reconstruction(): """ Testing the reconstruction of the position in the nominal frame with a three-telescopes system. This is done using a squared configuration, of which the impact point occupies a vertex, ad the three telescopes the other three vertices. """ hill_inter = HillasIntersection() delta = 1.0 * u.m horizon_frame = AltAz() altitude = 70 * u.deg azimuth = 10 * u.deg array_direction = SkyCoord(alt=altitude, az=azimuth, frame=horizon_frame) nominal_frame = NominalFrame(origin=array_direction) focal_length = 28 * u.m camera_frame = CameraFrame(focal_length=focal_length, telescope_pointing=array_direction) cog_coords_camera_1 = SkyCoord(x=delta, y=0 * u.m, frame=camera_frame) cog_coords_camera_2 = SkyCoord(x=delta / 0.7, y=delta / 0.7, frame=camera_frame) cog_coords_camera_3 = SkyCoord(x=0 * u.m, y=delta, frame=camera_frame) cog_coords_nom_1 = cog_coords_camera_1.transform_to(nominal_frame) cog_coords_nom_2 = cog_coords_camera_2.transform_to(nominal_frame) cog_coords_nom_3 = cog_coords_camera_3.transform_to(nominal_frame) # x-axis is along the altitude and y-axis is along the azimuth hillas_1 = HillasParametersContainer(x=cog_coords_nom_1.delta_alt, y=cog_coords_nom_1.delta_az, intensity=100, psi=0 * u.deg) hillas_2 = HillasParametersContainer(x=cog_coords_nom_2.delta_alt, y=cog_coords_nom_2.delta_az, intensity=100, psi=45 * u.deg) hillas_3 = HillasParametersContainer(x=cog_coords_nom_3.delta_alt, y=cog_coords_nom_3.delta_az, intensity=100, psi=90 * u.deg) hillas_dict = {1: hillas_1, 2: hillas_2, 3: hillas_3} reco_nominal = hill_inter.reconstruct_nominal(hillas_parameters=hillas_dict) nominal_pos = SkyCoord( delta_az=u.Quantity(reco_nominal[0], u.rad), delta_alt=u.Quantity(reco_nominal[1], u.rad), frame=nominal_frame ) np.testing.assert_allclose(nominal_pos.altaz.az.to_value(u.deg), azimuth.to_value(u.deg), atol=1e-8) np.testing.assert_allclose(nominal_pos.altaz.alt.to_value(u.deg), altitude.to_value(u.deg), atol=1e-8)
def __init__( self, star_coordinates, star_table, patterns, pixsize, minpixdist, engineering_frame, ): self.star_table = star_table self.star_coordinates = star_coordinates self.patterns = patterns self.pixsize = pixsize self.minpixdist = minpixdist self.engineering_frame = engineering_frame self.horizon_level = 20 self.obstime = engineering_frame.obstime altaz_frame = AltAz( location=self.engineering_frame.location, obstime=self.obstime ) altaz_stars = self.star_coordinates.transform_to(altaz_frame) self.stars_above_horizon_ind = altaz_stars.alt.deg > self.horizon_level self.stars_above_horizon = self.star_table.hip_number.values[ altaz_stars.alt.deg > self.horizon_level ] self.silence = False self.log = daiquiri.getLogger(__name__)
def test_intersection_xmax_reco(): """ Test the reconstruction of xmax with two LSTs that are pointing at zenith = 0. The telescopes are places along the x and y axis at the same distance from the center. The impact point is hard-coded to be happening in the center of this cartesian system. """ hill_inter = HillasIntersection() horizon_frame = AltAz() zen_pointing = 10 * u.deg array_direction = SkyCoord(alt=90 * u.deg - zen_pointing, az=0 * u.deg, frame=horizon_frame) nom_frame = NominalFrame(origin=array_direction) source_sky_pos_reco = SkyCoord(alt=90 * u.deg - zen_pointing, az=0 * u.deg, frame=horizon_frame) nom_pos_reco = source_sky_pos_reco.transform_to(nom_frame) delta = 1.0 * u.m # LST focal length focal_length = 28 * u.m hillas_dict = { 1: HillasParametersContainer( x=-(delta / focal_length) * u.rad, y=((0 * u.m) / focal_length) * u.rad, intensity=1, ), 2: HillasParametersContainer( x=((0 * u.m) / focal_length) * u.rad, y=-(delta / focal_length) * u.rad, intensity=1, ), } x_max = hill_inter.reconstruct_xmax( source_x=nom_pos_reco.fov_lon, source_y=nom_pos_reco.fov_lat, core_x=0 * u.m, core_y=0 * u.m, hillas_parameters=hillas_dict, tel_x={ 1: (150 * u.m), 2: (0 * u.m) }, tel_y={ 1: (0 * u.m), 2: (150 * u.m) }, zen=zen_pointing, ) print(x_max)
def cam_to_nom(): pix_x = np.ones(2048) * u.m pix_y = np.ones(2048) * u.m pointing_direction = SkyCoord(alt=70 * u.deg, az=180 * u.deg, frame=AltAz()) camera_frame = CameraFrame(focal_length=15 * u.m, telescope_pointing=pointing_direction) camera_coord = SkyCoord(pix_x, pix_y, frame=camera_frame) # In this case we bypass the telescope system nominal_frame = NominalFrame(origin=AltAz(alt=75 * u.deg, az=180 * u.deg)) nom_coord = camera_coord.transform_to(nominal_frame) horizon = camera_coord.transform_to(AltAz()) print("Nominal Coordinate", nom_coord) print("Horizon coordinate", horizon)
def recumpute_horizon(self, obstime, horizon_level): recumpute = False if obstime is not None and obstime != self.obstime: self.obstime = obstime recumpute = True if horizon_level is not None and horizon_level != self.horizon_level: self.horizon_level = horizon_level recumpute = True if recumpute: self.log.info("recomputing horizon and star selection") altaz_frame = AltAz( location=self.engineering_frame.location, obstime=self.obstime ) altaz_stars = self.star_coordinates.transform_to(altaz_frame) self.stars_above_horizon_ind = altaz_stars.alt.deg > self.horizon_level self.stars_above_horizon = self.star_table.hip_number.values[ self.stars_above_horizon_ind ]
def test_reconstruction(): """ a test of the complete fit procedure on one event including: • tailcut cleaning • hillas parametrisation • direction fit • position fit in the end, proper units in the output are asserted """ filename = get_dataset_path("gamma_test_large.simtel.gz") fit = HillasIntersection() source = EventSource(filename, max_events=10) calib = CameraCalibrator(source.subarray) horizon_frame = AltAz() reconstructed_events = 0 for event in source: calib(event) mc = event.simulation.shower array_pointing = SkyCoord(az=mc.az, alt=mc.alt, frame=horizon_frame) hillas_dict = {} telescope_pointings = {} for tel_id, dl1 in event.dl1.tel.items(): geom = source.subarray.tel[tel_id].camera.geometry telescope_pointings[tel_id] = SkyCoord( alt=event.pointing.tel[tel_id].altitude, az=event.pointing.tel[tel_id].azimuth, frame=horizon_frame, ) mask = tailcuts_clean(geom, dl1.image, picture_thresh=10.0, boundary_thresh=5.0) try: moments = hillas_parameters(geom[mask], dl1.image[mask]) hillas_dict[tel_id] = moments except HillasParameterizationError as e: print(e) continue if len(hillas_dict) < 2: continue else: reconstructed_events += 1 # divergent mode put to on even though the file has parallel pointing. fit_result = fit.predict(hillas_dict, source.subarray, array_pointing, telescope_pointings) print(fit_result) print(event.simulation.shower.core_x, event.simulation.shower.core_y) fit_result.alt.to(u.deg) fit_result.az.to(u.deg) fit_result.core_x.to(u.m) assert fit_result.is_valid assert reconstructed_events > 0
def test_reconstruction(): """ a test of the complete fit procedure on one event including: • tailcut cleaning • hillas parametrisation • direction fit • position fit in the end, proper units in the output are asserted """ filename = get_dataset_path("gamma_test_large.simtel.gz") fit = HillasIntersection() source = event_source(filename, max_events=10) horizon_frame = AltAz() reconstructed_events = 0 for event in source: array_pointing = SkyCoord(az=event.mc.az, alt=event.mc.alt, frame=horizon_frame) hillas_dict = {} telescope_pointings = {} for tel_id in event.dl0.tels_with_data: geom = source.subarray.tel[tel_id].camera.geometry telescope_pointings[tel_id] = SkyCoord( alt=event.pointing.tel[tel_id].altitude, az=event.pointing.tel[tel_id].azimuth, frame=horizon_frame) pmt_signal = event.r0.tel[tel_id].waveform[0].sum(axis=1) mask = tailcuts_clean(geom, pmt_signal, picture_thresh=10., boundary_thresh=5.) pmt_signal[mask == 0] = 0 try: moments = hillas_parameters(geom, pmt_signal) hillas_dict[tel_id] = moments except HillasParameterizationError as e: print(e) continue if len(hillas_dict) < 2: continue else: reconstructed_events += 1 # divergent mode put to on even though the file has parallel pointing. fit_result = fit.predict(hillas_dict, source.subarray, array_pointing, telescope_pointings) print(fit_result) print(event.mc.core_x, event.mc.core_y) fit_result.alt.to(u.deg) fit_result.az.to(u.deg) fit_result.core_x.to(u.m) assert fit_result.is_valid assert reconstructed_events > 0