Quick start#
This page walks through the most common workflow end-to-end: load data, fit a growth model, inspect results, and save to CSV.
1. Configure (once per machine)#
If you have a local KinBiont.jl clone, point pykinbiont at it. Skip this step to use the registry-installed version.
import pykinbiont
pykinbiont.configure("/path/to/KinBiont.jl")
# Restart the Python process / Jupyter kernel once after this call.
2. Load data#
from pykinbiont import GrowthData
# From a CSV file (first column = time, remaining columns = wells/curves)
data = GrowthData.from_csv("plate_reader_export.csv")
print(f"{len(data.labels)} curves, {len(data.times)} time points")
print("Labels:", data.labels[:4])
Or build from a NumPy array directly:
import numpy as np
from pykinbiont import GrowthData
times = np.linspace(0, 20, 100)
curves = np.stack([0.01 + 1.2 / (1 + 119 * np.exp(-0.5 * times))] * 3)
data = GrowthData(
curves=curves,
times=times,
labels=["A1", "A2", "A3"],
)
3. Choose a model#
pykinbiont exposes all KinBiont built-in models via MODEL_REGISTRY:
from pykinbiont import MODEL_REGISTRY, ModelSpec
# List available models
print(list(MODEL_REGISTRY.keys()))
# Pick the logistic model
logistic = MODEL_REGISTRY["NL_logistic"]
print("Parameters:", logistic.param_names) # ['N_max', 'growth_rate', 'lag']
Parameter naming
KinBiont uses legacy parameter names. For NL_logistic the actual order is
[N_max, N0, mu] but the names are ['N_max', 'growth_rate', 'lag'].
When setting initial guesses and bounds, use the positional order:
params=[[N_max, N0, mu]].
Build a ModelSpec with initial guesses and optional bounds:
spec = ModelSpec(
models=[logistic],
params=[[1.2, 0.01, 0.5]], # [N_max, N0, mu] initial guess
lower=[[0.3, 1e-3, 0.05]], # lower bounds
upper=[[3.0, 0.05, 3.0]], # upper bounds
)
4. Set fitting options#
from pykinbiont import FitOptions
opts = FitOptions(
smooth=True,
smooth_method="rolling_avg", # smooth before fitting
multistart=True,
n_restart=20, # multi-start restarts for robustness
)
5. Fit#
from pykinbiont import fit
results = fit(data, spec, opts)
fit() sends data and configuration to Julia, runs the optimizer for every
curve, selects the best model by AICc, and returns a GrowthFitResults.
6. Inspect results#
# Summary DataFrame
df = results.to_dataframe()
print(df[["label", "best_model", "aic", "param_1", "param_2", "param_3"]])
# Iterate over individual curve results
for r in results:
params = dict(zip(r.param_names, r.best_params))
print(f"{r.label}: N_max={params['N_max']:.3f} AIC={r.best_aic:.1f}")
7. Plot#
import matplotlib.pyplot as plt
for r in results:
idx = data.labels.index(r.label)
plt.plot(data.times, data.curves[idx], ".", alpha=0.4, label=f"{r.label} data")
plt.plot(r.times, r.fitted_curve, "-", label=f"{r.label} fit")
plt.xlabel("Time (h)")
plt.ylabel("OD")
plt.legend()
plt.tight_layout()
plt.show()
8. Save#
from pykinbiont import save_results
paths = save_results(results, "output/", prefix="my_experiment")
# Writes:
# output/my_experiment_summary.csv
# output/my_experiment_fitted_curves.csv
# output/my_experiment_all_models.csv
Next steps#
Loading data —
from_csv,from_dataframe, subsetting,IrregularGrowthDataGrowth models — built-in registry, custom Python functions, ODE models
FitOptions reference — all smoothing, preprocessing, and fitting parameters
Example 2 — Custom Python growth model — define your own growth model in Python