|
| 1 | +""" |
| 2 | +pipeline.py — Run the full NeuroGhost ingestion pipeline in one command. |
| 3 | +
|
| 4 | +Steps |
| 5 | +----- |
| 6 | +1. (Optional) Delete the database file for a clean rebuild |
| 7 | +2. Seed schema.org as the base vocabulary |
| 8 | +3. (Optional) Fetch + convert external schemas via converters/run_all.py |
| 9 | +4. Ingest every .yml file found in the schemas directory |
| 10 | +5. Compute cross-schema alignments |
| 11 | +6. Export registry.json + version snapshot |
| 12 | +
|
| 13 | +Usage |
| 14 | +----- |
| 15 | + # Fresh rebuild — wipe DB, fetch external schemas, ingest everything |
| 16 | + python neuro_ghost/pipeline.py --fresh |
| 17 | +
|
| 18 | + # Re-ingest local schemas only (skip external fetch) |
| 19 | + python neuro_ghost/pipeline.py --fresh --skip-converters |
| 20 | +
|
| 21 | + # Incremental — add one schema to an existing DB |
| 22 | + python neuro_ghost/pipeline.py --skip-converters --schemas schemas/bbqs.yml |
| 23 | +""" |
| 24 | + |
| 25 | +from __future__ import annotations |
| 26 | +import subprocess |
| 27 | +import sys |
| 28 | +from pathlib import Path |
| 29 | + |
| 30 | +import click |
| 31 | + |
| 32 | +HERE = Path(__file__).parent |
| 33 | +ROOT = HERE.parent |
| 34 | +SCHEMAS = ROOT / "schemas" |
| 35 | +DB_PATH = str(ROOT / "registry.lbug") |
| 36 | + |
| 37 | + |
| 38 | +def _run(cmd: list[str]) -> None: |
| 39 | + print(f"\n$ {' '.join(cmd)}") |
| 40 | + result = subprocess.run(cmd, check=False) |
| 41 | + if result.returncode != 0: |
| 42 | + print(f"\nERROR: command exited with code {result.returncode}") |
| 43 | + sys.exit(result.returncode) |
| 44 | + |
| 45 | + |
| 46 | +@click.command() |
| 47 | +@click.option("--db", default=DB_PATH, show_default=True, |
| 48 | + help="Path to the LadybugDB file.") |
| 49 | +@click.option("--fresh", is_flag=True, |
| 50 | + help="Delete the DB before starting (clean rebuild).") |
| 51 | +@click.option("--skip-converters", is_flag=True, |
| 52 | + help="Skip fetching external schemas (BIDS, NWB, DANDI, …).") |
| 53 | +@click.option("--schemas", default=None, multiple=True, |
| 54 | + help="Specific .yml files to ingest. Defaults to all files in schemas/.") |
| 55 | +@click.option("--bump", default="minor", show_default=True, |
| 56 | + type=click.Choice(["major", "minor", "patch"]), |
| 57 | + help="Version bump type for the registry export.") |
| 58 | +@click.option("--agent", default="local", show_default=True, |
| 59 | + help="Who is running this pipeline (recorded in provenance).") |
| 60 | +def cli(db: str, fresh: bool, skip_converters: bool, |
| 61 | + schemas: tuple, bump: str, agent: str) -> None: |
| 62 | + """Run the full NeuroGhost ingestion pipeline.""" |
| 63 | + |
| 64 | + py = sys.executable |
| 65 | + |
| 66 | + # 1. Fresh wipe |
| 67 | + if fresh: |
| 68 | + db_path = Path(db) |
| 69 | + if db_path.exists(): |
| 70 | + db_path.unlink() |
| 71 | + print(f"Deleted {db_path}") |
| 72 | + |
| 73 | + # 2. Seed schema.org |
| 74 | + _run([py, str(HERE / "seed.py"), "--db", db]) |
| 75 | + |
| 76 | + # 3. External converters |
| 77 | + if not skip_converters: |
| 78 | + _run([py, str(HERE / "converters" / "run_all.py")]) |
| 79 | + |
| 80 | + # 4. Ingest schemas |
| 81 | + targets: list[Path] = ( |
| 82 | + [Path(s) for s in schemas] |
| 83 | + if schemas |
| 84 | + else sorted(p for p in SCHEMAS.glob("*.yml") |
| 85 | + if p.name != "meta_model.yaml") |
| 86 | + ) |
| 87 | + |
| 88 | + if not targets: |
| 89 | + print("No schemas found to ingest.") |
| 90 | + sys.exit(1) |
| 91 | + |
| 92 | + for schema_file in targets: |
| 93 | + _run([py, str(HERE / "ingest_linkml.py"), |
| 94 | + "--file", str(schema_file), |
| 95 | + "--db", db, |
| 96 | + "--agent", agent]) |
| 97 | + |
| 98 | + # 5. Align |
| 99 | + _run([py, str(HERE / "align.py"), "--db", db]) |
| 100 | + |
| 101 | + # 6. Export |
| 102 | + _run([py, str(HERE / "export_json.py"), |
| 103 | + "--db", db, |
| 104 | + "--bump", bump, |
| 105 | + "--agent", agent]) |
| 106 | + |
| 107 | + print("\nPipeline complete.") |
| 108 | + |
| 109 | + |
| 110 | +if __name__ == "__main__": |
| 111 | + cli() |
0 commit comments