clophfit.prtecan.titration#
Prtecan/prtecan.py.
Classes#
Parameters defining the fitting data with callback support. |
|
Store (robust) linear fit result. |
|
Buffer handling for a titration. |
|
Manage titration results with optional lazy computation. |
|
Build titrations from grouped Tecanfiles and concentrations or pH values. |
|
Group tecan cli options. |
|
A per-well MCMC request, decided by the caller rather than parsed downstream. |
Module Contents#
- class clophfit.prtecan.titration.TitrationConfig#
Parameters defining the fitting data with callback support.
- noise_alpha: tuple[float, ...] = ()#
Proportional noise coefficients per label.
When provided, adds a proportional term to the error estimate so that high-signal wells are appropriately down-weighted: y_err^2 = gain * signal + bg_err^2 + (alpha * signal)^2
Values typically from MCMC multi-noise shared_noise_params.csv. Empty tuple disables the correction (legacy behaviour).
- noise_gain: tuple[float, ...] = ()#
Poisson gain coefficients per label.
Replaces the hardcoded gain=1 in the shot-noise Poisson term: y_err^2 = gain * signal + bg_err^2 + (alpha * signal)^2
Values typically from MCMC multi-noise shared_noise_params.csv. Empty tuple keeps gain=1 (legacy behaviour).
- mask_outliers: bool = False#
Mask geometric outliers in each well’s curve before fitting. Default is False.
- outlier_threshold: float = 0.2#
Threshold for geometric outlier scoring (0-1). Default is 0.2.
- set_callback(callback)#
Set the callback to be triggered on parameter change.
- Parameters:
callback (collections.abc.Callable[[], None])
- Return type:
None
- class clophfit.prtecan.titration.BufferFit#
Store (robust) linear fit result.
- property empty: bool#
True when all attributes are NaN, emulating DataFrame’s empty behavior.
- Return type:
bool
- class clophfit.prtecan.titration.Buffer#
Buffer handling for a titration.
Manages background correction and fitting for buffer wells.
- property dataframes: dict[str, pandas.DataFrame]#
Buffer dataframes with fit.
- Return type:
dict[str, pandas.DataFrame]
- property dataframes_nrm: dict[str, pandas.DataFrame]#
Buffer normalized dataframes with fit.
- Return type:
dict[str, pandas.DataFrame]
- property wells: list[str]#
List of buffer wells.
- Return type:
list[str]
- property bg: dict[str, clophfit.clophfit_types.ArrayF]#
List of buffer values.
- Return type:
dict[str, clophfit.clophfit_types.ArrayF]
- property bg_err: dict[str, clophfit.clophfit_types.ArrayF]#
List of buffer SEM values.
- Return type:
dict[str, clophfit.clophfit_types.ArrayF]
- property bg_noise: dict[str, float]#
Intrinsic well noise (RMSE/pooled SD) values.
- Return type:
dict[str, float]
- plot(*, nrm=False, title=None)#
Plot buffers of all labelblocksgroups.
- Parameters:
nrm (bool)
title (str | None)
- Return type:
seaborn.FacetGrid
- class clophfit.prtecan.titration.TitrationResults#
Bases:
clophfit.fitting.data_structures.ResidualsMixinManage titration results with optional lazy computation.
Provide either the small
scheme+fit_keysdirectly, or atitrationkeyword to snapshot both from aTitration:TitrationResults(scheme=tit.scheme, fit_keys=tit.fit_keys, results=res) TitrationResults(results=res, titration=tit) # equivalent, more concise
titrationis anInitVar: onlyschemeandfit_keysare copied off it, so the (potentially large) raw plate data is never retained.noise_modelcarries the calibrated per-label noise model when the fit produced one (fgls_fit_plate); it isNonefor plainfit_plate.- residual_table(*, binding_function=None, robust=None, student_t_nu=None, outlier_threshold=3.0)#
Compute the canonical plate-wide residual table.
Delegates to each well’s own
FitResult.residual_table(), so robustness is auto-detected per well from that well’s ownmini(its lmfitMinimizer, ODR output, or PyMC trace). A plate fitted withmethod="mcmc"therefore standardizes each well against its own trace, instead of being forced to Normal standardization.- Parameters:
binding_function (Callable[..., object] | None) – Model evaluated for
yhat; defaults tobinding_1site. Forwarded unchanged to each well.robust (bool | None) – Force the Student-t standardization of
std_res.Noneauto-detects per well from that well’s trace.student_t_nu (float | None) – Student-t degrees of freedom (
Noneuses detected/default).outlier_threshold (float) – Threshold for the
is_residual_outlierflag.
- Returns:
The canonical residual table (see
residuals), built by concatenating each well’s own table. Wells whose fit failed carry no dataset or result and are skipped, so the table may cover fewer wells thanfit_keys.- Return type:
pd.DataFrame
- property dataframe: pandas.DataFrame#
Convert FitResult dictionary to a DataFrame.
- Return type:
pandas.DataFrame
- compute_all()#
Compute results for all keys.
- Return type:
None
- n_sd(par='K', expected_sd=0.15)#
Compute median of K.
- Parameters:
par (str)
expected_sd (float)
- Return type:
float
- static all_computed()#
Check if all keys have been computed.
- Return type:
bool
- export_pngs(folder)#
Export all fit result plots as PNG files.
- Parameters:
folder (str | pathlib.Path)
- Return type:
None
- export_data(folder)#
Export all datasets as CSV files.
- Parameters:
folder (str | pathlib.Path)
- Return type:
None
- plot_k(xlim=None, title='')#
Plot K values as stripplot.
Wells fitted on fewer labels than the rest are marked with a trailing
*, and the title says how many there are. Their K rests on 3 parameters over 7 points rather than 6 over 14 and loses the ratiometric cancellation, so it is systematically less certain than its neighbours - which a bare stripplot would otherwise hide.- Parameters:
xlim (tuple[float, float] | None, optional) – Range.
title (str, optional) – To name the plot.
- Returns:
The figure.
- Return type:
figure.Figure
- class clophfit.prtecan.titration.Titration#
Bases:
clophfit.prtecan.models.TecanfilesGroupBuild titrations from grouped Tecanfiles and concentrations or pH values.
- Parameters:
tecanfiles (list[Tecanfile]) – List of Tecanfiles.
x (ArrayF) – Concentration or pH values.
is_ph
x_err
- Raises:
ValueError – For unexpected file format, e.g. header names.
- is_ph: bool = False#
Indicate if x values represent pH.
- x_err: clophfit.clophfit_types.ArrayF#
Uncertainties for x values (default is empty array).
- property fit_keys: set[str]#
Set of wells to be fitted.
- Return type:
set[str]
- detect_and_discard_bad_wells(*, outlier_threshold=0.2, bg_multiplier=3.0, max_k_stderr=None)#
Detect and discard bad wells from masked per-label signal quality.
By default, each well is converted to a per-label dataset with
_create_ds(), masked withapply_outlier_mask(), and then discarded when the mean masked signal of any label falls below a background-derived floor. The floor usesbg_errwhen available and falls back tobg_noise.A signal test alone cannot catch a well that is bright but uninformative. On L2, C05 has ample signal and a meaningless titration - K = 7.138 +- 254 pH - and survives every
bg_multiplierfrom 2.0 to 4.0, all of which discard the same single well. So a fit-quality test runs alongside it: fit the well and ask how well K is pinned.The smoothness, roughness and trendline criteria that used to sit here were removed. They were disabled by default, no caller ever passed them, and at plausible thresholds (0.5/0.5/3.0) they discarded 90 of 90 wells on L2 - not a criterion, a bug in waiting.
- Parameters:
outlier_threshold (float | None) – Threshold passed to
apply_outlier_mask()before computing per-label summary statistics. IfNone, no masking is applied.bg_multiplier (float | None) – Discard a well when any masked per-label mean signal is below
bg_multiplier * mean(background_floor). IfNone, this check is disabled.max_k_stderr (float | None) – Discard a well whose fitted K has a standard error above this, or a non-finite one.
Noneuses the titration’s own x span, which is the scale-free form of the rule: a well whose midpoint cannot be located inside the window actually titrated carries no information about K, however bright it is. Passmath.infto disable.
- Returns:
Newly discarded well keys.
- Return type:
list[str]
- clear_all_data_results()#
Clear fit keys, data, results and bg when buffer or scheme properties change.
- Return type:
None
- property params: TitrationConfig#
The datafit parameters.
- Return type:
- property bg: dict[str, clophfit.clophfit_types.ArrayF]#
List of buffer values.
- Return type:
dict[str, clophfit.clophfit_types.ArrayF]
- property bg_err: dict[str, clophfit.clophfit_types.ArrayF]#
List of buffer SEM values.
- Return type:
dict[str, clophfit.clophfit_types.ArrayF]
- property bg_noise: dict[str, float]#
Intrinsic well noise (RMSE/pooled SD) values.
- Return type:
dict[str, float]
- classmethod fromlistfile(list_file, *, is_ph, base_dir=None)#
Build Titration from a list[.pH|.Cl] file.
- Parameters:
list_file (Path | str) – Path to the list file containing [filenames x x_err].
is_ph (bool) – Whether x values represent pH (True) or concentrations (False).
base_dir (Path | str | None) – Directory holding the Tecan files. Relative filenames in the list file are resolved against it; defaults to the list file’s own directory. Use it when list files and .xls files are kept in separate trees (e.g. data/processed/ and data/raw/).
- Returns:
The constructed Titration object.
- Return type:
- property additions: list[float] | None#
List of initial volume followed by additions.
- Return type:
list[float] | None
- load_additions(additions_file)#
Load additions from file.
Reads a CSV file with a single column ‘add’ containing addition volumes, and updates the Titration’s additions property.
- Parameters:
additions_file (Path) – Path to the additions CSV file.
- Return type:
None
- property data: dict[str, dict[str, clophfit.clophfit_types.ArrayF]]#
Buffer subtracted and corrected for dilution data.
- Return type:
dict[str, dict[str, clophfit.clophfit_types.ArrayF]]
- property scheme: clophfit.prtecan.models.PlateScheme#
Scheme for known samples like {‘buffer’, [‘H12’, ‘H01’], ‘ctrl’…}.
- Return type:
- load_scheme(schemefile)#
Load scheme from file and set buffer wells.
Reads a scheme file to define buffer wells, known samples, and control wells, then updates the Titration’s scheme and buffer wells.
- Parameters:
schemefile (Path) – Path to the scheme CSV file.
- Return type:
None
- create_ds(key, label)#
Create a dataset for the given key.
- Parameters:
key (str)
label (str)
- Return type:
- property excluded_labels: dict[str, set[str]]#
Labels dropped per well, keyed by well.
- Returns:
Well to the set of its excluded labels. Wells with every label excluded are discarded outright instead of appearing here.
- Return type:
dict[str, set[str]]
- exclude_label(key, label)#
Drop one label of one well from the global fit.
The 400 nm channel is dim by construction, so a well can fail a background test on one label while the other is perfectly usable. Discarding the well would throw away a good titration; dropping the label keeps it, at the cost of a less certain K - which is why the results table records how many labels each well was fitted on.
- Parameters:
key (str) – Well identifier.
label (str) – Label to drop for that well. Dropping every label discards the well.
- Return type:
None
- create_global_ds(key)#
Create a global dataset for the given key.
- Parameters:
key (str)
- Return type:
- create_dataset_dict(label=None)#
Create a dictionary of datasets for all fit_keys, optionally masking outliers.
- Parameters:
label (str | None, optional) – Specific label to extract. If None, creates global datasets containing all labels. Default is None.
- Returns:
A dictionary mapping well keys to their corresponding Datasets.
- Return type:
dict[str, Dataset]
- fit_plate(datasets=None, method='', *, label=None, **kwargs)#
Run a single-pass fit on an entire plate of datasets.
- Parameters:
datasets (dict[str, Dataset] | None) – Mapping of well keys (e.g. ‘A01’) to Dataset objects. When
None, datasets are built withcreate_dataset_dict(), which also applies outlier masking whenparams.mask_outliersis set.method (str) – The fitting method: ‘lm’ (default), ‘huber’, ‘odr’, or ‘mcmc’. Other methods supported by
clophfit.fitting.core.fit_binding_glob()may also be used.label (str | None) – Build per-label datasets for this label instead of global ones. Only valid when datasets is
None.**kwargs (Any) – Additional keyword arguments passed to the fitting function.
- Returns:
Plate results carrying this titration’s
schemeandfit_keys.- Return type:
- Raises:
ValueError – If both datasets and label are given.
- fgls_fit_plate(datasets=None, *, label=None, sigma_floor=None, first_pass_method='huber', second_pass_method='lm', max_iter=3, tol=0.001)#
Run iterative Feasible Generalized Least Squares (FGLS) on the plate.
Fits every well with first_pass_method using the existing
y_errc, calibrates a per-label noise model from the plate-wide residuals with the floor anchored to sigma_floor, re-applies the calibrated weights and re-fits with second_pass_method, iterating until gain and alpha converge or max_iter is reached.- Parameters:
datasets (dict[str, Dataset] | None) – Mapping of well keys to Dataset objects. When
None, datasets are built withcreate_dataset_dict().label (str | None) – Build per-label datasets for this label instead of global ones. Only valid when datasets is
None.sigma_floor (dict[str, float] | None) – Known read-noise floor per label. Defaults to
bg_noise.first_pass_method (str) – Method for the first-pass fit.
second_pass_method (str) – Method for subsequent passes.
max_iter (int) – Maximum FGLS iterations.
tol (float) – Relative tolerance for gain/alpha convergence.
- Returns:
Plate results carrying this titration’s
schemeandfit_keys, withnoise_modelset to the converged (or last) calibration.- Return type:
- Raises:
ValueError – If both datasets and label are given.
- plot_temperature(title='')#
Plot temperatures of all labelblocksgroups.
Creates a line plot showing measured temperatures versus concentration/pH values, with statistics overlays.
- Parameters:
title (str, optional) – Additional title text to append to the plot.
- Returns:
The matplotlib Figure object containing the plot.
- Return type:
figure.Figure
- class clophfit.prtecan.titration.TecanConfig#
Group tecan cli options.
- detect_bad: bool = True#
Run bad-well detection before fitting (pre-fit) and after (post-fit).
- class clophfit.prtecan.titration.McmcSpec#
A per-well MCMC request, decided by the caller rather than parsed downstream.
- Parameters:
model (Literal["single", "single-refit", "multi"]) – Which fit to run.
"single"samples each well once;"single-refit"runs the robust screening pass then refits;"multi"fits every well jointly with control K shared across each control group.sampler (SamplerConfig) – NUTS controls forwarded to
pm.sample.structured_noise (bool) – Build the physical
floor + gain * y + (alpha * y) ** 2observation noise instead of scalingy_errby a learnedye_magmultiplier.noise_mode (Literal["centered", "fixed"]) – How a supplied gain/alpha hint is treated when structured_noise is set: centred on (a hint the posterior may leave) or pinned to it. A parameter with no supplied value is always free.
per_well_ye_mags (bool | None) – Whether the ye_mag multiplier is per well rather than per label.
Noneleaves the library to resolve it from the noise family, which couples the two; pass a bool to keep them independent. Only meaningful formodel="multi", since a single-well fit has one well.ye_mag_parameterization (Literal["centered", "hierarchical", "separable", "separable_step"]) – How per-well ye_mags are structured: independent per label (
"centered"), a shared well factor with per-label deviations ("hierarchical"), or a per-label level plus one shared well factor ("separable").robust (RobustConfig) – Likelihood family. The default is a plain Normal; a Student-t with
nu=3is the arm that scored best on this campaign’s plates.ctr_free_k (bool) – Give every well its own K instead of pooling each control group onto a shared one. Only meaningful for
model="multi". Pooling buys no accuracy at the construct level and makes the stated interval too narrow, and the library wells have no group to pool with, so free K is the setting that matches what a plate is fitted for.