Skip to content

virgil._linear

Internal module

virgil._linear is a private implementation detail, documented for contributors and for reading the source; its API may change without deprecation. Users reach it through OIData.with_gains, OIData.with_flux_scale, OIData.with_continuum and RVData.term(marginalize_offsets=...).

Analytic marginalization of parameters that enter the model linearly: the calibration gains and closure-phase offsets of virgil.gains, the grey scales and continuum terms of virgil.observables, and the RV zero points of RVData. The prior is always stated by the caller, never taken from the data, and a Gaussian on a scale-type parameter is a proposal for its Jeffreys prior.

Analytic marginalization of parameters that enter the model linearly.

The data are d = m + A w + n: a model m, a design A (n × k) times linear parameters w, and noise n ~ N(0, D), D = diag(σ²). With a Gaussian prior w ~ N(μ, Λ), w integrates out in closed form (Luger, Foreman-Mackey & Hogg 2017, AJ 153, 216):

d ~ N(m + A μ, D + A Λ Aᵀ).

In whitened coordinates, x = D^-½ (d - m - A μ) and U = D^-½ A Λ^½ (one column per parameter), the covariance is I + U Uᵀ. Everything here works on (x, U). It returns a whitened residual of the same length as x, so the likelihood keeps one residual vector, and the log-determinant ½ log det(I + UᵀU), kept as effective errors or a log-normalization.

Rules:

  • Keep the log-determinant. It depends on the model wherever A or σ does, e.g. a flux scale times the model's spectrum, or fitted jitter.
  • The prior is stated by the caller, finite, and never derived from the data. A flat prior is only a limit, up to a constant that depends on its width: the width is part of the model.
  • Report the conditional posterior of w (posterior).
  • A Gaussian on a scale-type parameter is a proposal only. For a positive scale such as an OI_FLUX grey scale k, the Jeffreys prior is 1/k on stated bounds. Reweight samples of the conditional posterior by 1 / (k N(k; μ, Λ)) (with bounds), and make no evidence claims from the Gaussian.

Two ways to whiten, with the same result.

  • Successive rank-one steps (whiten_rank_one, whiten_blocks): a rank-one covariance I + w wᵀ is whitened by R = I - w wᵀ / (q (q + 1)), q = √(1 + wᵀw), since R (I + w wᵀ) Rᵀ = I, with log-determinant log(1 + wᵀw). Applying R to x and to the remaining columns, column by column, whitens I + U Uᵀ. Only scalar square roots appear, so the gradients stay smooth where columns are degenerate (equal visibilities on every baseline) or widths go to zero, where an eigendecomposition's are not. Use it for the calibration gains, closure offsets and grey scales, blocked by frame.
  • A dense Cholesky (whiten_cholesky): S = I + UᵀU = L Lᵀ and u = x - W (I + L⁻ᵀ)⁻¹ Wᵀ x, with W = U L⁻ᵀ. This is an exact square root, again without an eigendecomposition. Use it for a few well-conditioned columns, such as RV zero points or a four-column Thiele–Innes basis. It is O(n k²).

LinearMarginal wraps either for one design with a stated prior. The Laplace covariance of a fit's latent parameters (fitting._gauss_newton_covariance) uses the same Woodbury identity, but to invert a curvature, not to marginalize a likelihood, so it is not built on this module.

LinearMarginal

Bases: Module

A design A whose parameters w are marginalized under a stated prior.

Parameters:

Name Type Description Default
design array - like

A, (n, k): how each parameter enters the data.

required
prior_mean array - like

μ, (k,) or a scalar: the prior mean, in the parameters' units. It is stated, never estimated from the data.

required
prior_sd array - like

Prior standard deviations (k,) (independent parameters).

None
prior_cov array - like

A full prior covariance (k, k), instead of prior_sd.

None
method (cholesky, rank_one)

How to whiten (see the module notes). "cholesky" (the default) suits a few well-conditioned columns. "rank_one" keeps gradients smooth when columns are degenerate.

"cholesky"
Notes

The prior must be finite: a flat prior is a limit only up to a constant that depends on its width. For a scale-type parameter the Gaussian is a proposal: see the module notes on reweighting to the Jeffreys prior.

design = design instance-attribute

prior_mean = mean instance-attribute

prior_root = root instance-attribute

method = method class-attribute instance-attribute

__init__(design, prior_mean, prior_sd=None, prior_cov=None, method='cholesky')

standardize(resid, sigma)

(x, U) for residuals resid = d - m and errors sigma.

whiten(resid, sigma)

Whitened residuals and the log-normalization.

Returns:

Type Description
tuple

u with uᵀu = rᵀ(D + AΛAᵀ)⁻¹r (r = d - m - Aμ), and ½ log det(D + AΛAᵀ) = Σ log σ + ½ log det(I + UᵀU).

loglike(resid, sigma)

The normalized Gaussian log density of the marginalized data.

posterior(resid, sigma)

Conditional posterior of w: (mean, cov), in w's own units.

whiten_blocks(x, rows, local, spanning=None)

Whiten x for the covariance I + Σ w_j w_jᵀ, block by block.

rows (n_block, n_row) indexes x (padded out of range) and local (n_block, n_row, n_mode) holds each block's columns there; spanning (n, n_spanning) holds columns across blocks, whitened after them. Successive rank-one steps (see the module notes).

Returns:

Type Description
tuple

The whitened x and, per entry, the log of the factor its effective error grows by. These sum to ½ log det(I + UᵀU).

whiten_rank_one(x, U)

Whiten x for I + U Uᵀ by successive rank-one steps.

Returns:

Type Description
tuple

The whitened x (same length) and ½ log det(I + UᵀU).

whiten_cholesky(x, U)

Whiten x for I + U Uᵀ with a dense k × k Cholesky.

Returns:

Type Description
tuple

The whitened x (same length) and ½ log det(I + UᵀU).

posterior(x, U)

Conditional posterior of the standardized parameters ω.

With w = μ + Λ^½ ω, the prior is ω ~ N(0, I). Given x = D^-½ (d - m - A μ), the posterior is ω ~ N(S⁻¹ Uᵀ x, S⁻¹), with S = I + UᵀU.

Returns:

Type Description
tuple

(mean, cov) of ω, of shapes (k,) and (k, k).