IC₅₀ analysis#

This tutorial fits two synthetic inhibitory dose-response datasets. Each compound has two independent experiments and three technical replicates per concentration. Concentrations are unit-agnostic but use one consistent scale. See the logistic-model theory for the model definition.

import matplotlib.pyplot as plt

import bindcurve as bc

Load the observations#

Wide input stores technical replicates in separate response columns. DoseResponseData converts them to the canonical long-form representation.

all_data = bc.DoseResponseData.from_csv(
    "data/competitive-binding.csv",
    format="wide",
)
data = all_data.keep_only(["ic50_a", "ic50_b"])
data.summary()
compound_id N_exp N_obs N_conc_total concentration_min concentration_max response_min response_max
0 ic50_a 2 78 13 0.0001 100.0 4.60059 95.2736
1 ic50_b 2 78 13 0.0001 100.0 4.59961 95.3107

Fit and summarize#

bindcurve averages technical replicates at each concentration, fits each independent experiment separately, and then summarizes the fitted parameters across experiments. Here the known lower and upper response plateaus are fixed so the fit focuses on IC₅₀ and Hill slope.

results = bc.fit(
    data,
    model="ic50",
    fixed={"ymin": 5.0, "ymax": 95.0},
)

results.summary()[
    ["compound_id", "N_exp", "N_fit_successful", "IC50", "hill_slope"]
]
compound_id N_exp N_fit_successful IC50 hill_slope
0 ic50_a 2 2 0.029872 1.102240
1 ic50_b 2 2 0.297373 1.200361
results.report(unit="concentration units", include_n_exp=True)
compound_id report N_fit_successful N_fit_failed
0 ic50_a 0.030 [0.03, 0.03] concentration units, N_exp = 2 2 0
1 ic50_b 0.30 [0.3, 0.3] concentration units, N_exp = 2 2 0

Plot compound summaries#

plot_compounds() shows one aggregate series per compound while preserving the experiment-level fits used for the summary.

fig, ax = plt.subplots(figsize=(6, 4))
bc.plot_compounds(data, results, ax=ax)
ax.set_xlabel("concentration")
ax.set_ylabel("response")
ax.legend()
plt.show()
../_images/235ab04fe4accaee3f83e281e9d8d265b594d4e77a7f1fa02bf5548d6fa8bdba.png