# Working with results `fit()` returns a {py:class}`~pykinbiont.GrowthFitResults` which contains: - `data` — the post-preprocessing `GrowthData` (smoothed, blank-subtracted, etc.) - `results` — a list of {py:class}`~pykinbiont.CurveFitResult`, one per curve ## GrowthFitResults ### to_dataframe() Returns a pandas DataFrame with one row per curve: ```python df = results.to_dataframe() print(df.columns.tolist()) # ['label', 'cluster', 'best_model', 'aic', 'loss', 'param_1', 'param_2', ...] ``` | Column | Description | |---|---| | `label` | Curve identifier | | `cluster` | Cluster ID (integer, or `None` if no clustering was run) | | `best_model` | Name of the winning model | | `aic` | AICc of the best model | | `loss` | Final loss value | | `param_1`, `param_2`, … | Best-fit parameters in positional order | ### Iteration `GrowthFitResults` is iterable and indexable: ```python # Iterate for r in results: print(r.label, r.best_model) # Index first = results[0] # Length print(len(results)) ``` ## CurveFitResult Each `CurveFitResult` has: | Attribute | Type | Description | |---|---|---| | `label` | `str` | Curve identifier | | `best_model` | `str` | Name of the selected model | | `best_params` | `list[float]` | Best-fit parameter values | | `param_names` | `list[str]` | Parameter names (matches `best_params`) | | `best_aic` | `float` | AICc of the best model | | `fitted_curve` | `ndarray` | Fitted OD values (same time axis as `times`) | | `times` | `ndarray` | Time axis for the fitted curve | | `loss` | `float` | Final loss value | | `all_results` | `list[dict]` | All candidate models with their params and AICc | ### Accessing parameters by name ```python for r in results: params = dict(zip(r.param_names, r.best_params)) print(f"{r.label}: {params}") ``` ### Plotting fitted vs observed ```python import matplotlib.pyplot as plt fig, axes = plt.subplots(1, len(results), figsize=(4 * len(results), 3)) for ax, r in zip(axes, results): idx = results.data.labels.index(r.label) obs = results.data.curves[idx] ax.plot(results.data.times, obs, ".", alpha=0.4, label="data") ax.plot(r.times, r.fitted_curve, "-", label=r.best_model) ax.set_title(r.label) ax.set_xlabel("Time") ax.set_ylabel("OD") ax.legend(fontsize=7) plt.tight_layout() ``` ### Comparing candidate models `all_results` contains every model that was tried: ```python r = results[0] for candidate in sorted(r.all_results, key=lambda x: x["aic"]): print(f" {candidate['model_name']:20s} AIC={candidate['aic']:.1f} loss={candidate['loss']:.4f}") ```