bindcurve is an lmfit-backed Python package for fitting dose-response curves.
The current API provides:
- dose-response data ingestion and validation through
DoseResponseData - logistic models such as
IC50Model,LogIC50Model, andEC50Model - direct-binding models for simple, specific, and total Kd fitting
- competitive three-state and four-state binding models
- IC50-to-Kd conversion helpers
- structured fit results and plotting helpers for reports and figures
uv add bindcurveFor local development:
uv python install 3.12
uv sync --group dev
uv run pytestbindcurve supports Python 3.10, 3.11, and 3.12. Python 3.9 is not supported.
bindcurve expects dose-response observations in long-form data:
compound_id | experiment_id | concentration | replicate_id | response
Only these columns are required:
compound_id | concentration | response
If experiment_id or replicate_id is missing, bindcurve fills defaults.
import pandas as pd
import bindcurve as bc
raw = pd.DataFrame(
{
"compound_id": ["cmpd_a", "cmpd_a", "cmpd_a", "cmpd_a"],
"experiment_id": ["exp1", "exp1", "exp1", "exp1"],
"concentration": [0.01, 0.1, 1.0, 10.0],
"response": [98.0, 85.0, 45.0, 5.0],
}
)
data = bc.DoseResponseData.from_dataframe(
raw,
concentration_unit="uM",
response_unit="percent",
)
results = bc.fit(
data,
model="ic50",
fixed={"ymin": 0.0, "ymax": 100.0},
)
print(results.fits_to_dataframe())
print(results.summary_to_dataframe())The default strategy is per_experiment.
For each compound, bindcurve:
- splits observations by independent experiment;
- aggregates technical replicates at each concentration;
- fits one curve per independent experiment;
- summarizes fitted parameters across independent experiments.
This avoids treating technical replicates as independent biological repeats.
Alternative strategies are available through FitSettings:
bc.FitSettings(strategy="per_experiment")
bc.FitSettings(strategy="pooled")
bc.FitSettings(strategy="per_compound_summary")Wide assay tables can be normalized with from_wide_dataframe:
data = bc.DoseResponseData.from_wide_dataframe(
df,
compound_col="compound",
concentration_col="dose",
experiment_col="experiment",
replicate_cols=["rep_1", "rep_2", "rep_3"],
)bindcurve is unitless by computation and unit-aware by annotation.
The user is responsible for providing all concentration-like values in consistent units. Fitted concentration-like parameters are reported in the same unit label as the input concentrations.
Common development commands:
uv sync --group dev
uv run pytest
uv run ruff check
uv buildThe tutorial notebooks use the same dev environment, which includes ipykernel
and Jupyter support.
See architecture.md for the intended design.
bindcurve has a DOI available from Zenodo. Please use the DOI or cite this repository directly.
bindcurve is published under the MIT license.
