pyfli.reconstruction.detailed_results#
Reconstruct fit curves and goodness-of-fit maps from pre-estimated FLI lifetime parameter maps.
This module belongs to pyfli.reconstruction and sits alongside
pyfli.reconstruction.decay_reconstruction: it drives
ParamToDecay to turn a dictionary of already-known
lifetime maps (e.g. F-BI output, or a posterior-sample parameter combination)
back into a decay cube and its fit-quality maps, packaged in the same
structure as pyfli.solver.FLICPUProcessor’s output so it drops
straight into Plotter / DataViewer. Public API includes class
DetailedRecon.
Classes
|
Reconstruct fit/residual/goodness-of-fit maps from pre-estimated FLI lifetime parameter maps, for a fixed acquisition setup (frequency, IRF, measured decay). |
- class DetailedRecon(freq_acq, binned_irf, binned_decay=None, alpha_upper=0.95, alpha_lower=0.05, tau_tol=0.05, eps=1e-8)[source]#
Bases:
objectReconstruct fit/residual/goodness-of-fit maps from pre-estimated FLI lifetime parameter maps, for a fixed acquisition setup (frequency, IRF, measured decay).
Three operations, all returning the same
{"name", "method", "results": {"maps", "error_maps", "TR_maps"}}shape (or, forsplit_mono_bi(), that shape twice):reconstruct()– direct reconstruction for either model_type, no classification involved. This is the general-purpose operation; the other two are bi-exponential-only.split_mono_bi()– classifies bi-exponentialparamsper pixel viaMonoBiClassifierand returns two separate results: the mono-classified pixel subset reconstructed as mono-exponential (using each such pixel’s dominant/coincidence lifetime), and the bi-classified subset (the rest) reconstructed with the full bi-exponential model. Each result is NaN’d outside its own subset.collapse_to_mono()– collapses every pixel (mono- and bi-classified alike) to a single effective lifetime and returns one whole-image mono-exponential reconstruction.
- Parameters:
freq_acq (
float) – Acquisition frequency freq[1] (MHz).binned_irf (
np.ndarray) – IRF, shape (bins,) or (H, W, bins). A 1-D IRF is broadcast across all pixels; normalized to sum to 1 per pixel before convolving.binned_decay (
np.ndarray | None) – Measured decay histogram per pixel, shape (H, W, bins), shared by everyreconstruct()call unless overridden per-call. When omitted (here or per-call), decay-dependent outputs (photon count, residuals, chi², R²) reduce to zero.alpha_upper (
float) –MonoBiClassifierthresholds used bysplit_mono_bi()andcollapse_to_mono().alpha_lower (
float) –MonoBiClassifierthresholds used bysplit_mono_bi()andcollapse_to_mono().tau_tol (
float) –MonoBiClassifierthresholds used bysplit_mono_bi()andcollapse_to_mono().eps (
float) – Numerical floor for clip / safe division.
- reconstruct(params, model_type, data_name='F-BI', n_params=None, binned_decay=None, log_summary=True)[source]#
Reconstruct fit curves + goodness-of-fit maps from pre-estimated lifetime parameter maps (e.g. F-BI output), packaged in the same structure as FLICPUProcessor.process_image so it drops straight into Plotter / DataViewer.
paramstakes exactly the same shape asParamToDecay’s ownparamsargument: a dict keyed byParamToDecay.PARAM_MAP_KEYS[model_type]–{"tau_map"}(plus optional"photon_count_map","v_shift_map","h_shift_map") for"mono-exponential", or{"alpha1_map", "tau1_map", "tau2_map"}(plus the same three optional keys) for"bi-exponential". Missing optional keys default viaParamToDecay.PARAM_MAP_DEFAULTS(1.0, 0.0, 0.0 respectively); missing required keys raiseKeyError."photon_count_map"is accepted for schema parity but never changes the result: the model is always rescaled to match the measured decay’s total (seeParamToDecay. rescale_fit_to_measured_totals()), which first normalizes the model to a PDF – so any literal amplitude supplied here cancels out exactly."h_shift_map"is honored directly (it shifts the kernel’s time axis before convolution, same as every other reconstruction path)."v_shift_map"is honored as an additive per-bin baseline: it’s subtracted from the measured decay before total-matching the peak shape (so the shape-only rescale isn’t skewed by the baseline), then added back – mirroringParamToDecay. _build_fit_map_vectorized()’s “add v_shift after convolution” convention, adapted for this method’s rescale-to-total amplitude handling. Both default to 0.0, so omitting them reproduces the baseline-free result exactly.- Parameters:
params (
dict[str,np.ndarray]) – Parameter maps formodel_type, each (H, W). See above for the required/optional keys per model_type.model_type (
str) –"mono-exponential"or"bi-exponential".data_name (
str) – Dataset name recorded in the returned result dict.n_params (
int | None) – Free-parameter count for the reduced-chi2 dof. Defaults to model_type’s full parameter count – 6 (photon_count, alpha1, tau1, tau2, v_shift, h_shift) for “bi-exponential”, 4 (photon_count, tau, v_shift, h_shift) for “mono-exponential” – matching the dof convention BaseFLIFitter/MLEFitter/ FLIGPUProcessor and ParamToDecay (PARAM_MAP_KEYS) use for the same model family.binned_decay (
np.ndarray | None) – Overridesself.binned_decayfor this call only, e.g. to score against a different decay cube than the one this instance was built with. When both are None, decay-dependent outputs reduce to zero.log_summary (bool)
- Returns:
{'name', 'results': {'maps', 'error_maps', 'TR_maps'}}- Return type:
dict[Any,Any]
- split_mono_bi(params, bool_mask, data_name='F-BI', n_params=None, display=True)[source]#
Classify bi-exponential
params({"tau1_map", "tau2_map", "alpha1_map"}) per pixel viaMonoBiClassifier, and reconstruct each subset with the model that actually applies to it: mono-classified pixels get a mono-exponential reconstruction (using each pixel’s dominant/coincidence lifetime), and the remaining (bi-classified) pixels get the full bi-exponential reconstruction. Each returned result is NaN’d outside its own pixel subset (see_apply_bool_mask()), so the two results can be recombined or inspected independently without the other subset’s placeholder values being mistaken for real fits.- Parameters:
params (
dict[str,np.ndarray]) –{"tau1_map", "tau2_map", "alpha1_map"}, each (H, W).bool_mask (
np.ndarray) – (H, W) boolean mask selecting which pixels to classify/reconstruct at all (e.g.photon_count > 0, or a real ROI mask).data_name (
str) – Base dataset name; the two results are recorded asf"{data_name}_mono"andf"{data_name}_bi".n_params (
int | None) – Forwarded toreconstruct()for both subsets.display (
bool) – WhetherMonoBiClassifierrenders its mono/bi classification maps via DataViewer as a side effect.
- Returns:
{"mono": <reconstruct() result>, "bi": <reconstruct() result>, "mono_mask": (H, W) bool, "bi_mask": (H, W) bool}.- Return type:
dict[str,Any]
- collapse_to_mono(params, bool_mask, data_name='F-BI', n_params=None, display=True)[source]#
Collapse bi-exponential
params({"tau1_map", "tau2_map", "alpha1_map"}) to a single per-pixel effective lifetime viaMonoBiClassifier– mono-classified pixels get their dominant/coincidence lifetime, bi-classified pixels get the amplitude-weighted meanalpha1*tau1 + (1-alpha1)*tau2– then run one whole-image mono-exponentialreconstruct()on the result.- Parameters:
params (
dict[str,np.ndarray]) –{"tau1_map", "tau2_map", "alpha1_map"}, each (H, W).bool_mask (
np.ndarray) – (H, W) boolean mask selecting which pixels to classify/collapse. Pixels outside it are NaN’d in the returned result (see_apply_bool_mask()).data_name (
str) – Dataset name recorded in the returned result dict.n_params (
int | None) – Forwarded toreconstruct().display (
bool) – WhetherMonoBiClassifierrenders its mono/bi classification maps via DataViewer as a side effect.
- Returns:
reconstruct()’s return shape, for the whole-image collapsed mono-exponential reconstruction.- Return type:
dict[Any,Any]