Repository: gammapy/gammapy

Issue:
Expect the `MapAxis` directly in `to_edisp_kernel`
Should we expect directly the `MapAxis` here? (Note: this is a TODO converted into an issue)

https://github.com/gammapy/gammapy/blob/e5aecb334e7aebe304affd96b545a636019f7626/gammapy/irf/edisp/core.py#L145-L148


**Solution**
'energy' should be a `MapAxis` type. This needs a small API changes and deprecations so that 'energy' is a `MapAxis` and not a `Quantity`.


Discussion:

Resolving patch:
diff --git a/gammapy/irf/edisp/core.py b/gammapy/irf/edisp/core.py
--- a/gammapy/irf/edisp/core.py
+++ b/gammapy/irf/edisp/core.py
@@ -1,18 +1,24 @@
 # Licensed under a 3-clause BSD style license - see LICENSE.rst
+import logging
 import numpy as np
 import scipy.special
 from astropy import units as u
 from astropy.coordinates import Angle, SkyCoord
+from astropy.units import Quantity
 from astropy.visualization import quantity_support
 import matplotlib.pyplot as plt
 from matplotlib.colors import PowerNorm
 from gammapy.maps import MapAxes, MapAxis, RegionGeom
+from gammapy.utils.deprecation import deprecated_renamed_argument
 from gammapy.visualization.utils import add_colorbar
 from ..core import IRF
 
 __all__ = ["EnergyDispersion2D"]
 
 
+log = logging.getLogger(__name__)
+
+
 class EnergyDispersion2D(IRF):
     """Offset-dependent energy dispersion matrix.
 
@@ -41,8 +47,9 @@ class EnergyDispersion2D(IRF):
     Create energy dispersion matrix (`~gammapy.irf.EnergyDispersion`)
     for a given field of view offset and energy binning:
 
-    >>> energy = MapAxis.from_bounds(0.1, 20, nbin=60, unit="TeV", interp="log").edges
-    >>> edisp = edisp2d.to_edisp_kernel(offset='1.2 deg', energy=energy, energy_true=energy)
+    >>> energy_axis = MapAxis.from_bounds(0.1, 20, nbin=60, unit="TeV", interp="log", name='energy')
+    >>> edisp = edisp2d.to_edisp_kernel(offset='1.2 deg', energy_axis=energy_axis,
+    ...                                 energy_axis_true=energy_axis.copy(name='energy_true'))
 
     See Also
     --------
@@ -117,7 +124,13 @@ def from_gauss(
             data=data.value,
         )
 
-    def to_edisp_kernel(self, offset, energy_true=None, energy=None):
+    @deprecated_renamed_argument(
+        ["energy_true", "energy"],
+        ["energy_axis_true", "energy_axis"],
+        ["v1.3", "v1.3"],
+        arg_in_kwargs=True,
+    )
+    def to_edisp_kernel(self, offset, energy_axis_true=None, energy_axis=None):
         """Detector response R(Delta E_reco, Delta E_true).
 
         Probability to reconstruct an energy in a given true energy band
@@ -127,9 +140,9 @@ def to_edisp_kernel(self, offset, energy_true=None, energy=None):
         ----------
         offset : `~astropy.coordinates.Angle`
             Offset.
-        energy_true : `~astropy.units.Quantity`, optional
+        energy_axis_true : `~gammapy.maps.MapAxis`, optional
             True energy axis. Default is None.
-        energy : `~astropy.units.Quantity`, optional
+        energy_axis : `~gammapy.maps.MapAxis`, optional
             Reconstructed energy axis. Default is None.
 
         Returns
@@ -141,18 +154,18 @@ def to_edisp_kernel(self, offset, energy_true=None, energy=None):
 
         offset = Angle(offset)
 
-        if energy is None:
+        if isinstance(energy_axis, Quantity):
+            energy_axis = MapAxis.from_energy_edges(energy_axis)
+        if energy_axis is None:
             energy_axis = self.axes["energy_true"].copy(name="energy")
-        else:
-            energy_axis = MapAxis.from_energy_edges(energy)
 
-        if energy_true is None:
-            energy_axis_true = self.axes["energy_true"]
-        else:
+        if isinstance(energy_axis_true, Quantity):
             energy_axis_true = MapAxis.from_energy_edges(
-                energy_true,
+                energy_axis_true,
                 name="energy_true",
             )
+        if energy_axis_true is None:
+            energy_axis_true = self.axes["energy_true"]
 
         pointing = SkyCoord("0d", "0d")
 
diff --git a/gammapy/irf/edisp/kernel.py b/gammapy/irf/edisp/kernel.py
--- a/gammapy/irf/edisp/kernel.py
+++ b/gammapy/irf/edisp/kernel.py
@@ -150,7 +150,7 @@ def from_gauss(cls, energy_axis_true, energy_axis, sigma, bias, pdf_threshold=1e
             pdf_threshold=pdf_threshold,
         )
         return edisp.to_edisp_kernel(
-            offset=offset_axis.center[0], energy=energy_axis.edges
+            offset=offset_axis.center[0], energy_axis=energy_axis
         )
 
     @classmethod


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
@@ -164,10 +164,10 @@ def get_psf():
 def get_edisp(geom, geom_etrue):
     filename = "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz"
     edisp2d = EnergyDispersion2D.read(filename, hdu="EDISP")
-    energy = geom.axes["energy"].edges
-    energy_true = geom_etrue.axes["energy_true"].edges
+    energy_axis = geom.axes["energy"]
+    energy_axis_true = geom_etrue.axes["energy_true"]
     edisp_kernel = edisp2d.to_edisp_kernel(
-        offset="1.2 deg", energy=energy, energy_true=energy_true
+        offset="1.2 deg", energy_axis=energy_axis, energy_axis_true=energy_axis_true
     )
     edisp = EDispKernelMap.from_edisp_kernel(edisp_kernel)
     return edisp
diff --git a/gammapy/irf/edisp/tests/test_core.py b/gammapy/irf/edisp/tests/test_core.py
--- a/gammapy/irf/edisp/tests/test_core.py
+++ b/gammapy/irf/edisp/tests/test_core.py
@@ -66,10 +66,17 @@ def test_evaluation(self):
     def test_exporter(self):
         # Check RMF exporter
         offset = Angle(0.612, "deg")
-        e_reco = MapAxis.from_energy_bounds(1, 10, 7, "TeV").edges
-        e_true = MapAxis.from_energy_bounds(0.8, 5, 5, "TeV").edges
-        rmf = self.edisp.to_edisp_kernel(offset, energy_true=e_true, energy=e_reco)
+        e_reco_axis = MapAxis.from_energy_bounds(1, 10, 7, "TeV")
+        e_true_axis = MapAxis.from_energy_bounds(0.8, 5, 5, "TeV", name="energy_true")
+        rmf = self.edisp.to_edisp_kernel(
+            offset, energy_axis_true=e_true_axis, energy_axis=e_reco_axis
+        )
         assert_allclose(rmf.data.data[2, 3], 0.08, atol=5e-2)  # same tolerance as above
+        # Test for v1.3
+        rmf2 = self.edisp.to_edisp_kernel(
+            offset, energy_axis_true=e_true_axis.edges, energy_axis=e_reco_axis.edges
+        )
+        assert_allclose(rmf2.data.data[2, 3], 0.08, atol=5e-2)
 
     def test_write(self):
         energy_axis_true = MapAxis.from_energy_bounds(