pyfli.simulator.calibration.summary_stats#

Model-free per-pixel summary statistics and distances between simulated and experimental decays.

Functions

_phasor_analyzer(n_bins, harmonic)

CPU PhasorAnalyzer whose period is the full n_bins time axis (1 ns per bin).

_scale(x)

_stat_vectors(stats)

Flatten the statistics into 1D samples: scalar stats plus phasor projections.

background_bins(mean_decay[, guard, min_bins])

Bins before the rising edge of the pooled decay (pure background + previous-pulse tail).

compute_stats(decays, bg_bins)

inactive_bins(pooled[, min_counts_per_bin])

Time bins that never record a count (outside the TCSPC TAC / ADC acquisition window).

phasor(decays[, harmonic])

Raw (IRF-uncalibrated) phasor (G, S) of each decay at harmonic, over the whole time window (one laser period), computed with pyfli's PhasorAnalyzer.

pooled_relative_variance(decays[, weights])

Relative variance, per time bin, of the pooled (summed or weighted-mean) decay of the pixels in decays (n, T): Var(m_k) / m_k^2 for the weighted mean m_k = sum_i w_i d_ik (weights summing to 1, uniform by default), estimated from the pixels as sum_i w_i^2 (d_ik - m_k)^2.

rising_edge(decays[, frac])

Sub-bin position where the (3-bin smoothed) decay first crosses frac of its rise.

Classes

PreparedSim(stats)

Simulated statistics sorted once, so any set of pixel weights is scored in ~1 ms.

StatsComparator(exp_stats[, weights])

Scale-free distance between simulated and experimental statistics, as a weighted sum of:

inactive_bins(pooled, min_counts_per_bin=100.0)[source]#

Time bins that never record a count (outside the TCSPC TAC / ADC acquisition window). Only reported when the pooled decay is bright enough (min_counts_per_bin on average) for an all-zero bin to be a property of the detector rather than chance. The pyfli simulator fills every bin, so these bins are zeroed in the simulated decays.

Parameters:
Return type:

ndarray

background_bins(mean_decay, guard=2, min_bins=4)[source]#

Bins before the rising edge of the pooled decay (pure background + previous-pulse tail). If the edge is too early for that, the lowest bins of the pooled decay are used.

Parameters:
Return type:

ndarray

phasor(decays, harmonic=1)[source]#

Raw (IRF-uncalibrated) phasor (G, S) of each decay at harmonic, over the whole time window (one laser period), computed with pyfli’s PhasorAnalyzer.

Parameters:
Return type:

tuple[ndarray, ndarray]

rising_edge(decays, frac=0.5)[source]#

Sub-bin position where the (3-bin smoothed) decay first crosses frac of its rise.

Parameters:
Return type:

ndarray

compute_stats(decays, bg_bins)[source]#
Parameters:
Return type:

dict[str, ndarray]

pooled_relative_variance(decays, weights=None)[source]#

Relative variance, per time bin, of the pooled (summed or weighted-mean) decay of the pixels in decays (n, T): Var(m_k) / m_k^2 for the weighted mean m_k = sum_i w_i d_ik (weights summing to 1, uniform by default), estimated from the pixels as sum_i w_i^2 (d_ik - m_k)^2. It contains the photon noise and the pixel-to-pixel spread, and is the variance of log m_k to first order. Bins with no counts get 0.

Parameters:
Return type:

ndarray

class PreparedSim(stats)[source]#

Bases: object

Simulated statistics sorted once, so any set of pixel weights is scored in ~1 ms.

Parameters:

stats (dict[str, ndarray])

quantiles(key, weights)[source]#
Parameters:
Return type:

ndarray

class StatsComparator(exp_stats, weights=None)[source]#

Bases: object

Scale-free distance between simulated and experimental statistics, as a weighted sum of:

  • log_counts, edge, bg_frac: Wasserstein-1 / robust spread of the experiment;

  • phasor1, phasor2: sliced Wasserstein over 12 directions / phasor spread;

  • mean_decay: RMS log-ratio of the pooled decay shape over bins above 1 % of the peak (lower bins are noise-dominated; bg_frac covers the baseline), in units of 5 %. The expected sampling noise of both pooled decays (pooled_relative_variance()) is subtracted from the mean squared log-ratio, so two samples of the same distribution score ~0 whatever the number of simulated pixels.

Wasserstein-1 is evaluated as the mean absolute difference of the quantile functions on a fixed grid, which supports importance weights at negligible cost.

Parameters:
distance(sim, mean_decay=None, pixel_weights=None, mean_decay_rel_var=None)[source]#
Parameters:
Return type:

tuple[float, dict[str, float]]