pyfli.simulator.calibration.irf_estimation#

IRF template and shift range for the simulator, from a measured IRF or the data.

Functions

_estimate(fm, pooled, mask, irf)

_fit_pooled(fm, pooled, irf_from_theta, ...)

Fit the pooled decay with: IRF(theta) + baseline b, two lifetimes, photon fraction f, and a background fraction beta.

_fourier_shift(y, shift)

Sub-bin circular delay of y by shift bins (pyfli's fourier_shift), negative ringing clipped.

_peak_position(irf)

Sub-bin peak position (centroid of the 5 bins around the maximum) per trace.

apply_irf_theta(est, fm, theta)

Return a copy of est with the optimiser's IRF parameters applied.

estimate_irf(fm, decay, mask[, irf, mode])

mode: "experimental" uses the given IRF, "simulated" fits an EMG IRF, "auto" does both when an IRF is given and keeps the one whose pooled fit has the lower deviance.

experimental_template(irf, mask)

Peak-normalised IRF template and the half-width (bins) of the per-pixel IRF shift range.

irf_theta_from_estimate(est)

irf_theta_names(source)

split_background(est, fm, bg_bins, slope, ...)

Split the pre-edge background of a circular (TCSPC) model into dark counts and the OffsetGen IRF baseline b, using the per-pixel regression pre-edge level = intercept + slope * counts.

Classes

IRFEstimate(source, template, a_center, ...)

class IRFEstimate(source: str, template: ndarray, a_center: float, a_half: float, b_max: float, params: dict = <factory>, pooled_fit: dict = <factory>, library: ndarray | None = None, library_b_max: ndarray | None = None)[source]#

Bases: object

Parameters:
source: str#
template: ndarray#
a_center: float#
a_half: float#
b_max: float#
params: dict#
pooled_fit: dict#
library: ndarray | None = None#
library_b_max: ndarray | None = None#
b_ranges()[source]#
Return type:

list[tuple[float, float]] | None

property a_range: tuple[float, float]#
property b_range: tuple[float, float]#
irf_cube()[source]#

(1, 1, T) cube in the layout SimGenerator / OffsetGen expect (pixel=(0, 0)), or (1, K, T) for an IRF library (see sim_bridge.MultiIRFSimGenerator).

Return type:

ndarray

effective_irf()[source]#

Peak-normalised IRF at the centre of the shift range (what a typical pixel sees).

Return type:

ndarray

experimental_template(irf, mask)[source]#

Peak-normalised IRF template and the half-width (bins) of the per-pixel IRF shift range.

Parameters:
Return type:

tuple[ndarray, float]

estimate_irf(fm, decay, mask, irf=None, mode='auto')[source]#

mode: “experimental” uses the given IRF, “simulated” fits an EMG IRF, “auto” does both when an IRF is given and keeps the one whose pooled fit has the lower deviance. A measured IRF can be the wrong one for the data (other day, wavelength, detector setting); “auto” catches that.

Parameters:
Return type:

IRFEstimate

split_background(est, fm, bg_bins, slope, intercept)[source]#

Split the pre-edge background of a circular (TCSPC) model into dark counts and the OffsetGen IRF baseline b, using the per-pixel regression pre-edge level = intercept + slope * counts.

A baseline b on the peak-normalised IRF adds b / (sum(IRF) + b T) to every bin per signal photon, the same flat floor as dark counts in a pooled decay, so the pooled fit cannot separate them. Per pixel they differ: dark counts give a constant level (the intercept), the baseline a level proportional to the signal (the slope left over after the previous-pulse tail of the pooled-fit lifetimes). Sets est.b_max (b ~ U(0, b_max), so b_max = 2 b) and pooled_fit["irf_baseline_b"]; returns the dark-count rate per bin per pixel (the pooled background when the intercept is not positive). The counts include the dark counts themselves, so intercept = dcr (1 - slope n_active).

Parameters:
Return type:

float

irf_theta_names(source)[source]#
Parameters:

source (str)

Return type:

list[str]

irf_theta_from_estimate(est)[source]#
Parameters:

est (IRFEstimate)

Return type:

ndarray

apply_irf_theta(est, fm, theta)[source]#

Return a copy of est with the optimiser’s IRF parameters applied.

Parameters:
Return type:

IRFEstimate