|
30 | 30 | TOPOLOGIES_DIR = project_root / "examples" / "topologies" |
31 | 31 | GUIDE_DIR = project_root / "examples" / "guide" |
32 | 32 | GALLERY_DIR = project_root / "docs" / "gallery" |
| 33 | +PIPELINES_DIR = project_root / "docs" / "pipelines" |
33 | 34 | RENDERS_DIR = project_root / "docs" / "assets" / "renders" |
34 | 35 |
|
35 | 36 | # Ordered list of examples. Each entry is (filename_stem, source_dir, description). |
|
44 | 45 | ( |
45 | 46 | "rnaseq_auto", |
46 | 47 | EXAMPLES_DIR, |
47 | | - "nf-core/rnaseq with fully auto-inferred layout.", |
| 48 | + "Demonstrates fully auto-inferred layout: no `%%metro grid:` directives " |
| 49 | + "needed. See [nf-core Pipelines](../pipelines/index.md) for the full gallery.", |
48 | 50 | ), |
49 | 51 | ( |
50 | 52 | "rnaseq_sections", |
51 | 53 | EXAMPLES_DIR, |
52 | | - "nf-core/rnaseq with manual grid overrides and file markers.", |
53 | | - ), |
54 | | - ( |
55 | | - "genomeassembly", |
56 | | - EXAMPLES_DIR, |
57 | | - "sanger-tol/genomeassembly with fan-out/fan-in across optional stages.", |
58 | | - ), |
59 | | - ( |
60 | | - "variantprioritization", |
61 | | - EXAMPLES_DIR, |
62 | | - "nf-core/variantprioritization with cross-row bypass routing.", |
| 54 | + "Same pipeline with manual `%%metro grid:` overrides and file markers, " |
| 55 | + "showing how explicit directives can fine-tune placement.", |
63 | 56 | ), |
64 | 57 | ( |
65 | 58 | "differentialabundance", |
|
177 | 170 | } |
178 | 171 |
|
179 | 172 |
|
| 173 | +# Ordered list of nf-core pipeline examples. |
| 174 | +# Each entry is (filename_stem, display_name, repo_url, description). |
| 175 | +PIPELINE_ENTRIES: list[tuple[str, str, str, str]] = [ |
| 176 | + ( |
| 177 | + "rnaseq_auto", |
| 178 | + "nf-core/rnaseq", |
| 179 | + "https://github.com/nf-core/rnaseq", |
| 180 | + "RNA-seq analysis with multiple aligner and quantification routes " |
| 181 | + "(STAR/RSEM, STAR/Salmon, HISAT2, Salmon pseudo-alignment, Kallisto).", |
| 182 | + ), |
| 183 | + ( |
| 184 | + "epitopeprediction", |
| 185 | + "nf-core/epitopeprediction", |
| 186 | + "https://github.com/nf-core/epitopeprediction", |
| 187 | + "MHC binding prediction from VCF, protein FASTA, or peptide TSV inputs " |
| 188 | + "through five prediction tools.", |
| 189 | + ), |
| 190 | + ( |
| 191 | + "hlatyping", |
| 192 | + "nf-core/hlatyping", |
| 193 | + "https://github.com/nf-core/hlatyping", |
| 194 | + "HLA typing from FASTQ or BAM inputs via OptiType and HLA-HD.", |
| 195 | + ), |
| 196 | + ( |
| 197 | + "variantprioritization", |
| 198 | + "nf-core/variantprioritization", |
| 199 | + "https://github.com/nf-core/variantprioritization", |
| 200 | + "Somatic and germline variant prioritization using PCGR and CPSR.", |
| 201 | + ), |
| 202 | + ( |
| 203 | + "variantbenchmarking", |
| 204 | + "nf-core/variantbenchmarking", |
| 205 | + "https://github.com/nf-core/variantbenchmarking", |
| 206 | + "Benchmarking of variant callers against truth sets with " |
| 207 | + "Truvari, hap.py, RTGtools, and more.", |
| 208 | + ), |
| 209 | + ( |
| 210 | + "genomeassembly", |
| 211 | + "sanger-tol/genomeassembly", |
| 212 | + "https://github.com/sanger-tol/genomeassembly", |
| 213 | + "Genome assembly from long reads and Hi-C data through " |
| 214 | + "purging, polishing, scaffolding, and QC.", |
| 215 | + ), |
| 216 | +] |
| 217 | + |
180 | 218 | # Manifest mapping SVG filename -> section for the render diff page. |
181 | 219 | # Populated by each render function, written to RENDERS_DIR/manifest.json. |
182 | 220 | _manifest: dict[str, str] = {} |
183 | 221 |
|
184 | 222 |
|
185 | | -def render_mmd(mmd_path: Path, svg_path: Path) -> None: |
| 223 | +def render_mmd( |
| 224 | + mmd_path: Path, svg_path: Path, *, debug: bool = DEBUG_RENDERS |
| 225 | +) -> None: |
186 | 226 | """Parse, layout, and render a .mmd file to SVG.""" |
187 | 227 | text = mmd_path.read_text() |
188 | 228 | graph = parse_metro_mermaid(text) |
189 | 229 | compute_layout(graph) |
190 | 230 | theme_name = graph.style if graph.style in THEMES else "nfcore" |
191 | 231 | theme = THEMES[theme_name] |
192 | | - svg_str = render_svg(graph, theme, debug=DEBUG_RENDERS) |
| 232 | + svg_str = render_svg(graph, theme, debug=debug) |
193 | 233 | svg_path.write_text(svg_str) |
194 | 234 |
|
195 | 235 |
|
@@ -360,28 +400,72 @@ def render_nextflow_examples() -> None: |
360 | 400 | print() |
361 | 401 |
|
362 | 402 |
|
363 | | -def render_pipeline_examples() -> None: |
364 | | - """Render pipeline examples not covered by the gallery or guide.""" |
| 403 | +def build_pipelines_page() -> None: |
| 404 | + """Generate docs/pipelines/index.md and render pipeline SVGs.""" |
| 405 | + PIPELINES_DIR.mkdir(parents=True, exist_ok=True) |
365 | 406 | RENDERS_DIR.mkdir(parents=True, exist_ok=True) |
366 | | - section = "Pipeline Examples" |
367 | | - print("Pipeline examples:") |
368 | | - for stem in ( |
369 | | - "epitopeprediction", |
370 | | - "hlatyping", |
371 | | - "rnaseq_sections_manual", |
372 | | - "variantprioritization", |
373 | | - ): |
| 407 | + section = "nf-core Pipelines" |
| 408 | + print("nf-core pipelines:") |
| 409 | + |
| 410 | + lines: list[str] = [ |
| 411 | + "# nf-core Pipelines", |
| 412 | + "", |
| 413 | + "Real-world pipelines rendered with nf-metro. These are maintained as " |
| 414 | + "`.mmd` files alongside the pipeline source code and rendered automatically.", |
| 415 | + "", |
| 416 | + "See the [Gallery](../gallery/index.md) for layout pattern examples and the " |
| 417 | + "[Guide](../guide.md) for how to write your own.", |
| 418 | + "", |
| 419 | + ] |
| 420 | + |
| 421 | + for stem, display_name, repo_url, description in PIPELINE_ENTRIES: |
| 422 | + mmd_path = EXAMPLES_DIR / f"{stem}.mmd" |
| 423 | + svg_path = RENDERS_DIR / f"pipeline_{stem}.svg" |
| 424 | + |
| 425 | + if not mmd_path.exists(): |
| 426 | + print(f" WARNING: {mmd_path} not found, skipping") |
| 427 | + continue |
| 428 | + |
| 429 | + try: |
| 430 | + render_mmd(mmd_path, svg_path, debug=True) |
| 431 | + status = "OK" |
| 432 | + except Exception as e: |
| 433 | + status = f"FAIL: {e}" |
| 434 | + print(f" {stem}: {status}") |
| 435 | + continue |
| 436 | + |
| 437 | + _manifest[svg_path.name] = section |
| 438 | + print(f" {stem}: {status}") |
| 439 | + |
| 440 | + mmd_source = mmd_path.read_text() |
| 441 | + |
| 442 | + lines.append(f"## [{display_name}]({repo_url})\n") |
| 443 | + lines.append(f"{description}\n") |
| 444 | + lines.append(f"\n") |
| 445 | + lines.append('??? note "Mermaid source"\n') |
| 446 | + lines.append(" ```text") |
| 447 | + for src_line in mmd_source.rstrip().split("\n"): |
| 448 | + lines.append(f" {src_line}") |
| 449 | + lines.append(" ```\n") |
| 450 | + |
| 451 | + pipelines_md = "\n".join(lines) |
| 452 | + pipelines_path = PIPELINES_DIR / "index.md" |
| 453 | + pipelines_path.write_text(pipelines_md) |
| 454 | + print(f"\nPipelines page written to {pipelines_path}") |
| 455 | + print() |
| 456 | + |
| 457 | + # Also render rnaseq_sections_manual for the guide (not on pipelines page) |
| 458 | + for stem in ("rnaseq_sections_manual",): |
374 | 459 | mmd_path = EXAMPLES_DIR / f"{stem}.mmd" |
375 | 460 | if not mmd_path.exists(): |
376 | 461 | continue |
377 | 462 | svg_path = RENDERS_DIR / f"{stem}.svg" |
378 | 463 | try: |
379 | 464 | render_mmd(mmd_path, svg_path) |
380 | | - _manifest[svg_path.name] = section |
| 465 | + _manifest[svg_path.name] = "Guide Examples" |
381 | 466 | print(f" {stem}: OK") |
382 | 467 | except Exception as e: |
383 | 468 | print(f" {stem}: FAIL - {e}") |
384 | | - print() |
385 | 469 |
|
386 | 470 |
|
387 | 471 | def render_test_fixtures() -> None: |
@@ -417,7 +501,7 @@ def write_manifest() -> None: |
417 | 501 | old_svg.unlink() |
418 | 502 | render_guide_examples() |
419 | 503 | render_nextflow_examples() |
420 | | - render_pipeline_examples() |
| 504 | + build_pipelines_page() |
421 | 505 | render_test_fixtures() |
422 | 506 | build_gallery() |
423 | 507 | write_manifest() |
0 commit comments