clophfit.fitting.plate_lm#

Fit a whole plate at once, classically, with plate-wide noise scales.

Every classical arm in this campaign fits one well at a time: fit_binding_glob takes a single well’s Dataset, and the control groups are only pooled afterwards, by averaging per-well K estimates. The Bayesian multi-well model does something the classical side cannot answer to - it shares one K across a control group during the fit, and learns a per-label noise scale from the whole plate - so the two have never been compared like for like on the control holdout.

This closes that gap. Residuals from every well are concatenated into one least-squares problem: K is shared within each control group and free elsewhere, S0 and S1 stay per well and label, and the per-label scale is profiled rather than fitted.

Profiling is not an optimisation detail. Multiplying every weight by a constant leaves the argmin of a least-squares objective untouched - only chi-square and the covariance move - so a global noise scale is not identifiable that way at all. For fixed structural parameters the maximum-likelihood scale has a closed form, the root-mean-square of that label’s standardised residuals, so the fit alternates: solve with current scales, update the scales, repeat. That is what lmfit’s scale_covar does with one global factor, generalised to one per label, which is the structure section 1 found to be the right amount.

Classes#

PlateLMResult

Outcome of one plate-wide classical fit.

Functions#

fit_plate_lm(datasets, groups, *[, max_iter, tol])

Fit every well of a plate jointly, profiling one noise scale per label.

Module Contents#

class clophfit.fitting.plate_lm.PlateLMResult#

Outcome of one plate-wide classical fit.

Parameters:
  • k (dict[str, float]) – Fitted K per well. Wells sharing a control group hold the identical value, not an average of separate fits.

  • k_stderr (dict[str, float]) – Standard error on each K, from the Jacobian at the solution, scaled by the profiled noise. Conditional on the profiled scales, so mildly optimistic.

  • ye_mag (dict[str, float]) – Profiled noise multiplier per label, relative to the supplied y_err.

  • n_points (int) – Unmasked observations entering the fit.

  • n_params (int) – Free structural parameters.

  • success (bool) – Whether the final least-squares solve converged.

  • residuals (list[dict[str, Any]]) – One record per unmasked observation, on the library’s canonical columns: well, label, step, yhat, raw_res, sigma and std_res. sigma includes the profiled scale, so std_res has per-label SD ~1 by construction and only its shape - tails, step dependence - carries information; raw_res and yhat are the signal-scale pair the noise-calibration estimators read.

clophfit.fitting.plate_lm.fit_plate_lm(datasets, groups, *, max_iter=6, tol=0.001)#

Fit every well of a plate jointly, profiling one noise scale per label.

Parameters:
  • datasets (Mapping[str, Any]) – Well identifier to Dataset.

  • groups (Mapping[str, Sequence[str]]) – Control group name to member wells; those wells share one K.

  • max_iter (int) – Maximum alternations between solving and rescaling.

  • tol (float) – Stop when every scale moves by less than this, relatively.

Returns:

Fitted K per well, its standard error, and the profiled scales.

Return type:

PlateLMResult