(
run_dir: Path,
status: str,
validation: dict[str, Any],
method: dict[str, Any],
review_app_info: dict[str, Any] | None = None,
)
| 314 | |
| 315 | |
| 316 | def write_summary( |
| 317 | run_dir: Path, |
| 318 | status: str, |
| 319 | validation: dict[str, Any], |
| 320 | method: dict[str, Any], |
| 321 | review_app_info: dict[str, Any] | None = None, |
| 322 | ) -> None: |
| 323 | outputs = build_outputs_map(str(method.get("input_mode", "normalized_expression"))) |
| 324 | lines = [ |
| 325 | "# Bulk RNA-seq Differential Expression Run Summary", |
| 326 | "", |
| 327 | f"Status: `{status}`", |
| 328 | f"Selected method: `{method.get('selected_method')}`", |
| 329 | f"Input mode: `{method.get('input_mode')}`", |
| 330 | f"Matrix integer-like: `{method.get('matrix_integer_like')}`", |
| 331 | f"Fit formula: `{method.get('fit_formula')}`", |
| 332 | f"Review app URL: `{review_app_info.get('url') if review_app_info and review_app_info.get('ok') else 'not started'}`", |
| 333 | "", |
| 334 | "## Contrast Status", |
| 335 | "", |
| 336 | ] |
| 337 | for contrast in validation.get("contrast_status", []): |
| 338 | lines.append( |
| 339 | f"- `{contrast['contrast']}`: {contrast['status']} " |
| 340 | f"({contrast['numerator_condition']} n={contrast['numerator_replicates']} vs " |
| 341 | f"{contrast['denominator_condition']} n={contrast['denominator_replicates']})" |
| 342 | ) |
| 343 | lines.extend( |
| 344 | [ |
| 345 | "", |
| 346 | "## Key Artifacts", |
| 347 | "", |
| 348 | "- `manifest/contrast_status.tsv`", |
| 349 | ] |
| 350 | ) |
| 351 | for artifact in [ |
| 352 | outputs.get("raw_counts"), |
| 353 | outputs.get("input_normalized_expression"), |
| 354 | outputs.get("normalized_expression"), |
| 355 | outputs.get("input_log_expression"), |
| 356 | outputs.get("modeling_expression"), |
| 357 | outputs.get("log_expression"), |
| 358 | ]: |
| 359 | if artifact: |
| 360 | lines.append(f"- `{artifact}`") |
| 361 | lines.extend( |
| 362 | [ |
| 363 | "- `qc/pca.png`", |
| 364 | "- `qc/sample_distance_heatmap.png`", |
| 365 | "- `qc/design_diagnostics.tsv`", |
| 366 | "- `qc/sample_outlier_metrics.tsv`", |
| 367 | "- `qc/statistical_warnings.tsv`", |
| 368 | "- `plots/*_volcano.png` and `plots/*_ma.png` for executed limma contrasts", |
| 369 | "- `notebooks/marimo_server.json`", |
| 370 | "- `visualizations/index.html`", |
| 371 | "- `artifact_index.json`", |
| 372 | "", |
| 373 | ] |
no test coverage detected