Repository: gammapy/gammapy

Issue:
Coordinate frame `fk5` not handled properly in `SpatialModel.evaluate_geom()`
Dear all,

I have trouble using SkyDiffuseMap from a 2D fits map

```

mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
print(sum(sum(mod.data)))

```
output  : 
0.9999999588496848

-----------------------------------------------------
```

spatial_model = SkyDiffuseMap(mod,norm=1)
print(spatial_model.evaluate(22.5 * u.deg,83 * u.deg,1 * u.Unit('cm-2 s-1')))

```

output  : 
[0.] 1 / sr
---------------------------------------------------


If I use this model as imput of a skymodel for a MapDataset then the npred is always zero from this model.
The BackgroundModel gives good npred values.

Did I do something wrong ?


Cheers,
Cyril.





Coordinate frame `fk5` not handled properly in `SpatialModel.evaluate_geom()`
Dear all,

I have trouble using SkyDiffuseMap from a 2D fits map

```

mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
print(sum(sum(mod.data)))

```
output  : 
0.9999999588496848

-----------------------------------------------------
```

spatial_model = SkyDiffuseMap(mod,norm=1)
print(spatial_model.evaluate(22.5 * u.deg,83 * u.deg,1 * u.Unit('cm-2 s-1')))

```

output  : 
[0.] 1 / sr
---------------------------------------------------


If I use this model as imput of a skymodel for a MapDataset then the npred is always zero from this model.
The BackgroundModel gives good npred values.

Did I do something wrong ?


Cheers,
Cyril.







Discussion:
Can you please execute the following:
```python3
mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
print(mod.geom)
```
...and post the output here? This will be helpful for the discussion.

Thx for looking into this !

Here is the output :  
```
Invalid value BUNIT='None' in FITS header. Setting empty unit.

WcsGeom

	axes       : lon, lat
	shape      : (200, 200)
	ndim       : 2
	coordsys   : CEL
	projection : SFL
	center     : 83.6 deg, 22.0 deg
	width      : 4.0 deg x 4.0 deg


```
In the specific example you posted above the order of the coordinates is not correct. What does the following code give:

```python3
spatial_model = SkyDiffuseMap(mod, norm=1)
print(spatial_model(lon=83 * u.deg, lat=22.5 * u.deg))
```
?
Here is the output :
`[0.] 1 / sr`
Ok, this makes it hard to debug remotely. Can you provide me with the specific FITS file somehow?
Thanks @ctrichard! I just checked out the notebook and data you send me and I was able to track down the problem. I can confirm it is a bug in Gammapy.

The spatial template you read is defined in the `fk5` coordinate frame, but currently Gammapy does only handle `galactic` and `icrs` coordinate frames in the model evaluation. Unfortunately this error went silently and Gammapy fell back to the `galactic` default to evaluate the model. Which leads of course to zero predicted counts. I'll submit a PR to fix this behaviour as soon as possible.

The work-around for now would be to reproject your template to the `icrs` coordinate frame like so:
```python3

mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
template = Map.create(
    skydir=SkyCoord('83.6 deg','22.0 deg'),
    width=(2, 2),
    coordsys="CEL",
    binsz=0.02
)

template.data = mod.interp_by_coord(template.geom.get_coord())
``` 


Thank you for spotting this bug !

Have you tried the work-around you propose ?

```
template = Map.create(
    skydir=SkyCoord('83.6 deg','22.0 deg'),
    width=(4, 4),
    coordsys="CEL",
    #map_type='wcs', 
    #proj='GLS',
    binsz=0.02
)
template.data = mod.interp_by_coord(template.geom.get_coord())
print(template.geom)


WcsGeom

	axes       : lon, lat
	shape      : (200, 200)
	ndim       : 2
	coordsys   : CEL
	projection : CAR
	center     : 83.6 deg, 22.0 deg
	width      : 4.0 deg x 4.0 deg


------------------------


spatial_model = SkyDiffuseMap(template,norm=1)
print(spatial_model(lon=83 * u.deg, lat=22.5 * u.deg))
[0.] 1 / sr

-------

```

The template Map is well filled but I have the same results at the end .


Yes, I've tried the work-around and it worked for me. However I think I adapted the exposure to be in the range of `1e10 m2 s`, because you use a spectral model with an amplitude of `1e-12`.  It also  turned out that at the position `lon=83 * u.deg, lat=22.5 * u.deg` the spatial model was zero indeed. If you evaluate at the center of the map:
```python3
spatial_model(lon=83.6 * u.deg, lat=22.0 * u.deg)
```
What do you get now?
Yes you are right ! Sorry for this stupid mistake.

Thanks a lot for your very fast help.
@ctrichard You're welcome!

Please keep the issue open as a reminder to fix the coordinations frame handling.
Can you please execute the following:
```python3
mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
print(mod.geom)
```
...and post the output here? This will be helpful for the discussion.

Thx for looking into this !

Here is the output :  
```
Invalid value BUNIT='None' in FITS header. Setting empty unit.

WcsGeom

	axes       : lon, lat
	shape      : (200, 200)
	ndim       : 2
	coordsys   : CEL
	projection : SFL
	center     : 83.6 deg, 22.0 deg
	width      : 4.0 deg x 4.0 deg


```
In the specific example you posted above the order of the coordinates is not correct. What does the following code give:

```python3
spatial_model = SkyDiffuseMap(mod, norm=1)
print(spatial_model(lon=83 * u.deg, lat=22.5 * u.deg))
```
?
Here is the output :
`[0.] 1 / sr`
Ok, this makes it hard to debug remotely. Can you provide me with the specific FITS file somehow?
Thanks @ctrichard! I just checked out the notebook and data you send me and I was able to track down the problem. I can confirm it is a bug in Gammapy.

The spatial template you read is defined in the `fk5` coordinate frame, but currently Gammapy does only handle `galactic` and `icrs` coordinate frames in the model evaluation. Unfortunately this error went silently and Gammapy fell back to the `galactic` default to evaluate the model. Which leads of course to zero predicted counts. I'll submit a PR to fix this behaviour as soon as possible.

The work-around for now would be to reproject your template to the `icrs` coordinate frame like so:
```python3

mod = Map.read("FakeModelMap_CrabGauss_XY83.63_22.01_SigmaXY0.00_0.00.fits")
template = Map.create(
    skydir=SkyCoord('83.6 deg','22.0 deg'),
    width=(2, 2),
    coordsys="CEL",
    binsz=0.02
)

template.data = mod.interp_by_coord(template.geom.get_coord())
``` 


Thank you for spotting this bug !

Have you tried the work-around you propose ?

```
template = Map.create(
    skydir=SkyCoord('83.6 deg','22.0 deg'),
    width=(4, 4),
    coordsys="CEL",
    #map_type='wcs', 
    #proj='GLS',
    binsz=0.02
)
template.data = mod.interp_by_coord(template.geom.get_coord())
print(template.geom)


WcsGeom

	axes       : lon, lat
	shape      : (200, 200)
	ndim       : 2
	coordsys   : CEL
	projection : CAR
	center     : 83.6 deg, 22.0 deg
	width      : 4.0 deg x 4.0 deg


------------------------


spatial_model = SkyDiffuseMap(template,norm=1)
print(spatial_model(lon=83 * u.deg, lat=22.5 * u.deg))
[0.] 1 / sr

-------

```

The template Map is well filled but I have the same results at the end .


Yes, I've tried the work-around and it worked for me. However I think I adapted the exposure to be in the range of `1e10 m2 s`, because you use a spectral model with an amplitude of `1e-12`.  It also  turned out that at the position `lon=83 * u.deg, lat=22.5 * u.deg` the spatial model was zero indeed. If you evaluate at the center of the map:
```python3
spatial_model(lon=83.6 * u.deg, lat=22.0 * u.deg)
```
What do you get now?
Yes you are right ! Sorry for this stupid mistake.

Thanks a lot for your very fast help.
@ctrichard You're welcome!

Please keep the issue open as a reminder to fix the coordinations frame handling.

Resolving patch:
diff --git a/gammapy/modeling/models/cube.py b/gammapy/modeling/models/cube.py
--- a/gammapy/modeling/models/cube.py
+++ b/gammapy/modeling/models/cube.py
@@ -31,7 +31,8 @@ def __call__(self, lon, lat, energy):
         return self.evaluate(lon, lat, energy)
 
     def evaluate_geom(self, geom):
-        coords = geom.get_coord()
+        coordsys = "CEL" if self.frame in ["icrs", "fk5"] else "GAL"
+        coords = geom.get_coord(coordsys=coordsys)
         return self(coords.lon, coords.lat, coords["energy"])
 
 
diff --git a/gammapy/modeling/models/spatial.py b/gammapy/modeling/models/spatial.py
--- a/gammapy/modeling/models/spatial.py
+++ b/gammapy/modeling/models/spatial.py
@@ -60,7 +60,7 @@ def position(self):
     def evaluate_geom(self, geom):
         """Evaluate model on `~gammapy.maps.Geom`."""
         # TODO: change to uniform coordinate frame names
-        coordsys = "CEL" if self.frame == "icrs" else "GAL"
+        coordsys = "CEL" if self.frame in ["icrs", "fk5"] else "GAL"
         coords = geom.get_coord(coordsys=coordsys)
         return self(coords.lon, coords.lat)
 


Test patch:
diff --git a/gammapy/modeling/models/tests/test_spatial.py b/gammapy/modeling/models/tests/test_spatial.py
--- a/gammapy/modeling/models/tests/test_spatial.py
+++ b/gammapy/modeling/models/tests/test_spatial.py
@@ -212,3 +212,10 @@ def test_sky_diffuse_map_normalize():
     assert vals.unit == ""
     integral = vals.sum()
     assert_allclose(integral.value, 1, rtol=1e-4)
+
+
+def test_evaluate_fk5():
+    geom = WcsGeom.create(width=(5, 5), binsz=0.1, coordsys="CEL")
+    model = GaussianSpatialModel("0 deg", "0 deg", "0.1 deg", frame="fk5")
+    data = model.evaluate_geom(geom)
+    assert data.value[12, 12] > 0