Source code for gammapy.modeling.model

# Licensed under a 3-clause BSD style license - see LICENSE.rst
import copy
import astropy.units as u
from .parameter import Parameter, Parameters

__all__ = ["Model"]


[docs]class Model: """Model base class.""" def __init__(self, **kwargs): # Copy default parameters from the class to the instance self._parameters = self.__class__.default_parameters.copy() for parameter in self._parameters: if parameter.name in self.__dict__: raise ValueError( f"Invalid parameter name: {parameter.name!r}." f"Attribute exists already: {getattr(self, parameter.name)!r}" ) setattr(self, parameter.name, parameter) # Update parameter information from kwargs for name, value in kwargs.items(): if name not in self.parameters.names: raise ValueError( f"Invalid argument: {name!r}. Parameter names are: {self.parameters.names}" ) self._parameters[name].quantity = u.Quantity(value) def __init_subclass__(cls, **kwargs): # Add parameters list on the model sub-class (not instances) cls.default_parameters = Parameters( [_ for _ in cls.__dict__.values() if isinstance(_, Parameter)] ) def _init_from_parameters(self, parameters): """Create model from list of parameters. This should be called for models that generate the parameters dynamically in ``__init__``, like the ``NaimaSpectralModel`` """ # TODO: should we pass through `Parameters` here? Why? parameters = Parameters(parameters) self._parameters = parameters for parameter in parameters: setattr(self, parameter.name, parameter) @property def parameters(self): """Parameters (`~gammapy.modeling.Parameters`)""" return self._parameters
[docs] def copy(self): """A deep copy.""" return copy.deepcopy(self)
def __str__(self): return f"{self.__class__.__name__}\n\n{self.parameters.to_table()}"
[docs] def to_dict(self): """Create dict for YAML serialisation""" return {"type": self.tag, "parameters": self.parameters.to_dict()["parameters"]}
[docs] @classmethod def from_dict(cls, data): params = { x["name"].split("@")[0]: x["value"] * u.Unit(x["unit"]) for x in data["parameters"] } # TODO: this is a special case for spatial models, maybe better move to `SpatialModel` base class if "frame" in data: params["frame"] = data["frame"] model = cls(**params) model._update_from_dict(data) return model
# TODO: try to get rid of this def _update_from_dict(self, data): self._parameters.update_from_dict(data) for parameter in self.parameters: setattr(self, parameter.name, parameter)
[docs] @staticmethod def create(tag, *args, **kwargs): """Create a model instance. Examples -------- >>> from gammapy.modeling import Model >>> spectral_model = Model.create("PowerLaw2SpectralModel", amplitude="1e-10 cm-2 s-1", index=3) >>> type(spectral_model) gammapy.modeling.models.spectral.PowerLaw2SpectralModel """ from .models import MODELS cls = MODELS.get_cls(tag) return cls(*args, **kwargs)