ClopHfit
This package provides a command line interface for fitting pH titration or binding assay data for macromolecules, such as fluorescence spectra. With this tool, users can easily analyze their data and obtain accurate fitting results.
Features
- Plate Reader Data Parser: Support for Tecan and EnSpire (PerkinElmer) file formats
- Non-linear Least Square Fitting: Advanced fitting algorithms with uncertainty estimation
- pH and Chloride Titration Analysis: Specialized tools for GFP library analysis
- Multi-wavelength analysis (e.g., 400, 485 nm) with separate and global fitting options
- Bootstrap uncertainty estimation
- Automatic buffer subtraction for each titration point
- Control variant reporting (S202N, E2, V224Q)
- Dilution correction for titration additions
- Robust error handling with automatic plot and data export
Fitting Methods
ClopHfit provides multiple fitting algorithms validated on 364+ real experimental wells:
- ODR-Recursive: Orthogonal Distance Regression (best error bar precision) ✅ Recommended. ODR is provided by
odrpack. - outlier2: Two-stage outlier detection (good precision, fast)
- IRLS: Iteratively Reweighted Least Squares
- Recursive: Iterative reweighting
- Bayesian (PyMC): MCMC for rigorous uncertainty quantification
- Standard LM and Robust Huber also available
See: FITTING_METHODS_SUMMARY.md for guidance on method selection.
Full analysis: FITTING_METHODS_COMPARISON.md
Installation
From PyPI
Using pip:
pip install clophfit
Recommended: Using pipx
For isolated installation (recommended):
pipx install clophfit
Shell Completion
Enable shell completion for the clop command:
Bash
_CLOP_COMPLETE=bash_source clop > ~/.local/bin/clop-complete.bash
source ~/.local/bin/clop-complete.bash
# Add to your ~/.bashrc to make it permanent:
echo 'source ~/.local/bin/clop-complete.bash' >> ~/.bashrc
Fish
_CLOP_COMPLETE=fish_source clop | source
# Add to fish config to make it permanent:
_CLOP_COMPLETE=fish_source clop > ~/.config/fish/completions/clop.fish
Usage
Docs: https://clophfit.readthedocs.io/
CLI
ClopHfit provides several command line interface tools for fitting and processing data.
prtecan - Tecan File Analysis
Extract and fit titrations from Tecan files collected at various pH or chloride concentrations:
# pH titration analysis
ppr -o output_folder --is-ph tecan list.pH --scheme scheme.txt --norm \
--dil additions.pH --Klim 6.8,8.4
# Chloride titration analysis
ppr -o output_folder tecan list.Cl --scheme scheme.txt --norm \
--dil additions.Cl --Klim 1.0,50.0
Note: Use --no-weight option to reproduce older pr.tecan behavior.
eq1 - Dissociation Constant Prediction
Predict chloride dissociation constant K_d at a given pH:
clop eq1 --help
clop eq1 12 8.2 7.3
prenspire - EnSpire File Parser
Process EnSpire (PerkinElmer) files:
# Basic parsing
ppr -o output_folder enspire data.csv
# With annotation file for titration analysis
ppr -o output_folder enspire data.csv note.csv
Destination folder (default: "./Meas-${version}") will contain for each Measurement:
- a table (csv) in wide tabular form e.g. <lambda, A01, ..., H12>;
- corresponding graphical (png) representation of spectra from all wells.
By adding a note.csv file:
ppr -o folder enspire file.csv note.csv
destination folder (default: "./Meas-${version}") will also contain:
- a pdf for each titration and label;
- a pdf for global (multiband) analysis pdfalong with global and all_SVD;
- a pdf for SVD analysis of all concatenated spectra.
note_to_csv - Note File Converter
Convert and combine note files for different experimental conditions:
# Convert notes for different temperatures
note_to_csv -t 37.0 -l "B E F" -o temp_37 NTT-G03-Cl_note
note_to_csv -t 20.0 -l "A C D" -o temp_20 NTT-G03-Cl_note
# Combine temperature conditions
cat temp_20 temp_37 > G03_Cl_note.csv
Python
ClopHfit can be imported and used as a Python package. The following modules are available:
clophfit.prenspire - parser for EnSpire (PerkinElmer) files
clophfit.prtecan - perform fitting of pH titration or binding assay data
clophfit.binding - perform fitting of macromolecule binding assay data
To use clophfit in your python:
from clophfit import prenspire, prtecan, binding
Model Validation & Diagnostics (v0.7+)
New reusable modules for comparing fitting methods and validating Bayesian models:
from clophfit.fitting.model_validation import (
residuals_from_multifit, # MultiFitResult → long DataFrame
residuals_from_fit_results, # dict[str, FitResult] → long DataFrame
model_residual_score_table, # all metrics in one call
residual_distribution_summary, # per-label σ, MAD, tail fractions
residual_x_trend_summary, # residual trend vs titration step
residual_lag1_autocorrelation, # per-well lag-1 correlation
residual_cross_label_correlation, # cross-label residual structure
x_axis_sanity, # check x_per_well invariants
trace_diagnostics, # ESS, R̂, divergences, optional LOO
)
from clophfit.fitting.ctr_validation import (
make_ctr_holdout_scheme, # remove one CTR well from scheme
iter_ctr_holdouts, # iterate all possible CTR holdouts
summarize_bayesian_ctr_holdout, # ΔK = K_heldout − K_ctr_group
classical_ctr_holdout_rows, # post-hoc CTR-LOO for classical fits
)
from clophfit.fitting.diagnostic_plots import (
plot_residual_overview, # 4-panel matplotlib (no seaborn)
)
Example — Bayesian fit diagnostics:
from clophfit.fitting.model_validation import (
residuals_from_multifit, trace_diagnostics, x_axis_sanity,
)
from clophfit.fitting.models import binding_1site
multi = fit_binding_pymc_multi(results, scheme, ...)
diag = trace_diagnostics(multi.trace, compute_loo=False)
x_check = x_axis_sanity(multi.trace)
assert x_check.get("x_step0_max_abs_spread", 1.0) < 1e-6
residuals = residuals_from_multifit(
multi, trace_id="my_model", binding_function=binding_1site,
)
# columns: trace_id, well, label, step, x, y, yhat, sigma, raw_res, std_res
Example — CTR holdout validation:
from clophfit.fitting.ctr_validation import (
make_ctr_holdout_scheme, summarize_bayesian_ctr_holdout,
)
heldout = make_ctr_holdout_scheme(scheme, group_name="E2GFP", heldout_well="B12")
multi_loo = fit_binding_pymc_multi(results, heldout, ...)
summary = summarize_bayesian_ctr_holdout(
multi_loo.trace, trace_id="loo_E2GFP_B12",
ctr_group="E2GFP", heldout_well="B12", rope=0.10,
)
# summary["delta_k_hdi94_contains_zero"] → True if K_heldout ≈ K_group
Development
Requires Python uv.
With uv:
# one-time
pre-commit install
# dev tools and deps
uv sync --group dev
# lint/test
uv run ruff check . (or: make lint)
uv run pytest -q (or: make test)
Dependency updates (Renovate)
We use Renovate to keep dependencies current.
Enable Renovate:
- Install the GitHub App: https://github.com/apps/renovate (Settings → Integrations → GitHub Apps → Configure → select this repo/org).
- This repo includes a
renovate.jsonpolicy. Renovate will open a “Dependency Dashboard” issue and PRs accordingly.
Notes:
- Commit style:
build(deps): bump <dep> from <old> to <new> - Pre-commit hooks are grouped and labeled; Python version bumps in
pyproject.tomlare disabled by policy.
Migrating from Dependabot:
- You may keep “Dependabot alerts” ON for vulnerability visibility, but disable Dependabot security PRs.
Template updates (Cruft)
This project is linked to its Cookiecutter template with Cruft.
- Check for updates:
cruft check - Apply updates:
cruft update -y(resolve conflicts, then commit)
CI runs a weekly job to open a PR when template updates are available.
First-time setup if you didn’t generate with Cruft:
pipx install cruft # or: pip install --user cruft
cruft link --checkout main https://github.com/darosio/cookiecutter-python.git
Notes:
- The CI workflow skips if
.cruft.jsonis absent. - If you maintain a stable template branch (e.g.,
v1), link with--checkout v1. You can also update within that line usingcruft update -y --checkout v1.
Enabling the CI push (GitHub App, one-time per repo)
The cruft-update workflow needs write access to push its update branch and
open a PR, and github.token alone cannot push changes under
.github/workflows/*. Rather than a personal access token (which expires and
must be rotated), this template uses a GitHub App installation token via
actions/create-github-app-token.
The workflow falls back to github.token automatically if the App isn't
configured, but that fallback fails whenever Cruft touches workflow files.
One-time setup (shared across all your repos once the App exists):
-
Create the App (skip if you already have one for this purpose): github.com/settings/apps/new — Repository permissions:
Contents: Read & write,Pull requests: Read & write,Workflows: Read & write. Webhook: inactive. -
Generate a private key on the App's settings page and download the
.pem. -
Install the App on this repository (or "All repositories" on your account to cover future repos too).
-
Set two repo-level secrets (GitHub Apps on personal accounts don't support org-wide shared secrets, so this step is repeated per repo):
gh secret set APP_ID --repo <owner>/<repo> --body "<app-id>" gh secret set APP_PRIVATE_KEY --repo <owner>/<repo> < /path/to/key.pem
License
We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.
All code is licensed under the terms of the revised BSD license.
Contributing
If you are interested in contributing to the project, please read our contributing and development environment guides, which outline the guidelines and conventions that we follow for contributing code, documentation, and other resources.
Metadata
Release files for clophfit 0.15.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| clophfit-0.15.3.tar.gz | 2.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| clophfit-0.15.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.2 MB
Release files / clophfit-0.15.3.tar.gz
| Download URL | clophfit-0.15.3.tar.gz |
|---|---|
| Size | 2.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7291f3c030f59d8fde4bff8e93d61636a915ceeaad98416e1b35e07f0157155f
|
|
BLAKE2b-256 checksum How to use checksums |
04b5b56e3a12e58e61aaea065cd05336b1f1637fb9d0464e80efdcd1458d4b55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / clophfit-0.15.3-py3-none-any.whl
| Download URL | clophfit-0.15.3-py3-none-any.whl |
|---|---|
| Size | 338.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8f5d79f8716a1d32b660168f6a5ac121d004486e7fca3f48eb6849de2d51574e
|
|
BLAKE2b-256 checksum How to use checksums |
3c560ade49e50eabab3c0dfca6d4a408620e0835702cb58e570d1b1dc11470db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|