spacr.multiple_testing

Multiple-testing corrections for spaCR, with one name for every method.

Every correction spaCR offers lives here, so the GUI dropdown, the CLI, the settings validator and spacr.guide_permutation cannot drift apart: the dropdown is built from METHODS, the validator checks against the same table, and the analysis calls adjust_p_values().

Two properties matter for a pooled screen and are easy to get wrong:

  • Missing P values must not join the family. A guide that could not be tested is not a test. Counting it inflates the family size and makes every real discovery less significant. NaNs pass through untouched here.

  • The family is the displayed set. The caller decides what a family is (spaCR corrects separately per classifier outcome and per minimum-support threshold); this module only corrects whatever vector it is handed.

Beyond the statsmodels inventory this module implements Storey’s q-value, which is standard in screening work and absent from statsmodels. It estimates the proportion of true nulls (pi0) rather than assuming it is 1, so it is uniformly less conservative than Benjamini-Hochberg while targeting the same false-discovery rate.

Classes

MethodSpec

One correction: its canonical key, label, family and controlled rate.

Functions

adjust_p_values(p_values[, method, alpha])

Return (adjusted, rejected) for one multiple-testing family.

canonical_method(→ str)

Return the canonical key for method.

critical_p_value(p_values[, method, alpha])

The largest RAW P value method calls at alpha, or None.

estimate_pi0(→ float)

Estimate the proportion of true null hypotheses (Storey's pi0).

local_fdr(p_values, *[, pi0])

Estimate the local false-discovery rate for a family of p values.

method_choices(→ list[str])

Canonical keys in dropdown order.

method_label(→ str)

Human-readable label for method.

storey_qvalue(p_values, *[, pi0])

Return Storey q-values for a vector of P values.

Module Contents

class spacr.multiple_testing.MethodSpec[source]

One correction: its canonical key, label, family and controlled rate.

Parameters:
  • key – canonical settings and command-line identifier for the correction.

  • label – human-readable method name shown in selectors.

  • controls – error rate controlled by the method: "FDR", "FWER", or "nothing".

  • statsmodels_name – method name passed to statsmodels, or None for locally implemented or absent correction.

  • summary – concise explanation of the method and its assumptions.

spacr.multiple_testing.adjust_p_values(p_values, method='fdr_bh', alpha=0.05)[source]

Return (adjusted, rejected) for one multiple-testing family.

Parameters:
  • p_values – P values for every test in the family. Non-finite entries stay non-finite, are never rejected, and do not count toward the family size.

  • method – any key, statsmodels name or alias accepted by canonical_method().

  • alpha – the level the correction targets, strictly inside (0, 1).

Returns:

adjusted (same shape as the input) and rejected, a boolean array.

spacr.multiple_testing.canonical_method(method) → str[source]

Return the canonical key for method.

Accepts the canonical keys, the statsmodels spellings and the common aliases. None maps to 'none'. Raises ValueError with the full inventory for anything else, rather than silently falling back to a correction the user did not ask for.

Parameters:

method – canonical key, statsmodels spelling, alias, or None.

spacr.multiple_testing.critical_p_value(p_values, method='fdr_bh', alpha=0.05)[source]

The largest RAW P value method calls at alpha, or None.

The threshold lets a plot with a raw-P axis show the corrected call. A volcano with the adjusted P on its y-axis inherits the step function created by the cumulative minimum in Benjamini-Hochberg. Every correction here is monotone in the raw P within a family, so the called set is a lower set: there is a rank k such that every test with p <= p_(k) is called and every test above it is not. One horizontal line at -log10(p_(k)) on the raw-P axis therefore separates the called tests exactly as the correction does.

For Benjamini-Hochberg this is the textbook identity

q_(i) <= alpha if and only if p_(i) <= alpha * i / n

taken at the largest i that satisfies it. The value is computed from the correction’s own rejection call rather than from that formula, so the line agrees with the point colours and the same function serves all thirteen methods in METHODS.

The threshold is not alpha. A line at -log10(0.05) marks the uncorrected threshold, which is higher than the corrected one, so more tests appear above it than the correction calls.

None is returned when the correction calls no test. There is then no k and no line to draw; a line at alpha would show a threshold the procedure did not reach.

Parameters:
  • p_values – the raw P values of one multiple-testing family.

  • method – any spelling canonical_method() accepts.

  • alpha – the level the correction targets.

Returns:

the raw-P threshold as a float, or None.

spacr.multiple_testing.estimate_pi0(p_values, *, lambdas: Sequence[float] | None = None) → float[source]

Estimate the proportion of true null hypotheses (Storey’s pi0).

pi0(lambda) = #{p > lambda} / (m * (1 - lambda)) is computed over a grid of lambda values (default 0.05 to 0.95 in steps of 0.05); the estimate is the minimum over the upper half of the grid (lambda at or above the grid median), clipped to (0, 1]. With fewer than 20 finite P values, an empty grid, or a non-positive estimate, the function returns 1.0, which makes the q-values equal to Benjamini-Hochberg adjusted P values.

Parameters:

p_values – raw P values; non-finite entries are excluded.

spacr.multiple_testing.local_fdr(p_values, *, pi0: float | None = None)[source]

Estimate the local false-discovery rate for a family of p values.

Parameters:
  • p_values (array-like) – Raw p values from one testing family.

  • pi0 (float, optional) – Proportion of true null hypotheses. When omitted, it is estimated as w + (1 - w) * a from the fitted beta-uniform mixture.

Returns:

numpy.ndarray – Local false-discovery rates in [0, 1] with the same shape as the input. NaNs are preserved and excluded from the fit.

Notes

The local FDR estimates the posterior probability that an individual test belongs to the null component:

lfdr(p) = pi0 * f0(p) / f(p), f0(p) = 1, p ∈ [0, 1]

f is a beta-uniform mixture whose alternative component is Beta(a, 1). Unlike a q value, which summarizes a tail of discoveries, the local FDR describes one test. Families smaller than LOCAL_FDR_MIN_TESTS return 1 for every finite value because a density cannot be estimated reliably from so few observations.

spacr.multiple_testing.method_choices() → list[str][source]

Canonical keys in dropdown order.

spacr.multiple_testing.method_label(method) → str[source]

Human-readable label for method.

Parameters:

method – any correction spelling accepted by canonical_method().

spacr.multiple_testing.storey_qvalue(p_values, *, pi0: float | None = None)[source]

Return Storey q-values for a vector of P values.

q[i] is the minimum positive-FDR at which test i is called significant. The result is monotone in the P value, as the definition requires. NaNs are preserved.

Parameters:

p_values – raw P-value array whose shape and NaNs are preserved.