Source code for pykinbiont.io

"""save_results() — write GrowthFitResults to CSV files (pure Python)."""

from __future__ import annotations

import csv
from pathlib import Path

from pykinbiont.types import GrowthFitResults


[docs] def save_results( results: GrowthFitResults, dir: str, prefix: str = "kinbiont", ) -> dict[str, str]: """Write fitting results to CSV files inside dir. Three files are written: - ``<prefix>_summary.csv``: one row per curve (best model, AICc, params). - ``<prefix>_fitted_curves.csv``: long-format (label, time, observed, fitted). - ``<prefix>_all_models.csv``: one row per (curve, candidate model). Parameters ---------- results: GrowthFitResults returned by fit(). dir: Directory path (created if it does not exist). prefix: File name prefix. Default ``"kinbiont"``. Returns ------- dict with keys ``"summary"``, ``"fitted_curves"``, ``"all_models"`` pointing to the written file paths. """ out = Path(dir) out.mkdir(parents=True, exist_ok=True) base = out / prefix summary_path = str(base) + "_summary.csv" fitted_curves_path = str(base) + "_fitted_curves.csv" all_models_path = str(base) + "_all_models.csv" _write_summary(results, summary_path) _write_fitted_curves(results, fitted_curves_path) _write_all_models(results, all_models_path) return { "summary": summary_path, "fitted_curves": fitted_curves_path, "all_models": all_models_path, }
def _write_summary(results: GrowthFitResults, path: str) -> None: n_max = max((len(r.best_params) for r in results.results), default=0) header = [ "label", "cluster", "best_model", "n_params", "param_names", "aic", "loss", ] + [f"param_{k+1}" for k in range(n_max)] with open(path, "w", newline="") as f: w = csv.writer(f) w.writerow(header) for r in results.results: idx = results.data.labels.index(r.label) cluster = ( int(results.data.clusters[idx]) if results.data.clusters is not None else "" ) param_names = ";".join(r.param_names) row = [r.label, cluster, r.best_model, len(r.best_params), param_names, r.best_aic, r.loss] for k in range(n_max): row.append(r.best_params[k] if k < len(r.best_params) else "") w.writerow(row) print(f"[ Info: Saved summary → {path}") def _write_fitted_curves(results: GrowthFitResults, path: str) -> None: with open(path, "w", newline="") as f: w = csv.writer(f) w.writerow(["label", "time", "observed", "fitted"]) for r in results.results: idx = results.data.labels.index(r.label) obs = results.data.curves[idx] n_fit = len(r.fitted_curve) for j, t in enumerate(r.times[:n_fit]): obs_j = float(obs[j]) if j < len(obs) else "" w.writerow([r.label, t, obs_j, r.fitted_curve[j]]) print(f"[ Info: Saved fitted curves → {path}") def _write_all_models(results: GrowthFitResults, path: str) -> None: # Determine max params across all candidate models n_max = 0 for r in results.results: for c in r.all_results: n_max = max(n_max, len(c.get("params", []))) header = [ "label", "model_name", "param_names", "aic", "loss", "is_best", ] + [f"param_{k+1}" for k in range(n_max)] with open(path, "w", newline="") as f: w = csv.writer(f) w.writerow(header) for r in results.results: for c in r.all_results: params = c.get("params", []) is_best = c.get("model_name") == r.best_model row = [ r.label, c.get("model_name", ""), "", # param_names not stored per candidate c.get("aic", ""), c.get("loss", ""), is_best, ] for k in range(n_max): row.append(params[k] if k < len(params) else "") w.writerow(row) print(f"[ Info: Saved all models → {path}")