Repository: gammapy/gammapy

Issue:
`FoVBackgroundModel` can't be loaded from dict when it includes a spatial model
# Problem

It seems like all `<SpatialModel>.from_dict()` expect a dictionary with a key 'spatial' (Same for spectral models)

https://github.com/gammapy/gammapy/blob/dc9a88aea9e8f721c3c1f57b39bd98719a061118/gammapy/modeling/models/spatial.py#L286

The `FoVBackgroundModel` handles loading from dict correctly for spectral models
https://github.com/gammapy/gammapy/blob/dc9a88aea9e8f721c3c1f57b39bd98719a061118/gammapy/modeling/models/cube.py#L798

but not for spatial models

https://github.com/gammapy/gammapy/blob/dc9a88aea9e8f721c3c1f57b39bd98719a061118/gammapy/modeling/models/cube.py#L802-L807

# Solution

Should an easy fix
```python
     spatial_model = model_class.from_dict({"spatial": spatial_data}) 
```


Discussion:

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
@@ -802,7 +802,7 @@ def from_dict(cls, data, **kwargs):
         spatial_data = data.get("spatial")
         if spatial_data is not None:
             model_class = SPATIAL_MODEL_REGISTRY.get_cls(spatial_data["type"])
-            spatial_model = model_class.from_dict(spatial_data)
+            spatial_model = model_class.from_dict({"spatial": spatial_data})
         else:
             spatial_model = None
 
@@ -1023,7 +1023,7 @@ def from_dict(cls, data, **kwargs):
         spatial_data = data.get("spatial")
         if spatial_data is not None:
             model_class = SPATIAL_MODEL_REGISTRY.get_cls(spatial_data["type"])
-            spatial_model = model_class.from_dict(spatial_data)
+            spatial_model = model_class.from_dict({"spatial": spatial_data})
         else:
             spatial_model = None
 


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
@@ -15,8 +15,10 @@
 )
 from gammapy.maps import Map, MapAxis, MapCoord, RegionGeom, WcsGeom, WcsNDMap
 from gammapy.modeling.models import (
+    SPATIAL_MODEL_REGISTRY,
     ConstantSpatialModel,
     DiskSpatialModel,
+    FoVBackgroundModel,
     GaussianSpatialModel,
     GeneralizedGaussianSpatialModel,
     PiecewiseNormSpatialModel,
@@ -480,6 +482,32 @@ def test_sky_diffuse_map_empty(caplog):
         assert np.all(np.isfinite(model.map.data))
 
 
+@pytest.mark.parametrize("model_cls", SPATIAL_MODEL_REGISTRY)
+def test_model_from_dict(tmpdir, model_cls):
+    if model_cls in [TemplateSpatialModel, TemplateNDSpatialModel]:
+        default_map = Map.create(map_type="wcs", width=(1, 1), binsz=0.5, unit="sr-1")
+        filename = str(tmpdir / "template.fits")
+        model = model_cls(default_map, filename=filename)
+        model.write()
+    elif model_cls is PiecewiseNormSpatialModel:
+        geom = WcsGeom.create(skydir=(0, 0), npix=(2, 2), binsz=0.3, frame="galactic")
+        default_coords = MapCoord.create(geom.footprint)
+        default_coords["lon"] *= u.deg
+        default_coords["lat"] *= u.deg
+        model = model_cls(default_coords, frame="galactic")
+    else:
+        model = model_cls()
+
+    data = model.to_dict()
+    model_from_dict = model_cls.from_dict(data)
+    assert model_from_dict.tag == model_from_dict.tag
+
+    bkg_model = FoVBackgroundModel(spatial_model=model, dataset_name="test")
+    bkg_model_dict = bkg_model.to_dict()
+    bkg_model_from_dict = FoVBackgroundModel.from_dict(bkg_model_dict)
+    assert bkg_model_from_dict.spatial_model is not None
+
+
 def test_evaluate_on_fk5_map():
     # Check if spatial model can be evaluated on a map with FK5 frame
     # Regression test for GH-2402