barracuda.donors¶
UI-neutral donor simulation, posterior extraction, variance decomposition, sensitivity, and independent-condition contrasts.
Leave-one-donor-out moments do not refit
leave_one_donor_out_moments reweights fitted posterior mixtures. It is a
sensitivity summary, not predictive cross-validation.
Donor-aware simulation and posterior analysis.
This module contains the numerical parts of the donor-aware notebook and web reporting workflows without Plotly or Dash. It deliberately distinguishes two kinds of pairing:
- parameters belonging to the same posterior particle retain their
chainanddrawlabels; and - independently fitted conditions are compared with Cartesian posterior pairs (or reproducible independent Monte Carlo pairs when the Cartesian product is too large).
The inference backend historically calls the zero-inflated fraction phi_0.
Public tables from this module use the package-wide p_zero spelling while
accepting either variable name in an :class:arviz.InferenceData object.
Attributes¶
DONOR_MODEL_KEYS
module-attribute
¶
_MODEL_ALIASES
module-attribute
¶
_MODEL_ALIASES: Final[dict[str, str]] = {'homo': 'homo', 'homogeneous': 'homo', 'homogeneouspoisson': 'homo', 'poisson': 'homo', 'z2p': 'z2p', 'zi': 'z2p', 'zeroinflated': 'z2p', 'zeroinflatedpoisson': 'z2p', 'dis2p': 'dis2p', 'distributed': 'dis2p', 'gamma': 'dis2p', 'gammapoisson': 'dis2p', 'hetero3': 'hetero3', 'full': 'hetero3', 'zir': 'hetero3', 'zigamma': 'hetero3', 'zeroinflatedgammapoisson': 'hetero3'}
_POPULATION_VARIABLES
module-attribute
¶
_POPULATION_VARIABLES: Final[tuple[tuple[str, tuple[str, ...]], ...]] = (('mu_lambda_population', ('mu_lambda_population',)), ('sigma_lambda_population', ('sigma_lambda_population',)), ('p_zero_population', ('p_zero_population', 'phi_0_population')))
_DONOR_VARIABLES
module-attribute
¶
_DONOR_VARIABLES: Final[tuple[tuple[str, tuple[str, ...]], ...]] = (('mu_lambda_donor', ('mu_lambda_donor',)), ('sigma_lambda_donor', ('sigma_lambda_donor',)), ('p_zero_donor', ('p_zero_donor', 'phi_0_donor')))
__all__
module-attribute
¶
__all__ = ['DONOR_MODEL_KEYS', 'ContrastScale', 'DonorSimulationSpec', 'canonical_donor_model_key', 'simulate_donor_event_counts', 'population_posterior_frame', 'donor_posterior_frame', 'population_variance_decomposition', 'leave_one_donor_out_moments', 'cartesian_contrast_draws', 'condition_contrast_frame', 'summarize_contrast_draws']
Classes¶
DonorSimulationSpec
dataclass
¶
DonorSimulationSpec(donor_sizes: Mapping[object, int] | Sequence[tuple[object, int]], mu_lambda: Real | Mapping[object, Real] | Sequence[Real], model_key: str = 'hetero3', sigma_lambda: Real | Mapping[object, Real] | Sequence[Real] = 0.0, p_zero: Real | Mapping[object, Real] | Sequence[Real] = 0.0, observation_time: float = 1.0, seed: int | None = 2026)
Validated settings for one donor-aware event-count simulation.
donor_sizes preserves insertion order and may contain unequal cell
counts. Each biological parameter may be a scalar shared by all donors,
a donor-labelled mapping, or a sequence aligned to donor_sizes.
Parameters are moments among engaging cells: mu_lambda and
sigma_lambda describe the donor's rate distribution, while p_zero
is its structural-zero probability. Model-incompatible nonzero values are
rejected rather than silently discarded.
Functions:¶
canonical_donor_model_key ¶
Return one lowercase key for a donor-aware event-count model.
Spaces, underscores and hyphens are ignored, so both backend spellings
such as "Dis2P" and descriptive names such as "gamma-poisson"
resolve to the stable public key "dis2p".
_donor_size_items ¶
_donor_size_items(values: Mapping[object, int] | Sequence[tuple[object, int]]) -> tuple[tuple[str, int], ...]
_donor_parameter_values ¶
_donor_parameter_values(values: Real | Mapping[object, Real] | Sequence[Real], *, donor_ids: Sequence[str], name: str) -> tuple[float, ...]
simulate_donor_event_counts ¶
simulate_donor_event_counts(spec: DonorSimulationSpec) -> tuple[DataFrame, dict[str, object]]
Simulate donor-labelled cell counts and return exact generating truths.
Engaging rates are fixed for homo/z2p and Gamma-distributed with
the requested mean and standard deviation for dis2p/hetero3.
Structural zeros are sampled independently before Poisson event counts.
Population truths use cell-count weights and, for rate moments, the active
donor weights used by the donor-aware inference backend.
_posterior ¶
Return a posterior and the object carrying optional result metadata.
_subsample_draw_pairs ¶
population_posterior_frame ¶
population_posterior_frame(source: Any, *, condition: str | None = None, model_key: str | None = None, max_draws: int | None = None, random_seed: int = 307) -> DataFrame
Extract paired population draws from InferenceData or InferenceResult.
The returned chain and draw columns identify the posterior particle
shared by every parameter in a row. phi_0_population is exposed as
p_zero_population. Optional subsampling selects whole particle rows.
_resolved_donor_labels ¶
_resolved_donor_labels(coordinates: ndarray, donor_labels: Sequence[object] | Mapping[object, object] | None) -> list[str]
donor_posterior_frame ¶
donor_posterior_frame(source: Any, *, condition: str | None = None, model_key: str | None = None, donor_labels: Sequence[object] | Mapping[object, object] | None = None, max_draws: int | None = None, random_seed: int = 307) -> DataFrame
Extract donor draws while retaining within-particle parameter pairing.
Donor labels default to posterior coordinates. For an InferenceResult,
stored donor_labels are used automatically. Backend
phi_0_donor values are exposed as p_zero_donor.
_normalised_donor_weights ¶
_normalised_donor_weights(values: Sequence[float] | Mapping[object, float] | ndarray, *, coordinates: ndarray) -> ndarray
_mixture_moments ¶
_mixture_moments(posterior: Dataset, donor_weights: ndarray, *, donor_dimension: str, require_sigma: bool) -> Dataset
population_variance_decomposition ¶
population_variance_decomposition(source: Any, donor_weights: Sequence[float] | Mapping[object, float] | ndarray, *, tolerance: float = 1e-10) -> Dataset
Split population rate variance into within- and between-donor terms.
Raw donor weights are normally observed cell counts. In zero-inflated
models the rate moments use active weights
:math:w_d(1-p_{0,d}) / \sum_j w_j(1-p_{0,j}). Every draw satisfies
variance_total == variance_within_donor + variance_between_donor and
sigma_lambda_population**2 == variance_total up to floating-point
precision. Saved backend population moments are checked within
tolerance when available.
leave_one_donor_out_moments ¶
leave_one_donor_out_moments(source: Any, donor_weights: Sequence[float] | Mapping[object, float] | ndarray, *, donor_labels: Sequence[object] | Mapping[object, object] | None = None) -> Dataset
Recompute population mixture moments after excluding each donor.
This is a posterior sensitivity calculation, not a model refit. It reuses every fitted donor parameter draw, removes one donor from the mixture, renormalizes the supplied cell weights, and recomputes population moments. It therefore answers how fitted mixture summaries depend on each donor; it does not include the posterior changes that refitting would induce.
_finite_sample_matrix ¶
cartesian_contrast_draws ¶
cartesian_contrast_draws(treatment_samples: Sequence[float] | ndarray, control_samples: Sequence[float] | ndarray, *, scale: ContrastScale = 'absolute', control_mean: Sequence[float] | ndarray | None = None, max_exact_pairs: int = 500000, approximate_pairs: int = 100000, random_seed: int = 307) -> tuple[ndarray, dict[str, object]]
Compare independent posteriors using all or sampled Cartesian pairs.
When len(treatment) * len(control) exceeds max_exact_pairs, indices
are sampled independently and uniformly using random_seed. Percentage
contrasts divide by the fixed control posterior mean, never by individual
control particles.
condition_contrast_frame ¶
condition_contrast_frame(posterior_draws: DataFrame, *, treatment: str, control: str, parameter_columns: Sequence[str] | None = None, group_columns: Sequence[str] | None = None, scale: ContrastScale = 'absolute', max_exact_pairs: int = 500000, approximate_pairs: int = 100000, random_seed: int = 307) -> DataFrame
Compare independently fitted conditions in extracted posterior tables.
Use :func:population_posterior_frame or :func:donor_posterior_frame
with condition=..., concatenate the resulting frames, then pass them
here. If group_columns is omitted, model keys and donor identifiers
present in the table are retained as comparison groups. Pass an explicit
empty sequence only when pooling those identities is scientifically
intended. Chain/draw labels are intentionally not paired across
independently fitted conditions.
summarize_contrast_draws ¶
summarize_contrast_draws(contrasts: DataFrame, *, group_columns: Sequence[str] | None = None, hdi_prob: float = 0.95) -> DataFrame
Summarize contrast columns with HDIs and sign probabilities.
When group_columns is omitted, treatment, control, model, and donor
identity columns present in the contrast table are retained. Supply an
explicit empty sequence to pool all rows.