Skip to content

API reference

The reference is generated from source docstrings and type annotations by mkdocstrings. Public modules are intentionally separated from _core and _backends; names under those private packages may change without deprecation.

Module Scope
barracuda.event_counts Count/donor/condition validation, simulation, inference, tables, archives
barracuda.trajectories Trajectory I/O, simulation, inference, tables, archives
barracuda.donors Donor simulation, posterior extraction, mixture moments, contrasts
barracuda.evidence Directed Bayes factors, model probabilities, independent aggregation, Savage–Dickey
barracuda.validation Typed scenarios, recovery, coverage, superiority/ROPE, validation runners
barracuda.scans Cumulative-prefix count and trajectory Bayes-factor scans
barracuda.diagnostics SMC, posterior, population, and trajectory diagnostics
barracuda.plotting Optional Matplotlib figures returning axes
barracuda.io Checksummed inference and scan persistence
barracuda.progress Per-chain SMC stage/tempering progress bridge

Stability

Version 0.2 is alpha. Public names listed here are the intended user surface, but signatures and result schemas can still evolve. Pin versions and read the changelog. Private modules beginning with _ are not part of the compatibility contract.

Top-level convenience exports

The package root re-exports common settings/result types and the primary event, trajectory, donor, evidence, validation, and scan functions. Complete donor analysis, diagnostics, persistence, plotting, and lower-frequency helpers remain organized in the named modules above.

Public Python interface for the BARRACUDA Bayesian modelling framework.

Attributes

__version__ module-attribute

__version__ = version('cyto-barracuda')

run_donor_aware_models module-attribute

run_donor_aware_models = run_donor_models

run_donor_ignorant_models module-attribute

run_donor_ignorant_models = run_count_models

DONOR_MODEL_KEYS module-attribute

DONOR_MODEL_KEYS: Final[tuple[str, ...]] = ('homo', 'z2p', 'dis2p', 'hetero3')

COUNT_SCENARIOS module-attribute

COUNT_SCENARIOS: Final[tuple[EventCountScenario, ...]] = (EventCountScenario('No1', 'No1: sigma_lambda=3, p_zero=0.2', 4.0, 3.0, 0.2, 'hetero3', 1), EventCountScenario('No2', 'No2: sigma_lambda=0, p_zero=0.2', 4.0, 0.0, 0.2, 'z2p', 2), EventCountScenario('No3', 'No3: sigma_lambda=3, p_zero=0', 4.0, 3.0, 0.0, 'dis2p', 3), EventCountScenario('No4', 'No4: sigma_lambda=0, p_zero=0', 4.0, 0.0, 0.0, 'homo', 4))

TRAJECTORY_SCENARIOS module-attribute

TRAJECTORY_SCENARIOS: Final[tuple[TrajectoryScenario, ...]] = (TrajectoryScenario('No1', 'No1: sigma_eta=1, beta=(0.8,-0.8)', 4.0, 2.0, 0.25, 1.0, 0.8, -0.8, 'heterogeneous_history_dependent', 1), TrajectoryScenario('No2', 'No2: sigma_eta=1, beta=(0,0)', 4.0, 2.0, 0.25, 1.0, 0.0, 0.0, 'heterogeneous_history_independent', 2), TrajectoryScenario('No3', 'No3: sigma_eta=0, beta=(0.8,-0.8)', 4.0, 2.0, 0.25, 0.0, 0.8, -0.8, 'homogeneous_history_dependent', 3), TrajectoryScenario('No4', 'No4: sigma_eta=0, beta=(0,0)', 4.0, 2.0, 0.25, 0.0, 0.0, 0.0, 'homogeneous_history_independent', 4))

__all__ module-attribute

__all__ = ['COUNT_SCENARIOS', 'DONOR_MODEL_KEYS', 'MODEL_SPECS', 'TRAJECTORY_MODEL_SPECS', 'TRAJECTORY_SCENARIOS', 'ConditionResults', 'DonorSimulationSpec', 'EventCountScenario', 'EventCountValidationResult', 'InferenceResult', 'InferenceSettings', 'ModelSpec', 'PosteriorProbabilityResult', 'SavageDickeyResult', 'ScanBundle', 'SMCProgressCallback', 'TrajectoryModelSpec', 'TrajectoryResult', 'TrajectoryScenario', 'TrajectorySettings', 'TrajectorySimulationSpec', 'TrajectoryValidationResult', '__version__', 'bayes_factor', 'boundary_recovery_summary', 'build_condition_results_zip', 'build_results_zip', 'build_scan_archive', 'build_trajectory_archive', 'cartesian_contrast_draws', 'canonical_json', 'canonical_donor_model_key', 'classify_bayes_factor', 'combine_independent_evidence', 'condition_contrast_frame', 'configuration_fingerprint', 'coverage_summary', 'dataframe_checksum', 'diagnostic_flags', 'diagnostics', 'donor_posterior_frame', 'donors', 'evidence', 'evidence_table', 'evidence_from_inference_data', 'event_count_recovery_table', 'expanded_trajectory_frame', 'history_effect_bayes_factors', 'io', 'leave_one_donor_out_moments', 'log_bayes_factor', 'load_inference_data', 'load_scan_bundle', 'normalize_condition_frame', 'normalize_trajectory_frame', 'pairwise_bayes_factors', 'plan_count_ground_truth_grid', 'plotting', 'plot_bayes_factor_scan', 'plot_event_count_distribution', 'plot_model_evidence', 'plot_parameter_recovery', 'plot_posterior_intervals', 'plot_posterior_pair', 'plot_rate_distribution', 'plot_trajectory_state_map', 'population_p0_draws', 'population_p0_summary', 'population_posterior_frame', 'population_variance_decomposition', 'posterior_draw_table', 'posterior_model_probabilities', 'posterior_diagnostics', 'posterior_recovery_table', 'posterior_rope_probabilities', 'posterior_superiority_probability', 'rate_distribution_curve', 'read_trajectory_csv', 'run_count_bf_scan', 'run_condition_models', 'run_count_models', 'run_donor_aware_models', 'run_donor_ignorant_models', 'run_donor_models', 'run_event_count_validation', 'run_trajectory_bf_scan', 'run_trajectory_conditions', 'run_trajectory_validation', 'run_with_smc_progress', 'sample_count_frame', 'sample_donor_frame', 'save_inference_data', 'save_scan_bundle', 'savage_dickey_ratio', 'scans', 'simulate_event_counts', 'simulate_donor_event_counts', 'simulate_trajectory_frame', 'smc_log_evidence', 'smc_evidence_summary', 'smc_log_evidence_by_chain', 'split_condition_frame', 'stable_seed', 'summary_table', 'summarize_bf_scan', 'summarize_contrast_draws', 'trajectory_evidence_frame', 'trajectory_posterior_draws', 'trajectory_recovery_table', 'trajectory_state_summary', 'trajectory_summary_frame', 'truth_model_key', 'validate_condition_frame', 'validate_count_frame', 'validate_donor_frame', 'validate_bf_scan_schema', 'validate_observation_time', 'validate_trajectory_frame', 'validation']

Classes

ScanBundle dataclass

ScanBundle(table: DataFrame, manifest: dict[str, Any], directory: Path)

A validated scan table and the manifest that describes it.

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.

Attributes

donor_ids property
donor_ids: tuple[str, ...]

Donor labels in the order used for simulation and parameter arrays.

cells_per_donor property
cells_per_donor: tuple[int, ...]

Validated cell counts aligned to :attr:donor_ids.

n_cells property
n_cells: int

Total number of simulated cells.

SavageDickeyResult dataclass

SavageDickeyResult(parameter: str, reference: float, prior_density: float, posterior_density: float, bf_01: float, bf_10: float, log_bf_10: float)

Density-ratio evidence for a point null nested in a larger model.

bf_01 supports the point null and bf_10 supports the alternative. The calculation assumes that the nuisance-parameter priors under both models are compatible, as required by the Savage--Dickey identity.

Methods:

as_dict
as_dict() -> dict[str, float | str]

Return a serialization-friendly representation.

EventCountScenario dataclass

EventCountScenario(scenario: str, label: str, mu_lambda: float, sigma_lambda: float, p_zero: float, true_model: str, seed_offset: int = 0)

Typed ground truth for one canonical event-count experiment.

EventCountValidationResult dataclass

EventCountValidationResult(scenario: EventCountScenario, replicate: int, simulation_seed: int, inference_seed: int, frame: DataFrame, truth: Mapping[str, Any], fits: Mapping[str, Any], evidence: DataFrame, recovery: DataFrame)

Complete in-memory result for one simulated event-count validation.

PosteriorProbabilityResult dataclass

PosteriorProbabilityResult(rope_lower: float, rope_upper: float, probability_below: float, probability_in_rope: float, probability_above: float, n_first: int, n_second: int, n_pairs: int)

Exact cross-draw probabilities for first - second and a ROPE.

Attributes

probability_first_superior property
probability_first_superior: float

Probability that first - second is above the ROPE.

probability_second_superior property
probability_second_superior: float

Probability that first - second is below the ROPE.

Methods:

as_dict
as_dict() -> dict[str, int | float]

Return a serialization-friendly representation.

TrajectoryScenario dataclass

TrajectoryScenario(scenario: str, label: str, mu_lambda: float, sigma_lambda: float, p0: float, sigma_eta: float, beta_f: float, beta_s: float, true_model: str, seed_offset: int = 0)

Typed ground truth for one canonical contact-trajectory experiment.

Attributes

mu_eta property
mu_eta: float

Logit-scale population killing propensity implied by p0.

TrajectoryValidationResult dataclass

TrajectoryValidationResult(scenario: TrajectoryScenario, replicate: int, simulation_seed: int, inference_seed: int, frame: DataFrame, truth: Mapping[str, Any], fits: Mapping[str, Any], evidence: DataFrame, recovery: DataFrame)

Complete in-memory result for one simulated trajectory validation.

Functions:

diagnostic_flags

diagnostic_flags(diagnostics: DataFrame, *, min_ess_bulk: float = 100.0, min_ess_tail: float = 100.0, max_r_hat: float = 1.01) -> DataFrame

Add transparent ESS/R-hat flags to a posterior diagnostic table.

Missing R-hat values (for example one-chain SMC output) are marked r_hat_available=False and are not treated as a pass.

population_p0_draws

population_p0_draws(idata: Any, *, n_parameter_draws: int | None = 1000, n_population_draws: int = 1000, seed: int | None = None) -> ndarray

Draw baseline lethal probabilities from a trajectory population.

For every retained posterior pair (mu_eta, sigma_eta), the function samples latent cell propensities and applies the logistic transform. The returned two-dimensional array preserves parameter-draw rows.

population_p0_summary

population_p0_summary(idata: Any, *, n_parameter_draws: int | None = 1000, n_population_draws: int = 1000, seed: int | None = None) -> Series

Summarize simulated baseline lethal probabilities.

posterior_diagnostics

posterior_diagnostics(idata: Any, *, var_names: Sequence[str] | None = None, hdi_prob: float = 0.95) -> DataFrame

Return an ArviZ posterior summary with stable parameter columns.

R-hat is undefined for one chain and remains NaN. Effective sample sizes should be interpreted cautiously for weighted/resampled SMC draws; the table is a diagnostic aid, not an automatic validity certificate.

smc_evidence_summary

smc_evidence_summary(idata: Any) -> Series

Summarize between-chain stability of the SMC evidence estimate.

smc_log_evidence_by_chain

smc_log_evidence_by_chain(idata: Any) -> DataFrame

Extract the final finite SMC log marginal likelihood for every chain.

BARRACUDA stores one final value per chain, but this parser also accepts older inference files containing a stage dimension or an attribute fallback. Chains with no finite value are retained with NaN so incomplete output cannot silently masquerade as a lower-chain run.

trajectory_state_summary

trajectory_state_summary(frame: DataFrame) -> DataFrame

Aggregate observed lethal decisions at every pre-contact state.

frame may be any compact/wide/long trajectory format accepted by :func:barracuda.trajectories.normalize_trajectory_frame, or an already expanded frame returned by expanded_trajectory_frame.

build_scan_archive

build_scan_archive(table: DataFrame, *, configuration: Mapping[str, Any], recovery: DataFrame | None = None, artifacts: Mapping[str, bytes] | None = None) -> bytes

Build a deterministic portable ZIP for a Bayes-factor scan.

canonical_json

canonical_json(payload: Any) -> str

Serialize configuration data deterministically for hashing.

configuration_fingerprint

configuration_fingerprint(payload: Any) -> str

Return a SHA-256 fingerprint for JSON-compatible configuration data.

dataframe_checksum

dataframe_checksum(frame: DataFrame, *, columns: Sequence[str] | None = None) -> str

Hash a table's schema, row order, values, and index-independent CSV.

A selected column order may be supplied when only the scientific input fields (rather than incidental report columns) should be covered.

load_inference_data

load_inference_data(path: str | Path)

Load an ArviZ InferenceData NetCDF written by BARRACUDA.

load_scan_bundle

load_scan_bundle(directory: str | Path, *, expected_configuration: Mapping[str, Any] | None = None, verify: bool = True) -> ScanBundle

Load and optionally verify a saved scan bundle.

save_inference_data

save_inference_data(idata: Any, path: str | Path, *, overwrite: bool = False) -> Path

Atomically save an ArviZ InferenceData object as NetCDF.

save_scan_bundle

save_scan_bundle(table: DataFrame, directory: str | Path, *, configuration: Mapping[str, Any], overwrite: bool = False) -> ScanBundle

Persist a scan CSV and fingerprinted manifest with atomic file writes.

Existing files are never silently reused. Load them with :func:load_scan_bundle and an expected_configuration to verify a resume request before deciding whether additional inference is required.

plot_bayes_factor_scan

plot_bayes_factor_scan(scan: DataFrame, *, scenario: str | None = None, model_keys: Sequence[str] | None = None, interval: float = 0.9, value_column: str | None = None, ax: Any = None) -> 'Axes'

Plot median Bayes-factor trajectories and replicate intervals.

Sample sizes are cumulative prefixes within each scenario/replicate, as in the package scan runners. The shaded interval therefore describes between-replicate variation, not independent samples at adjacent sizes.

plot_event_count_distribution

plot_event_count_distribution(frame: DataFrame, *, condition_column: str = 'condition', normalize: bool = False, ax: Any = None) -> 'Axes'

Plot an empirical count distribution, optionally split by condition.

plot_model_evidence

plot_model_evidence(evidence: DataFrame, *, condition: str | None = None, ax: Any = None, title: str | None = None) -> 'Axes'

Plot positive log10 BF(best / model) from any BARRACUDA evidence table.

plot_parameter_recovery

plot_parameter_recovery(recovery: DataFrame, *, parameter: str | None = None, model_key: str | None = None, mean_column: str | None = None, ax: Any = None) -> 'Axes'

Plot posterior means and HDIs against generating truth.

plot_posterior_intervals

plot_posterior_intervals(summary: DataFrame, *, parameter_column: str = 'parameter', mean_column: str = 'mean', lower_column: str = 'hdi_lower', upper_column: str = 'hdi_upper', ax: Any = None) -> 'Axes'

Plot any tidy posterior interval table as horizontal error bars.

plot_posterior_pair

plot_posterior_pair(draws: DataFrame, x: str, y: str, *, group: str | None = 'model_key', max_points_per_group: int | None = 5000, seed: int | None = 17, ax: Any = None) -> 'Axes'

Plot paired posterior draws without breaking joint dependence.

plot_rate_distribution

plot_rate_distribution(rate_distribution: str, mu_lambda: float, sigma_lambda: float, *, points: int = 320, ax: Any = None) -> 'Axes'

Plot the engaging-cell rate law used by an event-count simulation.

plot_trajectory_state_map

plot_trajectory_state_map(frame: DataFrame, *, condition: str | None = None, ax: Any = None) -> 'Axes'

Plot empirical lethal probability at each pre-contact history state.

canonical_donor_model_key

canonical_donor_model_key(model: object) -> str

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".

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.

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.

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.

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.

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.

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.

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.

bayes_factor

bayes_factor(log_evidence_1: float, log_evidence_2: float) -> float

Return the Bayes factor for model 1 against model 2.

Very large values are returned as inf and underflowing values as 0.0. Use :func:log_bayes_factor for lossless downstream work.

classify_bayes_factor

classify_bayes_factor(log_bf: float) -> str

Describe evidence strength using Kass--Raftery log-BF thresholds.

The magnitude thresholds are 1, 3, and 5 natural-log units. The returned label describes strength only; inspect the sign to determine which model is favoured.

combine_independent_evidence

combine_independent_evidence(evidence: DataFrame, *, model_column: str = 'model_key', log_evidence_column: str = 'log_evidence', dataset_columns: Sequence[str] | str | None = None, require_complete: bool = True) -> DataFrame

Sum log evidence across independent datasets for each model.

The caller is responsible for the scientific independence assumption. A common use is to combine condition-wise model comparisons after fitting the same candidate set separately to each condition. When condition is present it is used as the dataset identifier automatically. Complete and duplicate-free model coverage is required by default, preventing a model from winning merely because a difficult dataset was omitted.

evidence_from_inference_data

evidence_from_inference_data(idatas: Mapping[str, Any]) -> DataFrame

Build a ranked evidence table directly from InferenceData objects.

history_effect_bayes_factors

history_effect_bayes_factors(idata: Any, *, parameters: Sequence[str] = ('beta_f', 'beta_s'), reference: float = 0.0, bandwidth: str | float | None = None) -> DataFrame

Evaluate point-null Bayes factors for trajectory history effects.

Public names beta_f and beta_s are translated to the research backend's beta_x and beta_y variables when necessary. Parameters that are absent from either the prior or posterior are omitted, which makes the function safe across history-independent model results.

log_bayes_factor

log_bayes_factor(log_evidence_1: float, log_evidence_2: float) -> float

Return log p(data|model_1) - log p(data|model_2).

Positive values favour model 1, negative values favour model 2, and zero means equal evidence under the fitted priors.

pairwise_bayes_factors

pairwise_bayes_factors(log_evidence: Mapping[str, float], *, model_order: Sequence[str] | None = None) -> DataFrame

Compare every pair of models from a log-evidence mapping.

Parameters:

Name Type Description Default
log_evidence Mapping[str, float]

Mapping from model identifiers to finite log marginal likelihoods.

required
model_order Sequence[str] | None

Optional comparison order. It must name every supplied model exactly once. When omitted, insertion order is preserved.

None

Returns:

Type Description
DataFrame

One row per unordered pair. Positive log_BF_1_vs_2 values favour model_1. Both natural-log and base-10 representations are kept so plots never need to reconstruct them from rounded raw factors.

posterior_model_probabilities

posterior_model_probabilities(log_evidence: Mapping[str, float], *, prior_probabilities: Mapping[str, float] | None = None) -> DataFrame

Convert model evidence and model priors into posterior probabilities.

Equal model priors are used by default. User-supplied priors are normalized after validation, so they may be probabilities or positive relative weights.

savage_dickey_ratio

savage_dickey_ratio(idata: Any, parameter: str, *, reference: float = 0.0, bandwidth: str | float | None = None) -> SavageDickeyResult

Estimate a Savage--Dickey Bayes factor from prior/posterior draws.

idata must contain scalar draws for parameter in both its prior and posterior groups. Gaussian kernel density estimates are evaluated at reference. For bounded parameters or boundary nulls, use a method designed for boundary correction instead of this helper.

smc_log_evidence

smc_log_evidence(idata: Any) -> float

Return the mean final SMC log evidence across finite chains.

plan_count_ground_truth_grid

plan_count_ground_truth_grid(*, mu_lambda: float = 4.0, baseline_sigma_lambda: float = 3.0, baseline_p_zero: float = 0.2, sigma_lambda_values: Sequence[float] = (0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0), p_zero_values: Sequence[float] = (0.0, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5), reference_model: str = 'hetero3') -> DataFrame

Plan the canonical one-at-a-time count ground-truth sensitivity grid.

sigma_lambda varies while p_zero stays at its baseline, and p_zero varies while sigma_lambda stays at its baseline. The shared baseline is emitted once with membership in both slices; this is not a Cartesian product. Model identifiers are lowercase canonical keys.

run_count_bf_scan

run_count_bf_scan(sample_sizes: Sequence[int], *, scenarios: Sequence[EventCountScenario] = COUNT_SCENARIOS, replicates: int = 1, observation_time: float = 1.0, base_seed: int = 2026, settings: InferenceSettings | None = None, model_keys: Sequence[str] | str | None = COUNT_MODEL_KEYS, progress_callback: ScanProgressCallback | None = None) -> DataFrame

Run the event-count models over nested cumulative sample-size prefixes.

One dataset with max(sample_sizes) cells is simulated for each scenario and replicate. Every smaller fit receives full_frame.iloc[:N]. The output is long form with one row per fitted model. In columns named log_bf_model_vs_*, positive values favour model_key over the model named after vs.

run_trajectory_bf_scan

run_trajectory_bf_scan(sample_sizes: Sequence[int], *, scenarios: Sequence[TrajectoryScenario] = TRAJECTORY_SCENARIOS, replicates: int = 1, observation_time: float = 1.0, base_seed: int = 2026, settings: TrajectorySettings | None = None, model_keys: Sequence[str] | str | None = TRAJECTORY_MODEL_KEYS, progress_callback: ScanProgressCallback | None = None) -> DataFrame

Run trajectory models over nested cumulative sample-size prefixes.

One maximum-size trajectory frame is generated for each scenario and replicate. Fits at smaller sample sizes use its first N cells, so the evidence trajectory reflects accumulating data rather than resimulation. Positive log_bf_model_vs_* values favour model_key.

summarize_bf_scan

summarize_bf_scan(frame: DataFrame, *, interval: tuple[float, float] = (0.025, 0.975)) -> DataFrame

Summarize replicate-wise evidence trajectories by scenario, N, and model.

validate_bf_scan_schema

validate_bf_scan_schema(frame: DataFrame, *, workflow: str | None = None, require_true_model: bool = True, require_consistent_models: bool = True) -> DataFrame

Validate and return a copy of a standardized long-form BF scan.

Direction is checked numerically: log_bf_model_vs_true must equal the row model's log evidence minus the true model's log evidence, and the analogous best-model columns must use the same numerator convention. By default, every replicate and sample-size fit for a scenario must contain the same candidate-model set.

boundary_recovery_summary

boundary_recovery_summary(recovery: DataFrame, *, boundaries: Mapping[str, float] | None = None, truth_tolerance: float = 1e-12, estimate_tolerance: float = 0.1, group_by: Sequence[str] = ('model_key', 'parameter')) -> DataFrame

Summarise recovery rows whose generating truth lies on a boundary.

boundary_coverage_rate records whether the posterior HDI includes the boundary. estimate_within_tolerance_rate uses the posterior mean and the absolute estimate_tolerance supplied by the caller.

coverage_summary

coverage_summary(recovery: DataFrame, *, group_by: Sequence[str] = ('parameter',)) -> DataFrame

Aggregate HDI coverage, bias, RMSE, and interval width.

event_count_recovery_table

event_count_recovery_table(results: Mapping[str, Any], truth: Mapping[str, Any], *, hdi_prob: float = 0.95) -> DataFrame

Build recovery rows for every fitted event-count model.

posterior_recovery_table

posterior_recovery_table(idata: Any, truth: Mapping[str, Any], *, parameters: Sequence[str] | None = None, parameter_map: Mapping[str, str] | None = None, model_key: str | None = None, condition: str | None = None, hdi_prob: float = 0.95) -> DataFrame

Compare scalar posterior parameters with their generating truths.

parameter_map maps public/truth names to posterior variable names. The returned error is posterior mean - truth; covered states whether the closed HDI contains the truth.

posterior_rope_probabilities

posterior_rope_probabilities(first: Any, second: Any, *, rope: tuple[float, float] = (-0.1, 0.1)) -> PosteriorProbabilityResult

Return exact probabilities below, within, and above a difference ROPE.

The ROPE is closed: lower <= first - second <= upper. The below and above events are strict, so the three returned probabilities partition all cross-draw pairs exactly, including ties.

posterior_superiority_probability

posterior_superiority_probability(first: Any, second: Any, *, margin: float = 0.0) -> float

Return exact P(first - second > margin) over all cross-draw pairs.

The samples are treated as independent posterior populations. Sorting and binary search avoid constructing the potentially huge Cartesian product.

run_event_count_validation

run_event_count_validation(scenario: EventCountScenario, n_cells: int, *, observation_time: float = 1.0, replicate: int = 1, base_seed: int = 2026, settings: InferenceSettings | None = None, model_keys: Sequence[str] | str | None = None, hdi_prob: float = 0.95, progress_callback: Any = None) -> EventCountValidationResult

Simulate, fit, and assess one event-count validation dataset.

run_trajectory_validation

run_trajectory_validation(scenario: TrajectoryScenario, n_cells: int, *, observation_time: float = 1.0, replicate: int = 1, base_seed: int = 2026, settings: TrajectorySettings | None = None, model_keys: Sequence[str] | str | None = None, hdi_prob: float = 0.95, progress_callback: Any = None) -> TrajectoryValidationResult

Simulate, fit, and assess one trajectory validation dataset.

stable_seed

stable_seed(*parts: Any, namespace: str = 'barracuda') -> int

Derive a reproducible non-zero uint32 seed from structured values.

Unlike Python's built-in hash, this value is stable across processes. Mappings are JSON encoded with sorted keys, so their insertion order does not affect the seed.

trajectory_recovery_table

trajectory_recovery_table(results: Mapping[str, Any], truth: Mapping[str, Any], *, condition: str | None = None, hdi_prob: float = 0.95) -> DataFrame

Build recovery rows for every fitted trajectory decision model.

Error contract

Public validation and table helpers prefer TypeError, ValueError, and RuntimeError with actionable messages. Inference may also propagate PyMC or PyTensor exceptions. See Settings, results, and errors.