def test_model_class_par_init(): x = Parameter("x", 4, "cm") y = Parameter("y", 10) model = MyModel(x=x, y=y) assert x is model.x assert y is model.y
class CoModel(Model): """Compound model example""" norm = Parameter("norm", 42, "cm") def __init__(self, m1, m2, norm=norm.quantity): self.m1 = m1 self.m2 = m2 super().__init__(norm=norm) @property def parameters(self): return Parameters([self.norm]) + self.m1.parameters + self.m2.parameters
class MyModel(Model): """Simple model example""" x = Parameter("x", 1, "cm") y = Parameter("y", 2)
def __init__(self, m1, a=1, y=99): self.m1 = m1 a = Parameter("a", a) y = Parameter("y", y) self.default_parameters = Parameters([a, y]) super().__init__(a=a, y=y)
class SkyDiffuseCascadeCube(SpatialModel): """Cube sky map model for electromagnetic cascades. Parameters ---------- cascmap : `~simCRpropa.cascmaps.CascMap` Cascade Map template spectral_model : `SpectralModel` Spectral model of the injected particles. rotation: float Rotation angle of the cascade template tmax: float Maximum delay time in years allowed for the cascade. interp_kwargs : dict Interpolation keyword arguments passed to `gammapy.maps.Map.interp_by_coord`. Default arguments are {'interp': 'linear', 'fill_value': 0}. """ tag = "SkyDiffuseCascadeCube" rotation = Parameter("rotation", 0., unit="deg", frozen=True) tmax = Parameter("tmax", 1e7, unit="yr", frozen=True) _apply_irf_default = {"exposure": True, "psf": True, "edisp": True} def __init__( self, cascmap, spectral_model, rotation=rotation.quantity, tmax=tmax.quantity, interp_kwargs=None, apply_irf=None, name=None, ): self.cascmap = cascmap self._spectral_model = spectral_model self._energy_unit_spectral_model = energy_unit_spectral_model self._name = name interp_kwargs = {} if interp_kwargs is None else interp_kwargs interp_kwargs.setdefault("interp", "linear") interp_kwargs.setdefault("fill_value", 0) self._interp_kwargs = interp_kwargs self._cached_value = None self._cached_weights = None self._cached_coordinates = (None, None, None) if apply_irf is None: apply_irf = self._apply_irf_default.copy() self.apply_irf = apply_irf super().__init__(tmax=tmax, rotation=rotation) @property def name(self): return self._name def _interpolate(self, lon, lat, energy): coord = { "lon": lon.to_value("deg"), "lat": lat.to_value("deg"), "energy": energy, } return self.cascmap.add_primary_to_casc().interp_by_coord( coord, **self._interp_kwargs) def evaluate(self, lon, lat, energy, **kwargs): """Evaluate model at given coordinates""" rotation = kwargs.pop("rotation") tmax = kwargs.pop("tmax") # change max delay time if not tmax == self.cascmap.tmax: self.cascmap.tmax = tmax # change rotation angle # and apply rotation if not rotation == self.cascmap.angle: self.cascmap.angle = rotation # change spectral weights self.cascmap.apply_spectral_weights(self._inj_spec, smooth=True, **kwargs) is_cached_coord = [ _ is coord for _, coord in zip((lon, lat, energy), self._cached_coordinates) ] # reset cache if not np.all(is_cached_coord): self._cached_value = None if self._cached_weights is not None and \ not np.all(np.equal(self.cascmap.weights, self._cached_weights)): self._cached_weights = None if self._cached_value is None or self._cached_weights is None: self._cached_coordinates = (lon, lat, energy) self._cached_value = self._interpolate(lon, lat, energy) self._cached_weights = self.cascmap.weights return u.Quantity(self._cached_value, self.cascmap.casc_obs.unit, copy=False) def copy(self): """A shallow copy""" new = copy.copy(self) return new @property def position(self): """`~astropy.coordinates.SkyCoord`""" return self.cascmap.casc_obs.geom.center_skydir @property def evaluation_radius(self): """`~astropy.coordinates.Angle`""" return np.max(self.cascmap.casc_obs.geom.width) / 2.0 @property def parameters(self): return (Parameters([self.rotation, self.tmax]) + self.spectral_model.parameters) def to_dict(self): data = super().to_dict() data["name"] = self.name data["type"] = data.pop("type") data["spectral_model"] = self.spectral_model.to_dict() data["parameters"] = Parameters([self.rotation, self.tmax]).to_dict() if self.apply_irf != self._apply_irf_default: data["apply_irf"] = self.apply_irf return data def __str__(self): str_ = self.__class__.__name__ + "\n\n" str_ += "\tParameters:\n" info = _get_parameters_str(self.parameters) lines = info.split("\n") str_ += "\t" + "\n\t".join(lines[:-1]) str_ += "\n\n" return str_.expandtabs(tabsize=2)
class CascadeSpectralModel(SpectralModel): """Spectral model for electromagnetic cascades. Parameters ---------- cascmap : `~simCRpropa.cascmaps.CascMap` Cascade Map template spectral_model : `SpectralModel` Spectral model of the injected particles. ebl: `EBLAbsorptionNormSpectralModel` EBL model to be used region: region object region in which cascade is summed up rotation: float Rotation angle of the cascade template tmax: float Maximum delay time in years allowed for the cascade. bias: float energy bias for the TeV energy spectrum interp_kwargs : dict Interpolation keyword arguments passed to `gammapy.maps.Map.interp_by_coord`. Default arguments are {'interp': 'linear', 'fill_value': 0}. add_primary: bool if true, add the observed flux from the point source in evaluate function """ tag = "CascadeSpectralModel" rotation = Parameter("rotation", 0., unit="deg", frozen=True) tmax = Parameter("tmax", 1e7, unit="yr", frozen=True) bias = Parameter("bias", 0., unit=u.dimensionless_unscaled, frozen=True, min=-0.2, max=0.2) _apply_irf_default = {"exposure": True, "psf": True, "edisp": True} def __init__(self, cascmap, spectral_model, ebl, region, rotation=rotation.quantity, tmax=tmax.quantity, bias=bias.quantity, interp_kwargs=None, apply_irf=None, name=None, add_primary=True, energy_unit_spectral_model="TeV", use_gammapy_interp=False): self.cascmap = cascmap self._intrinsic_spectral_model = spectral_model self._ebl = ebl self._name = name self._inj_spec = None self._energy_unit_spectral_model = energy_unit_spectral_model self._set_injection_spectrum() self.region = region self.add_primary = add_primary # get central sky coordinates self._lon, self._lat = cascmap.casc_obs.geom.center_coord[:-1] interp_kwargs = {} if interp_kwargs is None else interp_kwargs #interp_kwargs.setdefault("interp", "linear") #interp_kwargs.setdefault("fill_value", 0) interp_kwargs.setdefault("interp", 1) self._interp_kwargs = interp_kwargs self._cached_value = None self._cached_weights = None self._cached_coordinates = (None, None, None) self.use_gammapy_interp = use_gammapy_interp if apply_irf is None: apply_irf = self._apply_irf_default.copy() self.apply_irf = apply_irf super().__init__(tmax=tmax, rotation=rotation, bias=bias) @property def name(self): return self._name @property def ebl(self): return self._ebl @property def intrinsic_spectral_model(self): return self._intrinsic_spectral_model def _set_injection_spectrum(self): def inj_spec(energy, **kwargs): if isinstance(energy, u.Quantity): x = energy.to(self._energy_unit_spectral_model) else: x = energy * u.Unit(self._energy_unit_spectral_model) return self._intrinsic_spectral_model.evaluate(x, **kwargs) self._inj_spec = inj_spec def _interpolate(self, energy): spec = self.cascmap.get_obs_spectrum(self.region) if self.use_gammapy_interp: coord = { "lon": self._lon, "lat": self._lat, "energy_true": energy, } result = spec.interp_by_coord(coord, ** self._interp_kwargs) * spec.unit else: data = spec.data[:, 0, 0] data[data <= 0] = 1e-40 x = spec.geom.axes['energy_true'].center interp = interp1d(np.log(x.value), np.log(data), fill_value='extrapolate', kind='linear') result = np.exp(interp(np.log(energy.to( x.unit).value))) * spec.unit return result def evaluate(self, energy, **kwargs): """Evaluate model at given coordinates""" rotation = kwargs.pop("rotation") tmax = kwargs.pop("tmax") smooth = kwargs.pop("smooth", True) bias = kwargs.pop("bias") # change max delay time if not tmax == self.cascmap.tmax: self.cascmap.tmax = tmax # change rotation angle # and apply rotation if not rotation == self.cascmap.angle: self.cascmap.angle = rotation # calculate flux from observed point source specturm # first the ebl contribution # and remove parameters from kwargs that belong to the EBL model kwargs_ebl = {} for k in self._ebl.parameters.names: kwargs_ebl[k] = kwargs.pop(k) result = self._ebl.evaluate(energy * (1. + bias), **kwargs_ebl) result *= self._intrinsic_spectral_model.evaluate( energy * (1. + bias), **kwargs) # change spectral weights self.cascmap.apply_spectral_weights(injspec=self._inj_spec, smooth=smooth, force_recompute=True, **kwargs) is_cached_coord = [ _ is coord for _, coord in zip(energy, self._cached_coordinates) ] # reset cache if not np.all(is_cached_coord): self._cached_value = None if self._cached_weights is not None and \ not np.all(np.equal(self.cascmap.weights, self._cached_weights)): self._cached_weights = None if self._cached_value is None or self._cached_weights is None: self._cached_coordinates = energy self._cached_value = self._interpolate(energy * (1. + bias)) self._cached_weights = self.cascmap.weights if self.add_primary: result += self._cached_value.to(result.unit) else: result = self._cached_value.to(result.unit) return result def copy(self): """A shallow copy""" new = copy.copy(self) return new @property def parameters(self): return (Parameters([self.rotation, self.tmax, self.bias]) + self._intrinsic_spectral_model.parameters + self._ebl.parameters) def to_dict(self): data = super().to_dict() data["name"] = self.name data["type"] = data.pop("type") data["spectral_model"] = self.spectral_model.to_dict() data["parameters"] = Parameters([self.rotation, self.tmax]).to_dict() if self.apply_irf != self._apply_irf_default: data["apply_irf"] = self.apply_irf return data def __str__(self): str_ = self.__class__.__name__ + "\n\n" str_ += "\tParameters:\n" info = _get_parameters_str(self.parameters) lines = info.split("\n") str_ += "\t" + "\n\t".join(lines[:-1]) str_ += "\n\n" return str_.expandtabs(tabsize=2)
def __init__(self, m1, a=1, y=99): self.m1 = m1 parameters = [Parameter("a", a), Parameter("y", y)] super()._init_from_parameters(parameters)