def get_prediction(self, tel_id, shower_reco, energy_reco): horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=horizon_seed)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value ground = GroundFrame(x=shower_reco.core_x, y=shower_reco.core_y, z=0*u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction)) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value zenith = 90*u.deg - self.array_direction.alt azimuth = self.array_direction.az x_max = shower_reco.h_max / np.cos(zenith) # Calculate expected Xmax given this energy x_max_exp = guess_shower_depth(energy_reco.energy) # Convert to binning of Xmax, addition of 100 can probably be removed x_max_bin = x_max - x_max_exp # Check for range if x_max_bin > 250 * (u.g*u.cm**-2): x_max_bin = 250 * (u.g*u.cm**-2) if x_max_bin < -250 * (u.g*u.cm**-2): x_max_bin = -250 * (u.g*u.cm**-2) x_max_bin = x_max_bin.value impact = np.sqrt(pow(self.tel_pos_x[tel_id] - tilt_x, 2) + pow(self.tel_pos_y[tel_id] - tilt_y, 2)) phi = np.arctan2( (self.tel_pos_y[tel_id] - tilt_y), (self.tel_pos_x[tel_id] - tilt_x)) pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1, self.pixel_y[tel_id], source_x, source_y, phi) prediction = self.image_prediction(self.type[tel_id], (90 * u.deg) - shower_reco.alt, shower_reco.az, energy_reco.energy.value, impact, x_max_bin, pix_x_rot * (180 / math.pi), pix_y_rot * (180 / math.pi)) prediction *= self.scale[self.type[tel_id]] #prediction *= self.pixel_area[tel_id] prediction[prediction < 0] = 0 prediction[np.isnan(prediction)] = 0 return prediction
def get_prediction(self, tel_id, shower_reco, energy_reco): horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=horizon_seed)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value ground = GroundFrame(x=shower_reco.core_x, y=shower_reco.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction)) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value zenith = 90 * u.deg - self.array_direction.alt x_max = shower_reco.h_max / np.cos(zenith) # Calculate expected Xmax given this energy x_max_exp = guess_shower_depth(energy_reco.energy) # Convert to binning of Xmax, addition of 100 can probably be removed x_max_bin = x_max - x_max_exp # Check for range if x_max_bin > 250 * (u.g * u.cm**-2): x_max_bin = 250 * (u.g * u.cm**-2) if x_max_bin < -250 * (u.g * u.cm**-2): x_max_bin = -250 * (u.g * u.cm**-2) x_max_bin = x_max_bin.value impact = np.sqrt( pow(self.tel_pos_x[tel_id] - tilt_x, 2) + pow(self.tel_pos_y[tel_id] - tilt_y, 2)) phi = np.arctan2((self.tel_pos_y[tel_id] - tilt_y), (self.tel_pos_x[tel_id] - tilt_x)) pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1, self.pixel_y[tel_id], source_x, source_y, phi) prediction = self.image_prediction(self.type[tel_id], (90 * u.deg) - shower_reco.alt, shower_reco.az, energy_reco.energy.value, impact, x_max_bin, pix_x_rot * (180 / math.pi), pix_y_rot * (180 / math.pi)) prediction *= self.scale[self.type[tel_id]] # prediction *= self.pixel_area[tel_id] prediction[prediction < 0] = 0 prediction[np.isnan(prediction)] = 0 return prediction
def sky_to_camera(alt, az, focal, pointing_alt, pointing_az): """ Coordinate transform from aky position (alt, az) (in angles) to camera coordinates (x, y) in distance Parameters ---------- alt: astropy Quantity az: astropy Quantity focal: astropy Quantity pointing_alt: pointing altitude in angle unit pointing_az: pointing altitude in angle unit Returns ------- """ pointing_direction = HorizonFrame(alt=pointing_alt, az=pointing_az) event_direction = HorizonFrame(alt=alt, az=az) nom_frame = NominalFrame(array_direction=pointing_direction, pointing_direction=pointing_direction) event_dir_nom = event_direction.transform_to(nom_frame) camera_pos = NominalFrame( pointing_direction=pointing_direction, x=event_dir_nom.x.to(u.rad).value * focal, y=event_dir_nom.y.to(u.rad).value * focal, ) # return focal * (event_dir_nom.x.to(u.rad).value, event_dir_nom.y.to(u.rad).value) return camera_pos
def get_position_in_cam(dir_alt, dir_az, event, tel_id): """ transform position in HorizonFrame to CameraFrame Parameters ---------- dir_alt : direction altitude dir_az : direction azimuth event : event data container tel_id : telescope ID Returns ------- cam_coord : position in camera of telescope tel_id """ # pointing direction of telescope pointing_az = event.mc.tel[tel_id].azimuth_raw * u.rad pointing_alt = event.mc.tel[tel_id].altitude_raw * u.rad pointing = SkyCoord(alt=pointing_alt, az=pointing_az, frame='altaz') focal_length = event.inst.subarray.tel[tel_id].\ optics.equivalent_focal_length cf = CameraFrame(focal_length=focal_length, array_direction=pointing, pointing_direction=pointing) # direction of event direction = HorizonFrame(alt=dir_alt, az=dir_az) cam_coord = direction.transform_to(cf) return cam_coord
def draw_tilted_surface(self, shower_seed, energy_seed, bins=50, core_range=100 * u.m): """ Simple reconstruction for evaluating the likelihood in a grid across the nominal system, fixing all values but the core position of the gamma rays. Useful for checking the reconstruction performance of the algorithm Parameters ---------- shower_seed: ReconstructedShowerContainer Best fit ImPACT shower geometry energy_seed: ReconstructedEnergyContainer Best fit ImPACT energy bins: int Number of bins in surface evaluation nominal_range: Quantity Range over which to create likelihood surface Returns ------- ndarray, ndarray, ndarray: Bin centres in X and Y coordinates and the values of the likelihood at each position """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=self.array_direction)) source_x = nominal_seed.x[0].to(u.rad).value source_y = nominal_seed.y[0].to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction) ) tilt_x = tilted.x.to(u.m) tilt_y = tilted.y.to(u.m) x_ground_list = np.linspace(tilt_x - core_range, tilt_x + core_range, num=bins) y_ground_list = np.linspace(tilt_y - core_range, tilt_y + core_range, num=bins) w = np.zeros([bins, bins]) zenith = 90*u.deg - self.array_direction.alt for xb in range(bins): for yb in range(bins): x_max_scale = shower_seed.h_max / \ self.get_shower_max(source_x, source_y, x_ground_list[xb].value, y_ground_list[yb].value, zenith.to(u.rad).value) w[xb][yb] = self.get_likelihood(source_x, source_y, x_ground_list[xb].value, y_ground_list[yb].value, energy_seed.energy.value, x_max_scale) return x_ground_list, y_ground_list, w
def get_prediction(self, tel_id, shower_reco, energy_reco): horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=horizon_seed)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value print(self.array_direction[0]) ground = GroundFrame(x=shower_reco.core_x, y=shower_reco.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame( pointing_direction=HorizonFrame(alt=self.array_direction[0], az=self.array_direction[1]) ) ) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value zenith = 90 * u.deg - self.array_direction[0] azimuth = self.array_direction[1] x_max_exp = 300 + 93 * np.log10(energy_reco.energy.value) x_max = shower_reco.h_max / np.cos(zenith) # Convert to binning of Xmax, addition of 100 can probably be removed x_max_bin = x_max.value - x_max_exp if x_max_bin > 100: x_max_bin = 100 if x_max_bin < -100: x_max_bin = -100 impact = np.sqrt(pow(self.tel_pos_x[tel_id] - tilt_x, 2) + pow(self.tel_pos_y[tel_id] - tilt_y, 2)) phi = np.arctan2( (self.tel_pos_y[tel_id] - tilt_y), (self.tel_pos_x[tel_id] - tilt_x)) pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1, self.pixel_y[tel_id], source_x, source_y, phi) prediction = self.image_prediction(self.type[tel_id], 20 * u.deg, 0 * u.deg, energy_reco.energy.value, impact, x_max_bin, pix_x_rot * (180 / math.pi), pix_y_rot * (180 / math.pi)) prediction *= self.scale[self.type[tel_id]] prediction[prediction < 0] = 0 prediction[np.isnan(prediction)] = 0 return prediction
def get_prediction(self, tel_id, shower_reco, energy_reco): horizon_seed = HorizonFrame(az=shower_reco.az, alt=shower_reco.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=horizon_seed)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value print(self.array_direction[0]) ground = GroundFrame(x=shower_reco.core_x, y=shower_reco.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=HorizonFrame( alt=self.array_direction[0], az=self.array_direction[1]))) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value zenith = 90 * u.deg - self.array_direction[0] azimuth = self.array_direction[1] x_max_exp = 300 + 93 * np.log10(energy_reco.energy.value) x_max = shower_reco.h_max / np.cos(zenith) # Convert to binning of Xmax, addition of 100 can probably be removed x_max_bin = x_max.value - x_max_exp if x_max_bin > 100: x_max_bin = 100 if x_max_bin < -100: x_max_bin = -100 impact = np.sqrt( pow(self.tel_pos_x[tel_id] - tilt_x, 2) + pow(self.tel_pos_y[tel_id] - tilt_y, 2)) phi = np.arctan2((self.tel_pos_y[tel_id] - tilt_y), (self.tel_pos_x[tel_id] - tilt_x)) pix_x_rot, pix_y_rot = self.rotate_translate(self.pixel_x[tel_id] * -1, self.pixel_y[tel_id], source_x, source_y, phi) prediction = self.image_prediction(self.type[tel_id], 20 * u.deg, 0 * u.deg, energy_reco.energy.value, impact, x_max_bin, pix_x_rot * (180 / math.pi), pix_y_rot * (180 / math.pi)) prediction *= self.scale[self.type[tel_id]] prediction[prediction < 0] = 0 prediction[np.isnan(prediction)] = 0 return prediction
def get_event_pos_in_camera(event, tel): """ Return the position of the source in the camera frame Parameters ---------- event: `ctapipe.io.containers.DataContainer` tel: `ctapipe.instruement.telescope.TelescopeDescription` Returns ------- (x, y) (float, float): position in the camera """ array_pointing = HorizonFrame(alt=event.mcheader.run_array_direction[1], az=event.mcheader.run_array_direction[0]) event_direction = HorizonFrame(alt=event.mc.alt.to(u.rad), az=event.mc.az.to(u.rad)) nom_frame = NominalFrame(array_direction=array_pointing, pointing_direction=array_pointing) event_dir_nom = event_direction.transform_to(nom_frame) focal = tel.optics.equivalent_focal_length return focal * (event_dir_nom.x.to(u.rad).value, event_dir_nom.y.to(u.rad).value)
def predict(self, shower_seed, energy_seed): """ Parameters ---------- shower_seed: ReconstructedShowerContainer Seed shower geometry to be used in the fit energy_seed: ReconstructedEnergyContainer Seed energy to be used in fit Returns ------- ReconstructedShowerContainer, ReconstructedEnergyContainer: Reconstructed ImPACT shower geometry and energy """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to(NominalFrame( array_direction=self.array_direction)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction) ) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value zenith = 90 * u.deg - self.array_direction.alt if len(self.hillas_parameters) > 3: shift = [1] else: shift = [1.5, 1, 0.5, 0, -0.5, -1, -1.5] seed_list = spread_line_seed(self.hillas_parameters, self.tel_pos_x, self.tel_pos_y, source_x[0], source_y[0], tilt_x, tilt_y, energy_seed.energy.value, shift_frac = shift) chosen_seed = self.choose_seed(seed_list) # Perform maximum likelihood fit fit_params, errors, like = self.minimise(params=chosen_seed[0], step=chosen_seed[1], limits=chosen_seed[2], minimiser_name=self.minimiser_name) # Create a container class for reconstructed shower shower_result = ReconstructedShowerContainer() # Convert the best fits direction and core to Horizon and ground systems and # copy to the shower container nominal = NominalFrame(x=fit_params[0] * u.rad, y=fit_params[1] * u.rad, array_direction=self.array_direction) horizon = nominal.transform_to(HorizonFrame()) shower_result.alt, shower_result.az = horizon.alt, horizon.az tilted = TiltedGroundFrame(x=fit_params[2] * u.m, y=fit_params[3] * u.m, pointing_direction=self.array_direction) ground = project_to_ground(tilted) shower_result.core_x = ground.x shower_result.core_y = ground.y shower_result.is_valid = True # Currently no errors not availible to copy NaN shower_result.alt_uncert = np.nan shower_result.az_uncert = np.nan shower_result.core_uncert = np.nan # Copy reconstructed Xmax shower_result.h_max = fit_params[5] * self.get_shower_max(fit_params[0], fit_params[1], fit_params[2], fit_params[3], zenith.to(u.rad).value) shower_result.h_max *= np.cos(zenith) shower_result.h_max_uncert = errors[5] * shower_result.h_max shower_result.goodness_of_fit = like # Create a container class for reconstructed energy energy_result = ReconstructedEnergyContainer() # Fill with results energy_result.energy = fit_params[4] * u.TeV energy_result.energy_uncert = errors[4] * u.TeV energy_result.is_valid = True return shower_result, energy_result
def predict(self, shower_seed, energy_seed): """ Parameters ---------- shower_seed: ReconstructedShowerContainer Seed shower geometry to be used in the fit energy_seed: ReconstructedEnergyContainer Seed energy to be used in fit Returns ------- ReconstructedShowerContainer, ReconstructedEnergyContainer: Reconstructed ImPACT shower geometry and energy """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=self.array_direction)) print(nominal_seed) print(horizon_seed) print(self.array_direction) source_x = nominal_seed.x[0].to(u.rad).value source_y = nominal_seed.y[0].to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction)) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value lower_en_limit = energy_seed.energy * 0.5 en_seed = energy_seed.energy if lower_en_limit < 0.04 * u.TeV: lower_en_limit = 0.04 * u.TeV en_seed = 0.041 * u.TeV seed = (source_x, source_y, tilt_x, tilt_y, en_seed.value, 0.8) step = (0.001, 0.001, 10, 10, en_seed.value * 0.1, 0.1) limits = ((source_x - 0.01, source_x + 0.01), (source_y - 0.01, source_y + 0.01), (tilt_x - 100, tilt_x + 100), (tilt_y - 100, tilt_y + 100), (lower_en_limit.value, en_seed.value * 2), (0.5, 2)) fit_params, errors = self.minimise(params=seed, step=step, limits=limits, minimiser_name=self.minimiser_name) # container class for reconstructed showers ''' shower_result = ReconstructedShowerContainer() nominal = NominalFrame(x=fit_params[0] * u.rad, y=fit_params[1] * u.rad, array_direction=self.array_direction) horizon = nominal.transform_to(HorizonFrame()) shower_result.alt, shower_result.az = horizon.alt, horizon.az tilted = TiltedGroundFrame(x=fit_params[2] * u.m, y=fit_params[3] * u.m, pointing_direction=self.array_direction) ground = project_to_ground(tilted) shower_result.core_x = ground.x shower_result.core_y = ground.y shower_result.is_valid = True shower_result.alt_uncert = np.nan shower_result.az_uncert = np.nan shower_result.core_uncert = np.nan zenith = 90 * u.deg - self.array_direction.alt shower_result.h_max = fit_params[5] * \ self.get_shower_max(fit_params[0], fit_params[1], fit_params[2], fit_params[3], zenith.to(u.rad).value) shower_result.h_max_uncert = errors[5] * shower_result.h_max shower_result.goodness_of_fit = np.nan shower_result.tel_ids = list(self.image.keys()) energy_result = ReconstructedEnergyContainer() energy_result.energy = fit_params[4] * u.TeV energy_result.energy_uncert = errors[4] * u.TeV energy_result.is_valid = True energy_result.tel_ids = list(self.image.keys()) # Return interesting stuff return shower_result, energy_result
def predict(self, shower_seed, energy_seed): """ Parameters ---------- source_x: float Initial guess of source position in the nominal frame source_y: float Initial guess of source position in the nominal frame core_x: float Initial guess of the core position in the tilted system core_y: float Initial guess of the core position in the tilted system energy: float Initial guess of energy Returns ------- Shower object with fit results """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=self.array_direction)) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction)) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value lower_en_limit = energy_seed.energy * 0.1 if lower_en_limit < 0.04 * u.TeV: lower_en_limit = 0.04 * u.TeV # Create Minuit object with first guesses at parameters, strip away the # units as Minuit doesnt like them min = Minuit(self.get_likelihood, print_level=1, source_x=source_x, error_source_x=0.01 / 57.3, fix_source_x=False, limit_source_x=(source_x - 0.5 / 57.3, source_x + 0.5 / 57.3), source_y=source_y, error_source_y=0.01 / 57.3, fix_source_y=False, limit_source_y=(source_y - 0.5 / 57.3, source_y + 0.5 / 57.3), core_x=tilt_x, error_core_x=10, limit_core_x=(tilt_x - 200, tilt_x + 200), core_y=tilt_y, error_core_y=10, limit_core_y=(tilt_y - 200, tilt_y + 200), energy=energy_seed.energy.value, error_energy=energy_seed.energy.value * 0.05, limit_energy=(lower_en_limit.value, energy_seed.energy.value * 10.), x_max_scale=1, error_x_max_scale=0.1, limit_x_max_scale=(0.5, 2), fix_x_max_scale=False, errordef=1) min.tol *= 1000 min.strategy = 0 # Perform minimisation migrad = min.migrad() fit_params = min.values errors = min.errors # print(migrad) # print(min.minos()) # container class for reconstructed showers ''' shower_result = ReconstructedShowerContainer() nominal = NominalFrame(x=fit_params["source_x"] * u.rad, y=fit_params["source_y"] * u.rad, array_direction=self.array_direction) horizon = nominal.transform_to(HorizonFrame()) shower_result.alt, shower_result.az = horizon.alt, horizon.az tilted = TiltedGroundFrame(x=fit_params["core_x"] * u.m, y=fit_params["core_y"] * u.m, pointing_direction=self.array_direction) ground = project_to_ground(tilted) shower_result.core_x = ground.x shower_result.core_y = ground.y shower_result.is_valid = True shower_result.alt_uncert = np.nan shower_result.az_uncert = np.nan shower_result.core_uncert = np.nan zenith = 90 * u.deg - self.array_direction[0] shower_result.h_max = fit_params["x_max_scale"] * \ self.get_shower_max(fit_params["source_x"], fit_params["source_y"], fit_params["core_x"], fit_params["core_y"], zenith.to(u.rad).value) shower_result.h_max_uncert = errors["x_max_scale"] * shower_result.h_max shower_result.goodness_of_fit = np.nan shower_result.tel_ids = list(self.image.keys()) energy_result = ReconstructedEnergyContainer() energy_result.energy = fit_params["energy"] * u.TeV energy_result.energy_uncert = errors["energy"] * u.TeV energy_result.is_valid = True energy_result.tel_ids = list(self.image.keys()) # Return interesting stuff return shower_result, energy_result
def predict(self, shower_seed, energy_seed): """ Parameters ---------- shower_seed: ReconstructedShowerContainer Seed shower geometry to be used in the fit energy_seed: ReconstructedEnergyContainer Seed energy to be used in fit Returns ------- ReconstructedShowerContainer, ReconstructedEnergyContainer: Reconstructed ImPACT shower geometry and energy """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to(NominalFrame(array_direction=self.array_direction)) print(nominal_seed) print(horizon_seed) print(self.array_direction) source_x = nominal_seed.x[0].to(u.rad).value source_y = nominal_seed.y[0].to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction) ) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value lower_en_limit = energy_seed.energy * 0.5 en_seed = energy_seed.energy if lower_en_limit < 0.04 * u.TeV: lower_en_limit = 0.04 * u.TeV en_seed = 0.041 * u.TeV seed = (source_x, source_y, tilt_x, tilt_y, en_seed.value, 0.8) step = (0.001, 0.001, 10, 10, en_seed.value*0.1, 0.1) limits = ((source_x-0.01, source_x+0.01), (source_y-0.01, source_y+0.01), (tilt_x-100, tilt_x+100), (tilt_y-100, tilt_y+100), (lower_en_limit.value, en_seed.value*2), (0.5,2)) fit_params, errors = self.minimise(params=seed, step=step, limits=limits, minimiser_name=self.minimiser_name) # container class for reconstructed showers ''' shower_result = ReconstructedShowerContainer() nominal = NominalFrame(x=fit_params[0] * u.rad, y=fit_params[1] * u.rad, array_direction=self.array_direction) horizon = nominal.transform_to(HorizonFrame()) shower_result.alt, shower_result.az = horizon.alt, horizon.az tilted = TiltedGroundFrame(x=fit_params[2] * u.m, y=fit_params[3] * u.m, pointing_direction=self.array_direction) ground = project_to_ground(tilted) shower_result.core_x = ground.x shower_result.core_y = ground.y shower_result.is_valid = True shower_result.alt_uncert = np.nan shower_result.az_uncert = np.nan shower_result.core_uncert = np.nan zenith = 90*u.deg - self.array_direction.alt shower_result.h_max = fit_params[5] * \ self.get_shower_max(fit_params[0], fit_params[1], fit_params[2], fit_params[3], zenith.to(u.rad).value) shower_result.h_max_uncert = errors[5] * shower_result.h_max shower_result.goodness_of_fit = np.nan shower_result.tel_ids = list(self.image.keys()) energy_result = ReconstructedEnergyContainer() energy_result.energy = fit_params[4] * u.TeV energy_result.energy_uncert = errors[4] * u.TeV energy_result.is_valid = True energy_result.tel_ids = list(self.image.keys()) # Return interesting stuff return shower_result, energy_result
def predict(self, shower_seed, energy_seed): """ Parameters ---------- source_x: float Initial guess of source position in the nominal frame source_y: float Initial guess of source position in the nominal frame core_x: float Initial guess of the core position in the tilted system core_y: float Initial guess of the core position in the tilted system energy: float Initial guess of energy Returns ------- Shower object with fit results """ horizon_seed = HorizonFrame(az=shower_seed.az, alt=shower_seed.alt) nominal_seed = horizon_seed.transform_to( NominalFrame(array_direction=self.array_direction) ) source_x = nominal_seed.x.to(u.rad).value source_y = nominal_seed.y.to(u.rad).value ground = GroundFrame(x=shower_seed.core_x, y=shower_seed.core_y, z=0 * u.m) tilted = ground.transform_to( TiltedGroundFrame(pointing_direction=self.array_direction) ) tilt_x = tilted.x.to(u.m).value tilt_y = tilted.y.to(u.m).value lower_en_limit = energy_seed.energy * 0.1 if lower_en_limit < 0.04 * u.TeV: lower_en_limit = 0.04 * u.TeV # Create Minuit object with first guesses at parameters, strip away the # units as Minuit doesnt like them min = Minuit(self.get_likelihood, print_level=1, source_x=source_x, error_source_x=0.01 / 57.3, fix_source_x=False, limit_source_x=(source_x - 0.5 / 57.3, source_x + 0.5 / 57.3), source_y=source_y, error_source_y=0.01 / 57.3, fix_source_y=False, limit_source_y=(source_y - 0.5 / 57.3, source_y + 0.5 / 57.3), core_x=tilt_x, error_core_x=10, limit_core_x=(tilt_x - 200, tilt_x + 200), core_y=tilt_y, error_core_y=10, limit_core_y=(tilt_y - 200, tilt_y + 200), energy=energy_seed.energy.value, error_energy=energy_seed.energy.value * 0.05, limit_energy=(lower_en_limit.value, energy_seed.energy.value * 10.), x_max_scale=1, error_x_max_scale=0.1, limit_x_max_scale=(0.5, 2), fix_x_max_scale=False, errordef=1) min.tol *= 1000 min.strategy = 0 # Perform minimisation migrad = min.migrad() fit_params = min.values errors = min.errors # print(migrad) # print(min.minos()) # container class for reconstructed showers ''' shower_result = ReconstructedShowerContainer() nominal = NominalFrame(x=fit_params["source_x"] * u.rad, y=fit_params["source_y"] * u.rad, array_direction=self.array_direction) horizon = nominal.transform_to(HorizonFrame()) shower_result.alt, shower_result.az = horizon.alt, horizon.az tilted = TiltedGroundFrame(x=fit_params["core_x"] * u.m, y=fit_params["core_y"] * u.m, pointing_direction=self.array_direction) ground = project_to_ground(tilted) shower_result.core_x = ground.x shower_result.core_y = ground.y shower_result.is_valid = True shower_result.alt_uncert = np.nan shower_result.az_uncert = np.nan shower_result.core_uncert = np.nan zenith = 90 * u.deg - self.array_direction[0] shower_result.h_max = fit_params["x_max_scale"] * \ self.get_shower_max(fit_params["source_x"], fit_params["source_y"], fit_params["core_x"], fit_params["core_y"], zenith.to(u.rad).value) shower_result.h_max_uncert = errors["x_max_scale"] * shower_result.h_max shower_result.goodness_of_fit = np.nan shower_result.tel_ids = list(self.image.keys()) energy_result = ReconstructedEnergyContainer() energy_result.energy = fit_params["energy"] * u.TeV energy_result.energy_uncert = errors["energy"] * u.TeV energy_result.is_valid = True energy_result.tel_ids = list(self.image.keys()) # Return interesting stuff return shower_result, energy_result