mixle.stats.directional.kent module

Kent (Fisher-Bingham FB5) distribution on the 2-sphere.

The Kent distribution is the elliptical analogue of the von Mises-Fisher law on S^2 (unit vectors in R^3). Its density at a unit vector x is

f(x) = c(kappa, beta)^{-1} exp( kappa * (g1 . x) + beta * [(g2 . x)^2 - (g3 . x)^2] ),

where G = [g1, g2, g3] is a 3 x 3 orthonormal orientation (g1 the mean direction, g2 the major axis, g3 the minor axis), kappa > 0 is the concentration and 0 <= 2 beta < kappa the ovalness. beta = 0 recovers von Mises-Fisher (circular contours); beta -> kappa/2 gives highly elliptical (girdle-like) contours. It is the standard model for asymmetric clusters of orientations (palaeomagnetism, structural geology, spherical data).

Normalizer (verified to 1e-12 against arbitrary-precision integration over S^2):

c(kappa, beta) = 2 pi sum_{j>=0} [Gamma(j+1/2)/Gamma(j+1)] beta^{2j} (2/kappa)^{2j+1/2} I_{2j+1/2}(kappa),

evaluated in log space with exponentially scaled Bessel functions for numerical stability. Sampling is by exact von Mises-Fisher-envelope rejection; kappa, beta and the orientation are fit by Kent’s moment method (mean direction + tangential scatter eigenvectors) followed by a maximum-likelihood refinement of (kappa, beta).

Reference: Kent, “The Fisher-Bingham distribution on the sphere”, J. Royal Statistical Society B 44 (1982); Mardia & Jupp, Directional Statistics (2000), ch. 9.

class KentDistribution(gamma, kappa, beta, name=None, keys=None)[source]

Bases: SequenceEncodableProbabilityDistribution

Kent (FB5) distribution on S^2 with orientation gamma (3x3), concentration and ovalness.

Parameters:
density(x)[source]

Return the probability density or mass at a single observation.

Concrete default: exponentiate log_density (the abstract method subclasses must provide). Leaves with a cheaper closed form may override this.

Parameters:

x (Any)

Return type:

float

log_density(x)[source]

Return the log-density at a unit 3-vector x.

Parameters:

x (Any)

Return type:

float

seq_log_density(x)[source]

Return vectorized log-density for a sequence-encoded (n, 3) array of unit vectors.

Parameters:

x (ndarray)

Return type:

ndarray

classmethod compute_capabilities()[source]
backend_seq_log_density(x, engine)[source]

Engine-neutral vectorized log-density for (N, 3) unit vectors.

Parameters:
Return type:

Any

sampler(seed=None)[source]

Return a sampler for drawing observations from this distribution.

Parameters:

seed (int | None)

Return type:

KentSampler

estimator(pseudo_count=None)[source]

Return an estimator for fitting this distribution from data.

Parameters:

pseudo_count (float | None)

Return type:

KentEstimator

dist_to_encoder()[source]

Return the data encoder used by this distribution for vectorized methods.

Return type:

KentDataEncoder

class KentSampler(dist, seed=None)[source]

Bases: DistributionSampler

Sample by von Mises-Fisher-envelope rejection (exact).

Parameters:
  • dist (KentDistribution)

  • seed (int | None)

sample(size=None)[source]

Draw observations.

Combinator samplers (mixture/sequence/…) accept batched. With batched=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 independent RandomState, batching consumes each stream in the same order as the loop, so the draws are identical to the legacy path. batched=False forces that legacy per-draw loop as a guaranteed- stable reference. Leaf samplers are already vectorized and ignore the flag.

Parameters:

size (int | None)

Return type:

Any

class KentAccumulator(name=None, keys=None)[source]

Bases: SequenceEncodableStatisticAccumulator

Accumulate (count, sum_x (3,), sum_xx (3,3)) – the sufficient statistics for the moment fit.

Parameters:
  • name (str | None)

  • keys (str | None)

update(x, weight, estimate)[source]
Parameters:
  • x (Any)

  • weight (float)

  • estimate (KentDistribution | None)

Return type:

None

initialize(x, weight, rng)[source]
Parameters:
Return type:

None

seq_update(x, weights, estimate)[source]
Parameters:
Return type:

None

seq_initialize(x, weights, rng)[source]
Parameters:
Return type:

None

combine(suff_stat)[source]
Parameters:

suff_stat (tuple[float, ndarray, ndarray])

Return type:

KentAccumulator

value()[source]
Return type:

tuple[float, ndarray, ndarray]

from_value(x)[source]
Parameters:

x (tuple[float, ndarray, ndarray])

Return type:

KentAccumulator

key_merge(stats_dict)[source]

Pool this accumulator’s statistics into stats_dict under its merge key.

The structural default implements the common single-key pattern: store the accumulator under self.keys the first time the key is seen, else combine into 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. A keys of None (the default) is a no-op.

Parameters:

stats_dict (dict[str, Any])

Return type:

None

key_replace(stats_dict)[source]

Replace this accumulator’s statistics from the pooled stats_dict entry (see key_merge).

Parameters:

stats_dict (dict[str, Any])

Return type:

None

acc_to_encoder()[source]
Return type:

KentDataEncoder

class KentAccumulatorFactory(name=None, keys=None)[source]

Bases: StatisticAccumulatorFactory

Factory for KentAccumulator.

Parameters:
  • name (str | None)

  • keys (str | None)

make()[source]
Return type:

KentAccumulator

class KentEstimator(name=None, keys=None)[source]

Bases: ParameterEstimator

Kent’s moment estimator for the orientation, with an ML refinement of (kappa, beta).

Parameters:
  • name (str | None)

  • keys (str | None)

accumulator_factory()[source]
Return type:

KentAccumulatorFactory

estimate(nobs, suff_stat)[source]
Parameters:
Return type:

KentDistribution

class KentDataEncoder[source]

Bases: DataSequenceEncoder

Encode unit vectors as a normalized (n, 3) float array.

seq_encode(x)[source]

Encode the iid observation sequence x for vectorized evaluation.

Parameters:

x (Sequence[Any])

Return type:

ndarray