class ShellSpatialModel(SpatialModel): r"""Shell model. For more information see :ref:`shell-spatial-model`. Parameters ---------- lon_0, lat_0 : `~astropy.coordinates.Angle` Center position radius : `~astropy.coordinates.Angle` Inner radius, :math:`r_{in}` width : `~astropy.coordinates.Angle` Shell width frame : {"icrs", "galactic"} Center position coordinate frame See Also -------- Shell2SpatialModel """ tag = ["ShellSpatialModel", "shell"] lon_0 = Parameter("lon_0", "0 deg") lat_0 = Parameter("lat_0", "0 deg", min=-90, max=90) radius = Parameter("radius", "1 deg") width = Parameter("width", "0.2 deg") @property def evaluation_radius(self): r"""Evaluation radius (`~astropy.coordinates.Angle`). Set to :math:`r_\text{out}`. """ return self.radius.quantity + self.width.quantity @staticmethod def evaluate(lon, lat, lon_0, lat_0, radius, width): """Evaluate model.""" sep = angular_separation(lon, lat, lon_0, lat_0) radius_out = radius + width norm = 3 / (2 * np.pi * (radius_out**3 - radius**3)) with np.errstate(invalid="ignore"): # np.where and np.select do not work with quantities, so we use the # workaround with indexing value = np.sqrt(radius_out**2 - sep**2) mask = sep < radius value[mask] = (value - np.sqrt(radius**2 - sep**2))[mask] value[sep > radius_out] = 0 return norm * value def to_region(self, **kwargs): """Model outline (`~regions.CircleAnnulusSkyRegion`).""" return CircleAnnulusSkyRegion( center=self.position, inner_radius=self.radius.quantity, outer_radius=self.radius.quantity + self.width.quantity, **kwargs, )
class GeneralizedGaussianTemporalModel(TemporalModel): r"""A generalized Gaussian temporal profile .. math:: F(t) = exp( - 0.5 * (\frac{ \lvert t - t_{ref} \rvert}{t_rise}) ^ {1 / \eta}) for t < t_ref F(t) = exp( - 0.5 * (\frac{ \lvert t - t_{ref} \rvert}{t_decay}) ^ {1 / \eta}) for t > t_ref Parameters ---------- t_ref : `~astropy.units.Quantity` The time of the pulse's maximum intensity. t_rise : `~astropy.units.Quantity` Rise time constant. t_decay : `~astropy.units.Quantity` Decay time constant. eta : `~astropy.units.Quantity` Inverse pulse sharpness -> higher values implies a more peaked pulse """ tag = ["GeneralizedGaussianTemporalModel", "gengauss"] _t_ref_default = Time("2000-01-01") t_ref = Parameter("t_ref", _t_ref_default.mjd, unit = "day", frozen=False) t_rise = Parameter("t_rise", "1d", frozen=False) t_decay = Parameter("t_decay", "1d", frozen=False) eta = Parameter("eta", 1/2, unit = "", frozen=False) @staticmethod def evaluate(time, t_ref, t_rise, t_decay, eta): val_rise = np.exp( - 0.5 * (np.abs(u.Quantity(time - t_ref,"d")) ** (1/eta)) / (t_rise ** (1/eta))) val_decay = np.exp( - 0.5 * (np.abs(u.Quantity(time - t_ref,"d")) ** (1/eta)) / (t_decay ** (1/eta))) val = np.where(time < t_ref, val_rise, val_decay) return val def integral(self, t_min, t_max, **kwargs): """Evaluate the integrated flux within the given time intervals Parameters ---------- t_min: `~astropy.time.Time` Start times of observation t_max: `~astropy.time.Time` Stop times of observation Returns ------- norm : float Integrated flux norm on the given time intervals """ pars = self.parameters t_rise = pars["t_rise"].quantity t_decay = pars["t_decay"].quantity eta = pars["eta"].quantity t_ref = Time(pars["t_ref"].quantity, format = "mjd") integral = scipy.integrate.quad(self.evaluate, t_min.mjd, t_max.mjd, args=(t_ref.mjd,t_rise,t_decay,eta))[0] return integral / self.time_sum(t_min, t_max).to_value("d")
def covariance_diagonal(): x = Parameter("x", 1, error=0.1) y = Parameter("y", 2, error=0.2) z = Parameter("z", 3, error=0.3) parameters = Parameters([x, y, z]) return Covariance(parameters=parameters)
class GaussianTemporalModel(TemporalModel): """A Gaussian Temporal profile Parameters ---------- t_ref: The reference time in mjd sigma : `~astropy.units.Quantity` """ tag = "GaussianTemporalModel" t_ref = Parameter("t_ref", 55555, frozen=False) sigma = Parameter("sigma", "1 d", frozen=False) def evaluate(self, time, t_ref, sigma): return np.exp(-((time.mjd - t_ref)**2) / (2 * sigma.to_value("d")**2)) def integral(self, t_min, t_max, **kwargs): r"""Integrate Gaussian analytically. Parameters ---------- t_min, t_max : `~astropy.time` Lower and upper bound of integration range """ pars = self.parameters norm = pars["sigma"].quantity * np.sqrt(2 * np.pi) u_min = norm * ((t_min.mjd - pars["t_ref"].quantity) / (np.sqrt(2) * pars["sigma"].quantity)) u_max = norm * ((t_max.mjd - pars["t_ref"].quantity) / (np.sqrt(2) * pars["sigma"].quantity)) integ = 1.0 / 2 * (scipy.special.erf(u_max) - scipy.special.erf(u_min)) unit = getattr(pars["sigma"], "unit") return integ / self.time_sum(t_min, t_max).to_value(unit)
class ExpDecayTemporalModel(TemporalModel): """Temporal model with an exponential decay. Parameters ---------- t0 : Decay time scale t_ref: The reference time in mjd ..math:: F(t) = exp(t - t_ref)/t0 """ tag = "ExponentialDecayTemporalModel" t0 = Parameter("t0", "1 d", frozen=False) t_ref = Parameter("t_ref", 55555, frozen=True) def evaluate(self, time, t0, t_ref): return np.exp(-(time.mjd - t_ref) / t0.to_value("d")) def integral(self, t_min, t_max): pars = self.parameters t0 = pars["t0"].quantity t_ref = pars["t_ref"].quantity val = self.evaluate(t_max, t0, t_ref) - self.evaluate(t_min, t0, t_ref) integ = u.Quantity(-t0 * val) return (integ / self.time_sum(t_min, t_max)).to_value("")
def __init__(self, table, time_0, phase_0, f0, f1=0, f2=0): self.table = table self.time_0 = Parameter("time_0", time_0) self.phase_0 = Parameter("phase_0", phase_0) self.f0 = Parameter("f0", f0) self.f1 = Parameter("f1", f1) self.f2 = Parameter("f2", f2) super().__init__([self.time_0, self.phase_0, self.f0, self.f1, self.f2])