|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import copy |
3 | 4 | import csv |
4 | 5 | import hashlib |
5 | 6 | import json |
@@ -1317,3 +1318,84 @@ def generate_ifu_experiment_report(output_dir: str) -> dict[str, Any]: |
1317 | 1318 | report["artifacts"]["residual_products_keys"] = list(data.files) |
1318 | 1319 |
|
1319 | 1320 | return report |
| 1321 | + |
| 1322 | + |
| 1323 | +def run_ifu_experiment_sequence( |
| 1324 | + config: ExperimentConfigInput, |
| 1325 | + pipeline_factory: PipelineFactory = make_inference_pipeline, |
| 1326 | + run_validate: bool = True, |
| 1327 | + run_smoke: bool = True, |
| 1328 | + run_full: bool = True, |
| 1329 | + output_root_dir: Optional[str] = None, |
| 1330 | +) -> dict[str, Any]: |
| 1331 | + """Run validate -> smoke -> full IFU workflow sequence. |
| 1332 | +
|
| 1333 | + Args: |
| 1334 | + config (ExperimentConfigInput): Mapping or YAML path following the |
| 1335 | + experiment schema consumed by :func:`normalize_experiment_config`. |
| 1336 | + pipeline_factory (PipelineFactory, optional): Pipeline builder used to |
| 1337 | + instantiate and prepare a Rubix pipeline. Defaults to |
| 1338 | + :func:`make_inference_pipeline`. |
| 1339 | + run_validate (bool, optional): Whether to run input validation phase. |
| 1340 | + Defaults to ``True``. |
| 1341 | + run_smoke (bool, optional): Whether to run smoke-only phase. |
| 1342 | + Defaults to ``True``. |
| 1343 | + run_full (bool, optional): Whether to run full optimization/VI phase. |
| 1344 | + Defaults to ``True``. |
| 1345 | + output_root_dir (Optional[str], optional): Optional root output |
| 1346 | + directory for phase artifacts. Defaults to ``None`` (use config). |
| 1347 | +
|
| 1348 | + Raises: |
| 1349 | + RuntimeError: If requested validation phase fails. |
| 1350 | +
|
| 1351 | + Returns: |
| 1352 | + dict[str, Any]: Per-phase outputs/statuses and output directories. |
| 1353 | + """ |
| 1354 | + raw_cfg = read_yaml(config) if isinstance(config, str) else dict(config) |
| 1355 | + base_cfg = normalize_experiment_config(raw_cfg) |
| 1356 | + |
| 1357 | + if output_root_dir is None: |
| 1358 | + output_root = Path(str(base_cfg["run"]["output_dir"])) |
| 1359 | + else: |
| 1360 | + output_root = Path(output_root_dir) |
| 1361 | + output_root.mkdir(parents=True, exist_ok=True) |
| 1362 | + |
| 1363 | + sequence: dict[str, Any] = { |
| 1364 | + "output_root_dir": str(output_root), |
| 1365 | + "validate": None, |
| 1366 | + "smoke": None, |
| 1367 | + "full": None, |
| 1368 | + } |
| 1369 | + |
| 1370 | + if run_validate: |
| 1371 | + report = validate_ifu_experiment_inputs( |
| 1372 | + config=base_cfg, |
| 1373 | + pipeline_factory=pipeline_factory, |
| 1374 | + ) |
| 1375 | + (output_root / "validate_report.json").write_text( |
| 1376 | + json.dumps(_to_jsonable(report), indent=2), |
| 1377 | + encoding="utf-8", |
| 1378 | + ) |
| 1379 | + sequence["validate"] = {"ok": bool(report["ok"]), "report": report} |
| 1380 | + if not report["ok"]: |
| 1381 | + raise RuntimeError("validation phase failed; see validate_report.json") |
| 1382 | + |
| 1383 | + if run_smoke: |
| 1384 | + smoke_cfg = copy.deepcopy(base_cfg) |
| 1385 | + smoke_cfg["run"]["smoke_only"] = True |
| 1386 | + smoke_cfg["optimization"]["enabled"] = False |
| 1387 | + smoke_cfg["variational"]["enabled"] = False |
| 1388 | + smoke_out = run_ifu_experiment(smoke_cfg, pipeline_factory=pipeline_factory) |
| 1389 | + smoke_dir = output_root / "smoke" |
| 1390 | + save_ifu_experiment_outputs(smoke_out, str(smoke_dir)) |
| 1391 | + sequence["smoke"] = {"output_dir": str(smoke_dir), "outputs": smoke_out} |
| 1392 | + |
| 1393 | + if run_full: |
| 1394 | + full_cfg = copy.deepcopy(base_cfg) |
| 1395 | + full_cfg["run"]["smoke_only"] = False |
| 1396 | + full_out = run_ifu_experiment(full_cfg, pipeline_factory=pipeline_factory) |
| 1397 | + full_dir = output_root / "full" |
| 1398 | + save_ifu_experiment_outputs(full_out, str(full_dir)) |
| 1399 | + sequence["full"] = {"output_dir": str(full_dir), "outputs": full_out} |
| 1400 | + |
| 1401 | + return sequence |
0 commit comments