DAG Visualization with Mermaid

NeuroDAGs can render any pipeline or derivative definition as an interactive Mermaid diagram saved to a standalone HTML file.

Two levels of detail are available:

  • Pipeline DAG — high-level view: one node per derivative, edges showing inter-derivative dependencies.

  • Derivative DAG — fine-grained view: every computation node and data reference inside a single derivative.

Two layout engines are supported:

  • ELK (default) — orthogonal edge routing with active crossing minimisation. Significantly cleaner for dense pipelines with many interconnected derivatives. Requires internet access to load the ELK bundle from the CDN when the HTML is opened.

  • dagre — right-angle step edges, no CDN dependency. Use for offline environments.

Setup

import yaml

Sample pipeline

We define a three-step pipeline in YAML — the same format used in a real pipeline.yml file.

PIPELINE_YAML = """\
DerivativeDefinitions:

  BasicPrep:
    nodes:
      - id: 0
        derivative: SourceFile
      - id: 1
        node: basic_preprocessing
        args:
          mne_object: id.0
          filter_args: {l_freq: 1.0, h_freq: 80.0}
          epoch_config: {duration: 2.0, overlap: 0.0}

  Spectrum:
    nodes:
      - id: 0
        derivative: BasicPrep.fif
      - id: 1
        node: mne_spectrum_array
        args:
          meeg: id.0
          method: welch

  BandPower:
    save: false
    for_dataframe: true
    nodes:
      - id: 0
        derivative: Spectrum.nc
      - id: 1
        node: extract_data_var
        args: {dataset_like: id.0, data_var: spectrum}
      - id: 2
        node: bandpower
        args:
          psd_like: id.1
          relative: true
          bands:
            delta: [1.0,  4.0]
            theta: [4.0,  8.0]
            alpha: [8.0, 13.0]
            beta:  [13.0, 30.0]
      - id: 3
        node: aggregate_across_dimension
        args: {xarray_data: id.2, dim: epochs, operation: mean}
"""

pipeline_config = yaml.safe_load(PIPELINE_YAML)

Pipeline-level Mermaid diagram

pipeline_to_mermaid() returns the raw Mermaid string. pipeline_to_html() saves it to a self-contained HTML file that renders in any browser.

from neurodags.mermaid import pipeline_to_html, pipeline_to_mermaid

mermaid_str = pipeline_to_mermaid(pipeline_config)
print("Pipeline Mermaid diagram:")
print(mermaid_str)
Pipeline Mermaid diagram:
    %% Pipeline DAG
    flowchart TD
      BasicPrep["BasicPrep"]
      Spectrum["Spectrum"]
      BandPower["BandPower"]
      BasicPrep --> Spectrum
      Spectrum --> BandPower

Save to HTML with ELK layout (default)

ELK produces orthogonal edges with crossing minimisation — the clearest layout for pipelines with many interconnected derivatives. Requires CDN access when the HTML file is opened in a browser.

import tempfile
from pathlib import Path

out_dir = Path(tempfile.mkdtemp(prefix="neurodags_mermaid_"))

pipeline_html = pipeline_to_html(
    pipeline_config,
    output_path=out_dir / "pipeline_dag_elk.html",
    title="My Pipeline DAG (ELK)",
    auto_open=False,  # set True to open in browser
    layout="elk",     # default — orthogonal routing via ELK
)
print(f"Pipeline DAG (ELK) saved to: {pipeline_html}")
Pipeline DAG (ELK) saved to: /tmp/neurodags_mermaid_y3eh9q4b/pipeline_dag_elk.html

Save to HTML with dagre layout (offline fallback)

dagre uses right-angle step edges and loads no external resources — suitable for air-gapped environments or when CDN access is unavailable.

pipeline_html_dagre = pipeline_to_html(
    pipeline_config,
    output_path=out_dir / "pipeline_dag_dagre.html",
    title="My Pipeline DAG (dagre)",
    auto_open=False,
    layout="dagre",   # offline fallback, no CDN dependency
)
print(f"Pipeline DAG (dagre) saved to: {pipeline_html_dagre}")
Pipeline DAG (dagre) saved to: /tmp/neurodags_mermaid_y3eh9q4b/pipeline_dag_dagre.html

Derivative-level Mermaid diagram

Zoom into a single derivative to see every node and data reference.

Node shapes:

  • Circle (((...)))SourceFile (raw input).

  • Cylinder [(...)] — upstream derivative artifact (cached on disk).

  • Rectangle [...] — computation node.

from neurodags.mermaid import derivative_to_html, derivative_to_mermaid

deriv_name = "BandPower"
deriv_def = pipeline_config["DerivativeDefinitions"][deriv_name]

mermaid_str = derivative_to_mermaid(deriv_def, deriv_name)
print(f"\n{deriv_name} derivative Mermaid diagram:")
print(mermaid_str)
BandPower derivative Mermaid diagram:
    %% BandPower
    flowchart TD
      id0[("Spectrum.nc")]
      id1["extract_data_var"]
      id2["bandpower"]
      id3["aggregate_across_dimension"]
      id0 --> id1
      id1 --> id2
      id2 --> id3

Save the derivative diagram to HTML (ELK layout).

deriv_html = derivative_to_html(
    deriv_def,
    deriv_name,
    output_path=out_dir / f"{deriv_name}_dag.html",
    auto_open=False,
    layout="elk",
)
print(f"{deriv_name} DAG saved to: {deriv_html}")
BandPower DAG saved to: /tmp/neurodags_mermaid_y3eh9q4b/BandPower_dag.html

Using a real pipeline.yml

In a real project, load your config from disk and call the same functions:

import yaml
from neurodags.mermaid import pipeline_to_html, derivative_to_html

with open("pipeline.yml") as f:
    config = yaml.safe_load(f)

# Full pipeline overview — ELK layout (default)
pipeline_to_html(config, output_path="pipeline_dag.html", auto_open=True)

# Offline fallback — dagre layout
pipeline_to_html(config, output_path="pipeline_dag.html", layout="dagre", auto_open=True)

# Single derivative detail
derivative_to_html(
    config["DerivativeDefinitions"]["BandPower"],
    "BandPower",
    output_path="bandpower_dag.html",
    auto_open=True,
)

CLI equivalents:

neurodags dag pipeline.yml
neurodags dag pipeline.yml --html pipeline_dag.html               # ELK layout (default)
neurodags dag pipeline.yml --html pipeline_dag.html --layout dagre # offline fallback
neurodags dag pipeline.yml --derivative BandPower --html bandpower_dag.html

Direct Mermaid string access

Use the raw string functions when you need to embed diagrams in Jupyter notebooks or custom HTML templates. Pass layout= to save_mermaid_html to select the layout engine for the wrapper HTML.

from neurodags.mermaid import save_mermaid_html

custom_diagram = """    flowchart TD
      A["load_raw"] --> B["filter"]
      B --> C["epoch"]
      C --> D[("BasicPrep.fif")]"""

out = save_mermaid_html(
    custom_diagram,
    output_path=out_dir / "custom_dag.html",
    title="Custom DAG",
    layout="elk",
)
print(f"Custom DAG saved to: {out}")
Custom DAG saved to: /tmp/neurodags_mermaid_y3eh9q4b/custom_dag.html

Total running time of the script: (0 minutes 0.089 seconds)

Gallery generated by Sphinx-Gallery