Repository: gammapy/gammapy

Issue:
`Dataset.npred_signal()` should take model name
`Dataset.npred_signal()` takes a model as argument, whereas in most other places (eg:`FluxPointEstimator` we access models by their names. This create some confusion.

@adonath shall I put in a PR to change this?


Discussion:
Thanks @AtreyeeS! I agree the string is the more consistent choice here!
@AtreyeeS Can you work this? Shouldn't be much more than half an hour of work...

Resolving patch:
diff --git a/gammapy/datasets/map.py b/gammapy/datasets/map.py
--- a/gammapy/datasets/map.py
+++ b/gammapy/datasets/map.py
@@ -387,7 +387,7 @@ def npred_background(self):
 
         return background
 
-    def npred_signal(self, model=None):
+    def npred_signal(self, model_name=None):
         """"Model predicted signal counts.
 
         If a model is passed, predicted counts from that component is returned.
@@ -395,8 +395,8 @@ def npred_signal(self, model=None):
 
         Parameters
         -------------
-        model: `~gammapy.modeling.models.SkyModel`, optional
-            Sky model to compute the npred for.
+        model_name: str
+        Name of  SkyModel for which to compute the npred for.
             If none, the sum of all components (minus the background model)
             is returned
 
@@ -407,10 +407,10 @@ def npred_signal(self, model=None):
         """
         npred_total = Map.from_geom(self._geom, dtype=float)
 
-        for evaluator in self.evaluators.values():
-            if model is evaluator.model:
-                return evaluator.compute_npred()
+        if model_name is not None:
+            return self.evaluators[model_name].compute_npred()
 
+        for evaluator in self.evaluators.values():
             if evaluator.needs_update:
                 evaluator.update(
                     self.exposure, self.psf, self.edisp, self._geom, self.mask_image,


Test patch:
diff --git a/gammapy/datasets/tests/test_map.py b/gammapy/datasets/tests/test_map.py
--- a/gammapy/datasets/tests/test_map.py
+++ b/gammapy/datasets/tests/test_map.py
@@ -818,14 +818,20 @@ def test_npred_sig(sky_model, geom, geom_etrue):
     gauss = GaussianSpatialModel(
         lon_0="0.0 deg", lat_0="0.0 deg", sigma="0.5 deg", frame="galactic"
     )
-    model1 = SkyModel(pwl, gauss)
+    model1 = SkyModel(pwl, gauss, name="m1")
 
     bkg = FoVBackgroundModel(dataset_name=dataset.name)
     dataset.models = [bkg, sky_model, model1]
 
     assert_allclose(dataset.npred().data.sum(), 9676.047906, rtol=1e-3)
     assert_allclose(dataset.npred_signal().data.sum(), 5676.04790, rtol=1e-3)
-    assert_allclose(dataset.npred_signal(model=model1).data.sum(), 150.7487, rtol=1e-3)
+    assert_allclose(
+        dataset.npred_signal(model_name=model1.name).data.sum(), 150.7487, rtol=1e-3
+    )
+    with pytest.raises(
+        KeyError, match="m2",
+    ):
+        dataset.npred_signal(model_name="m2")
 
 
 def test_stack_npred():
diff --git a/gammapy/datasets/tests/test_spectrum.py b/gammapy/datasets/tests/test_spectrum.py
--- a/gammapy/datasets/tests/test_spectrum.py
+++ b/gammapy/datasets/tests/test_spectrum.py
@@ -126,7 +126,7 @@ def test_npred_models():
     npred_sig = spectrum_dataset.npred_signal()
     assert_allclose(npred_sig.data.sum(), 64.8)
 
-    npred_sig_model1 = spectrum_dataset.npred_signal(model=model_1)
+    npred_sig_model1 = spectrum_dataset.npred_signal(model_name=model_1.name)
     assert_allclose(npred_sig_model1.data.sum(), 32.4)
 
 
@@ -191,10 +191,7 @@ def test_spectrum_dataset_stack_diagonal_safe_mask(spectrum_dataset):
 
     geom_true = geom.as_energy_true
     exposure = make_map_exposure_true_energy(
-        geom=geom_true,
-        livetime=livetime,
-        pointing=geom_true.center_skydir,
-        aeff=aeff
+        geom=geom_true, livetime=livetime, pointing=geom_true.center_skydir, aeff=aeff
     )
 
     edisp = EDispKernelMap.from_diagonal_response(
@@ -214,7 +211,7 @@ def test_spectrum_dataset_stack_diagonal_safe_mask(spectrum_dataset):
         edisp=edisp.copy(),
         background=background.copy(),
         gti=gti.copy(),
-        mask_safe=mask_safe
+        mask_safe=mask_safe,
     )
 
     livetime2 = 0.5 * livetime
@@ -244,10 +241,10 @@ def test_spectrum_dataset_stack_diagonal_safe_mask(spectrum_dataset):
     reference = spectrum_dataset.counts.data
     assert_allclose(spectrum_dataset1.counts.data[1:], reference[1:] * 2)
     assert_allclose(spectrum_dataset1.counts.data[0], 141363)
-    assert_allclose(spectrum_dataset1.exposure.quantity[0], 4.755644e09 * u.Unit("cm2 s"))
     assert_allclose(
-        spectrum_dataset1.background.data[1:], 3 * background.data[1:]
+        spectrum_dataset1.exposure.quantity[0], 4.755644e09 * u.Unit("cm2 s")
     )
+    assert_allclose(spectrum_dataset1.background.data[1:], 3 * background.data[1:])
     assert_allclose(spectrum_dataset1.background.data[0], background.data[0])
 
     kernel = edisp.get_edisp_kernel()
@@ -266,7 +263,7 @@ def test_spectrum_dataset_stack_nondiagonal_no_bkg(spectrum_dataset):
         energy_axis_true=energy.copy(name="energy_true"),
         sigma=0.1,
         bias=0,
-        geom=geom.to_image()
+        geom=geom.to_image(),
     )
     edisp1.exposure_map.data += 1
 
@@ -278,10 +275,7 @@ def test_spectrum_dataset_stack_nondiagonal_no_bkg(spectrum_dataset):
 
     geom_true = geom.as_energy_true
     exposure = make_map_exposure_true_energy(
-        geom=geom_true,
-        livetime=livetime,
-        pointing=geom_true.center_skydir,
-        aeff=aeff
+        geom=geom_true, livetime=livetime, pointing=geom_true.center_skydir, aeff=aeff
     )
 
     geom = spectrum_dataset.counts.geom
@@ -301,7 +295,7 @@ def test_spectrum_dataset_stack_nondiagonal_no_bkg(spectrum_dataset):
         energy_axis_true=energy.copy(name="energy_true"),
         sigma=0.2,
         bias=0.0,
-        geom=geom
+        geom=geom,
     )
     edisp2.exposure_map.data += 1
 
@@ -416,7 +410,7 @@ def setup(self):
             acceptance_off=acceptance_off,
             name="test",
             gti=self.gti,
-            mask_safe=mask_safe
+            mask_safe=mask_safe,
         )
 
     def test_spectrum_dataset_on_off_create(self):
@@ -425,9 +419,7 @@ def test_spectrum_dataset_on_off_create(self):
             u.Quantity([0.05, 0.5, 5, 20.0], "TeV"), name="energy_true"
         )
         geom = RegionGeom(region=None, axes=[e_reco])
-        empty_dataset = SpectrumDatasetOnOff.create(
-            geom=geom, energy_axis_true=e_true
-        )
+        empty_dataset = SpectrumDatasetOnOff.create(geom=geom, energy_axis_true=e_true)
 
         assert empty_dataset.counts.data.sum() == 0
         assert empty_dataset.data_shape[0] == 2
@@ -444,9 +436,7 @@ def test_spectrum_dataset_on_off_create(self):
     def test_create_stack(self):
         geom = RegionGeom(region=None, axes=[self.e_reco])
 
-        stacked = SpectrumDatasetOnOff.create(
-            geom=geom, energy_axis_true=self.e_true
-        )
+        stacked = SpectrumDatasetOnOff.create(geom=geom, energy_axis_true=self.e_true)
         stacked.mask_safe.data += True
 
         stacked.stack(self.dataset)
@@ -551,7 +541,7 @@ def test_to_from_ogip_files_no_edisp(self, tmp_path):
         mask_safe = RegionNDMap.from_geom(self.on_counts.geom, dtype=bool)
         mask_safe.data += True
 
-        acceptance = RegionNDMap.from_geom(self.on_counts.geom, data=1.)
+        acceptance = RegionNDMap.from_geom(self.on_counts.geom, data=1.0)
 
         exposure = self.aeff * self.livetime
         exposure.meta["livetime"] = self.livetime
@@ -878,7 +868,9 @@ def setup(self):
         # Change threshold to make stuff more interesting
 
         geom = self.datasets[0]._geom
-        self.datasets[0].mask_safe = geom.energy_mask(energy_min=1.2 * u.TeV, energy_max=50 * u.TeV)
+        self.datasets[0].mask_safe = geom.energy_mask(
+            energy_min=1.2 * u.TeV, energy_max=50 * u.TeV
+        )
 
         mask = geom.energy_mask(energy_max=20 * u.TeV)
         self.datasets[1].mask_safe &= mask
@@ -972,6 +964,7 @@ def test_datasets_stack_reduce():
     assert_allclose(info_table_cum["counts"], [124, 250, 369, 459])
     assert stacked.name == "stacked"
 
+
 @requires_data("gammapy-data")
 def test_datasets_stack_reduce_no_off():
     datasets = Datasets()
@@ -1010,9 +1003,7 @@ def test_stack_livetime():
 
     geom = RegionGeom(region=None, axes=[energy_axis])
 
-    dataset = SpectrumDatasetOnOff.create(
-        geom=geom, energy_axis_true=energy_axis_true
-    )
+    dataset = SpectrumDatasetOnOff.create(geom=geom, energy_axis_true=energy_axis_true)
 
     dataset.stack(dataset_ref)
     assert_allclose(dataset.exposure.meta["livetime"], 1581.736758 * u.s)
@@ -1075,9 +1066,7 @@ def setup(self):
     def test_cash(self):
         """Simple CASH fit to the on vector"""
         dataset = SpectrumDataset(
-            models=self.source_model,
-            counts=self.src,
-            exposure=self.exposure,
+            models=self.source_model, counts=self.src, exposure=self.exposure,
         )
 
         npred = dataset.npred().data