pyfli.simulator.calibration.prior_estimation#

Beta priors for the pyfli simulator config.

Functions

fit_beta(values[, offset, scale, inflation])

Method-of-moments Beta fit on (values - offset) / scale, with the variance multiplied by inflation.

infer_bit_depth(peaks_a, data_max)

lifetime_priors(values, is_bi, period, inflation)

photon_prior_continuous(peaks, data_max, bit)

Beta over A / (2**bit - 1).

photon_prior_discrete(counts, n_active_bins, dcr)

Beta over n_cycles in [lo, hi] such that 0.01 * n_cycles * active_fraction matches the observed signal photons.

quick_pixel_fits(fm, decays, irf_norm, ...)

Per-pixel Poisson fits with the IRF and the background fixed, parameterised like the simulator: bi -> (tau2, E, A1, N), mono -> (tau, N).

tau_bounds(tau, period)

(offset, scale) for the simulator's tau2_beta_range, with a 20 % margin.

Classes

BetaPrior(a, b[, offset, scale])

PriorSet(tau2, efficiency, alpha1, photon, ...)

class BetaPrior(a: float, b: float, offset: float = 0.0, scale: float = 1.0)[source]#

Bases: object

Parameters:
a: float#
b: float#
offset: float = 0.0#
scale: float = 1.0#
property mean_norm: float#
property conc: float#
property mean: float#
property sd: float#
classmethod from_mean_conc(m, k, offset=0.0, scale=1.0)[source]#
Parameters:
Return type:

BetaPrior

sample(n, rng)[source]#
Parameters:
Return type:

ndarray

as_tuple()[source]#
Return type:

tuple[float, float]

fit_beta(values, offset=0.0, scale=1.0, inflation=1.0)[source]#

Method-of-moments Beta fit on (values - offset) / scale, with the variance multiplied by inflation. The values are winsorized at their 0.5 / 99.5 percentiles (capped, not dropped), which limits single outliers without the ~3 % variance loss that trimming the tails causes.

Parameters:
Return type:

BetaPrior

class PriorSet(tau2: pyfli.simulator.calibration.prior_estimation.BetaPrior, efficiency: pyfli.simulator.calibration.prior_estimation.BetaPrior | None, alpha1: pyfli.simulator.calibration.prior_estimation.BetaPrior | None, photon: pyfli.simulator.calibration.prior_estimation.BetaPrior, photon_range: tuple[float, float], bit: int, mono_fraction: float, source: str, reference_moments: dict = <factory>)[source]#

Bases: object

Parameters:
tau2: BetaPrior#
efficiency: BetaPrior | None#
alpha1: BetaPrior | None#
photon: BetaPrior#
photon_range: tuple[float, float]#
bit: int#
mono_fraction: float#
source: str#
reference_moments: dict#
summary()[source]#
Return type:

dict

quick_pixel_fits(fm, decays, irf_norm, bg_per_bin, is_bi, init)[source]#

Per-pixel Poisson fits with the IRF and the background fixed, parameterised like the simulator: bi -> (tau2, E, A1, N), mono -> (tau, N). Bi-exponential fits are MAP with a weak Gaussian prior around the pooled fit (BI_FIT_PRIOR_SD). They only initialise the priors; the simulation-based search refines them.

Parameters:
Return type:

dict[str, ndarray]

photon_prior_discrete(counts, n_active_bins, dcr, inflation=1.0, active_fraction=1.0)[source]#

Beta over n_cycles in [lo, hi] such that 0.01 * n_cycles * active_fraction matches the observed signal photons. active_fraction is the expected share of signal photons that land in active time bins (photons in bins outside the acquisition window are lost, in the data and in the windowed simulation).

Parameters:
infer_bit_depth(peaks_a, data_max)[source]#
Parameters:
Return type:

int

photon_prior_continuous(peaks, data_max, bit, qe_on=True, inflation=1.0, scale_corr=1.0)[source]#

Beta over A / (2**bit - 1). The observed peak is A * QE with QE ~ U(0.15, 0.35) independent of A, so E[A] = E[peak] / E[QE] and E[A^2] = E[peak^2] / E[QE^2].

Parameters:
tau_bounds(tau, period)[source]#

(offset, scale) for the simulator’s tau2_beta_range, with a 20 % margin.

Parameters:
Return type:

tuple[float, float]

lifetime_priors(values, is_bi, period, inflation)[source]#
Parameters: