Point Processes — Primitives¶
Pure functions for every process family. Each family follows the same shape:
an intensity \(\lambda(\cdot)\), a compensator \(\Lambda(\cdot)\) (the
integrated intensity), a log-likelihood built from
\(\sum_i \log \lambda(x_i) - \Lambda\), and a sampler. Everything is JAX —
differentiable, jit-able, vmap-able — and PRNG keys are explicit
arguments.
The operators and distributions are thin wrappers over these; call the primitives directly when you want a custom likelihood or a vmapped parameter sweep.
Homogeneous Poisson — temporal¶
Constant intensity \(\lambda(t) = \lambda\), so every quantity is closed-form: the compensator is \(\lambda t\), inter-event gaps are \(\mathrm{Exp}(\lambda)\), and memorylessness makes the mean residual life exactly \(1/\lambda\).
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
hpp_intensity(t: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Constant intensity :math:\lambda(t) = \lambda.
Broadcasts to the joint shape of t and rate so scalar t
with batched rate (and vice versa) both work, matching the
broadcasting semantics of the other HPP primitives.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_cumulative_intensity(t: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Compensator :math:\Lambda(t) = \lambda t.
hpp_log_prob(n_events: Int[Array, ...], rate: Float[Array, ...], T: Float[Array, ...]) -> Float[Array, ...]
¶
Log-likelihood :math:\log L = n \log \lambda - \lambda T.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_events
|
Int[Array, ...]
|
Observed event count. |
required |
rate
|
Float[Array, ...]
|
Intensity |
required |
T
|
Float[Array, ...]
|
Length of the observation window. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Log-likelihood, broadcast over inputs. |
Notes
The event times drop out because, given n, they are uniform
on [0, T] and their density cancels with the Poisson count
factors :math:n! and :math:T^n. What remains is
:math:\lambda^n \exp(-\lambda T), which is what this
returns in log-space. If you instead want the full
Poisson-count log-probability, add
:math:-\log(n!) - n \log T.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_sample(key: PRNGKeyArray, rate: Float[Array, ...], T: Float[Array, ...], max_events: int, sample_shape: tuple[int, ...] = ()) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample ordered event times from a homogeneous Poisson process.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
rate
|
Float[Array, ...]
|
Intensity |
required |
T
|
Float[Array, ...]
|
Observation window length (broadcasts with |
required |
max_events
|
int
|
Static buffer size. The sampler truncates at this
cap; choose comfortably above the expected count to avoid
loss of realism ( |
required |
sample_shape
|
tuple[int, ...]
|
Optional leading sample dimensions. |
()
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Notes
The algorithm draws n from :math:\mathrm{Poisson}(\lambda T)
and then, unconditionally, generates max_events uniform
candidates on [0, T]. Sorting and masking by rank lets the
same padded buffer serve any batch element regardless of its
count — and keeps the whole routine jit-compatible.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_hazard(t: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
hpp_survival(t: Float[Array, ...], given_time: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
:math:S(t|s) = \exp(-\lambda (t - s)) for t >= s.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_inter_event_log_prob(tau: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Log density of τ ~ Exp(λ): :math:\log \lambda - \lambda \tau.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_mean_residual_life(rate: Float[Array, ...], given_time: Float[Array, ...] | None = None) -> Float[Array, ...]
¶
Memorylessness gives :math:\mathbb{E}[T - s \mid T > s] = 1/\lambda.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rate
|
Float[Array, ...]
|
Intensity. |
required |
given_time
|
Float[Array, ...] | None
|
Ignored — present for API symmetry with IPP, where mean residual life does depend on the conditioning time. |
None
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_predict_count(start_time: Float[Array, ...], end_time: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Expected event count on [start, end]: λ (end - start).
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_exceedance_log_prob(k: Int[Array, ...], start_time: Float[Array, ...], end_time: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
log P(N > k) over [start, end], computed via the Poisson CDF.
Returns log(1 - F_Poisson(k; λ (end - start))). Uses
:func:jax.scipy.stats.poisson.cdf under the hood; for large k
or small tails this can underflow — callers that care about very
rare events should work in log-space end to end.
Source code in src/xtremax/point_processes/primitives/hpp.py
hpp_return_period(probability: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Time τ such that :math:P(\text{no event in } \tau) = 1 - p.
Equivalently :math:\tau = -\log(1 - p) / \lambda. The log1p
form stays accurate as p → 0.
Source code in src/xtremax/point_processes/primitives/hpp.py
Homogeneous Poisson — spatial¶
Complete spatial randomness (CSR) on a rectangular domain: the joint Janossy likelihood, the marginal Poisson count, and the CSR reference quantities that spatial diagnostics compare against.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
hpp_spatial_intensity(locations: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Constant intensity λ(s) = λ, broadcast against locations.
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
hpp_spatial_log_prob(n_events: Int[Array, ...], rate: Float[Array, ...], domain_volume: Float[Array, ...]) -> Float[Array, ...]
¶
Joint Janossy log-likelihood of a homogeneous Poisson pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_events
|
Int[Array, ...]
|
Observed event count. |
required |
rate
|
Float[Array, ...]
|
Intensity |
required |
domain_volume
|
Float[Array, ...]
|
Lebesgue measure |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Float[Array, ...]
|
Janossy log-likelihood |
|
Float[Array, ...]
|
constant-intensity specialisation of |
|
Float[Array, ...]
|
func: |
|
Float[Array, ...]
|
which evaluates :math: |
|
Setting |
Float[Array, ...]
|
math: |
Float[Array, ...]
|
expression. |
Notes
The Janossy form drops both the :math:-\log(n!) Poisson-count
normaliser and the :math:-n \log |D| iid-uniform location
density. Those normalisers cancel out in likelihood ratios used
for parameter estimation, so omitting them keeps the HPP log-prob
directly comparable to IPP / Hawkes / renewal log-probs across
the package. To recover the count-only log-pmf with the
:math:\log(n!) term, use :func:hpp_spatial_count_log_prob.
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
hpp_spatial_count_log_prob(n_events: Int[Array, ...], rate: Float[Array, ...], domain_volume: Float[Array, ...]) -> Float[Array, ...]
¶
Marginal Poisson-count log-pmf log P(N = n).
Useful for predict-count workflows that only need the count distribution, ignoring conditional location density.
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
hpp_spatial_sample(key: PRNGKeyArray, rate: Float[Array, ...], domain: RectangularDomain, max_events: int) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample a CSR realisation on a rectangular domain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
rate
|
Float[Array, ...]
|
Intensity |
required |
domain
|
RectangularDomain
|
Spatial domain. |
required |
max_events
|
int
|
Static buffer cap. Choose generously above
:math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
hpp_spatial_predict_count(rate: Float[Array, ...], subdomain_volume: Float[Array, ...]) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Mean and variance of the count in a sub-domain (both λ |A|).
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
hpp_spatial_nearest_neighbor_distance(rate: Float[Array, ...], n_dims: int) -> Float[Array, ...]
¶
Expected nearest-neighbour distance for a CSR pattern in ℝᵈ.
For a homogeneous Poisson process,
.. math:: \mathbb{E}[D_1] = \frac{\Gamma(1 + 1/d)}{(\lambda \, V_d)^{1/d}},
with :math:V_d = \pi^{d/2} / \Gamma(d/2 + 1) the unit-ball volume.
Source code in src/xtremax/point_processes/primitives/hpp_spatial.py
Homogeneous Poisson — spatiotemporal¶
The same constant-intensity process on \(D \times [t_0, t_1)\).
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
hpp_spatiotemporal_intensity(locations: Float[Array, ...], times: Float[Array, ...], rate: Float[Array, ...]) -> Float[Array, ...]
¶
Constant intensity λ(s, t) = λ, broadcast against times.
Source code in src/xtremax/point_processes/primitives/hpp_spatiotemporal.py
hpp_spatiotemporal_log_prob(n_events: Int[Array, ...], rate: Float[Array, ...], spatial_volume: Float[Array, ...], temporal_duration: Float[Array, ...]) -> Float[Array, ...]
¶
Janossy log-likelihood n log λ − λ |D| (t1 − t0).
Same convention as :func:hpp_spatial_log_prob: drops the
:math:-\log(n!) count normaliser and the iid-uniform location
density so this stays directly comparable to the IPP-spatiotemporal
log-prob (which uses the matching Janossy form).
Source code in src/xtremax/point_processes/primitives/hpp_spatiotemporal.py
hpp_spatiotemporal_count_log_prob(n_events: Int[Array, ...], rate: Float[Array, ...], spatial_volume: Float[Array, ...], temporal_duration: Float[Array, ...]) -> Float[Array, ...]
¶
Marginal Poisson-count log-pmf log P(N = n) with mean λ |D| T.
Source code in src/xtremax/point_processes/primitives/hpp_spatiotemporal.py
hpp_spatiotemporal_sample(key: PRNGKeyArray, rate: Float[Array, ...], spatial: RectangularDomain, temporal: TemporalDomain, max_events: int) -> tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample a homogeneous spatiotemporal Poisson realisation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
rate
|
Float[Array, ...]
|
Intensity |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
temporal
|
TemporalDomain
|
Temporal interval. |
required |
max_events
|
int
|
Static buffer cap; choose generously above
:math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Float[Array, ...]
|
|
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/hpp_spatiotemporal.py
hpp_spatiotemporal_predict_count(rate: Float[Array, ...], sub_volume: Float[Array, ...], sub_duration: Float[Array, ...]) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Mean and variance of the count in a sub-slab (both λ |A| τ).
Source code in src/xtremax/point_processes/primitives/hpp_spatiotemporal.py
Inhomogeneous Poisson — temporal¶
Intensity supplied as a log-intensity callable, so positivity is structural rather than a constraint. The compensator comes from composite trapezoid quadrature; sampling is either Lewis–Shedler thinning (general) or exact inversion when \(\Lambda^{-1}\) is available.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
ipp_intensity(t: Float[Array, ...], log_intensity_fn: Callable[[Array], Array]) -> Float[Array, ...]
¶
Pointwise intensity λ(t) = exp(log_intensity_fn(t)).
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_cumulative_intensity(t: Float[Array, ...], log_intensity_fn: Callable[[Array], Array], n_points: int = 100) -> Float[Array, ...]
¶
Compensator :math:\Lambda(t) via composite trapezoid.
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_log_prob(event_times: Float[Array, ...], mask: Bool[Array, ...], log_intensity_fn: Callable[[Array], Array], integrated_intensity: Float[Array, ...]) -> Float[Array, ...]
¶
Log-likelihood of an observed IPP event sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded array of event times. Padding positions are
evaluated by |
required |
mask
|
Bool[Array, ...]
|
Boolean mask with the same shape as |
required |
log_intensity_fn
|
Callable[[Array], Array]
|
Callable returning |
required |
integrated_intensity
|
Float[Array, ...]
|
:math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Log-likelihood with shape equal to the leading (batch) dims of |
Float[Array, ...]
|
|
Notes
Padding positions contribute 0 to the sum because mask
zeros them out. Keeping the log-intensity call unmasked (rather
than gathering only real events) preserves jit / vmap
compatibility with static shapes.
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_sample_thinning(key: PRNGKeyArray, log_intensity_fn: Callable[[Array], Array], T: Float[Array, ...], lambda_max: Float[Array, ...], max_candidates: int) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample via Lewis–Shedler thinning with a static buffer.
Algorithm (Lewis & Shedler, 1979):
- Draw
ncandidates from a homogeneous Poisson process with rateλ_maxon[0, T]. - Accept candidate at time
twith probability :math:\lambda(t) / \lambda_{\max}.
For JAX-friendliness the candidate buffer is of static size
max_candidates: the Poisson draw is capped to this cap via a
rank mask so the returned shape is deterministic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
log_intensity_fn
|
Callable[[Array], Array]
|
Log-intensity callable. |
required |
T
|
Float[Array, ...]
|
Observation window length (scalar). |
required |
lambda_max
|
Float[Array, ...]
|
Upper bound on :math: |
required |
max_candidates
|
int
|
Static cap on the candidate pool. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/ipp.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
ipp_sample_inversion(key: PRNGKeyArray, inverse_cumulative_intensity_fn: Callable[[Array], Array], Lambda_T: Float[Array, ...], max_events: int) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Exact inversion sampling when :math:\Lambda^{-1} is available.
When the inverse compensator is known in closed form, sampling is exact and does not require an upper bound:
- Draw
nfrom :math:\mathrm{Poisson}(\Lambda(T)). - Draw
niid points :math:u_i \sim \mathrm{Uniform}(0, \Lambda(T)). - Map through :math:
\Lambda^{-1}and sort.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
inverse_cumulative_intensity_fn
|
Callable[[Array], Array]
|
Callable computing
:math: |
required |
Lambda_T
|
Float[Array, ...]
|
:math: |
required |
max_events
|
int
|
Static buffer size. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
func: |
Int[Array, ...]
|
split — every position is either a real event or padding). |
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_hazard(t: Float[Array, ...], log_intensity_fn: Callable[[Array], Array]) -> Float[Array, ...]
¶
Hazard equals the intensity for an IPP.
ipp_cumulative_hazard(t: Float[Array, ...], given_time: Float[Array, ...], log_intensity_fn: Callable[[Array], Array], n_points: int = 100) -> Float[Array, ...]
¶
:math:\Lambda(t) - \Lambda(s) via quadrature.
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_survival(t: Float[Array, ...], given_time: Float[Array, ...], log_intensity_fn: Callable[[Array], Array], n_points: int = 100) -> Float[Array, ...]
¶
:math:S(t|s) = \exp(-[\Lambda(t) - \Lambda(s)]) for t >= s.
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_inter_event_log_prob(tau: Float[Array, ...], current_time: Float[Array, ...], log_intensity_fn: Callable[[Array], Array], n_points: int = 100) -> Float[Array, ...]
¶
Log density of the next-event delay τ given last event at s.
For an IPP,
.. math:: f(\tau \mid s) = \lambda(s + \tau) \exp(-[\Lambda(s + \tau) - \Lambda(s)]).
Source code in src/xtremax/point_processes/primitives/ipp.py
ipp_predict_count(start_time: Float[Array, ...], end_time: Float[Array, ...], log_intensity_fn: Callable[[Array], Array], n_points: int = 100) -> Float[Array, ...]
¶
Expected count :math:\Lambda(end) - \Lambda(start) on [start, end].
Source code in src/xtremax/point_processes/primitives/ipp.py
Inhomogeneous Poisson — spatial¶
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
ipp_spatial_intensity(locations: Float[Array, ...], log_intensity_fn: Callable[[Array], Array]) -> Float[Array, ...]
¶
Pointwise intensity λ(s) = exp(log_intensity_fn(s)).
Source code in src/xtremax/point_processes/primitives/ipp_spatial.py
ipp_spatial_log_prob(locations: Float[Array, ...], mask: Bool[Array, ...], log_intensity_fn: Callable[[Array], Array], integrated_intensity: Float[Array, ...]) -> Float[Array, ...]
¶
Log-likelihood of an observed inhomogeneous spatial pattern.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
Padded locations |
required |
mask
|
Bool[Array, ...]
|
Event mask shape |
required |
log_intensity_fn
|
Callable[[Array], Array]
|
Callable mapping |
required |
integrated_intensity
|
Float[Array, ...]
|
|
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Log-likelihood with shape |
Source code in src/xtremax/point_processes/primitives/ipp_spatial.py
ipp_spatial_sample_thinning(key: PRNGKeyArray, log_intensity_fn: Callable[[Array], Array], domain: RectangularDomain, lambda_max: Float[Array, ...], max_candidates: int) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Lewis–Shedler thinning sampler with a static buffer.
Algorithm:
- Generate
ncandidates from a homogeneous Poisson process at rateλ_maxoverD(uniform on the box). - Accept candidate
swith probability :math:\lambda(s) / \lambda_{\max}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
log_intensity_fn
|
Callable[[Array], Array]
|
Log-intensity callable. |
required |
domain
|
RectangularDomain
|
Spatial domain. |
required |
lambda_max
|
Float[Array, ...]
|
Upper bound on :math: |
required |
max_candidates
|
int
|
Static cap on the candidate pool — choose
comfortably above |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/ipp_spatial.py
ipp_spatial_predict_count(log_intensity_fn: Callable[[Array], Array], subdomain: RectangularDomain, n_integration_points: int = 2048, method: str = 'qmc') -> Float[Array, ...]
¶
Expected count over a sub-domain A.
:math:\mathbb{E}[N(A)] = \int_A \lambda(s) ds — same quadrature
machinery as the :math:\Lambda(D) calculation.
Source code in src/xtremax/point_processes/primitives/ipp_spatial.py
Inhomogeneous Poisson — spatiotemporal¶
Beyond the core four, this family carries the marginalisation helpers you need for plotting — collapsing \(\lambda(s, t)\) onto space or time — and the residual-based goodness-of-fit tests that stand in for the temporal time-rescaling diagnostics.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
ipp_spatiotemporal_intensity(locations: Float[Array, ...], times: Float[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]) -> Float[Array, ...]
¶
Evaluate λ(s, t) = exp(log λ(s, t)) on a batch of events.
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_log_prob(locations: Float[Array, ...], times: Float[Array, ...], mask: Bool[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], integrated_intensity: Float[Array, ...]) -> Float[Array, ...]
¶
Janossy log-likelihood :math:\sum_i \log \lambda(s_i, t_i) - \Lambda.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
|
required |
times
|
Float[Array, ...]
|
|
required |
mask
|
Bool[Array, ...]
|
|
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
integrated_intensity
|
Float[Array, ...]
|
Pre-computed
:math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood. |
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_sample_thinning(key: PRNGKeyArray, log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], spatial: RectangularDomain, temporal: TemporalDomain, lambda_max: Float[Array, ...], max_candidates: int) -> tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Lewis–Shedler thinning on D × [t_0, t_1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
PRNG key. |
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
temporal
|
TemporalDomain
|
Temporal interval. |
required |
lambda_max
|
Float[Array, ...]
|
Upper bound on :math: |
required |
max_candidates
|
int
|
Static cap on candidate-buffer size; choose
generously above :math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Float[Array, ...]
|
contract as :func: |
Bool[Array, ...]
|
ascending; locations follow the time order. |
Int[Array, ...]
|
uncapped candidate count (the Poisson draw before capping at |
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
siblings, so a value above |
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
truncated candidate pool. The accepted-event count is |
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_predict_count(integrated_intensity: Float[Array, ...]) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Mean and variance of the Poisson count over the integration domain.
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_intensity_surface_at_time(t: Float[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], spatial: RectangularDomain, grid_size: int = 50) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Evaluate λ(s, t) on a tensor-product spatial grid at fixed t.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
Float[Array, ...]
|
Scalar query time. |
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
grid_size
|
int
|
Static per-axis grid size. |
50
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Float[Array, ...]
|
|
tuple[Float[Array, ...], Float[Array, ...]]
|
shape |
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_marginal_spatial_intensity(locations: Float[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], temporal: TemporalDomain, n_time_points: int = 100) -> Float[Array, ...]
¶
Compute :math:\lambda_S(s) = \int_{t_0}^{t_1} \lambda(s, t)\, dt.
Trapezoid quadrature on a n_time_points-uniform grid in time;
vectorised over an arbitrary leading event axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
|
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
temporal
|
TemporalDomain
|
Temporal interval. |
required |
n_time_points
|
int
|
Static number of trapezoid nodes in time. |
100
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_marginal_temporal_intensity(times: Float[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], spatial: RectangularDomain, n_spatial_points: int = 256) -> Float[Array, ...]
¶
Compute :math:\lambda_T(t) = \int_D \lambda(s, t)\, ds.
Halton-QMC over the spatial domain at each query time; cheap and
deterministic, and converges as :math:O(\log^d N / N).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
Float[Array, ...]
|
|
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
n_spatial_points
|
int
|
Static number of QMC nodes. |
256
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
ipp_spatiotemporal_pearson_residuals(locations: Float[Array, ...], times: Float[Array, ...], mask: Bool[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], spatial: RectangularDomain, temporal: TemporalDomain, n_spatial_bins: int = 5, n_temporal_bins: int = 5, n_integration_points: int = 16) -> Float[Array, ...]
¶
Pearson residuals on a tensor-product space-time grid.
For each cell A_k = R_k × [τ_k, τ_{k+1}),
.. math:: r_k = \frac{N(A_k) - \Lambda(A_k)}{\sqrt{\Lambda(A_k)}}.
Cells with :math:\Lambda(A_k) = 0 return 0 to keep the
residual array finite.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
|
required |
times
|
Float[Array, ...]
|
|
required |
mask
|
Bool[Array, ...]
|
|
required |
log_intensity_fn
|
Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]]
|
Callable |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
temporal
|
TemporalDomain
|
Temporal interval. |
required |
n_spatial_bins
|
int
|
Bins per spatial axis (so |
5
|
n_temporal_bins
|
int
|
Bins along the time axis. |
5
|
n_integration_points
|
int
|
Per-cell trapezoid nodes per axis when
estimating :math: |
16
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Flattened residual array of shape |
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | |
ipp_spatiotemporal_chi_square_gof(locations: Float[Array, ...], times: Float[Array, ...], mask: Bool[Array, ...], log_intensity_fn: Callable[[Float[Array, ...], Float[Array, ...]], Float[Array, ...]], spatial: RectangularDomain, temporal: TemporalDomain, n_spatial_bins: int = 5, n_temporal_bins: int = 5, n_integration_points: int = 16) -> Float[Array, ...]
¶
Pearson :math:\chi^2 statistic from binned residuals.
Returns :math:\sum_k r_k^2. Compare to a :math:\chi^2_{K - p}
distribution with degrees of freedom equal to the number of cells
minus the number of fitted parameters.
Source code in src/xtremax/point_processes/primitives/ipp_spatiotemporal.py
Renewal processes¶
Parameterised by the inter-event distribution rather than an intensity:
the conditional intensity is the hazard evaluated since the last event,
\(\lambda^*(t) = h(t - t_{N(t)})\). renewal_ogata_intensity_fn adapts a
renewal process into the (t, history) -> λ*(t) closure that the thinning
samplers expect.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
renewal_intensity(t: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
Conditional intensity :math:\lambda^*(t) = h(t - t_{N(t)}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
Float[Array, ...]
|
Evaluation time. |
required |
event_times
|
Float[Array, ...]
|
Padded history. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
inter_event_dist
|
Distribution
|
Inter-event distribution. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Float[Array, ...]
|
strictly before |
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_log_prob(event_times: Float[Array, ...], mask: Bool[Array, ...], T: Float[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
Log-likelihood of an observed renewal-process sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded, sorted event times. |
required |
mask
|
Bool[Array, ...]
|
Boolean event mask. |
required |
T
|
Float[Array, ...]
|
Observation window length. |
required |
inter_event_dist
|
Distribution
|
NumPyro Distribution for inter-event times.
Must expose |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood. |
Notes
The final survival term uses log1p(-cdf(T - t_n)) with
clipping to avoid log(0) when the observed gap has CDF
very close to 1. The inter-event densities at padding positions
are zeroed out by the mask.
Requires the package padded-buffer invariant (contiguous-prefix mask): gaps are taken between consecutive buffer slots, so a hole mask (a masked-out slot between two real events) silently corrupts the gap terms. Package samplers always emit contiguous-prefix masks.
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_sample(key: PRNGKeyArray, inter_event_dist: dist.Distribution, T: Float[Array, ...], max_events: int) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample a renewal-process event sequence by accumulating gaps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
inter_event_dist
|
Distribution
|
Inter-event NumPyro Distribution. Must have
a reparameterised |
required |
T
|
Float[Array, ...]
|
Observation window length. |
required |
max_events
|
int
|
Static buffer size. |
required |
Returns:
| Type | Description |
|---|---|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
Tuple |
Notes
Draws max_events iid gaps unconditionally and cumulative-
sums them; events past T are masked out. This keeps shape
static while preserving the exact renewal distribution on
[0, T]. If the buffer fills (sum of gaps < T) the
returned sequence is truncated — choose max_events so that
max_events * E[Δt] >> T.
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_hazard(tau: Float[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
Hazard of the inter-event distribution: :math:h(\tau) = f(\tau)/S(\tau).
Implemented as exp(log_prob(τ) - log(1 - cdf(τ))) to stay
numerically safe.
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_cumulative_hazard(tau: Float[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
:math:\Lambda(\tau) = -\log S(\tau) = -\log(1 - F(\tau)).
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_survival(tau: Float[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
S(τ) = 1 − F(τ) clipped to be non-negative.
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_inter_event_log_prob(tau: Float[Array, ...], inter_event_dist: dist.Distribution) -> Float[Array, ...]
¶
Log density of an inter-event gap: log f(τ).
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_expected_count(T: Float[Array, ...], inter_event_dist: dist.Distribution, n_points: int = 200) -> Float[Array, ...]
¶
Expected number of events on [0, T] via the renewal equation.
Solves :math:m(T) = F(T) + \\int_0^T m(T - s)\\, f(s)\\, ds on an
n_points trapezoid grid by forward substitution: the
discretized equation is lower-triangular in the grid values of
m, so a single sweep over grid rows solves it exactly (up to
quadrature error) at any horizon. The previous fixed 8-iteration
Neumann series added one convolution power per iteration and
therefore saturated near E[N] ≈ 9 regardless of T. For
Exponential inter-events this recovers λT to quadrature
tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
T
|
Float[Array, ...]
|
Window length (scalar). |
required |
inter_event_dist
|
Distribution
|
Inter-event NumPyro Distribution. |
required |
n_points
|
int
|
Trapezoid grid size. |
200
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar expected count. |
Source code in src/xtremax/point_processes/primitives/renewal.py
renewal_ogata_intensity_fn(event_times: Float[Array, ...], mask: Bool[Array, ...], inter_event_dist: dist.Distribution)
¶
Build a (t, history) -> λ*(t) closure usable by thinning samplers.
Convenience constructor for callers that want to mix renewal with
other history-dependent constructions (e.g. a ThinningProcess
wrapping a renewal base). The event_times / mask arguments
are unused — they exist only for signature symmetry with the
other *_intensity_fn builders; the returned closure evaluates
against the live history the sampler passes in, so
self-generated chains see their own events.
Source code in src/xtremax/point_processes/primitives/renewal.py
Hawkes — temporal¶
Self-exciting processes where past events raise the intensity. The
exponential-kernel variant has a closed-form compensator and a recursive
intensity; the general-kernel variant takes any excitation function \(\phi\) at
the cost of quadrature. Both sample via Ogata thinning, which needs the
lambda_max upper bound.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
exp_hawkes_intensity(t: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...]) -> Float[Array, ...]
¶
Conditional intensity of the exponential-kernel Hawkes process.
:math:\lambda^*(t) = \mu + \alpha \sum_{t_i < t} e^{-\beta (t - t_i)}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
Float[Array, ...]
|
Evaluation time(s). |
required |
event_times
|
Float[Array, ...]
|
Padded, sorted past events. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
mu
|
Float[Array, ...]
|
Baseline rate (positive). |
required |
alpha
|
Float[Array, ...]
|
Excitation amplitude (positive). |
required |
beta
|
Float[Array, ...]
|
Excitation decay rate (positive). |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
math: |
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/hawkes.py
exp_hawkes_cumulative_intensity(t: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...]) -> Float[Array, ...]
¶
Exponential-kernel Hawkes compensator.
:math:\Lambda(t) = \mu t + (\alpha / \beta) \sum_{t_i \leq t}
(1 - e^{-\beta(t - t_i)}).
Source code in src/xtremax/point_processes/primitives/hawkes.py
exp_hawkes_log_prob(event_times: Float[Array, ...], mask: Bool[Array, ...], T: Float[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...]) -> Float[Array, ...]
¶
Log-likelihood :math:\sum_i \log \lambda^*(t_i) - \Lambda(T) for exp Hawkes.
Uses the Ozaki recursion :math:R_i = e^{-\beta (t_i - t_{i-1})}(1 + R_{i-1})
so intensity evaluation at each observed event is O(1) amortised,
giving O(n) total cost. The recursion consumes consecutive buffer
gaps, so it requires the package padded-buffer invariant
(contiguous-prefix mask, padding at T) that all package
samplers guarantee.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded, sorted event times. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
T
|
Float[Array, ...]
|
Observation window length. |
required |
mu
|
Float[Array, ...]
|
Baseline. |
required |
alpha
|
Float[Array, ...]
|
Excitation amplitude. |
required |
beta
|
Float[Array, ...]
|
Excitation decay. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood. |
Source code in src/xtremax/point_processes/primitives/hawkes.py
exp_hawkes_sample(key: PRNGKeyArray, T: Float[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], max_events: int, max_candidates: int | None = None) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Ogata thinning sample of an exponential-kernel Hawkes process.
Uses the adaptive envelope :math:\bar\lambda_k = \mu + \alpha k
valid for :math:t \geq t_k. With a decaying excitation this
bound is tight just after each event and loosens in between —
efficient enough for :math:\alpha / \beta < 1 (sub-critical).
Source code in src/xtremax/point_processes/primitives/hawkes.py
exp_hawkes_lambda_max(history: EventHistory, mu: Float[Array, ...], alpha: Float[Array, ...]) -> Float[Array, ...]
¶
Upper bound :math:\mu + \alpha \cdot N(t) valid from the last event onward.
Source code in src/xtremax/point_processes/primitives/hawkes.py
general_hawkes_intensity(t: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], kernel_fn: Callable[[Array], Array]) -> Float[Array, ...]
¶
Conditional intensity for a general kernel.
:math:\lambda^*(t) = \mu + \sum_{t_i < t} \phi(t - t_i).
Source code in src/xtremax/point_processes/primitives/hawkes.py
general_hawkes_cumulative_intensity(T: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], kernel_integral_fn: Callable[[Array, Array], Array]) -> Float[Array, ...]
¶
Compensator :math:\mu T + \sum_i \int_{t_i}^{T} \phi(s - t_i) ds.
Supports scalar and array-valued T. Array T takes a pairwise
branch — upper[k, i] = clip(T[k] - t_i) — mirroring the
exponential-kernel primitive; the previous elementwise subtraction
made cumulative_intensity(t=event_times) return upper ≡ 0,
so every kernel integral vanished and GOF diagnostics silently
degenerated to a homogeneous Poisson with rate μ.
Source code in src/xtremax/point_processes/primitives/hawkes.py
general_hawkes_log_prob(event_times: Float[Array, ...], mask: Bool[Array, ...], T: Float[Array, ...], mu: Float[Array, ...], kernel_fn: Callable[[Array], Array], kernel_integral_fn: Callable[[Array, Array], Array]) -> Float[Array, ...]
¶
Log-likelihood for a general-kernel Hawkes process.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded event times. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
T
|
Float[Array, ...]
|
Window length. |
required |
mu
|
Float[Array, ...]
|
Baseline rate. |
required |
kernel_fn
|
Callable[[Array], Array]
|
|
required |
kernel_integral_fn
|
Callable[[Array, Array], Array]
|
|
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood. |
Source code in src/xtremax/point_processes/primitives/hawkes.py
general_hawkes_sample(key: PRNGKeyArray, T: Float[Array, ...], mu: Float[Array, ...], kernel_fn: Callable[[Array], Array], kernel_max_fn: Callable[[EventHistory], Array], max_events: int, max_candidates: int | None = None) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Ogata thinning for a general-kernel Hawkes process.
The caller supplies kernel_max_fn(history) -> λ_bar — the
history-dependent upper bound. For monotone-decreasing kernels
with maximum at :math:\tau = 0, a safe choice is
:math:\mu + \phi(0) \cdot N(t); tighter bounds give higher
acceptance.
Source code in src/xtremax/point_processes/primitives/hawkes.py
Hawkes — spatiotemporal (ETAS)¶
Separable exp-Gaussian excitation: an exponential temporal decay times a Gaussian spatial kernel, the ETAS form used for aftershock and contagion modelling.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
stpp_hawkes_intensity(s: Float[Array, ...], t: Float[Array, ...], event_locations: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], sigma: Float[Array, ...]) -> Float[Array, ...]
¶
Conditional intensity :math:\lambda^*(s, t) of the ETAS Hawkes process.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
Float[Array, ...]
|
|
required |
t
|
Float[Array, ...]
|
Scalar or |
required |
event_locations
|
Float[Array, ...]
|
|
required |
event_times
|
Float[Array, ...]
|
|
required |
mask
|
Bool[Array, ...]
|
|
required |
mu
|
Float[Array, ...]
|
Baseline rate (positive scalar). |
required |
alpha
|
Float[Array, ...]
|
Excitation amplitude (must satisfy |
required |
beta
|
Float[Array, ...]
|
Temporal decay rate (positive). |
required |
sigma
|
Float[Array, ...]
|
Spatial bandwidth (positive). |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Intensity at the query, with shape matching the broadcast of |
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/hawkes_spatiotemporal.py
stpp_hawkes_compensator(event_locations: Float[Array, ...], event_times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], sigma: Float[Array, ...], spatial: RectangularDomain, temporal: TemporalDomain, boundary_correction: bool = True) -> Float[Array, ...]
¶
Closed-form compensator :math:\Lambda of the ETAS Hawkes process.
.. math:: \Lambda = \mu |D| (t_1 - t_0) + \alpha \sum_i (1 - e^{-\beta (t_1 - t_i)}) \kappa_i,
where :math:\kappa_i = \int_D k_s(s - s_i)\, ds is exactly
:math:1 if boundary_correction=False (infinite-domain
approximation, valid when :math:\sigma is small relative to the
box and events are interior) or computed via axis-wise erf when
boundary_correction=True.
Source code in src/xtremax/point_processes/primitives/hawkes_spatiotemporal.py
stpp_hawkes_log_prob(locations: Float[Array, ...], times: Float[Array, ...], mask: Bool[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], sigma: Float[Array, ...], spatial: RectangularDomain, temporal: TemporalDomain, boundary_correction: bool = True) -> Float[Array, ...]
¶
Log-likelihood :math:\sum_i \log \lambda^*(s_i, t_i) - \Lambda.
Computed by O(n²) pairwise construction of the per-event
intensities (matches the temporal :func:general_hawkes_log_prob
pattern); for typical event counts under a few thousand this is
competitive with the recursive Ozaki form and far simpler to
extend to non-exponential temporal kernels in a follow-up.
Source code in src/xtremax/point_processes/primitives/hawkes_spatiotemporal.py
stpp_hawkes_sample(key: PRNGKeyArray, mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], sigma: Float[Array, ...], spatial: RectangularDomain, temporal: TemporalDomain, max_events: int) -> tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Ogata-style spatiotemporal thinning sample.
Algorithm (per Daley & Vere-Jones, §7.3):
- Maintain a running history
(locs, times, mask). - At each step, draw a candidate inter-event time from
Exp(λ̄)with adaptive bound :math:\bar\lambdafrom :func:stpp_hawkes_lambda_max. - Draw a candidate location uniformly on
D. - Accept with probability
:math:
\lambda^*(s, t)/\bar\lambda; otherwise discard and try again.
Loops via :func:jax.lax.scan over a fixed budget of
5 * max_events candidates so the function is jit-compatible.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
PRNG key. |
required |
mu
|
Float[Array, ...]
|
Baseline rate. |
required |
alpha
|
Float[Array, ...]
|
Excitation amplitude (sub-critical: |
required |
beta
|
Float[Array, ...]
|
Temporal decay. |
required |
sigma
|
Float[Array, ...]
|
Spatial bandwidth. |
required |
spatial
|
RectangularDomain
|
Spatial domain. |
required |
temporal
|
TemporalDomain
|
Temporal interval. |
required |
max_events
|
int
|
Static buffer cap. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
|
Float[Array, ...]
|
ascending. |
Bool[Array, ...]
|
exceed |
Int[Array, ...]
|
full, so a saturated buffer ( |
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
the user should increase |
tuple[Float[Array, ...], Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
uncapped attempt count. |
Source code in src/xtremax/point_processes/primitives/hawkes_spatiotemporal.py
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | |
stpp_hawkes_lambda_max(n_events: Int[Array, ...], mu: Float[Array, ...], alpha: Float[Array, ...], beta: Float[Array, ...], sigma: Float[Array, ...], n_dims: int) -> Float[Array, ...]
¶
Adaptive upper bound :math:\bar\lambda = \mu + N \alpha \beta k_s(0).
The temporal kernel peaks at :math:\beta and the spatial kernel
peaks at :math:(2\pi)^{-d/2} / \sigma^d. For a sub-critical
process this bound is finite and tight just after the most recent
event; it loosens between events but stays a true upper bound.
Source code in src/xtremax/point_processes/primitives/hawkes_spatiotemporal.py
Marks¶
Marked processes factorise as ground process × mark distribution, so the mark contribution to the likelihood is a separate additive term. These functions supply that term and the matching samplers for each event geometry.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
marks_log_prob(event_times: Float[Array, ...], marks: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array, EventHistory], dist.Distribution], history_at_each_event: bool = True) -> Float[Array, ...]
¶
Sum of log f(mᵢ | tᵢ, Hᵢ) over real events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded event times |
required |
marks
|
Float[Array, ...]
|
Padded marks aligned with |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
mark_distribution_fn
|
Callable[[Array, EventHistory], Distribution]
|
Callable |
required |
history_at_each_event
|
bool
|
When |
True
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood contribution from the marks. |
Notes
At padding positions mark_distribution_fn is still called
(to keep shapes static) but the padding mark is first replaced
with a value inside the distribution's support
(:func:safe_padding_mark) and the log-prob is masked out.
Without the substitution, bounded-support mark laws (Gamma,
LogNormal, ...) return -inf at zero padding and autodiff
propagates NaN gradients through the discarded jnp.where
branch — the same guard the spatial variants already had.
Source code in src/xtremax/point_processes/primitives/marked.py
sample_marks_at_times(key: PRNGKeyArray, event_times: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array, EventHistory], dist.Distribution], history_at_each_event: bool = True) -> Float[Array, ...]
¶
Draw marks mᵢ ~ f(· | tᵢ, Hᵢ) at each observed time.
When history_at_each_event=True sampling is sequential: each
draw's history pytree includes the previously drawn marks, so mark
distributions can legitimately depend on both past times and past
marks. When False a single vmap fans the draws out in
parallel and the mark distribution is evaluated against the full
observed history with marks=None — cheaper, but only correct
for mark laws that do not look at prior marks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
event_times
|
Float[Array, ...]
|
Padded event times. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
mark_distribution_fn
|
Callable[[Array, EventHistory], Distribution]
|
Mark distribution callable. |
required |
history_at_each_event
|
bool
|
See above. |
True
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Array of marks shaped |
Float[Array, ...]
|
|
Float[Array, ...]
|
padding positions zeroed out. |
Source code in src/xtremax/point_processes/primitives/marked.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
spatial_marks_log_prob(locations: Float[Array, ...], marks: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array], dist.Distribution]) -> Float[Array, ...]
¶
Sum of log f(mᵢ | sᵢ) over real events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
Padded locations |
required |
marks
|
Float[Array, ...]
|
Padded marks. Shape |
required |
mask
|
Bool[Array, ...]
|
Event mask shape |
required |
mark_distribution_fn
|
Callable[[Array], Distribution]
|
Callable |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood contribution from marks. |
Notes
log_prob is still called at padding positions for shape
stability, but padding marks are first replaced with a value
inside the distribution's support
(:func:_safe_padding_mark). Without this, distributions with
bounded support produce -inf log-probs and NaN gradients
even though the result is masked out — JAX's autodiff threads
through both branches of jnp.where.
Source code in src/xtremax/point_processes/primitives/marked_spatial.py
sample_spatial_marks_at_locations(key: PRNGKeyArray, locations: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array], dist.Distribution]) -> Float[Array, ...]
¶
Draw marks mᵢ ~ f(· | sᵢ) at every location.
Independent across events, so a single vmap over PRNG splits is
sufficient — no scan is needed (unlike the temporal marked PP,
which threads history through each step).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
locations
|
Float[Array, ...]
|
Padded locations |
required |
mask
|
Bool[Array, ...]
|
Event mask |
required |
mark_distribution_fn
|
Callable[[Array], Distribution]
|
Mark distribution callable. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Marks aligned with |
Float[Array, ...]
|
with a dtype-preserving zero ( |
Float[Array, ...]
|
/ integer marks keep their dtype. Scalar marks have shape |
Float[Array, ...]
|
|
Source code in src/xtremax/point_processes/primitives/marked_spatial.py
spatiotemporal_marks_log_prob(locations: Float[Array, ...], times: Float[Array, ...], marks: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array, Array], dist.Distribution]) -> Float[Array, ...]
¶
Sum of :math:\log f(m_i \mid s_i, t_i) over real events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
locations
|
Float[Array, ...]
|
|
required |
times
|
Float[Array, ...]
|
|
required |
marks
|
Float[Array, ...]
|
|
required |
mask
|
Bool[Array, ...]
|
|
required |
mark_distribution_fn
|
Callable[[Array, Array], Distribution]
|
Callable |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar log-likelihood contribution from marks. Padding rows are |
Float[Array, ...]
|
substituted with a value inside the distribution's support |
Float[Array, ...]
|
before |
Float[Array, ...]
|
support do not produce NaN gradients. |
Source code in src/xtremax/point_processes/primitives/marked_spatiotemporal.py
sample_spatiotemporal_marks(key: PRNGKeyArray, locations: Float[Array, ...], times: Float[Array, ...], mask: Bool[Array, ...], mark_distribution_fn: Callable[[Array, Array], dist.Distribution]) -> Float[Array, ...]
¶
Draw marks :math:m_i \sim f(\cdot \mid s_i, t_i) at every event.
Independent across events, so a single vmap over PRNG splits
suffices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
locations
|
Float[Array, ...]
|
|
required |
times
|
Float[Array, ...]
|
|
required |
mask
|
Bool[Array, ...]
|
|
required |
mark_distribution_fn
|
Callable[[Array, Array], Distribution]
|
Callable |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Marks with the same leading shape as |
Float[Array, ...]
|
are filled with |
Float[Array, ...]
|
dtype (important for discrete distributions). |
Source code in src/xtremax/point_processes/primitives/marked_spatiotemporal.py
Thinning & observation operators¶
Thinning models partial observation: a base process generates events and a retention probability decides which are recorded. Useful as an observation operator on top of any ground process.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
thinning_sample(key: PRNGKeyArray, conditional_intensity_fn: Callable[[Array, EventHistory], Array], lambda_max_fn: Callable[[EventHistory], Array], T: Float[Array, ...], max_events: int, max_candidates: int | None = None, initial_history: EventHistory | None = None) -> tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
¶
Sample a history-dependent temporal point process via Ogata thinning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
PRNGKeyArray
|
JAX PRNG key. |
required |
conditional_intensity_fn
|
Callable[[Array, EventHistory], Array]
|
Callable |
required |
lambda_max_fn
|
Callable[[EventHistory], Array]
|
Callable |
required |
T
|
Float[Array, ...]
|
Observation window length (scalar). |
required |
max_events
|
int
|
Static cap on the number of accepted events. |
required |
max_candidates
|
int | None
|
Static cap on the number of proposals. Defaults
to |
None
|
initial_history
|
EventHistory | None
|
Optional starting history. Defaults to an
empty buffer of size |
None
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
Int[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...], Int[Array, ...]]
|
|
Source code in src/xtremax/point_processes/primitives/thinning.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
thinning_retention_log_prob(retention_fn: Callable[[Array, EventHistory, Array | None], Array], event_times: Float[Array, ...], mask: Bool[Array, ...], history: EventHistory, marks: Float[Array, ...] | None = None) -> Float[Array, ...]
¶
Sum of log p(tᵢ | Hᵢ, mᵢ) over retained events.
At each event index i the retention callable sees only events
{j : j < i} in the history — so the contract
:math:p(t_i \mid \mathcal{H}_i, m_i) is honoured exactly, even
for history-dependent retention.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
retention_fn
|
Callable[[Array, EventHistory, Array | None], Array]
|
Retention callable. |
required |
event_times
|
Float[Array, ...]
|
Observed times (padded). |
required |
mask
|
Bool[Array, ...]
|
Observed mask. |
required |
history
|
EventHistory
|
The full observed history. Restricted per-event to the
prefix |
required |
marks
|
Float[Array, ...] | None
|
Optional marks aligned with |
None
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar sum; padding positions contribute |
Source code in src/xtremax/point_processes/primitives/thinning.py
retention_compensator(retention_fn: Callable[[Array, EventHistory, Array | None], Array], conditional_intensity_fn: Callable[[Array, EventHistory], Array], history: EventHistory, T: Float[Array, ...], n_points: int = 100, mark_sampler_fn: Callable[[Array, EventHistory, PRNGKeyArray], Array] | None = None, mark_sample_key: PRNGKeyArray | None = None, n_mark_samples: int = 8) -> Float[Array, ...]
¶
Compute the retention compensator via trapezoid quadrature.
:math:\int_0^T (1 - \bar p(t|H(t)))\,\lambda_g(t|H(t))\, dt.
Used by :class:~xtremax.point_processes.operators.ThinningProcess
to correct the thinned-process log-likelihood by the expected
compensator of the discarded events. At each quadrature node
t the retention and intensity callables see only the observed
events with time < t, so a history-dependent retention never
"peeks" at events in the future of its query point.
For mark-independent retention (the common case), retention_fn
is called as retention_fn(t, prefix, None) and :math:\bar p = p.
For mark-dependent retention, pass a mark_sampler_fn that
draws one mark from the base's mark distribution given
(t, prefix, key). The retention is then averaged over
n_mark_samples such marks per grid point, yielding a Monte-Carlo
estimate of
:math:\bar p(t|H) = \mathbb{E}_{m \sim f(\cdot|t,H)}[p(t|H,m)].
Without mark_sampler_fn, mark-dependent retention silently
receives None; callers who need the mark-averaged correction
must supply the sampler explicitly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
retention_fn
|
Callable[[Array, EventHistory, Array | None], Array]
|
Retention callable. |
required |
conditional_intensity_fn
|
Callable[[Array, EventHistory], Array]
|
Intensity callable (the ground intensity when the base is a marked process — see the operator layer). |
required |
history
|
EventHistory
|
Observed (retained) history. Filtered per- |
required |
T
|
Float[Array, ...]
|
Window upper limit. |
required |
n_points
|
int
|
Trapezoid grid size (static Python int). |
100
|
mark_sampler_fn
|
Callable[[Array, EventHistory, PRNGKeyArray], Array] | None
|
Optional |
None
|
mark_sample_key
|
PRNGKeyArray | None
|
JAX key used for mark MC; required when
|
None
|
n_mark_samples
|
int
|
Number of mark MC samples per grid point. |
8
|
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Scalar integral. |
Source code in src/xtremax/point_processes/primitives/thinning.py
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
Diagnostics¶
Temporal diagnostics rest on the time-rescaling theorem: under the correct model, rescaled inter-event times are \(\mathrm{Exp}(1)\), which turns model checking into a KS test or a QQ plot. Spatial diagnostics instead compare against CSR through Ripley's \(K\) and its variance-stabilised relatives.
Pure-function primitives for temporal and spatial point processes.
Each submodule is free of class state and free of framework dependencies (no NumPyro — save that for the outer-layer wrappers — no equinox). These are the canonical reference implementations; the operator and distribution layers delegate to them.
time_rescaling_residuals(event_times: Float[Array, ...], mask: Bool[Array, ...], cumulative_intensity_fn: Callable[[Array], Array]) -> tuple[Float[Array, ...], Bool[Array, ...]]
¶
Rescaled inter-event times under the compensator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded, sorted event times. |
required |
mask
|
Bool[Array, ...]
|
|
required |
cumulative_intensity_fn
|
Callable[[Array], Array]
|
Callable computing :math: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Bool[Array, ...]
|
|
tuple[Float[Array, ...], Bool[Array, ...]]
|
|
Notes
Residuals at padding positions are deliberately returned as
0 (rather than NaN) so downstream reductions that
forget to mask do not propagate NaNs — they will instead see a
biased statistic. All consumers in this module apply the mask.
The previous-event compensator is taken from the previous valid event, not the previous buffer slot, so the function is robust to hole masks (a masked-out slot between two real events no longer shrinks the following residual). Samplers in this package emit contiguous-prefix masks (see the package docstring), but diagnostics stay correct either way.
Source code in src/xtremax/point_processes/primitives/diagnostics.py
compensator_curve(event_times: Float[Array, ...], mask: Bool[Array, ...], cumulative_intensity_fn: Callable[[Array], Array]) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Pairs (t_i, Λ(t_i)) for a compensator plot.
Under the null the points lie along the line
:math:y = \Lambda(t_i) with slope 1 when plotted against the
event index i — the purpose of the plot is to see deviations
from that line.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_times
|
Float[Array, ...]
|
Padded event times. |
required |
mask
|
Bool[Array, ...]
|
Event mask. |
required |
cumulative_intensity_fn
|
Callable[[Array], Array]
|
Compensator callable. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Float[Array, ...]
|
replaced with |
Source code in src/xtremax/point_processes/primitives/diagnostics.py
ks_statistic_exp1(residuals: Float[Array, ...], mask: Bool[Array, ...]) -> Float[Array, ...]
¶
Two-sided Kolmogorov–Smirnov statistic against Exp(1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
residuals
|
Float[Array, ...]
|
Time-rescaled residuals. |
required |
mask
|
Bool[Array, ...]
|
|
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
math: |
Float[Array, ...]
|
math: |
Float[Array, ...]
|
residuals only. |
Notes
With padding present this requires a little care: we sort
residuals with padding positions pushed to +inf so they
land at the top of the sorted order, and compute empirical
ranks using the per-batch real count. Padding contributes no
mass to the empirical CDF.
Source code in src/xtremax/point_processes/primitives/diagnostics.py
qq_exp1_quantiles(residuals: Float[Array, ...], mask: Bool[Array, ...]) -> tuple[Float[Array, ...], Float[Array, ...]]
¶
Theoretical vs empirical quantiles against Exp(1) for a QQ plot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
residuals
|
Float[Array, ...]
|
Time-rescaling residuals. |
required |
mask
|
Bool[Array, ...]
|
|
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ...]
|
Tuple |
Float[Array, ...]
|
|
tuple[Float[Array, ...], Float[Array, ...]]
|
with |
Source code in src/xtremax/point_processes/primitives/diagnostics.py
csr_ripleys_k(r: Float[Array, ...], n_dims: int) -> Float[Array, ...]
¶
Theoretical Ripley's K-function under CSR, :math:K(r) = V_d r^d.
Special-cased for the common dimensions to keep the formulas
legible: :math:2r (1D), :math:\pi r^2 (2D),
:math:\frac{4}{3}\pi r^3 (3D). Higher dimensions fall through
to the generic V_d r^d form.
Source code in src/xtremax/point_processes/primitives/diagnostics_spatial.py
csr_l_function(r: Float[Array, ...], n_dims: int) -> Float[Array, ...]
¶
Besag's L-function, the variance-stabilised K.
:math:L(r) = (K(r) / V_d)^{1/d}. Under CSR, L(r) = r
identically, so any departure of the empirical estimator from the
diagonal is a sign of clustering or regularity.
Source code in src/xtremax/point_processes/primitives/diagnostics_spatial.py
csr_pair_correlation(r: Float[Array, ...], n_dims: int) -> Float[Array, ...]
¶
Pair correlation function under CSR: g(r) ≡ 1.
unit_ball_volume(n_dims: int) -> float
¶
Volume of the unit ℝᵈ ball: :math:V_d = \pi^{d/2}/\Gamma(d/2+1).