derivkit.forecasting.expansions module#

Utilities for evaluating Fisher and DALI likelihoods expansions.

This module provides functional helpers to evaluate approximate likelihoods (or posterior) surfaces from forecast tensors:

  • Fisher quadratic approximation (F)

  • Doublet-DALI cubic/quartic corrections (F, G, H)

Conventions#

We expose two conventions that are common in the codebase:

  • convention="delta_chi2":

    Uses the standard DALI delta_chi2 form:

    delta_chi2 = d.T @ F @ d + (1/3) einsum(G, d, d, d) + (1/12) einsum(H, d, d, d, d)
    

    and returns log posterior (up to a constant) as:

    log p = -0.5 * delta_chi2.
    
  • convention="matplotlib_loglike":

    Matches the prefactors used in some matplotlib contour scripts:

    log p = -0.5 d.T @ F @ d - 0.5 einsum(G, d, d, d) - 0.125 einsum(H, d, d, d, d)
    

    which corresponds to:

    delta_chi2 = d.T @ F @ d + einsum(G, d, d, d) + 0.25 einsum(H, d, d, d, d)
    

    so that again log p = -0.5 * delta_chi2.

GetDist convention#

GetDist expects loglikes to be the negative log posterior:

loglikes = -log(posterior)

up to an additive constant. Since this module defines:

log(posterior) = -0.5 * delta_chi2 + const

a compatible choice for GetDist is therefore:

loglikes = 0.5 * delta_chi2

(optionally shifted by a constant for numerical stability).

derivkit.forecasting.expansions.delta_chi2_dali(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]], g_tensor: ndarray[tuple[Any, ...], dtype[floating]], h_tensor: ndarray[tuple[Any, ...], dtype[floating]] | None, *, convention: str = 'delta_chi2') float#

Computes a displacement chi-squared under the DALI approximation.

This function evaluates a scalar delta_chi2 from the displacement d = theta - theta0 using the Fisher matrix and (optionally) the cubic and quartic DALI tensors.

The convention parameter controls the numerical prefactors applied to the cubic/quartic contractions, i.e. it changes the scaling of the higher- order corrections relative to the quadratic Fisher term:

  • convention="delta_chi2":

    delta_chi2 = d.T @ F @ d + (1/3) * G[d,d,d] + (1/12) * H[d,d,d,d]

  • convention="matplotlib_loglike":

    delta_chi2 = d.T @ F @ d + 1 * G[d,d,d] + (1/4) * H[d,d,d,d]

Parameters:
  • theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher/DALI expansion is evaluated.

  • theta0 – Expansion point (reference parameter vector). The Fisher matrix and any DALI tensors are assumed to have been computed at this point, and the expansion is taken in the displacement theta - theta0.

  • fisher – Fisher matrix (p, p) with p the number of parameters.

  • g_tensor – DALI cubic tensor with shape (p, p, p).

  • h_tensor – DALI quartic tensor (p, p, p, p) or None.

  • convention – Controls the prefactors used in the cubic/quartic tensor contractions inside delta_chi2.

Returns:

The scalar delta chi-squared value.

Raises:

ValueError – If an unknown convention is provided.

derivkit.forecasting.expansions.delta_chi2_fisher(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]]) float#

Computes a displacement chi-squared under the Fisher approximation.

Parameters:
  • theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher expansion is evaluated.

  • theta0 – Expansion point (reference parameter vector). The Fisher matrix and any DALI tensors are assumed to have been computed at this point, and the expansion is taken in the displacement theta - theta0.

  • fisher – Fisher matrix with shape (p, p) with p the number of parameters.

Returns:

The scalar delta chi-squared value between theta and theta_0.

derivkit.forecasting.expansions.logposterior_dali(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]], g_tensor: ndarray[tuple[Any, ...], dtype[floating]], h_tensor: ndarray[tuple[Any, ...], dtype[floating]] | None, *, convention: str = 'delta_chi2', prior_terms: Sequence[tuple[str, dict[str, Any]] | dict[str, Any]] | None = None, prior_bounds: Sequence[tuple[float | None, float | None]] | None = None, logprior: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], float] | None = None) float#

Computes the log posterior (up to a constant) under the DALI approximation.

If no prior is provided, this returns the DALI log-likelihoods expansion with a flat prior and no hard cutoffs.

Parameters:
  • theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher/DALI expansion is evaluated.

  • theta0 – Expansion point (reference parameter vector). The Fisher matrix and any DALI tensors are assumed to have been computed at this point, and the expansion is taken in the displacement theta - theta0.

  • fisher – Fisher matrix with shape (p, p) with p the number of parameters.

  • g_tensor – DALI cubic tensor (p, p, p).

  • h_tensor – DALI quartic tensor (p, p, p, p) or None.

  • convention – The normalization to use ("delta_chi2" or "matplotlib_loglike").

  • prior_terms – prior term specification passed to derivkit.forecasting.priors.core.build_prior().

  • prior_bounds – Global hard bounds passed to derivkit.forecasting.priors.core.build_prior().

  • logprior – Optional custom log-prior callable. If it returns a non-finite value, the posterior is treated as zero at that point and the function returns -np.inf.

Returns:

Scalar log posterior value, defined up to an additive constant.

Raises:

ValueError – If an unknown convention is provided.

derivkit.forecasting.expansions.logposterior_fisher(theta: ndarray[tuple[Any, ...], dtype[floating]], theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]], *, prior_terms: Sequence[tuple[str, dict[str, Any]] | dict[str, Any]] | None = None, prior_bounds: Sequence[tuple[float | None, float | None]] | None = None, logprior: Callable[[ndarray[tuple[Any, ...], dtype[floating]]], float] | None = None) float#

Computes the log posterior under the Fisher approximation.

The returned value is defined up to an additive constant in log space. This corresponds to an overall multiplicative normalization of the posterior density in probability space.

If no prior is provided, this returns the Fisher log-likelihoods expansion with a flat prior and no hard cutoffs.

The Fisher approximation corresponds to a purely quadratic delta_chi2 surface:

delta_chi2 = d.T @ F @ d

so the log posterior is:

log p = -0.5 * delta_chi2

This normalization is equivalent to the convention="delta_chi2" used for DALI. In this interpretation, fixed delta_chi2 values correspond to fixed probability content (e.g. 68%, 95%) in parameter space, as for a Gaussian likelihoods. See derivkit.forecasting.expansions.delta_chi2_dali() for the corresponding DALI definition of delta_chi2 and its supported conventions.

Unlike the DALI case, there is no alternative normalization for the Fisher approximation: the likelihoods is strictly Gaussian and fully described by the quadratic form.

Parameters:
  • theta – Evaluation point in parameter space. This is the trial parameter vector at which the Fisher/DALI expansion is evaluated.

  • theta0 – Expansion point (reference parameter vector). The Fisher matrix and any DALI tensors are assumed to have been computed at this point, and the expansion is taken in the displacement theta - theta0.

  • fisher – Fisher matrix with shape (p, p) with p the number of parameters.

  • prior_terms – prior term specification passed to derivkit.forecasting.priors.core.build_prior().

  • prior_bounds – Global hard bounds passed to derivkit.forecasting.priors.core.build_prior().

  • logprior – Optional custom log-prior callable. If it returns a non-finite value, the posterior is treated as zero at that point and the function returns -np.inf.

Returns:

Scalar log posterior value, defined up to an additive constant.

derivkit.forecasting.expansions.submatrix_dali(theta0: ndarray[tuple[Any, ...], dtype[floating]], fisher: ndarray[tuple[Any, ...], dtype[floating]], g_tensor: ndarray[tuple[Any, ...], dtype[floating]], h_tensor: ndarray[tuple[Any, ...], dtype[floating]] | None, idx: Sequence[int]) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]] | None]#

Extracts sub-DALI tensors for a subset of parameter indices.

The tensors are constructed by selecting entries of theta0 and the corresponding rows and columns of the Fisher, cubic, and quartic tensors using the indices in idx. The indices may be any subset and any order and do not need to correspond to a contiguous block.

This operation is useful for evaluating a DALI expansion on a lower-dimensional parameter subspace while holding all other parameters fixed at their expansion values. It represents a slice through parameter space rather than a marginalization.

Parameters:
  • theta0 – Full expansion point with shape (p,) with p the number of parameters.

  • fisher – Full Fisher matrix with shape (p, p).

  • g_tensor – Full DALI cubic tensor with shape (p, p, p).

  • h_tensor – Full DALI quartic tensor with shape (p, p, p, p) or None.

  • idx – Sequence of parameter indices to extract.

Returns:

A tuple (theta0_sub, f_sub, g_sub, h_sub) where each entry is selected using the specified indices. Shapes are:

  • theta0_sub: (len(idx),)

  • f_sub: (len(idx), len(idx))

  • g_sub: (len(idx), len(idx), len(idx))

  • h_sub: (len(idx), len(idx), len(idx), len(idx)) or None.

Raises:
  • ValueError – If input tensors have invalid shapes.

  • TypeError – If idx contains non-integer indices.

  • IndexError – If any index in idx is out of bounds.

derivkit.forecasting.expansions.submatrix_fisher(fisher: ndarray[tuple[Any, ...], dtype[floating]], idx: Sequence[int]) ndarray[tuple[Any, ...], dtype[float64]]#

Extracts a sub-Fisher matrix for a subset of parameter indices.

The submatrix is constructed by selecting rows and columns of fisher at the indices such that F_sub[a, b] = fisher[idx[a], idx[b]].

The indices in idx may be any subset and any order. They do not need to correspond to a contiguous block in the original matrix. For example, selecting two parameters that appear at opposite corners of the full Fisher matrix produces the full 2x2 Fisher submatrix for those parameters, including their off-diagonal correlation.

This operation is useful for extracting a lower-dimensional slice of a Fisher matrix for plotting or evaluation while holding all other parameters fixed at their expansion values. It represents a slice through parameter space rather than a marginalization. Marginalized constraints instead require operating on the covariance matrix obtained by inverting the full Fisher matrix.

Parameters:
  • fisher – Full Fisher matrix of shape (p, p) with p the number of parameters.

  • idx – Sequence of parameter indices to extract.

Returns:

Sub-Fisher matrix (len(idx), len(idx)).

Raises:
  • ValueError – If fisher is not square 2D.

  • TypeError – If idx contains non-integer indices.

  • IndexError – If any index in idx is out of bounds.