Rayleigh first-harmonic test#
Public verdict: validated and exposed as pysht.circular.rayleigh. This is
a pySHT-native method with no SHT 0.1.9 crosswalk entry.
Scientific scope and statistic#
For normalized angles \(\theta_i\in[0,2\pi)\), define
The reported statistic is the conventional \(Z=n\bar R^2\). The null is circular uniformity, but the alternative is specifically a nonzero first trigonometric moment–a preferred first-harmonic direction. It is not described as an omnibus test: antipodally symmetric nonuniform distributions can have zero first moment.
The result reports \(\bar R\). It reports \(\operatorname{atan2}(\bar S,\bar C)\) in the input-period units only when the resultant is numerically nonzero; otherwise the direction is omitted and an explicit diagnostic marks it undefined. The implementation and terminology follow the standard Rayleigh circular-uniformity statistic.
Units, calibration, and boundaries#
Finite values are reduced modulo a positive finite period and divided by
that period before multiplication by \(2\pi\). This order remains valid for
subnormal and near-maximum float64 periods. Tests cover radians/degrees,
rotation, reflection, wrapping, row order, huge and subnormal periods, and an
exactly antipodal zero-resultant fixture.
The finite-sample null is simulated directly: each replicate contains \(n\) iid uniform angles, with no fitted nuisance parameters. A public call consumes exactly \(nB\) uniform variates after the observed statistic. Upper-tail ties count and \(p=(b+1)/(B+1)\); MCSE and a 95% binomial interval are returned.
Complexity#
Each resultant calculation is \(O(n)\) time and \(O(n)\) storage. Direct finite-null calibration with \(B\) replicates therefore costs \(O(Bn)\) time and retains only one size-\(n\) replicate, so peak storage is independent of \(B\).
Release evidence#
At \(n=20\), each independent 20,000-dataset stream was compared with its own independently seeded 99,999-statistic reference bank:
reference seed |
dataset seed |
0.01 |
0.05 |
0.10 |
|---|---|---|---|---|
20260917 |
20260918 |
199 (0.00995) |
1,004 (0.05020) |
1,997 (0.09985) |
20260933 |
20260919 |
221 (0.01105) |
996 (0.04980) |
2,008 (0.10040) |
All pass the release tolerance. Because a single independent finite reference bank is shared within a stream, the gate uses \(\max\{0.005,4\sqrt{a(1-a)(1/20000+1/99999)}\}\) at nominal level \(a\); this accounts for both the 20,000 datasets and reference-quantile variation. For a targeted power audit, seed 20260928 generated 2,000 size-20 von Mises samples with concentration 2.5. Against a 19,999-statistic null bank from seed 20260927, 2,000/2,000 rejected at 0.05. This supports the intended first-harmonic direction only.
The table is an empirical-bank audit rather than 20,000 complete public calls; focused tests separately replay the literal public generator, tie, and plus-one path.