using StatsOrdinalPatterns, Random, Statistics, DataFrames, CairoMakieTutorial for spatial ordinal pattern tests
Libraries
Hypothesis Testing with Spatial Ordinal Patterns
A spatial ordinal pattern (SOP) test asks whether the frequencies of rank permutations in a 2D image are consistent with a spatially i.i.d. process. For an \(M \times N\) image, overlapping \(2 \times 2\) windows at delays \((d_1, d_2)\) are each mapped to the permutation that describes the relative order of the four values. The resulting frequency distribution is summarised by a scalar test statistic. Under \(H_0\) (spatial white noise) that distribution is uniform across all \(4! = 24\) patterns.
StatsOrdinalPatterns.jl provides:
- Computing the statistic
stat_sop()— computes the chosen test statistic from the observed pattern frequencies.
- Asymptotic inference
test_sop()— compares the statistic to an analytical critical value. Supports all image sizes.
- Bootstrap inference
bootstrap_sop()— generates the empirical null distribution by 2D resampling.test_sop_bootstrap()— combines statistic computation and bootstrap inference in one call.
Key functions
stat_sop(data, d1, d2; chart_choice, refinement=OrdinaryType())- Returns
[test_statistic, pattern_frequencies]. data: the 2D image (Matrix).d1: row delay.d2: column delay.chart_choice: one ofTauTilde(),TauHat(),KappaTilde(),KappaHat(),DistanceToWhiteNoise(),Shannon(base=exp(1)),ShannonExtropy(base=exp(1)).refinement:OrdinaryType()for classical types, orRotationType(),DirectionType(),DiagonalType().
- Returns
test_sop(data, d1, d2; chart_choice, refinement=OrdinaryType(), alpha=0.05)- Returns an
SOPTestResultwith the test statistic, critical value, p-value, and reject decision. - Critical value, p-value, and rejection direction are chosen automatically from
chart_choice. alpha: significance level.
- Returns an
bootstrap_sop(data, n_boot, d1, d2; chart_choice, refinement=OrdinaryType(), block_size=1)- Returns a length-
n_bootvector of resampled statistics under \(H_0\). block_size > 1: 2D block bootstrap that preserves spatial structure.
- Returns a length-
-
- Returns an
SOPTestResultBootstruct with the bootstrap critical value, p-value, and reject decision. - For Tau/Kappa charts: two-sided bootstrap using the raw statistic.
- For entropy charts: the bootstrap null distribution is built on the same standardised scale used internally by
test_sop, so the bootstrap and asymptotic critical values are directly comparable.
- Returns an
Available chart statistics
Seven chart statistics are available. They differ in what they measure and the direction of the rejection region.
| Statistic | Constructor | Under \(H_0\) | Reject \(H_0\) when | Distribution |
|---|---|---|---|---|
| \(\hat{\tau}\) (TauTilde) | TauTilde() |
\(\hat{\tau} = 0\) | \(\lvert\hat{\tau}\rvert > c\) | Normal |
| \(\hat{\tau}_1\) (TauHat) | TauHat() |
\(\hat{\tau}_1 = 0\) | \(\lvert\hat{\tau}_1\rvert > c\) | Normal |
| \(\hat{\kappa}\) (KappaTilde) | KappaTilde() |
\(\hat{\kappa} = 0\) | \(\lvert\hat{\kappa}\rvert > c\) | Normal |
| \(\hat{\kappa}_1\) (KappaHat) | KappaHat() |
\(\hat{\kappa}_1 = 0\) | \(\lvert\hat{\kappa}_1\rvert > c\) | Normal |
| DistanceToWhiteNoise (\(\hat{\Delta}\)) | DistanceToWhiteNoise() |
\(\hat{\Delta} = 0\) | \(\hat{\Delta} > c\) | Generalized \(\chi^2\) |
| Shannon entropy (\(\hat{H}\)) | Shannon(base=exp(1)) |
\(\hat{H} = \log(3)\) | \(\hat{H} > c\) | Generalized \(\chi^2\) |
| Shannon extropy (\(\hat{H}_\text{ex}\)) | ShannonExtropy(base=exp(1)) |
\(\hat{H}_\text{ex} = \cdots\) | \(\hat{H}_\text{ex} > c\) | Generalized \(\chi^2\) |
- The four Tau/Kappa statistics use a two-sided test (signed deviation from zero).
- The three entropy statistics undergo an internal standardisation that converts them to upper-tail tests — both
test_sopandtest_sop_bootstrapapply this standardisation consistently, so their critical values sit on the same scale and can be compared directly. - The asymptotic critical values and limiting distributions are derived in Weiß (2022).
ShannonandShannonExtropyuse base 2 by default, while the papers use the natural logarithm. The rescaled statistic, the p-value and the test decision do not depend on the base. See Logarithm base for details.
Setup
Random.seed!(42)
M, N = 20, 20 # image dimensions
d1, d2 = 1, 1 # row and column delays(1, 1)
Example data
data_iid = randn(M, N) # spatial white noise — H₀ is true
φ = 0.4
data_sar = zeros(M, N)
data_sar[1, :] .= randn(N);
data_sar[:, 1] .= randn(M);
for i in 2:M, j in 2:N
data_sar[i, j] = φ * (data_sar[i-1, j] + data_sar[i, j-1]) / 2 + randn()
end # SAR-type process — H₀ is falseAsymptotic testing: test_sop()
Two-sided — TauTilde
test_sop(data_iid, d1, d2; chart_choice=TauTilde())SOPTestResult Chart: TauTilde() Statistic: -0.0148 ───────────────────────────── Asymptotic test Critical value: 0.053 p-value: 0.5851 Reject H₀: false
test_sop(data_sar, d1, d2; chart_choice=TauTilde())SOPTestResult Chart: TauTilde() Statistic: -0.1034 ───────────────────────────── Asymptotic test Critical value: 0.053 p-value: 0.0001 Reject H₀: true
Upper-tail — DistanceToWhiteNoise
test_sop(data_iid, d1, d2; chart_choice=DistanceToWhiteNoise())SOPTestResult Chart: DistanceToWhiteNoise() Statistic: 0.0059 ───────────────────────────── Asymptotic test Critical value: 0.0063 p-value: 0.0607 Reject H₀: false
test_sop(data_sar, d1, d2; chart_choice=DistanceToWhiteNoise())SOPTestResult Chart: DistanceToWhiteNoise() Statistic: 0.016 ───────────────────────────── Asymptotic test Critical value: 0.0063 p-value: 0.0005 Reject H₀: true
Upper-tail — Shannon entropy
test_sop(data_iid, d1, d2; chart_choice=Shannon(base=exp(1)))SOPTestResult Chart: Shannon(base = 2.718281828459045) Statistic: 0.0058 ───────────────────────────── Asymptotic test Critical value: 0.0063 p-value: 0.0636 Reject H₀: false
test_sop(data_sar, d1, d2; chart_choice=Shannon(base=exp(1)))SOPTestResult Chart: Shannon(base = 2.718281828459045) Statistic: 0.0171 ───────────────────────────── Asymptotic test Critical value: 0.0063 p-value: 0.0003 Reject H₀: true
The white-noise image is not rejected; the SAR image is. The critical value depends on the image dimensions M, N, the delays d1, d2, and alpha — not on the data.
Bootstrap testing: test_sop_bootstrap()
test_sop_bootstrap() generates the empirical null distribution via 2D resampling of the observed image and computes the bootstrap critical value and p-value in the correct direction.
Random.seed!(42)
res_boot = test_sop_bootstrap(data_sar, 2_000, d1, d2; chart_choice=TauTilde())SOPTestResultBoot Chart: TauTilde() Statistic: -0.1034 ───────────────────────────── Bootstrap (n_boot = 2000) Critical value: 0.0536 p-value: 0.0 Reject H₀: true
The bootstrap critical value agrees closely with the asymptotic one shown above.
With CairoMakie loaded, plot shows the resampled statistics stored in res_boot.boot_dist as a histogram, together with the two sided rejection region, the critical values and the observed statistic. See the plotting tutorial for the options.
plot(res_boot)Full comparison: asymptotic vs. bootstrap
Random.seed!(42)
chart_list = [
("TauTilde (τ̃)", TauTilde(), "two-sided"),
("TauHat (τ̂)", TauHat(), "two-sided"),
("KappaTilde (κ̃)", KappaTilde(), "two-sided"),
("KappaHat (κ̂)", KappaHat(), "two-sided"),
("DistanceToWhiteNoise (Δ)", DistanceToWhiteNoise(), "upper-tail"),
("Shannon entropy (H)", Shannon(base=exp(1)), "upper-tail"),
("Shannon extropy (Hex)", ShannonExtropy(base=exp(1)), "upper-tail"),
]
asymp_res = [test_sop(data_sar, d1, d2; chart_choice=c) for (_, c, _) in chart_list]
boot_res = [test_sop_bootstrap(data_sar, 2_000, d1, d2; chart_choice=c) for (_, c, _) in chart_list]DataFrame(
Statistic=[t[1] for t in chart_list],
Direction=[t[3] for t in chart_list],
asymp_crit=round.([r.asymp_crit for r in asymp_res], digits=3),
asymp_pval=round.([r.asymp_pval for r in asymp_res], digits=3),
boot_crit=round.([r.boot_crit for r in boot_res], digits=3),
boot_pval=round.([r.boot_pval for r in boot_res], digits=3),
reject=[r.asymp_reject for r in asymp_res],
)| Row | Statistic | Direction | asymp_crit | asymp_pval | boot_crit | boot_pval | reject |
|---|---|---|---|---|---|---|---|
| String | String | Float64 | Float64 | Float64 | Float64 | Bool | |
| 1 | TauTilde (τ̃) | two-sided | 0.053 | 0.0 | 0.054 | 0.0 | true |
| 2 | TauHat (τ̂) | two-sided | 0.051 | 0.046 | 0.052 | 0.055 | true |
| 3 | KappaTilde (κ̃) | two-sided | 0.087 | 1.0 | 0.086 | 1.0 | false |
| 4 | KappaHat (κ̂) | two-sided | 0.091 | 0.001 | 0.089 | 0.001 | true |
| 5 | DistanceToWhiteNoise (Δ) | upper-tail | 0.006 | 0.0 | 0.006 | 0.0 | true |
| 6 | Shannon entropy (H) | upper-tail | 0.006 | 0.0 | 0.007 | 0.001 | true |
| 7 | Shannon extropy (Hex) | upper-tail | 0.006 | 0.001 | 0.006 | 0.0 | true |
The asymptotic and bootstrap critical values are in close agreement across all statistics, and the bootstrap p-values are consistent with the reject column.