pyfli.data_vnp.model_selector#
Per-pixel mono- vs bi-exponential model selection (nested-model F-test + AICc).
Classes
|
Per-pixel mono- versus bi-exponential model selection using a nested-model F-test (BH-FDR corrected) combined with an AICc criterion. |
- class ModelSelector(b_bool_mask, fdr_q=0.05, daicc_min=4.0, tau_bound=12.5, k_mono=4, k_bi=6)[source]#
Bases:
objectPer-pixel mono- versus bi-exponential model selection using a nested-model F-test (BH-FDR corrected) combined with an AICc criterion.
Pixels are assigned to one of four classes: mono sufficient, bi justified, bi significant but with a parameter at a fit limit, and bi fit worse than mono (optimiser failure). Class
0marks pixels outside the ROI or invalid.- Parameters:
b_bool_mask (
np.ndarray) – ROI mask; only pixels where it is truthy are analysed.fdr_q (
float) – False-discovery rate for the F-test.daicc_min (
float) – Minimum ΔAICc additionally required for a pixel to be classified as bi.tau_bound (
float) – Upper τ fit bound in ns; τ2 near it (or τ1 ≈ 0) flags a parameter at a limit.k_mono (
int) – Number of fitted parameters in the mono-exponential model (A, τ, v, h).k_bi (
int) – Number of fitted parameters in the bi-exponential model (A, α, τ1, τ2, v, h).
- DEFAULT_FITS: ClassVar[dict[str, str]] = {'MLE': 'CPU_MLE_poisson', 'NLSF': 'CPU_NLSF_least_squares'}#
- CLASS_NAMES: ClassVar[list[str]] = ['Mono sufficient', 'Bi justified', 'Bi, parameter at limit', 'Bi fit worse than mono']#
- RC: ClassVar[dict[str, Any]] = {'axes.grid': False, 'axes.labelsize': 7, 'axes.linewidth': 0.6, 'axes.titlesize': 8, 'font.size': 7, 'mathtext.default': 'regular', 'pdf.fonttype': 42, 'svg.fonttype': 'none', 'xtick.labelsize': 6, 'ytick.labelsize': 6}#
- static bh_fdr(p)[source]#
Benjamini–Hochberg adjusted p-values (q-values) for a 1-D array.
- Parameters:
p (
np.ndarray) – Raw p-values.- Returns:
q-values in the original order, clipped to
[0, 1].- Return type:
np.ndarray
- compare(label, maps_mono, maps_bi)[source]#
Run model selection for one pair of mono/bi fit result maps.
- Parameters:
- Returns:
class_map,bi_justified,F_map,p_map,q_map,dAICc_map,dDev_mapandn_points.- Return type:
- compare_from_dir(save_dir, fits=None)[source]#
Load saved mono/bi fit results from
save_dirand runcompare()on each.Files are expected as
{prefix}_mono-exponential.npyand{prefix}_bi-exponential.npy. Fits missing either file are skipped.- Parameters:
save_dir (
str) – Directory containing the saved fit results (e.g.saver.save_dir).fits (
dict[str,str] | None) – Mapping of label to file prefix; defaults toDEFAULT_FITS.
- Returns:
results, keyed by fit label.- Return type:
- summary()[source]#
Per-fit summary of class fractions and test statistics.
- Returns:
One row per compared fit, indexed by fit label.
- Return type:
pd.DataFrame
- agreement()[source]#
Jaccard index of the ‘Bi justified’ masks when exactly two fits were compared.
- Returns:
Jaccard index, or
Noneif the number of compared fits is not two.- Return type:
float | None
- plot(saver=None, name='model_selection_mono_vs_bi')[source]#
Plot one row per fit: ΔAICc map, −log10 q map, class map and class fractions.
- Parameters:
saver (
Any | None) – Optional object with asave_plot(name, fig=..., close=...)method (e.g.pyfli.io.data_saving.DataSaver).name (
str) – File name passed tosaver.save_plot.
- Returns:
The figure, or
Noneif nothing has been compared.- Return type:
matplotlib.figure.Figure | None