Repository: gammapy/gammapy

Issue:
Log scale and grids
This issue is triggered by https://github.com/gammapy/gammapy/issues/2270#issue-464031097 - there's a test fail with Numpy dev - the issue is that we are making an `nbins` float here:

https://github.com/gammapy/gammapy/blob/7a19c4b3b3e82831c6c683db9799a1d803cf928f/gammapy/utils/energy.py#L34

@adonath - Could you please fix this? I'm not sure if the proper fix is to round up or down to the nearest int.

There's other options as well, e.g. we could just remove the `per_decade` argument or that helper function completely and use this:
https://github.com/gammapy/gammapy/blob/76ab409e6bee09436127ce67e11de1ad5b2d7bb0/gammapy/maps/geom.py#L479

Or introduce an equivalent of `numpy.arange` - Numpy offered a separate function for the case where the caller wants a stepsize instead of a given number of points - maybe we should do that as well to be symmetric, and to keep support for setting up grids of a desired step size easily.

Finally, there's the option to attache the grid-making functionality to the existing scale classes here and to use those throughout Gammapy:
https://github.com/gammapy/gammapy/blob/5a24919d91a9aa601f7a1ee3d677cf4bebfc6b3b/gammapy/utils/interpolation.py#L138

I think https://observablehq.com/@d3/scale-ticks and also matplotlib have the feature to make grids or ticks attached to the scales. Here in Astropy this wasn't needed/added so far http://docs.astropy.org/en/stable/visualization/normalization.html

In principle having energy-specific scale and grid functions for log isn't needed or good design,  on the other hand it's the only case (currently, but later?) where we need a log scale, so just fixing up the existing helper function is not too bad.


Discussion:
I agree we should just remove the helper functions `energy_logspace` and `sqrt_space` and probably replace it with `MapAxis` and also re-use the scaling classes we have in `MapAxis.`  

Resolving patch:
diff --git a/gammapy/utils/nddata.py b/gammapy/utils/nddata.py
--- a/gammapy/utils/nddata.py
+++ b/gammapy/utils/nddata.py
@@ -5,7 +5,7 @@
 from .array import array_stats_str
 from .interpolation import ScaledRegularGridInterpolator
 
-__all__ = ["NDDataArray", "sqrt_space"]
+__all__ = ["NDDataArray"]
 
 
 class NDDataArray:
@@ -156,31 +156,3 @@ def _add_regular_grid_interp(self, interp_kwargs=None):
         self._regular_grid_interp = ScaledRegularGridInterpolator(
             points, self.data, points_scale=points_scale, **interp_kwargs
         )
-
-
-def sqrt_space(start, stop, num):
-    """Return numbers spaced evenly on a square root scale.
-
-    This function is similar to `numpy.linspace` and `numpy.logspace`.
-
-    Parameters
-    ----------
-    start : float
-        start is the starting value of the sequence
-    stop : float
-        stop is the final value of the sequence
-    num : int
-        Number of samples to generate.
-
-    Returns
-    -------
-    samples : `~numpy.ndarray`
-        1D array with a square root scale
-
-    Examples
-    --------
-    >>> from gammapy.utils.nddata import sqrt_space
-    >>> sqrt_space(0, 2, 5)
-    array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ])
-    """
-    return np.sqrt(np.linspace(start ** 2, stop ** 2, num))


Test patch:
diff --git a/gammapy/cube/tests/test_fit.py b/gammapy/cube/tests/test_fit.py
--- a/gammapy/cube/tests/test_fit.py
+++ b/gammapy/cube/tests/test_fit.py
@@ -305,9 +305,7 @@ def test_map_fit(sky_model, geom, geom_etrue):
     dataset_1.background_model.norm.value = 0.5
     dataset_1.counts = dataset_1.npred()
 
-    dataset_2 = get_map_dataset(
-        sky_model, geom, geom_etrue, evaluation_mode="global"
-    )
+    dataset_2 = get_map_dataset(sky_model, geom, geom_etrue, evaluation_mode="global")
     dataset_2.counts = dataset_2.npred()
 
     sky_model.parameters["sigma"].frozen = True