mixle.stats.directional.wrapped_normal module¶
Wrapped normal distribution – a Gaussian wrapped around the circle.
Wrapping X ~ N(mu, sigma^2) onto angles gives the wrapped normal WN(mu, sigma^2), the most
common symmetric circular law and the maximum-entropy distribution for a fixed circular mean and
resultant. Its density is the periodic sum of Gaussians,
f(theta; mu, sigma^2) = (1 / (sigma sqrt(2 pi))) sum_k exp(-(wrap(theta - mu) + 2 pi k)^2 / (2 sigma^2)),
which is uniform as sigma -> inf and concentrates at mu as sigma -> 0. Its first
trigonometric moment is rho e^{i mu} with rho = exp(-sigma^2 / 2), so the mean direction and
concentration are estimated in closed form from the mean resultant: mu = atan2(sum sin, sum cos) and
sigma^2 = -2 log Rbar. It samples exactly by wrapping N(mu, sigma^2).
The density is summed over enough wraps (K set from sigma) that every retained Gaussian is
machine-negligible past the window, which keeps the truncated sum strictly positive (unlike the
trigonometric-series form, which can dip negative when truncated).
Reference: Mardia & Jupp, Directional Statistics (2000), sec. 3.5.7.
- class WrappedNormalDistribution(mu, sigma2, name=None, keys=None)[source]
Bases:
SequenceEncodableProbabilityDistributionWrapped normal distribution with mean direction
muand wrapped variancesigma2> 0.- property K: int
Number of wraps summed on each side of the window.
- density(x)[source]
Return the probability density at a single angle (radians).
- log_density(x)[source]
Return the log-density at a single angle (radians).
- seq_log_density(x)[source]
Return vectorized log-density for a sequence-encoded array of angles.
- classmethod compute_capabilities()[source]
- classmethod compute_declaration()[source]
- static backend_legacy_sufficient_statistics(x, params, engine)[source]
Per-row circular moments
(sum_cos, sum_sin, count)— uses the engine trig tier.
- backend_seq_log_density(x, engine)[source]
Engine-neutral vectorized log-density: the (2K+1)-branch wrapped logsumexp on engine ops.
- sampler(seed=None)[source]
Return a sampler that wraps
N(mu, sigma2)onto the circle.- Parameters:
seed (int | None)
- Return type:
WrappedNormalSampler
- estimator(pseudo_count=None)[source]
Return a closed-form (mean-resultant) estimator for
muandsigma2.- Parameters:
pseudo_count (float | None)
- Return type:
WrappedNormalEstimator
- dist_to_encoder()[source]
Return the data encoder used by this distribution (the angle itself).
- Return type:
WrappedNormalDataEncoder
- class WrappedNormalSampler(dist, seed=None)[source]
Bases:
DistributionSamplerDraw angles by wrapping
N(mu, sigma2)around the circle.- Parameters:
dist (WrappedNormalDistribution)
seed (int | None)
- sample(size=None)[source]
Draw observations.
Combinator samplers (mixture/sequence/…) accept
batched. Withbatched=True(the default) each child stream is drawn in one vectorized call instead of a per-draw Python loop – far faster. Because every child sampler owns an independentRandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path.batched=Falseforces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.
- class WrappedNormalAccumulator(name=None, keys=None)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulate the weighted circular resultant
(sum cos, sum sin, count).- update(x, weight, estimate)[source]
- initialize(x, weight, rng)[source]
- Parameters:
x (float)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_update(x, weights, estimate)[source]
- seq_initialize(x, weights, rng)[source]
- Parameters:
x (ndarray)
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
- from_value(x)[source]
- key_merge(stats_dict)[source]
Pool this accumulator’s statistics into
stats_dictunder its merge key.The structural default implements the common single-key pattern: store the accumulator under
self.keysthe first time the key is seen, elsecombineinto the one already there. Accumulators with several named keys (e.g. an HMM’s init/trans/state keys) or a non-accumulator stats payload override this. AkeysofNone(the default) is a no-op.
- key_replace(stats_dict)[source]
Replace this accumulator’s statistics from the pooled
stats_dictentry (see key_merge).
- acc_to_encoder()[source]
- Return type:
WrappedNormalDataEncoder
- class WrappedNormalAccumulatorFactory(name=None, keys=None)[source]
Bases:
StatisticAccumulatorFactoryFactory for WrappedNormalAccumulator.
- make()[source]
- Return type:
WrappedNormalAccumulator