def test_validation_checks(): config = AnalysisConfig() analysis = Analysis(config) analysis.settings["observations"]["datastore"] = "other" with pytest.raises(FileNotFoundError): analysis.get_observations() config = AnalysisConfig.from_template("1d") analysis = Analysis(config) assert analysis.get_flux_points() is False assert analysis.run_fit() is False assert analysis.set_model() is False assert analysis.get_datasets() is False analysis.get_observations() analysis.settings["datasets"]["dataset-type"] = "not assigned" assert analysis.get_datasets() is False analysis.settings["datasets"]["dataset-type"] = "SpectrumDatasetOnOff" analysis.get_observations() analysis.get_datasets() model_str = Path(MODEL_FILE).read_text() analysis.set_model(model=model_str) assert isinstance(analysis.model, SkyModels) is True assert analysis.set_model() is False analysis.run_fit() del analysis.settings["flux-points"] assert analysis.get_flux_points() is False
def run_3d(name): """Run 3D analysis for one source.""" logging.info(f"run3d: {name}") mode = "3d" config_file = f"config{mode}.yaml" target_config_file = f"targets.yaml" model_file = f"model{mode}_{name}.yaml" outdir = f"results/{name}" config = target_config3d(config_file, target_config_file, name) analysis = Analysis(config) analysis.get_observations() conf = config.settings["observations"]["filters"][0] nb, lon, lat, rad = ( len(analysis.observations.ids), conf["lon"], conf["lat"], conf["radius"], ) logging.info(f"{nb} observations found in {rad} around {lon}, {lat} ") analysis.get_datasets() # test plt.figure(figsize=(5, 5)) analysis.datasets["stacked"].counts.sum_over_axes().plot(add_cbar=True) plt.savefig(f"{outdir}/{name}_{mode}_counts.png", bbox_inches="tight") analysis.set_model(filename=model_file) logging.info(analysis.model) analysis.run_fit() logging.info(analysis.fit_result.parameters.to_table()) analysis.fit_result.parameters.to_table().write( f"{outdir}/{name}_{mode}_bestfit.dat", format="ascii", overwrite=True) analysis.get_flux_points(source=f"{name}") analysis.flux_points.write(f"{outdir}/{name}_{mode}_fluxpoints.fits") plt.figure(figsize=(5, 5)) analysis.datasets["stacked"].counts.sum_over_axes().plot(add_cbar=True) plt.savefig(f"{outdir}/{name}_{mode}_counts.png", bbox_inches="tight") plt.figure(figsize=(5, 5)) analysis.datasets["stacked"].plot_residuals(method="diff/sqrt(model)", vmin=-0.5, vmax=0.5) plt.savefig(f"{outdir}/{name}_{mode}_residuals.png", bbox_inches="tight") plt.figure(figsize=(8, 5)) ax_sed, ax_residuals = analysis.flux_points.peek() plt.savefig(f"{outdir}/{name}_{mode}_fluxpoints.png", bbox_inches="tight")
def test_analysis_1d_stacked(): config = AnalysisConfig.from_template("1d") analysis = Analysis(config) analysis.settings["datasets"]["stack-datasets"] = True analysis.get_observations() analysis.get_datasets() analysis.set_model(filename=MODEL_FILE) analysis.run_fit() assert len(analysis.datasets) == 1 assert_allclose(analysis.datasets["stacked"].counts.data.sum(), 404) pars = analysis.fit_result.parameters assert_allclose(pars["index"].value, 2.689559, rtol=1e-3) assert_allclose(pars["amplitude"].value, 2.81629e-11, rtol=1e-3)
def test_analysis_1d(config_analysis_data): config = AnalysisConfig.from_template("1d") analysis = Analysis(config) analysis.config.update_settings(config_analysis_data) analysis.get_observations() analysis.get_datasets() analysis.set_model(filename=MODEL_FILE) analysis.run_fit() analysis.get_flux_points() assert len(analysis.datasets) == 2 assert len(analysis.flux_points.data.table) == 4 dnde = analysis.flux_points.data.table["dnde"].quantity assert dnde.unit == "cm-2 s-1 TeV-1" assert_allclose(dnde[0].value, 8.03604e-12, rtol=1e-2) assert_allclose(dnde[-1].value, 4.780021e-21, rtol=1e-2)
def test_analysis_3d(): config = AnalysisConfig.from_template("3d") analysis = Analysis(config) analysis.get_observations() analysis.get_datasets() analysis.set_model(filename=MODEL_FILE) analysis.datasets["stacked"].background_model.tilt.frozen = False analysis.run_fit() analysis.get_flux_points() assert len(analysis.datasets) == 1 assert len(analysis.fit_result.parameters) == 8 res = analysis.fit_result.parameters assert res[3].unit == "cm-2 s-1 TeV-1" assert len(analysis.flux_points.data.table) == 2 dnde = analysis.flux_points.data.table["dnde"].quantity assert_allclose(dnde[0].value, 1.182768e-11, rtol=1e-1) assert_allclose(dnde[-1].value, 4.051367e-13, rtol=1e-1) assert_allclose(res["index"].value, 2.76607, rtol=1e-1) assert_allclose(res["tilt"].value, -0.143204, rtol=1e-1)
def run_analysis_3d(target_dict): """Run 3D analysis for the selected target""" tag = target_dict["tag"] name = target_dict["name"] log.info(f"running 3d analysis, {tag}") path_res = Path(tag + "/results/") ra = target_dict["ra"] dec = target_dict["dec"] e_decorr = target_dict["e_decorr"] config_str = f""" general: logging: level: INFO outdir: . observations: datastore: $GAMMAPY_DATA/hess-dl3-dr1/ filters: - filter_type: par_value value_param: {name} variable: TARGET_NAME datasets: dataset-type: MapDataset stack-datasets: true offset-max: 2.5 deg geom: skydir: [{ra}, {dec}] width: [5, 5] binsz: 0.02 coordsys: CEL proj: TAN axes: - name: energy hi_bnd: 100 lo_bnd: 0.1 nbin: 24 interp: log node_type: edges unit: TeV energy-axis-true: name: energy hi_bnd: 100 lo_bnd: 0.1 nbin: 72 interp: log node_type: edges unit: TeV """ print(config_str) config = AnalysisConfig(config_str) # Observation selection analysis = Analysis(config) analysis.get_observations() if DEBUG is True: analysis.observations.list = [analysis.observations.list[0]] # Data reduction analysis.get_datasets() # Set runwise energy threshold. See reference paper, section 5.1.1. for dataset in analysis.datasets: # energy threshold given by the 10% edisp criterium e_thr_bias = dataset.edisp.get_bias_energy(0.1) # energy at which the background peaks background_model = dataset.background_model bkg_spectrum = background_model.map.get_spectrum() peak = bkg_spectrum.data.max() idx = list(bkg_spectrum.data).index(peak) e_thr_bkg = bkg_spectrum.energy.center[idx] esafe = max(e_thr_bias, e_thr_bkg) dataset.mask_fit = dataset.counts.geom.energy_mask(emin=esafe) # Model fitting spatial_model = target_dict["spatial_model"] model_config = f""" components: - name: {tag} type: SkyModel spatial: type: {spatial_model} frame: icrs parameters: - name: lon_0 value: {ra} unit: deg - name: lat_0 value: {dec} unit: deg spectral: type: PowerLawSpectralModel parameters: - name: amplitude value: 1.0e-12 unit: cm-2 s-1 TeV-1 - name: index value: 2.0 unit: '' - name: reference value: {e_decorr} unit: TeV frozen: true """ model_npars = 5 if spatial_model == "DiskSpatialModel": model_config = yaml.load(model_config) parameters = model_config["components"][0]["spatial"]["parameters"] parameters.append( { "name": "r_0", "value": 0.2, "unit": "deg", "frozen": False } ) parameters.append( { "name": "e", "value": 0.8, "unit": "", "frozen": False } ) parameters.append( { "name": "phi", "value": 150, "unit": "deg", "frozen": False } ) parameters.append( { "name": "edge", "value": 0.01, "unit": "deg", "frozen": True } ) model_npars += 4 analysis.set_model(model=model_config) for dataset in analysis.datasets: dataset.background_model.norm.frozen = False analysis.run_fit() parameters = analysis.model.parameters parameters.covariance = analysis.fit_result.parameters.covariance[0:model_npars, 0:model_npars] write_fit_summary(parameters, str(path_res / "results-summary-fit-3d.yaml")) # Flux points # TODO: This is a workaround to re-optimize the bkg in each energy bin. Add has to be added to the Analysis class datasets = analysis.datasets.copy() for dataset in datasets: for par in dataset.parameters: if par is not dataset.background_model.norm: par.frozen = True reoptimize = True if DEBUG is False else False fpe = FluxPointsEstimator( datasets=datasets, e_edges=FLUXP_EDGES, source=tag, reoptimize=reoptimize ) flux_points = fpe.run() flux_points.table["is_ul"] = flux_points.table["ts"] < 4 keys = ["e_ref", "e_min", "e_max", "dnde", "dnde_errp", "dnde_errn"] flux_points.table_formatted[keys].write( path_res / "flux-points-3d.ecsv", format="ascii.ecsv" )