def test_fov_bkg_maker_fit(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) dataset1 = obs_dataset.copy(name="test-fov") dataset = fov_bkg_maker.run(dataset1) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.83077, rtol=1e-4) assert_allclose(model.norm.error, 0.02069, rtol=1e-2) assert_allclose(model.tilt.value, 0.0, rtol=1e-4) assert_allclose(model.tilt.error, 0.0, rtol=1e-2) assert_allclose(fov_bkg_maker.default_spectral_model.tilt.value, 0.0) assert_allclose(fov_bkg_maker.default_spectral_model.norm.value, 1.0) spectral_model = PowerLawNormSpectralModel() spectral_model.tilt.frozen = False fov_bkg_maker = FoVBackgroundMaker( method="fit", exclusion_mask=exclusion_mask, spectral_model=spectral_model ) dataset2 = obs_dataset.copy(name="test-fov") dataset = fov_bkg_maker.run(dataset2) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.901523, rtol=1e-4) assert_allclose(model.norm.error, 0.6088, rtol=1e-2) assert_allclose(model.tilt.value, 0.071069, rtol=1e-4) assert_allclose(model.tilt.error, 0.5866, rtol=1e-2) assert_allclose(fov_bkg_maker.default_spectral_model.tilt.value, 0.0) assert_allclose(fov_bkg_maker.default_spectral_model.norm.value, 1.0)
def test_fov_bkg_maker_fit_with_source_model(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") spatial_model = GaussianSpatialModel(lon_0="0.2 deg", lat_0="0.1 deg", sigma="0.2 deg", frame="galactic") spectral_model = PowerLawSpectralModel(index=3, amplitude="1e-11 cm-2 s-1 TeV-1", reference="1 TeV") model = SkyModel(spatial_model=spatial_model, spectral_model=spectral_model, name="test-source") bkg_model = FoVBackgroundModel(dataset_name="test-fov") test_dataset.models = [model, bkg_model] dataset = fov_bkg_maker.run(test_dataset) # Here we check that source parameters are correctly thawed after fit. assert not dataset.models.parameters["index"].frozen assert not dataset.models.parameters["lon_0"].frozen model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert not model.norm.frozen assert_allclose(model.norm.value, 0.830789, rtol=1e-4) assert_allclose(model.tilt.value, 0.0, rtol=1e-4)
def test_fov_bkg_maker_spectrumdataset(obs_dataset): from regions import CircleSkyRegion maker = FoVBackgroundMaker() energy_axis = MapAxis.from_edges([1, 10], unit="TeV", name="energy", interp="log") region = CircleSkyRegion(obs_dataset._geom.center_skydir, Angle('0.1 deg')) geom = RegionGeom.create(region, axes=[energy_axis]) dataset = SpectrumDataset.create(geom) with pytest.raises(TypeError): maker.run(dataset) region_dataset = obs_dataset.to_region_map_dataset(region) with pytest.raises(TypeError): maker.run(region_dataset)
def test_fov_bkg_maker_fit(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") dataset = fov_bkg_maker.run(test_dataset) assert_allclose(dataset.background_model.norm.value, 0.8307, rtol=1e-4) assert_allclose(dataset.background_model.tilt.value, 0.0, rtol=1e-4)
def test_fov_bkg_maker_fit(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.830789, rtol=1e-4) assert_allclose(model.tilt.value, 0.0, rtol=1e-4)
def test_fov_bkg_maker_scale_fail(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy() # Putting negative background model to prevent correct scaling test_dataset.background.data *= -1 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4)
def test_fov_bkg_maker_fit_fail(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy() # Putting negative background model to prevent convergence test_dataset.background_model.map.data *= -1 dataset = fov_bkg_maker.run(test_dataset) assert_allclose(dataset.background_model.norm.value, 1, rtol=1e-4)
def test_fov_bkg_maker_scale(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.83, rtol=1e-2) assert_allclose(model.norm.error, 0.0207, rtol=1e-2) assert_allclose(model.tilt.value, 0.0, rtol=1e-2)
def test_fov_bkg_maker_fit_with_tilt(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") test_dataset.background_model.tilt.frozen = False dataset = fov_bkg_maker.run(test_dataset) assert_allclose(dataset.background_model.norm.value, 0.9034, rtol=1e-4) assert_allclose(dataset.background_model.tilt.value, 0.0728, rtol=1e-4)
def test_fov_bkg_maker_scale_fail(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") # Putting negative background model to prevent correct scaling test_dataset.background.data *= -1 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert "WARNING" in [_.levelname for _ in caplog.records] message1 = "FoVBackgroundMaker failed. Only -1940 background counts outside exclusion mask for test-fov. Setting mask to False." assert message1 in [_.message for _ in caplog.records]
def test_fov_bkg_maker_fit_fail(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") # Putting null background model to prevent convergence test_dataset.background.data *= 0 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert caplog.records[-1].levelname == "WARNING" assert f"Fit did not converge for {dataset.name}" in caplog.records[-1].message
def test_fov_bkg_maker_fit_with_tilt(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask,) test_dataset = obs_dataset.copy(name="test-fov") model = FoVBackgroundModel(dataset_name="test-fov") model.spectral_model.tilt.frozen = False test_dataset.models = [model] dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.901523, rtol=1e-4) assert_allclose(model.tilt.value, 0.071069, rtol=1e-4)
def test_fov_bkg_maker_scale_nocounts(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") test_dataset.counts *= 0 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert_allclose(model.tilt.value, 0.0, rtol=1e-2) assert "WARNING" in [_.levelname for _ in caplog.records] message1 = "FoVBackgroundMaker failed. Only 0 counts outside exclusion mask for test-fov. Setting mask to False." assert message1 in [_.message for _ in caplog.records]
def test_fov_bkg_maker_scale_nocounts(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") test_dataset.counts *= 0 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert_allclose(model.tilt.value, 0.0, rtol=1e-4) assert caplog.records[-1].levelname == "WARNING" assert "No counts found outside exclusion mask for test-fov" in caplog.records[-1].message assert "FoVBackgroundMaker failed" in caplog.records[-1].message
def test_fov_bkg_maker_scale_fail(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy() # Putting negative background model to prevent correct scaling test_dataset.background.data *= -1 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert caplog.records[-1].levelname == "WARNING" assert f"No positive background found outside exclusion mask for {dataset.name}" in caplog.records[-1].message assert "FoVBackgroundMaker failed" in caplog.records[-1].message
def test_fov_bkg_maker_fit_fail(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") # Putting null background model to prevent convergence test_dataset.background.data *= 0 dataset = fov_bkg_maker.run(test_dataset) model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert "WARNING" in [_.levelname for _ in caplog.records] message1 = "FoVBackgroundMaker failed. Non-finite normalisation value for test-fov. Setting mask to False." assert message1 in [_.message for _ in caplog.records]
def test_fov_bkg_maker_mask_fit_handling(obs_dataset, exclusion_mask): fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") region = CircleSkyRegion(obs_dataset._geom.center_skydir, Angle(0.4, "deg")) mask_fit = obs_dataset._geom.region_mask(regions=[region]) test_dataset.mask_fit = mask_fit dataset = fov_bkg_maker.run(test_dataset) assert np.all(test_dataset.mask_fit == mask_fit) == True model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 0.9975, rtol=1e-3) assert_allclose(model.norm.error, 0.1115, rtol=1e-3) assert_allclose(model.tilt.value, 0.0, rtol=1e-2)
def test_fov_bkg_maker_fit_nocounts(obs_dataset, exclusion_mask, caplog): fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) test_dataset = obs_dataset.copy(name="test-fov") test_dataset.counts *= 0 dataset = fov_bkg_maker.run(test_dataset) # This should be solved along with issue https://github.com/gammapy/gammapy/issues/3175 model = dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(model.norm.value, 1, rtol=1e-4) assert_allclose(model.tilt.value, 0.0, rtol=1e-4) assert caplog.records[-1].levelname == "WARNING" assert f"Fit did not converge for {dataset.name}" in caplog.records[-1].message
def create_datasets_3d(observations, target_position): # Target geometry definition e_reco = MapAxis.from_energy_bounds(0.23, 20, 12, "TeV") e_true = MapAxis.from_energy_bounds(0.1, 40, 40, "TeV", name="energy_true") geom = WcsGeom.create(skydir=target_position, width=(2, 2), binsz=0.02, axes=[e_reco]) exclusion_region = CircleSkyRegion(target_position, 0.3 * u.deg) exclusion_mask = geom.region_mask([exclusion_region], inside=False) offset_max = 2.0 * u.deg #data reduction makers maker = MapDatasetMaker() bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) safe_mask_maker = SafeMaskMaker(methods=["aeff-max", "offset-max"], aeff_percent=10, offset_max=offset_max) datasets = [] dataset_empty = MapDataset.create(geom=geom, energy_axis_true=e_true) for obs in observations: cutout = dataset_empty.cutout(obs.pointing_radec, width=2 * offset_max) # A MapDataset is filled in this cutout geometry dataset = maker.run(cutout, obs) # The data quality cut is applied dataset = safe_mask_maker.run(dataset, obs) # fit background model dataset = bkg_maker.run(dataset) print( f"Background norm obs {obs.obs_id}: {dataset.background_model.spectral_model.norm.value:.2f}" ) datasets.append(dataset) return datasets
def test_minimal_datastore(): """ "Check that a standard analysis runs on a minimal datastore""" energy_axis = MapAxis.from_energy_bounds(1, 10, nbin=3, per_decade=False, unit="TeV", name="energy") geom = WcsGeom.create( skydir=(83.633, 22.014), binsz=0.5, width=(2, 2), frame="icrs", proj="CAR", axes=[energy_axis], ) data_store = DataStore.from_dir("$GAMMAPY_DATA/tests/minimal_datastore") observations = data_store.get_observations() maker = MapDatasetMaker() offset_max = 2.3 * u.deg maker_safe_mask = SafeMaskMaker(methods=["offset-max"], offset_max=offset_max) circle = CircleSkyRegion(center=SkyCoord("83.63 deg", "22.14 deg"), radius=0.2 * u.deg) exclusion_mask = ~geom.region_mask(regions=[circle]) maker_fov = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) stacked = MapDataset.create(geom=geom, name="crab-stacked") for obs in observations: dataset = maker.run(stacked, obs) dataset = maker_safe_mask.run(dataset, obs) dataset = maker_fov.run(dataset) stacked.stack(dataset) assert_allclose(stacked.exposure.data.sum(), 6.01909e10) assert_allclose(stacked.counts.data.sum(), 1446) assert_allclose(stacked.background.data.sum(), 1445.9841)
def _map_making(self): """Make maps and datasets for 3d analysis.""" datasets_settings = self.config.datasets log.info("Creating geometry.") geom = self._create_geometry() geom_settings = datasets_settings.geom geom_irf = dict(energy_axis_true=None, binsz_irf=None) if geom_settings.axes.energy_true.min is not None: geom_irf["energy_axis_true"] = self._make_energy_axis( geom_settings.axes.energy_true, name="energy_true") geom_irf["binsz_irf"] = geom_settings.wcs.binsize_irf.to("deg").value offset_max = geom_settings.selection.offset_max log.info("Creating datasets.") maker = MapDatasetMaker(selection=datasets_settings.map_selection) safe_mask_selection = datasets_settings.safe_mask.methods safe_mask_settings = datasets_settings.safe_mask.parameters maker_safe_mask = SafeMaskMaker(methods=safe_mask_selection, **safe_mask_settings) bkg_maker_config = {} if datasets_settings.background.exclusion: exclusion_region = Map.read(datasets_settings.background.exclusion) bkg_maker_config["exclusion_mask"] = exclusion_region bkg_maker_config.update(datasets_settings.background.parameters) bkg_method = datasets_settings.background.method if bkg_method == "fov_background": log.debug( f"Creating FoVBackgroundMaker with arguments {bkg_maker_config}" ) bkg_maker = FoVBackgroundMaker(**bkg_maker_config) elif bkg_method == "ring": bkg_maker = RingBackgroundMaker(**bkg_maker_config) log.debug( f"Creating RingBackgroundMaker with arguments {bkg_maker_config}" ) if datasets_settings.geom.axes.energy.nbins > 1: raise ValueError( "You need to define a single-bin energy geometry for your dataset." ) else: bkg_maker = None log.warning( f"No background maker set for 3d analysis. Check configuration." ) stacked = MapDataset.create(geom=geom, name="stacked", **geom_irf) if datasets_settings.stack: for obs in self.observations: log.info(f"Processing observation {obs.obs_id}") cutout = stacked.cutout(obs.pointing_radec, width=2 * offset_max) dataset = maker.run(cutout, obs) dataset = maker_safe_mask.run(dataset, obs) if bkg_maker is not None: dataset = bkg_maker.run(dataset) if bkg_method == "ring": dataset = dataset.to_map_dataset() log.debug(dataset) stacked.stack(dataset) datasets = [stacked] else: datasets = [] for obs in self.observations: log.info(f"Processing observation {obs.obs_id}") cutout = stacked.cutout(obs.pointing_radec, width=2 * offset_max) dataset = maker.run(cutout, obs) dataset = maker_safe_mask.run(dataset, obs) if bkg_maker is not None: dataset = bkg_maker.run(dataset) log.debug(dataset) datasets.append(dataset) self.datasets = Datasets(datasets)
def test_fov_bkg_maker_with_source_model(obs_dataset, exclusion_mask, caplog): test_dataset = obs_dataset.copy(name="test-fov") # crab model spatial_model = PointSpatialModel( lon_0="83.619deg", lat_0="22.024deg", frame="icrs" ) spectral_model = PowerLawSpectralModel( index=2.6, amplitude="4.5906e-11 cm-2 s-1 TeV-1", reference="1 TeV" ) model = SkyModel( spatial_model=spatial_model, spectral_model=spectral_model, name="test-source" ) bkg_model = FoVBackgroundModel(dataset_name="test-fov") test_dataset.models = [model, bkg_model] # pre-fit both source and background to get reference model Fit().run(test_dataset) bkg_model_spec = test_dataset.models[f"{test_dataset.name}-bkg"].spectral_model norm_ref = 0.897 assert not bkg_model_spec.norm.frozen assert_allclose(bkg_model_spec.norm.value, norm_ref, rtol=1e-4) assert_allclose(bkg_model_spec.tilt.value, 0.0, rtol=1e-4) # apply scale method with pre-fitted source model and no exclusion_mask bkg_model_spec.norm.value = 1 fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=None) dataset = fov_bkg_maker.run(test_dataset) bkg_model_spec = test_dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(bkg_model_spec.norm.value, norm_ref, rtol=1e-4) assert_allclose(bkg_model_spec.tilt.value, 0.0, rtol=1e-4) # apply fit method with pre-fitted source model and no exlusion mask bkg_model_spec.norm.value = 1 fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=None) dataset = fov_bkg_maker.run(test_dataset) bkg_model_spec = test_dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(bkg_model_spec.norm.value, norm_ref, rtol=1e-4) assert_allclose(bkg_model_spec.tilt.value, 0.0, rtol=1e-4) # apply scale method with pre-fitted source model and exclusion_mask bkg_model_spec.norm.value = 1 fov_bkg_maker = FoVBackgroundMaker(method="scale", exclusion_mask=exclusion_mask) dataset = fov_bkg_maker.run(test_dataset) bkg_model_spec = test_dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(bkg_model_spec.norm.value, 0.830779, rtol=1e-4) assert_allclose(bkg_model_spec.tilt.value, 0.0, rtol=1e-4) # apply fit method with pre-fitted source model and exlusion mask bkg_model_spec.norm.value = 1 fov_bkg_maker = FoVBackgroundMaker(method="fit", exclusion_mask=exclusion_mask) dataset = fov_bkg_maker.run(test_dataset) bkg_model_spec = test_dataset.models[f"{dataset.name}-bkg"].spectral_model assert_allclose(bkg_model_spec.norm.value, 0.830779, rtol=1e-4) assert_allclose(bkg_model_spec.tilt.value, 0.0, rtol=1e-4) # Here we check that source parameters are correctly thawed after fit. assert not dataset.models.parameters["index"].frozen assert not dataset.models.parameters["lon_0"].frozen # test model.spectral_model.amplitude.value *= 1e5 fov_bkg_maker = FoVBackgroundMaker(method="scale") dataset = fov_bkg_maker.run(test_dataset) assert "WARNING" in [_.levelname for _ in caplog.records] message1 = "FoVBackgroundMaker failed. Negative residuals counts for test-fov. Setting mask to False." assert message1 in [_.message for _ in caplog.records]