#!/usr/bin/env python3 """Run the complete project from its checked-in YAML configuration.""" import argparse import hashlib import os from pathlib import Path import platform import sys import time from importlib.metadata import version import numpy import scipy import yaml from cell_auto.experiments import run_all, write_json def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--config', default='configs/experiments.yaml') parser.add_argument('--output', default='results', help='Results directory; relative paths use this script directory') parser.add_argument('--tables', help='CSV destination; defaults beside a custom results directory') parser.add_argument('--figures', help='Figure destination; defaults beside a custom results directory') parser.add_argument('--only', default='all', choices=['all', 'tests', 'convergence', 'spectroscopy', 'collision', 'source_check', 'reference_check', 'causal']) parser.add_argument('--no-plots', action='store_true') args = parser.parse_args() here = Path(__file__).resolve().parent def resolve(value): path = Path(value) return path.resolve() if path.is_absolute() else (here / path).resolve() config_path, out = resolve(args.config), resolve(args.output) # Preserve the delivered project layout for the default run; keep a custom # run's tables and figures next to its results, away from delivered outputs. output_parent = here.parent if out == here / 'results' else out.parent tables = resolve(args.tables) if args.tables else output_parent / 'tables' figures = resolve(args.figures) if args.figures else output_parent / 'figures' cfg = yaml.safe_load(config_path.read_text()) sources = sorted(list((here / 'cell_auto').glob('*.py')) + [Path(__file__).resolve(), config_path, here / 'requirements.txt', here / 'requirements-lock.txt']) hashes = {Path(os.path.relpath(path, here)).as_posix(): hashlib.sha256(path.read_bytes()).hexdigest() for path in sources} command = ['python3', 'reproduce.py', '--config', os.path.relpath(config_path, here), '--output', os.path.relpath(out, here), '--tables', os.path.relpath(tables, here), '--figures', os.path.relpath(figures, here), '--only', args.only] if args.no_plots: command.append('--no-plots') write_json(out / 'environment.json', dict(python=sys.version, platform=platform.platform(), numpy=numpy.__version__, scipy=scipy.__version__, matplotlib=version('matplotlib'), pyyaml=version('PyYAML'), command=command, command_base='experiment directory', config=cfg, source_sha256=hashes)) started = time.perf_counter() summary = run_all(cfg, out, args.only, tables=tables) plotting_seconds = 0. if not args.no_plots: before = time.perf_counter() from cell_auto.plotting import make_plots make_plots(out, figures) plotting_seconds = time.perf_counter() - before write_json(out / 'run_record.json', dict(selection=args.only, numerics_seconds=summary['runtime_seconds'], plotting_seconds=plotting_seconds, total_seconds=time.perf_counter()-started)) print(f'Elapsed: {summary["runtime_seconds"]:.2f} seconds', flush=True) if __name__ == '__main__': main()