.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/details/models.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. or to run this example in your browser via Binder .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_details_models.py: Models ====== This is an introduction and overview on how to work with models in Gammapy. The sub-package `~gammapy.modeling` contains all the functionality related to modeling and fitting data. This includes spectral, spatial and temporal model classes, as well as the fit and parameter API.The models follow a naming scheme which contains the category as a suffix to the class name. An overview of all the available models can be found in the :ref:`model-gallery`. Note that there are separate tutorials, :doc:`/tutorials/details/model_management` and :doc:`/tutorials/details/fitting` that explains about `~gammapy.modeling`, the Gammapy modeling and fitting framework. You have to read that to learn how to work with models in order to analyse data. .. GENERATED FROM PYTHON SOURCE LINES 24-27 Setup ----- .. GENERATED FROM PYTHON SOURCE LINES 27-36 .. code-block:: Python # %matplotlib inline import numpy as np from astropy import units as u import matplotlib.pyplot as plt from IPython.display import display from gammapy.maps import Map, MapAxis, WcsGeom .. GENERATED FROM PYTHON SOURCE LINES 37-43 Spectral models --------------- All models are imported from the `~gammapy.modeling.models` namespace. Let’s start with a `~gammapy.modeling.models.PowerLawSpectralModel`: .. GENERATED FROM PYTHON SOURCE LINES 43-50 .. code-block:: Python from gammapy.modeling.models import PowerLawSpectralModel pwl = PowerLawSpectralModel() print(pwl) .. rst-class:: sphx-glr-script-out .. code-block:: none PowerLawSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- -------------- --------- --- --- ------ ---- ----- index 2.0000e+00 0.000e+00 nan nan False amplitude 1.0000e-12 TeV-1 s-1 cm-2 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True .. GENERATED FROM PYTHON SOURCE LINES 51-54 To get a list of all available spectral models you can import and print the spectral model registry or take a look at the :ref:`model-gallery` .. GENERATED FROM PYTHON SOURCE LINES 54-60 .. code-block:: Python from gammapy.modeling.models import SPECTRAL_MODEL_REGISTRY print(SPECTRAL_MODEL_REGISTRY) .. rst-class:: sphx-glr-script-out .. code-block:: none Registry -------- ConstantSpectralModel : ['ConstantSpectralModel', 'const'] CompoundSpectralModel : ['CompoundSpectralModel', 'compound'] PowerLawSpectralModel : ['PowerLawSpectralModel', 'pl'] PowerLaw2SpectralModel : ['PowerLaw2SpectralModel', 'pl-2'] BrokenPowerLawSpectralModel : ['BrokenPowerLawSpectralModel', 'bpl'] SmoothBrokenPowerLawSpectralModel : ['SmoothBrokenPowerLawSpectralModel', 'sbpl'] PiecewiseNormSpectralModel : ['PiecewiseNormSpectralModel', 'piecewise-norm'] ExpCutoffPowerLawSpectralModel : ['ExpCutoffPowerLawSpectralModel', 'ecpl'] ExpCutoffPowerLaw3FGLSpectralModel : ['ExpCutoffPowerLaw3FGLSpectralModel', 'ecpl-3fgl'] SuperExpCutoffPowerLaw3FGLSpectralModel : ['SuperExpCutoffPowerLaw3FGLSpectralModel', 'secpl-3fgl'] SuperExpCutoffPowerLaw4FGLDR3SpectralModel: ['SuperExpCutoffPowerLaw4FGLDR3SpectralModel', 'secpl-4fgl-dr3'] SuperExpCutoffPowerLaw4FGLSpectralModel : ['SuperExpCutoffPowerLaw4FGLSpectralModel', 'secpl-4fgl'] LogParabolaSpectralModel : ['LogParabolaSpectralModel', 'lp'] TemplateSpectralModel : ['TemplateSpectralModel', 'template'] TemplateNDSpectralModel : ['TemplateNDSpectralModel', 'templateND'] GaussianSpectralModel : ['GaussianSpectralModel', 'gauss'] EBLAbsorptionNormSpectralModel : ['EBLAbsorptionNormSpectralModel', 'ebl-norm'] NaimaSpectralModel : ['NaimaSpectralModel', 'naima'] ScaleSpectralModel : ['ScaleSpectralModel', 'scale'] PowerLawNormSpectralModel : ['PowerLawNormSpectralModel', 'pl-norm'] LogParabolaNormSpectralModel : ['LogParabolaNormSpectralModel', 'lp-norm'] ExpCutoffPowerLawNormSpectralModel : ['ExpCutoffPowerLawNormSpectralModel', 'ecpl-norm'] DarkMatterAnnihilationSpectralModel : ['DarkMatterAnnihilationSpectralModel', 'dm-annihilation'] DarkMatterDecaySpectralModel : ['DarkMatterDecaySpectralModel', 'dm-decay'] .. GENERATED FROM PYTHON SOURCE LINES 61-66 Spectral models all come with default parameters. Different parameter values can be passed on creation of the model, either as a string defining the value and unit or as an `astropy.units.Quantity` object directly: .. GENERATED FROM PYTHON SOURCE LINES 66-71 .. code-block:: Python amplitude = 1e-12 * u.Unit("TeV-1 cm-2 s-1") pwl = PowerLawSpectralModel(amplitude=amplitude, index=2.2) .. GENERATED FROM PYTHON SOURCE LINES 72-75 For convenience a `str` specifying the value and unit can be passed as well: .. GENERATED FROM PYTHON SOURCE LINES 75-80 .. code-block:: Python pwl = PowerLawSpectralModel(amplitude="2.7e-12 TeV-1 cm-2 s-1", index=2.2) print(pwl) .. rst-class:: sphx-glr-script-out .. code-block:: none PowerLawSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- -------------- --------- --- --- ------ ---- ----- index 2.2000e+00 0.000e+00 nan nan False amplitude 2.7000e-12 TeV-1 s-1 cm-2 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True .. GENERATED FROM PYTHON SOURCE LINES 81-84 The model can be evaluated at given energies by calling the model instance: .. GENERATED FROM PYTHON SOURCE LINES 84-90 .. code-block:: Python energy = [1, 3, 10, 30] * u.TeV dnde = pwl(energy) print(dnde) .. rst-class:: sphx-glr-script-out .. code-block:: none [2.70000000e-12 2.40822469e-13 1.70358483e-14 1.51948705e-15] 1 / (TeV s cm2) .. GENERATED FROM PYTHON SOURCE LINES 91-96 The returned quantity is a differential photon flux. For spectral models you can additionally compute the integrated and energy flux in a given energy range: .. GENERATED FROM PYTHON SOURCE LINES 96-104 .. code-block:: Python flux = pwl.integral(energy_min=1 * u.TeV, energy_max=10 * u.TeV) print(flux) eflux = pwl.energy_flux(energy_min=1 * u.TeV, energy_max=10 * u.TeV) print(eflux) .. rst-class:: sphx-glr-script-out .. code-block:: none 2.108034597491956e-12 1 / (s cm2) 4.982075849517389e-12 TeV / (s cm2) .. GENERATED FROM PYTHON SOURCE LINES 105-107 This also works for a list or an array of integration boundaries: .. GENERATED FROM PYTHON SOURCE LINES 107-113 .. code-block:: Python energy = [1, 3, 10, 30] * u.TeV flux = pwl.integral(energy_min=energy[:-1], energy_max=energy[1:]) print(flux) .. rst-class:: sphx-glr-script-out .. code-block:: none [1.64794383e-12 4.60090769e-13 1.03978226e-13] 1 / (s cm2) .. GENERATED FROM PYTHON SOURCE LINES 114-117 In some cases it can be useful to find use the inverse of a spectral model, to find the energy at which a given flux is reached: .. GENERATED FROM PYTHON SOURCE LINES 117-123 .. code-block:: Python dnde = 2.7e-12 * u.Unit("TeV-1 cm-2 s-1") energy = pwl.inverse(dnde) print(energy) .. rst-class:: sphx-glr-script-out .. code-block:: none 1.0 TeV .. GENERATED FROM PYTHON SOURCE LINES 124-127 As a convenience you can also plot any spectral model in a given energy range: .. GENERATED FROM PYTHON SOURCE LINES 127-132 .. code-block:: Python pwl.plot(energy_bounds=[1, 100] * u.TeV) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_001.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 133-136 Norm Spectral Models ~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 139-150 Normed spectral models are a special class of Spectral Models, which have a dimension-less normalisation. These spectral models feature a norm parameter instead of amplitude and are named using the ``NormSpectralModel`` suffix. They **must** be used along with another spectral model, as a multiplicative correction factor according to their spectral shape. They can be typically used for adjusting template based models, or adding a EBL correction to some analytic model. To check if a given `~gammapy.modeling.models.SpectralModel` is a norm model, you can simply look at the ``is_norm_spectral_model`` property .. GENERATED FROM PYTHON SOURCE LINES 150-157 .. code-block:: Python # To see the available norm models shipped with gammapy: for model in SPECTRAL_MODEL_REGISTRY: if model.is_norm_spectral_model: print(model) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 158-160 As an example, we see the `~gammapy.modeling.models.PowerLawNormSpectralModel` .. GENERATED FROM PYTHON SOURCE LINES 160-167 .. code-block:: Python from gammapy.modeling.models import PowerLawNormSpectralModel pwl_norm = PowerLawNormSpectralModel(tilt=0.1) print(pwl_norm) .. rst-class:: sphx-glr-script-out .. code-block:: none PowerLawNormSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- ---- --------- --- --- ------ ---- ----- tilt 1.0000e-01 0.000e+00 nan nan True norm 1.0000e+00 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True .. GENERATED FROM PYTHON SOURCE LINES 168-170 We can check the correction introduced at each energy .. GENERATED FROM PYTHON SOURCE LINES 170-175 .. code-block:: Python energy = [0.3, 1, 3, 10, 30] * u.TeV print(pwl_norm(energy)) .. rst-class:: sphx-glr-script-out .. code-block:: none [1.12794487 1. 0.89595846 0.79432823 0.7116851 ] .. GENERATED FROM PYTHON SOURCE LINES 176-180 A typical use case of a norm model would be in applying spectral correction to a `~gammapy.modeling.models.TemplateSpectralModel`. A template model is defined by custom tabular values provided at initialization. .. GENERATED FROM PYTHON SOURCE LINES 180-193 .. code-block:: Python from gammapy.modeling.models import TemplateSpectralModel energy = [0.3, 1, 3, 10, 30] * u.TeV values = [40, 30, 20, 10, 1] * u.Unit("TeV-1 s-1 cm-2") template = TemplateSpectralModel(energy, values) template.plot(energy_bounds=[0.2, 50] * u.TeV, label="template model") normed_template = template * pwl_norm normed_template.plot(energy_bounds=[0.2, 50] * u.TeV, label="normed_template model") plt.legend() plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_002.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 194-201 Compound Spectral Model ~~~~~~~~~~~~~~~~~~~~~~~ A `~gammapy.modeling.models.CompoundSpectralModel` is an arithmetic combination of two spectral models. The model ``normed_template`` created in the preceding example is an example of a `~gammapy.modeling.models.CompoundSpectralModel` .. GENERATED FROM PYTHON SOURCE LINES 201-205 .. code-block:: Python print(normed_template) .. rst-class:: sphx-glr-script-out .. code-block:: none CompoundSpectralModel Component 1 : TemplateSpectralModel Component 2 : PowerLawNormSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- ---- --------- --- --- ------ ---- ----- tilt 1.0000e-01 0.000e+00 nan nan True norm 1.0000e+00 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True Operator : mul .. GENERATED FROM PYTHON SOURCE LINES 206-208 To create an additive model, you can do simply: .. GENERATED FROM PYTHON SOURCE LINES 208-213 .. code-block:: Python model_add = pwl + template print(model_add) .. rst-class:: sphx-glr-script-out .. code-block:: none CompoundSpectralModel Component 1 : PowerLawSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- -------------- --------- --- --- ------ ---- ----- index 2.2000e+00 0.000e+00 nan nan False amplitude 2.7000e-12 TeV-1 s-1 cm-2 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True Component 2 : TemplateSpectralModel Operator : add .. GENERATED FROM PYTHON SOURCE LINES 214-217 Spatial models -------------- .. GENERATED FROM PYTHON SOURCE LINES 220-223 Spatial models are imported from the same `~gammapy.modeling.models` namespace, let’s start with a `~gammapy.modeling.models.GaussianSpatialModel`: .. GENERATED FROM PYTHON SOURCE LINES 223-230 .. code-block:: Python from gammapy.modeling.models import GaussianSpatialModel gauss = GaussianSpatialModel(lon_0="0 deg", lat_0="0 deg", sigma="0.2 deg") print(gauss) .. rst-class:: sphx-glr-script-out .. code-block:: none GaussianSpatialModel type name value unit error min max frozen link prior ---- ----- ---------- ---- --------- ---------- --------- ------ ---- ----- lon_0 0.0000e+00 deg 0.000e+00 nan nan False lat_0 0.0000e+00 deg 0.000e+00 -9.000e+01 9.000e+01 False sigma 2.0000e-01 deg 0.000e+00 0.000e+00 nan False e 0.0000e+00 0.000e+00 0.000e+00 1.000e+00 True phi 0.0000e+00 deg 0.000e+00 -1.800e+02 1.800e+02 True .. GENERATED FROM PYTHON SOURCE LINES 231-234 Again you can check the ``SPATIAL_MODELS`` registry to see which models are available or take a look at the :ref:`model-gallery` .. GENERATED FROM PYTHON SOURCE LINES 234-240 .. code-block:: Python from gammapy.modeling.models import SPATIAL_MODEL_REGISTRY print(SPATIAL_MODEL_REGISTRY) .. rst-class:: sphx-glr-script-out .. code-block:: none Registry -------- ConstantSpatialModel : ['ConstantSpatialModel', 'const'] TemplateSpatialModel : ['TemplateSpatialModel', 'template'] TemplateNDSpatialModel : ['TemplateNDSpatialModel', 'templateND'] DiskSpatialModel : ['DiskSpatialModel', 'disk'] GaussianSpatialModel : ['GaussianSpatialModel', 'gauss'] GeneralizedGaussianSpatialModel: ['GeneralizedGaussianSpatialModel', 'gauss-general'] PiecewiseNormSpatialModel : ['PiecewiseNormSpatialModel', 'piecewise-norm'] PointSpatialModel : ['PointSpatialModel', 'point'] ShellSpatialModel : ['ShellSpatialModel', 'shell'] Shell2SpatialModel : ['Shell2SpatialModel', 'shell2'] .. GENERATED FROM PYTHON SOURCE LINES 241-244 The default coordinate frame for all spatial models is ``"icrs"``, but the frame can be modified using the ``frame`` argument: .. GENERATED FROM PYTHON SOURCE LINES 244-250 .. code-block:: Python gauss = GaussianSpatialModel( lon_0="0 deg", lat_0="0 deg", sigma="0.2 deg", frame="galactic" ) .. GENERATED FROM PYTHON SOURCE LINES 251-255 You can specify any valid `astropy.coordinates` frame. The center position of the model can be retrieved as a `astropy.coordinates.SkyCoord` object using `~gammapy.modeling.models.SpatialModel.position`: .. GENERATED FROM PYTHON SOURCE LINES 255-259 .. code-block:: Python print(gauss.position) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 260-262 Spatial models can be evaluated again by calling the instance: .. GENERATED FROM PYTHON SOURCE LINES 262-270 .. code-block:: Python lon = [0, 0.1] * u.deg lat = [0, 0.1] * u.deg flux_per_omega = gauss(lon, lat) print(flux_per_omega) .. rst-class:: sphx-glr-script-out .. code-block:: none [13061.88470839 10172.60603928] 1 / sr .. GENERATED FROM PYTHON SOURCE LINES 271-275 The returned quantity corresponds to a surface brightness. Spatial model can be also evaluated using `~gammapy.maps.Map` and `~gammapy.maps.Geom` objects: .. GENERATED FROM PYTHON SOURCE LINES 275-282 .. code-block:: Python m = Map.create(skydir=(0, 0), width=(1, 1), binsz=0.02, frame="galactic") m.quantity = gauss.evaluate_geom(m.geom) m.plot(add_cbar=True) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_003.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 283-285 Again for convenience the model can be plotted directly: .. GENERATED FROM PYTHON SOURCE LINES 285-289 .. code-block:: Python gauss.plot(add_cbar=True) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_004.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 290-294 All spatial models have an associated sky region to it e.g. to illustrate the extension of the model on a sky image. The returned object is an `~regions.SkyRegion` object: .. GENERATED FROM PYTHON SOURCE LINES 294-298 .. code-block:: Python print(gauss.to_region()) .. rst-class:: sphx-glr-script-out .. code-block:: none Region: EllipseSkyRegion center: width: 0.4 deg height: 0.4 deg angle: 0.0 deg .. GENERATED FROM PYTHON SOURCE LINES 299-301 Now we can plot the region on a sky image: .. GENERATED FROM PYTHON SOURCE LINES 301-314 .. code-block:: Python plt.figure() gauss_elongated = GaussianSpatialModel( lon_0="0 deg", lat_0="0 deg", sigma="0.2 deg", e=0.7, phi="45 deg" ) ax = gauss_elongated.plot(add_cbar=True) region = gauss_elongated.to_region() region_pix = region.to_pixel(ax.wcs) ax.add_artist(region_pix.as_artist(ec="w", fc="None")) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_005.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 315-318 The `~gammapy.modeling.models.GaussianSpatialModel.to_region()` method can also be useful to write e.g. ds9 region files using ``write_ds9`` from the `regions` package: .. GENERATED FROM PYTHON SOURCE LINES 318-333 .. code-block:: Python from regions import Regions regions = Regions([gauss.to_region(), gauss_elongated.to_region()]) filename = "regions.reg" regions.write( filename, format="ds9", overwrite=True, ) # !cat regions.reg .. GENERATED FROM PYTHON SOURCE LINES 334-337 Temporal models --------------- .. GENERATED FROM PYTHON SOURCE LINES 340-343 Temporal models are imported from the same `~gammapy.modeling.models` namespace, let’s start with a `~gammapy.modeling.models.GaussianTemporalModel`: .. GENERATED FROM PYTHON SOURCE LINES 343-350 .. code-block:: Python from gammapy.modeling.models import GaussianTemporalModel gauss_temp = GaussianTemporalModel(t_ref=59240.0 * u.d, sigma=2.0 * u.d) print(gauss_temp) .. rst-class:: sphx-glr-script-out .. code-block:: none GaussianTemporalModel type name value unit error min max frozen link prior ---- ----- ---------- ---- --------- --- --- ------ ---- ----- t_ref 5.9240e+04 d 0.000e+00 nan nan False sigma 2.0000e+00 d 0.000e+00 nan nan False .. GENERATED FROM PYTHON SOURCE LINES 351-354 To check the ``TEMPORAL_MODELS`` registry to see which models are available: .. GENERATED FROM PYTHON SOURCE LINES 354-360 .. code-block:: Python from gammapy.modeling.models import TEMPORAL_MODEL_REGISTRY print(TEMPORAL_MODEL_REGISTRY) .. rst-class:: sphx-glr-script-out .. code-block:: none Registry -------- ConstantTemporalModel : ['ConstantTemporalModel', 'const'] LinearTemporalModel : ['LinearTemporalModel', 'linear'] LightCurveTemplateTemporalModel : ['LightCurveTemplateTemporalModel', 'template'] ExpDecayTemporalModel : ['ExpDecayTemporalModel', 'exp-decay'] GaussianTemporalModel : ['GaussianTemporalModel', 'gauss'] GeneralizedGaussianTemporalModel: ['GeneralizedGaussianTemporalModel', 'gengauss'] PowerLawTemporalModel : ['PowerLawTemporalModel', 'powerlaw'] SineTemporalModel : ['SineTemporalModel', 'sinus'] TemplatePhaseCurveTemporalModel : ['TemplatePhaseCurveTemporalModel', 'template-phase'] .. GENERATED FROM PYTHON SOURCE LINES 361-364 Temporal models can be evaluated on `astropy.time.Time` objects. The returned quantity is a dimensionless number .. GENERATED FROM PYTHON SOURCE LINES 364-371 .. code-block:: Python from astropy.time import Time time = Time("2021-01-29 00:00:00.000") gauss_temp(time) .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 372-374 As for other models, they can be plotted in a given time range .. GENERATED FROM PYTHON SOURCE LINES 374-380 .. code-block:: Python time = Time([59233.0, 59250], format="mjd") gauss_temp.plot(time) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_006.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 381-388 `~gammapy.modeling.models.SkyModel` ----------------------------------- The `~gammapy.modeling.models.SkyModel` class combines a spectral, and optionally, a spatial model and a temporal. It can be created from existing spectral, spatial and temporal model components: .. GENERATED FROM PYTHON SOURCE LINES 388-400 .. code-block:: Python from gammapy.modeling.models import SkyModel model = SkyModel( spectral_model=pwl, spatial_model=gauss, temporal_model=gauss_temp, name="my-source", ) print(model) .. rst-class:: sphx-glr-script-out .. code-block:: none SkyModel Name : my-source Datasets names : None Spectral model type : PowerLawSpectralModel Spatial model type : GaussianSpatialModel Temporal model type : GaussianTemporalModel Parameters: index : 2.200 +/- 0.00 amplitude : 2.70e-12 +/- 0.0e+00 1 / (TeV s cm2) reference (frozen): 1.000 TeV lon_0 : 0.000 +/- 0.00 deg lat_0 : 0.000 +/- 0.00 deg sigma : 0.200 +/- 0.00 deg e (frozen): 0.000 phi (frozen): 0.000 deg t_ref : 59240.000 +/- 0.00 d sigma : 2.000 +/- 0.00 d .. GENERATED FROM PYTHON SOURCE LINES 401-406 It is good practice to specify a name for your sky model, so that you can access it later by name and have meaningful identifier you serialisation. If you don’t define a name, a unique random name is generated: .. GENERATED FROM PYTHON SOURCE LINES 406-411 .. code-block:: Python model_without_name = SkyModel(spectral_model=pwl, spatial_model=gauss) print(model_without_name.name) .. rst-class:: sphx-glr-script-out .. code-block:: none 1QIDQyGQ .. GENERATED FROM PYTHON SOURCE LINES 412-415 The individual components of the source model can be accessed using ``.spectral_model``, ``.spatial_model`` and ``.temporal_model``: .. GENERATED FROM PYTHON SOURCE LINES 415-418 .. code-block:: Python print(model.spectral_model) .. rst-class:: sphx-glr-script-out .. code-block:: none PowerLawSpectralModel type name value unit error min max frozen link prior ---- --------- ---------- -------------- --------- --- --- ------ ---- ----- index 2.2000e+00 0.000e+00 nan nan False amplitude 2.7000e-12 TeV-1 s-1 cm-2 0.000e+00 nan nan False reference 1.0000e+00 TeV 0.000e+00 nan nan True .. GENERATED FROM PYTHON SOURCE LINES 419-421 .. code-block:: Python print(model.spatial_model) .. rst-class:: sphx-glr-script-out .. code-block:: none GaussianSpatialModel type name value unit error min max frozen link prior ---- ----- ---------- ---- --------- ---------- --------- ------ ---- ----- lon_0 0.0000e+00 deg 0.000e+00 nan nan False lat_0 0.0000e+00 deg 0.000e+00 -9.000e+01 9.000e+01 False sigma 2.0000e-01 deg 0.000e+00 0.000e+00 nan False e 0.0000e+00 0.000e+00 0.000e+00 1.000e+00 True phi 0.0000e+00 deg 0.000e+00 -1.800e+02 1.800e+02 True .. GENERATED FROM PYTHON SOURCE LINES 422-425 .. code-block:: Python print(model.temporal_model) .. rst-class:: sphx-glr-script-out .. code-block:: none GaussianTemporalModel type name value unit error min max frozen link prior ---- ----- ---------- ---- --------- --- --- ------ ---- ----- t_ref 5.9240e+04 d 0.000e+00 nan nan False sigma 2.0000e+00 d 0.000e+00 nan nan False .. GENERATED FROM PYTHON SOURCE LINES 426-428 And can be used as you have seen already seen above: .. GENERATED FROM PYTHON SOURCE LINES 428-433 .. code-block:: Python model.spectral_model.plot(energy_bounds=[1, 10] * u.TeV) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_007.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_007.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 434-444 Note that the gammapy fitting can interface only with a `~gammapy.modeling.models.SkyModel` and **not** its individual components. So, it is customary to work with `~gammapy.modeling.models.SkyModel` even if you are not doing a 3D fit. Since the amplitude parameter resides on the `~gammapy.modeling.models.SpectralModel`, specifying a spectral component is compulsory. The temporal and spatial components are optional. The temporal model needs to be specified only for timing analysis. In some cases (e.g. when doing a spectral analysis) there is no need for a spatial component either, and only a spectral model is associated with the source. .. GENERATED FROM PYTHON SOURCE LINES 444-449 .. code-block:: Python model_spectrum = SkyModel(spectral_model=pwl, name="source-spectrum") print(model_spectrum) .. rst-class:: sphx-glr-script-out .. code-block:: none SkyModel Name : source-spectrum Datasets names : None Spectral model type : PowerLawSpectralModel Spatial model type : Temporal model type : Parameters: index : 2.200 +/- 0.00 amplitude : 2.70e-12 +/- 0.0e+00 1 / (TeV s cm2) reference (frozen): 1.000 TeV .. GENERATED FROM PYTHON SOURCE LINES 450-455 Additionally the spatial model of `~gammapy.modeling.models.SkyModel` can be used to represent source models based on templates, where the spatial and energy axes are correlated. It can be created e.g. from an existing FITS file: .. GENERATED FROM PYTHON SOURCE LINES 455-465 .. code-block:: Python from gammapy.modeling.models import PowerLawNormSpectralModel, TemplateSpatialModel diffuse_cube = TemplateSpatialModel.read( "$GAMMAPY_DATA/fermi-3fhl-gc/gll_iem_v06_gc.fits.gz", normalize=False ) diffuse = SkyModel(PowerLawNormSpectralModel(), diffuse_cube) print(diffuse) .. rst-class:: sphx-glr-script-out .. code-block:: none SkyModel Name : zC5lFtwD Datasets names : None Spectral model type : PowerLawNormSpectralModel Spatial model type : TemplateSpatialModel Temporal model type : Parameters: tilt (frozen): 0.000 norm : 1.000 +/- 0.00 reference (frozen): 1.000 TeV lon_0 (frozen): 0.000 deg lat_0 (frozen): -0.062 deg .. GENERATED FROM PYTHON SOURCE LINES 466-472 Note that if the spatial model is not normalized over the sky it has to be combined with a normalized spectral model, for example `~gammapy.modeling.models.PowerLawNormSpectralModel`. This is the only case in `~gammapy.modeling.models.SkyModel` where the unit is fully attached to the spatial model. .. GENERATED FROM PYTHON SOURCE LINES 475-483 .. _modifying-model-parameters: Modifying model parameters -------------------------- Model parameters can be modified (eg: frozen, values changed, etc at any point), eg: .. GENERATED FROM PYTHON SOURCE LINES 483-500 .. code-block:: Python # Freezing a parameter model.spectral_model.index.frozen = True # Making a parameter free model.spectral_model.index.frozen = False # Changing a value model.spectral_model.index.value = 3 # Setting min and max ranges on parameters model.spectral_model.index.min = 1.0 model.spectral_model.index.max = 5.0 # Visualise the model as a table display(model.parameters.to_table()) .. rst-class:: sphx-glr-script-out .. code-block:: none type name value unit ... max frozen link prior ---- --------- ---------- -------------- ... --------- ------ ---- ----- index 3.0000e+00 ... 5.000e+00 False amplitude 2.7000e-12 TeV-1 s-1 cm-2 ... nan False reference 1.0000e+00 TeV ... nan True lon_0 0.0000e+00 deg ... nan False lat_0 0.0000e+00 deg ... 9.000e+01 False sigma 2.0000e-01 deg ... nan False e 0.0000e+00 ... 1.000e+00 True phi 0.0000e+00 deg ... 1.800e+02 True t_ref 5.9240e+04 d ... nan False sigma 2.0000e+00 d ... nan False .. GENERATED FROM PYTHON SOURCE LINES 501-504 You can use the interactive boxes to choose model parameters by name, type or other attributes mentioned in the column names. .. GENERATED FROM PYTHON SOURCE LINES 507-514 Model lists and serialisation ----------------------------- In a typical analysis scenario a model consists of multiple model components, or a “catalog” or “source library”. To handle this list of multiple model components, Gammapy has a `~gammapy.modeling.models.Models` class: .. GENERATED FROM PYTHON SOURCE LINES 514-521 .. code-block:: Python from gammapy.modeling.models import Models models = Models([model, diffuse]) print(models) .. rst-class:: sphx-glr-script-out .. code-block:: none Models Component 0: SkyModel Name : my-source Datasets names : None Spectral model type : PowerLawSpectralModel Spatial model type : GaussianSpatialModel Temporal model type : GaussianTemporalModel Parameters: index : 3.000 +/- 0.00 amplitude : 2.70e-12 +/- 0.0e+00 1 / (TeV s cm2) reference (frozen): 1.000 TeV lon_0 : 0.000 +/- 0.00 deg lat_0 : 0.000 +/- 0.00 deg sigma : 0.200 +/- 0.00 deg e (frozen): 0.000 phi (frozen): 0.000 deg t_ref : 59240.000 +/- 0.00 d sigma : 2.000 +/- 0.00 d Component 1: SkyModel Name : zC5lFtwD Datasets names : None Spectral model type : PowerLawNormSpectralModel Spatial model type : TemplateSpatialModel Temporal model type : Parameters: tilt (frozen): 0.000 norm : 1.000 +/- 0.00 reference (frozen): 1.000 TeV lon_0 (frozen): 0.000 deg lat_0 (frozen): -0.062 deg .. GENERATED FROM PYTHON SOURCE LINES 522-524 Individual model components in the list can be accessed by their name: .. GENERATED FROM PYTHON SOURCE LINES 524-528 .. code-block:: Python print(models["my-source"]) .. rst-class:: sphx-glr-script-out .. code-block:: none SkyModel Name : my-source Datasets names : None Spectral model type : PowerLawSpectralModel Spatial model type : GaussianSpatialModel Temporal model type : GaussianTemporalModel Parameters: index : 3.000 +/- 0.00 amplitude : 2.70e-12 +/- 0.0e+00 1 / (TeV s cm2) reference (frozen): 1.000 TeV lon_0 : 0.000 +/- 0.00 deg lat_0 : 0.000 +/- 0.00 deg sigma : 0.200 +/- 0.00 deg e (frozen): 0.000 phi (frozen): 0.000 deg t_ref : 59240.000 +/- 0.00 d sigma : 2.000 +/- 0.00 d .. GENERATED FROM PYTHON SOURCE LINES 529-534 **Note:** To make the access by name unambiguous, models are required to have a unique name, otherwise an error will be thrown. To see which models are available you can use the ``.names`` attribute: .. GENERATED FROM PYTHON SOURCE LINES 534-538 .. code-block:: Python print(models.names) .. rst-class:: sphx-glr-script-out .. code-block:: none ['my-source', 'zC5lFtwD'] .. GENERATED FROM PYTHON SOURCE LINES 539-549 Note that a `~gammapy.modeling.models.SkyModel` object can be evaluated for a given longitude, latitude, and energy, but the `~gammapy.modeling.models.Models` object cannot. This `~gammapy.modeling.models.Models` container object will be assigned to `~gammapy.datasets.Dataset` or `~gammapy.datasets.Datasets` together with the data to be fitted. Checkout e.g. the :doc:`/tutorials/details/model_management` tutorial for details. The `~gammapy.modeling.models.Models` class also has in place ``.append()`` and ``.extend()`` methods: .. GENERATED FROM PYTHON SOURCE LINES 549-554 .. code-block:: Python model_copy = model.copy(name="my-source-copy") models.append(model_copy) .. GENERATED FROM PYTHON SOURCE LINES 555-558 This list of models can be also serialised to a custom YAML based format: .. GENERATED FROM PYTHON SOURCE LINES 558-563 .. code-block:: Python models_yaml = models.to_yaml() print(models_yaml) .. rst-class:: sphx-glr-script-out .. code-block:: none components: - name: my-source type: SkyModel spectral: type: PowerLawSpectralModel parameters: - name: index value: 3.0 min: 1.0 max: 5.0 - name: amplitude value: 2.7e-12 unit: TeV-1 s-1 cm-2 - name: reference value: 1.0 unit: TeV spatial: type: GaussianSpatialModel frame: galactic parameters: - name: lon_0 value: 0.0 unit: deg - name: lat_0 value: 0.0 unit: deg - name: sigma value: 0.2 unit: deg - name: e value: 0.0 - name: phi value: 0.0 unit: deg temporal: type: GaussianTemporalModel parameters: - name: t_ref value: 59240.0 unit: d - name: sigma value: 2.0 unit: d scale: utc - name: zC5lFtwD type: SkyModel spectral: type: PowerLawNormSpectralModel parameters: - name: tilt value: 0.0 - name: norm value: 1.0 - name: reference value: 1.0 unit: TeV spatial: type: TemplateSpatialModel frame: galactic parameters: - name: lon_0 value: 0.0 unit: deg - name: lat_0 value: -0.0625 unit: deg filename: /home/runner/work/gammapy-docs/gammapy-docs/gammapy-datasets/dev/fermi-3fhl-gc/gll_iem_v06_gc.fits.gz normalize: false unit: 1 / (MeV s sr cm2) - name: my-source-copy type: SkyModel spectral: type: PowerLawSpectralModel parameters: - name: index value: 3.0 min: 1.0 max: 5.0 - name: amplitude value: 2.7e-12 unit: TeV-1 s-1 cm-2 - name: reference value: 1.0 unit: TeV spatial: type: GaussianSpatialModel frame: galactic parameters: - name: lon_0 value: 0.0 unit: deg - name: lat_0 value: 0.0 unit: deg - name: sigma value: 0.2 unit: deg - name: e value: 0.0 - name: phi value: 0.0 unit: deg temporal: type: GaussianTemporalModel parameters: - name: t_ref value: 59240.0 unit: d - name: sigma value: 2.0 unit: d scale: utc metadata: creator: Gammapy 2.0.dev2264+gce6472842 date: '2025-09-03T12:51:20.807850' origin: null .. GENERATED FROM PYTHON SOURCE LINES 564-577 The structure of the yaml files follows the structure of the python objects. The ``components`` listed correspond to the `~gammapy.modeling.models.SkyModel` and components of the `~gammapy.modeling.models.Models`. For each `~gammapy.modeling.models.SkyModel` we have information about its ``name``, ``type`` (corresponding to the tag attribute) and sub-models (i.e ``spectral`` model and eventually ``spatial`` model). Then the spatial and spectral models are defined by their type and parameters. The ``parameters`` keys name/value/unit are mandatory, while the keys min/max/frozen are optional (so you can prepare shorter files). If you want to write this list of models to disk and read it back later you can use: .. GENERATED FROM PYTHON SOURCE LINES 577-583 .. code-block:: Python models.write("models.yaml", overwrite=True) models_read = Models.read("models.yaml") .. GENERATED FROM PYTHON SOURCE LINES 584-596 Additionally the models can be exported and imported together with the data using the `~gammapy.datasets.Datasets.read()` and `~gammapy.datasets.Datasets.write()` methods as shown in the :doc:`/tutorials/analysis-3d/analysis_mwl` notebook. Models with shared parameter ---------------------------- A model parameter can be shared with other models, for example we can define two power-law models with the same spectral index but different amplitudes: .. GENERATED FROM PYTHON SOURCE LINES 596-606 .. code-block:: Python pwl2 = PowerLawSpectralModel() pwl2.index = pwl.index pwl.index.value = ( 2.3 # also update pwl2 as the parameter object is now the same as shown below ) print(pwl.index) print(pwl2.index) .. rst-class:: sphx-glr-script-out .. code-block:: none Parameter(name='index', value=2.3, factor=2.3, scale=1.0, unit=Unit(dimensionless), min=1.0, max=5.0, frozen=False, prior=None, id=0x7f86aed94590) Parameter(name='index', value=2.3, factor=2.3, scale=1.0, unit=Unit(dimensionless), min=1.0, max=5.0, frozen=False, prior=None, id=0x7f86aed94590) .. GENERATED FROM PYTHON SOURCE LINES 607-610 In the YAML files the shared parameter is flagged by the additional ``link`` entry that follows the convention ``parameter.name@unique_id``: .. GENERATED FROM PYTHON SOURCE LINES 610-616 .. code-block:: Python models = Models([SkyModel(pwl, name="source1"), SkyModel(pwl2, name="source2")]) models_yaml = models.to_yaml() print(models_yaml) .. rst-class:: sphx-glr-script-out .. code-block:: none components: - name: source1 type: SkyModel spectral: type: PowerLawSpectralModel parameters: - name: index value: 2.3 min: 1.0 max: 5.0 link: index@FZmtVQNX - name: amplitude value: 2.7e-12 unit: TeV-1 s-1 cm-2 - name: reference value: 1.0 unit: TeV - name: source2 type: SkyModel spectral: type: PowerLawSpectralModel parameters: - name: index value: 2.3 min: 1.0 max: 5.0 link: index@FZmtVQNX - name: amplitude value: 1.0e-12 unit: TeV-1 s-1 cm-2 - name: reference value: 1.0 unit: TeV metadata: creator: Gammapy 2.0.dev2264+gce6472842 date: '2025-09-03T12:51:20.956190' origin: null .. GENERATED FROM PYTHON SOURCE LINES 617-635 .. _custom-model: Implementing a custom model --------------------------- In order to add a user defined spectral model you have to create a `~gammapy.modeling.models.SpectralModel` subclass. This new model class should include: - a tag used for serialization (it can be the same as the class name) - an instantiation of each Parameter with their unit, default values and frozen status - the evaluate function where the mathematical expression for the model is defined. As an example we will use a PowerLawSpectralModel plus a Gaussian (with fixed width). First we define the new custom model class that we name ``MyCustomSpectralModel``: .. GENERATED FROM PYTHON SOURCE LINES 635-677 .. code-block:: Python from gammapy.modeling import Parameter from gammapy.modeling.models import SpectralModel class MyCustomSpectralModel(SpectralModel): """My custom spectral model, parametrizing a power law plus a Gaussian spectral line. Parameters ---------- amplitude : `astropy.units.Quantity` Amplitude of the spectra model. index : `astropy.units.Quantity` Spectral index of the model. reference : `astropy.units.Quantity` Reference energy of the power law. mean : `astropy.units.Quantity` Mean value of the Gaussian. width : `astropy.units.Quantity` Sigma width of the Gaussian line. """ tag = "MyCustomSpectralModel" amplitude = Parameter("amplitude", "1e-12 cm-2 s-1 TeV-1", min=0) index = Parameter("index", 2, min=0) reference = Parameter("reference", "1 TeV", frozen=True) mean = Parameter("mean", "1 TeV", min=0) width = Parameter("width", "0.1 TeV", min=0, frozen=True) @staticmethod def evaluate(energy, index, amplitude, reference, mean, width): pwl = PowerLawSpectralModel.evaluate( energy=energy, index=index, amplitude=amplitude, reference=reference, ) gauss = amplitude * np.exp(-((energy - mean) ** 2) / (2 * width**2)) return pwl + gauss .. GENERATED FROM PYTHON SOURCE LINES 678-686 It is good practice to also implement a docstring for the model, defining the parameters and also defining a ``.tag``, which specifies the name of the model for serialisation. Also note that gammapy assumes that all `~gammapy.modeling.models.SpectralModel` evaluate functions return a flux in unit of `"cm-2 s-1 TeV-1"` (or equivalent dimensions). This model can now be used as any other spectral model in Gammapy: .. GENERATED FROM PYTHON SOURCE LINES 686-696 .. code-block:: Python my_custom_model = MyCustomSpectralModel(mean="3 TeV") print(my_custom_model) print(my_custom_model.integral(1 * u.TeV, 10 * u.TeV)) my_custom_model.plot(energy_bounds=[1, 10] * u.TeV) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_008.png :alt: models :srcset: /tutorials/details/images/sphx_glr_models_008.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none MyCustomSpectralModel type name value unit error ... max frozen link prior ---- --------- ---------- -------------- --------- ... --- ------ ---- ----- amplitude 1.0000e-12 TeV-1 s-1 cm-2 0.000e+00 ... nan False index 2.0000e+00 0.000e+00 ... nan False reference 1.0000e+00 TeV 0.000e+00 ... nan True mean 3.0000e+00 TeV 0.000e+00 ... nan False width 1.0000e-01 TeV 0.000e+00 ... nan True 1.1442739329466746e-12 1 / (s cm2) .. GENERATED FROM PYTHON SOURCE LINES 697-701 As a next step we can also register the custom model in the ``SPECTRAL_MODELS`` registry, so that it becomes available for serialization: .. GENERATED FROM PYTHON SOURCE LINES 701-711 .. code-block:: Python SPECTRAL_MODEL_REGISTRY.append(MyCustomSpectralModel) model = SkyModel(spectral_model=my_custom_model, name="my-source") models = Models([model]) models.write("my-custom-models.yaml", overwrite=True) # !cat my-custom-models.yaml .. GENERATED FROM PYTHON SOURCE LINES 712-717 Similarly you can also create custom spatial models and add them to the ``SPATIAL_MODELS`` registry. In that case gammapy assumes that the evaluate function return a normalized quantity in “sr-1” such as the model integral over the whole sky is one. .. GENERATED FROM PYTHON SOURCE LINES 720-752 Models with energy dependent morphology --------------------------------------- A common science case in the study of extended sources is to probe for energy dependent morphology, eg: in Supernova Remnants or Pulsar Wind Nebulae. Traditionally, this has been done by splitting the data into energy bands and doing individual fits of the morphology in these energy bands. `~gammapy.modeling.models.SkyModel` offers a natural framework to simultaneously model the energy and morphology, e.g. spatial extent described by a parametric model expression with energy dependent parameters. The models shipped within gammapy use a “factorised” representation of the source model, where the spatial (:math:`l,b`), energy (:math:`E`) and time (:math:`t`) dependence are independent model components and not correlated: .. math:: \begin{align}f(l, b, E, t) = F(l, b) \cdot G(E) \cdot H(t)\end{align} To use full 3D models, ie :math:`f(l, b, E) = F(l, b, E) \cdot \ G(E)`, you have to implement your own custom `~gammapy.modeling.models.SpatialModel`. Note that it is still necessary to multiply by a `~gammapy.modeling.models.SpectralModel`, :math:`G(E)` to be dimensionally consistent. In this example, we create Gaussian Spatial Model with the extension varying with energy. For simplicity, we assume a linear dependency on energy and parameterize this by specifying the extension at 2 energies. You can add more complex dependencies, probably motivated by physical models. .. GENERATED FROM PYTHON SOURCE LINES 752-796 .. code-block:: Python from astropy.coordinates import angular_separation from gammapy.modeling.models import SpatialModel class MyCustomGaussianModel(SpatialModel): """My custom Energy Dependent Gaussian model. Parameters ---------- lon_0, lat_0 : `~astropy.coordinates.Angle` Center position sigma_1TeV : `~astropy.coordinates.Angle` Width of the Gaussian at 1 TeV sigma_10TeV : `~astropy.coordinates.Angle` Width of the Gaussian at 10 TeV """ tag = "MyCustomGaussianModel" is_energy_dependent = True lon_0 = Parameter("lon_0", "0 deg") lat_0 = Parameter("lat_0", "0 deg", min=-90, max=90) sigma_1TeV = Parameter("sigma_1TeV", "2.0 deg", min=0) sigma_10TeV = Parameter("sigma_10TeV", "0.2 deg", min=0) @staticmethod def evaluate(lon, lat, energy, lon_0, lat_0, sigma_1TeV, sigma_10TeV): sep = angular_separation(lon, lat, lon_0, lat_0) # Compute sigma for the given energy using linear interpolation in log energy sigma_nodes = u.Quantity([sigma_1TeV, sigma_10TeV]) energy_nodes = [1, 10] * u.TeV log_s = np.log(sigma_nodes.to("deg").value) log_en = np.log(energy_nodes.to("TeV").value) log_e = np.log(energy.to("TeV").value) sigma = np.exp(np.interp(log_e, log_en, log_s)) * u.deg exponent = -0.5 * (sep / sigma) ** 2 norm = 1 / (2 * np.pi * sigma**2) return norm * np.exp(exponent) .. GENERATED FROM PYTHON SOURCE LINES 797-803 Serialisation of this model can be achieved as explained in the previous section. You can now use it as standard `~gammapy.modeling.models.SpatialModel` in your analysis. Note that this is still a `~gammapy.modeling.models.SpatialModel` and not a `~gammapy.modeling.models.SkyModel`, so it needs to be multiplied by a `~gammapy.modeling.models.SpectralModel` as before. .. GENERATED FROM PYTHON SOURCE LINES 803-811 .. code-block:: Python spatial_model = MyCustomGaussianModel() spectral_model = PowerLawSpectralModel() sky_model = SkyModel(spatial_model=spatial_model, spectral_model=spectral_model) print(spatial_model.evaluation_radius) .. rst-class:: sphx-glr-script-out .. code-block:: none None .. GENERATED FROM PYTHON SOURCE LINES 812-814 To visualise it, we evaluate it on a 3D geom. .. GENERATED FROM PYTHON SOURCE LINES 814-824 .. code-block:: Python energy_axis = MapAxis.from_energy_bounds( energy_min=0.1 * u.TeV, energy_max=10.0 * u.TeV, nbin=3, name="energy_true" ) geom = WcsGeom.create(skydir=(0, 0), width=5.0 * u.deg, binsz=0.1, axes=[energy_axis]) spatial_model.plot_grid(geom=geom, add_cbar=True, figsize=(14, 3)) plt.show() .. image-sg:: /tutorials/details/images/sphx_glr_models_009.png :alt: Energy_true 100 GeV - 464 GeV, Energy_true 464 GeV - 2.15 TeV, Energy_true 2.15 TeV - 10.0 TeV :srcset: /tutorials/details/images/sphx_glr_models_009.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 825-831 For computational purposes, it is useful to specify a ``evaluation_radius`` for `~gammapy.modeling.models.SpatialModel` - this gives a size on which to compute the model. Though optional, it is highly recommended for Custom Spatial Models. This can be done, for ex, by defining the following function inside the above class: .. GENERATED FROM PYTHON SOURCE LINES 831-837 .. code-block:: Python @property def evaluation_radius(self): """Evaluation radius (`~astropy.coordinates.Angle`).""" return 5 * np.max([self.sigma_1TeV.value, self.sigma_10TeV.value]) * u.deg .. _sphx_glr_download_tutorials_details_models.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/gammapy/gammapy-webpage/main?urlpath=lab/tree/notebooks/dev/tutorials/details/models.ipynb :alt: Launch binder :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: models.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: models.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: models.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_