cointf.chebyshev: approximate kernel

Piecewise Chebyshev kernel for the fast likelihood.

For a fixed \(\nu\), \(\log f^*(u; \nu)\) and \(\log S^*(u; \nu)\) are smooth in \(u > 0\), so each can be replaced by a piecewise Chebyshev interpolant built once from the exact series and then evaluated with a short Clenshaw recurrence. ChebyshevKernel has the kernel signature of cointf.fastlik.series_kernel(), so it plugs into cointf.fastlik.loglik_fast() unchanged.

Notes

  • Fits are in log space, so the interpolation error is relative in \(f^*\) and \(S^*\). For \(f^*\) the singular part \((\nu - 1)\log u\) is subtracted before fitting and added back after.

  • Pieces below u_split use the variable \(\log u\), where the functions are nearly linear; pieces above use \(u\), where \(f^*\) has bumps near \(u = 1/2, 1, \dots\) for large \(\nu\). Pieces are halved until the trailing Chebyshev coefficients fall below the tolerance.

  • Distances outside [u_min, u_max] fall back to the exact series, so the kernel is exact there and approximate inside. tol is an acceptance threshold on trailing coefficients, not a guaranteed error bound; see ChebyshevKernel.

  • One fit is built per distinct \(\nu\) and cached. When \(\nu\) differs between meioses and there are more than max_distinct distinct values in one call, the kernel falls back to the exact series.

class cointf.chebyshev.ChebyshevKernel(tol=1e-12, u_min=1e-06, u_max=5.0, u_split=0.25, n_nodes=16, max_distinct=16, max_cached=256)

Likelihood kernel with piecewise Chebyshev fits of log f* and log S*.

Parameters:
tolfloat, default 1e-12

Acceptance threshold for each piece: its last three Chebyshev coefficients must be below tol / 4 times the largest absolute value being fitted on the piece (at least 1). This is a heuristic, not a bound. With the default, measured errors in \(\log f^*\) and \(\log S^*\) are about 1e-14 for \(\nu \le 4\) and grow to about 3e-12 at \(\nu = 100\), where the fitted values are largest.

u_min, u_maxfloat, default 1e-6 and 5.0

Distances (on the interference scale) inside this range use the fit; the rest use the exact series.

u_splitfloat, default 0.25

Boundary between pieces fitted in \(\log u\) and in \(u\).

n_nodesint, default 16

Nodes per piece.

max_distinctint, default 16

Largest number of distinct \(\nu\) values in one call for which fits are built; above it the call uses the exact series.

max_cachedint, default 256

Fits kept in the cache before it is cleared.

Examples

>>> from cointf.chebyshev import ChebyshevKernel
>>> from cointf.fastlik import loglik_fast
>>> data = [[0.31, 1.12], [0.70], []]
>>> kernel = ChebyshevKernel()
>>> exact = loglik_fast(data, 1.5, nu=4.0, p=0.05)
>>> approx = loglik_fast(data, 1.5, nu=4.0, p=0.05, kernel=kernel)
>>> bool(abs(exact - approx) < 1e-10)
True
fits(nu)

Return the cached fits for one value of nu, building them if needed.

Parameters:
nufloat

Interference parameter, > 0.

Returns:
fit_fPiecewiseChebyshev

Fit of \(\log f^*(u) - (\nu - 1) \log u\).

fit_sPiecewiseChebyshev

Fit of \(\log S^*(u)\).

evaluate(u, nu, which)

Evaluate log f* or log S* at distances u.

Parameters:
uarray_like

Distances, >= 0. Flattened to 1-D.

nufloat or array_like

A scalar, or one value per element of u.

which{“f”, “S”}

\(\log f^*\) or \(\log S^*\).

Returns:
numpy.ndarray

Values, shape (u.size,).

evaluate_shared(u, nu, which, exact)

Evaluate at distances u for one scalar nu.

Parameters:
unumpy.ndarray

1-D distances.

nufloat

Interference parameter.

which{“f”, “S”}

Function to evaluate.

exactcallable

Exact series used outside the fitted range.

Returns:
numpy.ndarray

Values, shape (u.size,).

log_fstar(u, nu)

Approximate log density of the unit-rate inter-crossover distance.

Parameters:
uarray_like

Distances, >= 0. Flattened to 1-D.

nufloat or array_like

Interference parameter: a scalar, or one value per element of u.

Returns:
numpy.ndarray

\(\log f^*(u; \nu)\), shape (u.size,).

See also

cointf.fastlik.log_fstar_fast

The exact series this approximates.

log_sstar(u, nu)

Approximate log survival function of the inter-crossover distance.

Parameters:
uarray_like

Distances, >= 0. Flattened to 1-D.

nufloat or array_like

Interference parameter: a scalar, or one value per element of u.

Returns:
numpy.ndarray

\(\log S^*(u; \nu)\), shape (u.size,).

See also

cointf.fastlik.log_sstar_fast

The exact series this approximates.

__call__(u_gap, nu_gap, u_end, nu_end)

Kernel interface of cointf.fastlik.series_kernel().

Parameters:
u_gapnumpy.ndarray

Gaps between crossovers on the interference scale, >= 0.

nu_gapfloat or numpy.ndarray

Interference parameter: a scalar, or an array shaped like u_gap.

u_endnumpy.ndarray

Distances from a crossover to a chromosome end, on the interference scale, >= 0.

nu_endfloat or numpy.ndarray

Interference parameter: a scalar, or an array shaped like u_end.

Returns:
log_fnumpy.ndarray

\(\log f^*\) at u_gap.

log_Snumpy.ndarray

\(\log S^*\) at u_end.

class cointf.chebyshev.PiecewiseChebyshev(fn, u_min, u_split, u_max, n_nodes=16, tol=1e-12, max_pieces=4096)

Adaptive piecewise Chebyshev interpolant of a smooth function of u.

Parameters:
fncallable

Vectorised function of a 1-D array of u > 0.

u_min, u_split, u_maxfloat

Domain [u_min, u_max]; pieces below u_split are fitted in \(\log u\), pieces above in \(u\).

n_nodesint

Nodes per piece (degree plus one).

tolfloat

Acceptance threshold, not an error bound: a piece is accepted when its last three coefficients are below tol / 4 times max(1, max |fn|) on the piece.

max_piecesint

Upper bound on the number of pieces.

Attributes:
u_lonumpy.ndarray

Lower end of each piece in u, sorted, shape (P,).

center, halfnumpy.ndarray

Midpoint and half-width of each piece in its own variable.

log_scalenumpy.ndarray

True for pieces fitted in \(\log u\).

coefsnumpy.ndarray

Coefficients, shape (n_nodes, P).

n_evaluationsint

Calls of fn made while building, counted per point.

Raises:
RuntimeError

If the tolerance is not reached within max_pieces pieces.

property n_pieces

Number of pieces.

__call__(u)

Evaluate the interpolant at points inside [u_min, u_max].

Parameters:
unumpy.ndarray

1-D array of points in [u_min, u_max].

Returns:
numpy.ndarray

Interpolated values, shape (u.size,).