Inputs & interpolation¶
The streaming integral repeatedly evaluates \(\xi(r)\) and the velocity moments at \(r\) values between your tabulated points, and sometimes just outside the table. How those tables are interpolated and extrapolated has a real, measurable effect on the prediction — this page covers the choices and the safe defaults.
Real-space correlation xi(r)¶
TabulatedXi(r_table, xi_table, interpolator=None)
interpolates a measured/theoretical \(\xi(r)\).
- Default interpolator: log–log (linear in \(\log\xi\) vs \(\log r\)). \(\xi(r)\) is steeply falling and approximately power-law on these scales, so log–log is near-exact, whereas the older log-linear scheme overestimates the convex curve between bins and biased the model monopole high by ~1.4%. log–log falls back to log-linear wherever \(\xi \le 0\).
- Out-of-range policy: constant (edge) extrapolation below \(r_\min\) (so the \([1+\xi]\) streaming weight keeps clustering on small scales) and \(\xi\to0\) above \(r_\max\) (its physical large-separation limit).
from liulu.physics.real_space import TabulatedXi
xi_real = TabulatedXi(r_table=r, xi_table=xi) # log-log by default
# from a power spectrum instead:
from liulu.physics.real_space import LinearTheoryXi, HalofitXi
xi_real = LinearTheoryXi(k=k, pk=pk) # Hankel transform of P(k)
Extend the table to cover the integral's range
The integral samples \(r\) up to \(\sqrt{s_{\perp,\max}^2 + y_\text{max}^2}\).
Make sure your \(\xi(r)\) and moment tables span that range (or rely on the
documented edge behaviour); querying outside the table emits a one-time
RuntimeWarning.
Pairwise velocity moments¶
TabulatedMoments accepts the convenient
dispersion/shape inputs and stores canonical central moments:
from liulu.physics.pairwise_velocity import TabulatedMoments
moments = TabulatedMoments(
r_table=r,
v_r=v_r, # mean radial pairwise velocity -> m_10
sigma_r=sigma_r, # radial dispersion -> c_20 = sigma_r^2
sigma_t=sigma_t, # tangential dispersion -> c_02 = sigma_t^2
gamma_r=gamma_r, # radial skewness -> c_30
kappa_r=kappa_r, # radial excess kurtosis -> c_40
kappa_t=kappa_t, # tangential excess kurtosis -> c_04
c_12_table=None, # cross moment; defaults to 0
c_22_table=None, # cross moment; defaults to c_20*c_02 (independence)
)
Only v_r, sigma_r, sigma_t are required (Gaussian level). The higher
moments are needed for the skew-\(t\)/GH PDFs; unspecified ones default to the
Gaussian + independence values.
Dispersions must not collapse to zero below the table
Moments use edge extrapolation below \(r_\min\), so the dispersions plateau rather than dropping to zero. (A zero variance would make the PDF a delta and silently drop those pairs from the integral.) This is deliberate — see the interpolation tests.
Interpolation routines¶
The pure-numerics interpolators live in
liulu.numerics.interpolation:
| function | space | use |
|---|---|---|
loglog_interp |
linear in \((\log r, \log y)\) | power-law positive data (xi(r) default) |
log_linear_interp |
linear in \(\log r\), linear in \(y\) | data that can be negative (velocities) |
log_spline_interp |
cubic spline in \(\log r\) | smooth data needing curvature |
All share the same out-of-range policy: a scalar fill_value, or a
(below, above) tuple, where either side may be "edge" for constant
extrapolation. Out-of-range queries emit a stable, deduplicated RuntimeWarning
(silence with warn=False).
You can inject any of these into TabulatedXi(..., interpolator=...) if you need
to override the default.