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

DetailedRecon(freq_acq, binned_irf[, ...])

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: object

Reconstruct 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, for split_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-exponential params per pixel via MonoBiClassifier and 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 every reconstruct() 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) – MonoBiClassifier thresholds used by split_mono_bi() and collapse_to_mono().

  • alpha_lower (float) – MonoBiClassifier thresholds used by split_mono_bi() and collapse_to_mono().

  • tau_tol (float) – MonoBiClassifier thresholds used by split_mono_bi() and collapse_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.

params takes exactly the same shape as ParamToDecay’s own params argument: a dict keyed by ParamToDecay.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 via ParamToDecay.PARAM_MAP_DEFAULTS (1.0, 0.0, 0.0 respectively); missing required keys raise KeyError.

"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 (see ParamToDecay. 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 – mirroring ParamToDecay. _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 for model_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) – Overrides self.binned_decay for 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 via MonoBiClassifier, 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 as f"{data_name}_mono" and f"{data_name}_bi".

  • n_params (int | None) – Forwarded to reconstruct() for both subsets.

  • display (bool) – Whether MonoBiClassifier renders 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 via MonoBiClassifier – mono-classified pixels get their dominant/coincidence lifetime, bi-classified pixels get the amplitude-weighted mean alpha1*tau1 + (1-alpha1)*tau2 – then run one whole-image mono-exponential reconstruct() 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 to reconstruct().

  • display (bool) – Whether MonoBiClassifier renders 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]