class BrokenPowerLawAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "BrokenPowerLawAuxSampler" xmin = AuxiliaryParameter(vmin=0) alpha = AuxiliaryParameter() xbreak = AuxiliaryParameter(vmin=0) beta = AuxiliaryParameter() xmax = AuxiliaryParameter(vmin=0) def __init__(self, name: str, observed: bool = True): """ A broken power law distribution sampler, where property ~ x^``alpha`` for x < ``xbreak``, and property ~ x^``beta`` for x > ``xbreak``. :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param xmin: Minimum value of the broken power law :type xmin: :class:`AuxiliaryParameter` :param xmax: Maximum value of the broken power law :type xmax: :class:``AuxiliaryParameter :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(BrokenPowerLawAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size: int): u = np.atleast_1d(np.random.uniform(size=size)) self._true_values = bpl(u, self.xmin, self.xbreak, self.xmax, self.alpha, self.beta) def observation_sampler(self, size: int): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values
class ViewingAngleSampler(NonObservedAuxSampler): _auxiliary_sampler_name = "ViewingAngleSampler" max_angle = AuxiliaryParameter(default=90, vmin=0, vmax=180) def __init__(self): """ A viewing angle sampler that samples from 0 to ``max_angle``. Unlike other samplers, it assumes that this is NOT an observed property :param max_angle: The maximum angle to which to sample in degrees :type max_angle: :class:`AuxiliaryParameter` """ super(ViewingAngleSampler, self).__init__(name="va", ) def true_sampler(self, size: int) -> None: """ Sample the viewing angle by inverse CDF :param size: Number of samples :type size: int """ theta_inverse = np.random.uniform(0.0, 1 - np.cos(np.deg2rad(self.max_angle)), size=size) self._true_values = np.arccos(1.0 - theta_inverse)
class PowerLawAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "PowerLawAuxSampler" xmin = AuxiliaryParameter(default=1, vmin=0) xmax = AuxiliaryParameter(default=2, vmin=0) alpha = AuxiliaryParameter(default=1) sigma = AuxiliaryParameter(default=1, vmin=0) def __init__(self, name: str, observed: bool = True): """ A bounded power law distribution sampler, where property ~ x^``alpha``. :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param xmin: Minimum value of the power law :type xmin: :class:`AuxiliaryParameter` :param xmax: Maximum value of the power law :type xmax: :class:``AuxiliaryParameter :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(PowerLawAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size: int): self._true_values = _sample_power_law(self.xmin, self.xmax, self.alpha, size) def observation_sampler(self, size: int): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values
class NormalAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "NormalAuxSampler" mu = AuxiliaryParameter(default=0) tau = AuxiliaryParameter(default=1, vmin=0) sigma = AuxiliaryParameter(default=1, vmin=0) def __init__(self, name: str, observed: bool = True): """ A normal distribution sampler, where property ~ N(``mu``, ``sigma``). :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param mu: Mean of the normal :type mu: :class:`AuxiliaryParameter` :param tau: Standard deviation of the normal :type tau: :class:`AuxiliaryParameter` :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(NormalAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size: int): self._true_values = stats.norm.rvs(loc=self.mu, scale=self.tau, size=size) def observation_sampler(self, size: int): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values
class ParetoAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "ParetoAuxSampler" xmin = AuxiliaryParameter(default=1, vmin=0) alpha = AuxiliaryParameter(default=1, vmin=0) sigma = AuxiliaryParameter(default=1, vmin=0) def __init__(self, name: str, observed: bool = True): """ A pareto distribution sampler, where property ~ 1 / x^(``alpha`` + 1). :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param xmin: Minimum value of the pareto :type xmin: :class:`AuxiliaryParameter` :param alpha: Index of the pareto :type alpha: :class:`AuxiliaryParameter` :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(ParetoAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size: int): self._true_values = (np.random.pareto(self.alpha, size) + 1) * self.xmin def observation_sampler(self, size: int): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values
class DeltaAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "DeltaAuxSampler" xp = AuxiliaryParameter(default=0) sigma = AuxiliaryParameter(default=1, vmin=0) def __init__(self, name: str, observed: bool = True): """ A delta-function sampler for which the true value is fixed at ``xp``. Assumes property is observed by default, in which case the observed value is sampled from the true value with some normally-distributed error, ``sigma``. :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param xp: Value at which delta function is located :type xp: :class:`AuxiliaryParameter` :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(DeltaAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size: int): self._true_values = np.repeat(self.xp, repeats=size) def observation_sampler(self, size: int): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values
class TruncatedNormalAuxSampler(AuxiliarySampler): _auxiliary_sampler_name = "TruncatedNormalAuxSampler" mu = AuxiliaryParameter(default=0) tau = AuxiliaryParameter(default=1, vmin=0) lower = AuxiliaryParameter() upper = AuxiliaryParameter() sigma = AuxiliaryParameter(default=1, vmin=0) def __init__(self, name: str, observed: bool = True): """ A truncated normal sampler, where property ~ N(``mu``, ``sigma``), between ``lower`` and ``upper``. :param name: Name of the property :type name: str :param observed: `True` if the property is observed, `False` if it is latent. Defaults to `True` :type observed: bool :param mu: Mean of the normal :type mu: :class:`AuxiliaryParameter` :param tau: Standard deviation of the normal :type tau: :class:`AuxiliaryParameter` :param lower: Lower bound of the truncation :type lower: :class:`AuxiliaryParameter` :param upper: Upper bound of the truncation :type upper: :class:`AuxiliaryParameter` :param sigma: Standard deviation of normal distribution from which observed values are sampled, if ``observed`` is `True` :type sigma: :class:`AuxiliaryParameter` """ super(TruncatedNormalAuxSampler, self).__init__(name=name, observed=observed) def true_sampler(self, size): l = (self.lower - self.mu) / self.tau u = (self.upper - self.mu) / self.tau self._true_values = stats.truncnorm.rvs( l, u, loc=self.mu, scale=self.tau, size=size, ) assert np.alltrue(self._true_values >= self.lower) assert np.alltrue(self._true_values <= self.upper) def observation_sampler(self, size): if self._is_observed: self._obs_values = stats.norm.rvs(loc=self._true_values, scale=self.sigma, size=size) else: self._obs_values = self._true_values