# 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. ```python import pykinbiont pykinbiont.configure("/path/to/KinBiont.jl") # Restart the Python process / Jupyter kernel once after this call. ``` ## 2. Load data ```python 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: ```python 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`: ```python 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'] ``` ```{admonition} Parameter naming :class: note 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: ```python 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 ```python 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 ```python 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 ```python # 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 ```python 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 ```python 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 - {doc}`user-guide/data-loading` — `from_csv`, `from_dataframe`, subsetting, `IrregularGrowthData` - {doc}`user-guide/models` — built-in registry, custom Python functions, ODE models - {doc}`user-guide/fit-options` — all smoothing, preprocessing, and fitting parameters - {doc}`examples/custom-model` — define your own growth model in Python