Skip to content

FEAT: add Mermaid graph rendering - #347

Open
Flomber wants to merge 32 commits into
mainfrom
Mermaidrendering
Open

FEAT: add Mermaid graph rendering#347
Flomber wants to merge 32 commits into
mainfrom
Mermaidrendering

Conversation

@Flomber

@Flomber Flomber commented Aug 18, 2026

Copy link
Copy Markdown

Closes #159

@Flomber
Flomber requested a review from redeboer August 18, 2026 12:22
@Flomber Flomber added the ✨ Feature New feature added to the package label Aug 18, 2026
Flomber and others added 6 commits August 18, 2026 14:35
…mermaid in Jupyter notebooks

- Updated the visualize_mermaid.ipynb to use asmermaid for generating Mermaid source directly.
- Removed show_mermaid_markdown function and integrated its functionality into asmermaid.
- Adjusted documentation and examples to reflect the new usage of asmermaid.
- Cleaned up the io module by consolidating Mermaid-related functions and removing unnecessary code.
- Enhanced tests to verify the new asmermaid functionality and removed tests related to the deprecated show_mermaid_markdown.
@redeboer redeboer changed the title Add Mermaid graph rendering parallel to Graphvis rendering including … FEAT: add Mermaid graph rendering Aug 19, 2026
redeboer

This comment was marked as resolved.

redeboer

This comment was marked as resolved.

Comment thread docs/usage/visualize.ipynb
Comment thread docs/usage.ipynb Outdated
Comment thread docs/usage/visualize_mermaid.ipynb
@Flomber

Flomber commented Aug 20, 2026

Copy link
Copy Markdown
Author

Found issue with rendering long lines eg. in graph edges.

isospin_magnitude ∊ [0, 1/2, 1, 3/2 ]

gets displayed as

isospin_magnitude ∊ [0, 1/2, 1, 3/2

@redeboer redeboer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! 💯
Some smaller comments below.

One general thought I had: it seems that Mermaid (as opposed to Graphviz) supports LaTeX, even if not for all backends. Rewriting the example of #159:

```mermaid
graph LR
    A["$$J/\psi$$"] --> N0[ ]
    N0 --> N1["$$f_0(980)$$"]
    N0 --> 0[$$\gamma$$]
    N1 --> 1[$$\pi^0$$]
    N1 --> 2[$$\pi^0$$]
    style A fill:#FFFFFF, stroke:#FFFFFF;
    style N0 fill:#FFFFFF, stroke:#FFFFFF;
    style N1 fill:#FFFFFF, stroke:#FFFFFF;
    style 0 fill:#FFFFFF, stroke:#FFFFFF;
    style 1 fill:#FFFFFF, stroke:#FFFFFF;
    style 2 fill:#FFFFFF, stroke:#FFFFFF;
```

Maybe worth posting a follow-up issue. Similarly to #348, one could select LaTeX as rendering with a flag, for instance.

Rendering on Sphinx Image
Rendering on VS Code Jupyter Image
Rendering on Jupyter Lab Image
Rendering on GitHub ❌
graph LR
    A["$$J/\psi$$"] --> N0[ ]
    N0 --> N1["$$f_0(980)$$"]
    N0 --> 0[$$\gamma$$]
    N1 --> 1[$$\pi^0$$]
    N1 --> 2[$$\pi^0$$]
    style A fill:#FFFFFF, stroke:#FFFFFF;
    style N0 fill:#FFFFFF, stroke:#FFFFFF;
    style N1 fill:#FFFFFF, stroke:#FFFFFF;
    style 0 fill:#FFFFFF, stroke:#FFFFFF;
    style 1 fill:#FFFFFF, stroke:#FFFFFF;
    style 2 fill:#FFFFFF, stroke:#FFFFFF;
Loading

Comment thread pyproject.toml Outdated
Comment thread .cspell.json Outdated
Comment thread docs/usage/visualize.ipynb
Comment thread docs/usage/visualize.ipynb
Comment thread docs/usage/visualize_mermaid.ipynb
Comment thread src/qrules/io/_mermaid.py
Comment thread src/qrules/io/_mermaid.py Outdated
Comment thread src/qrules/io/_mermaid.py
Comment thread src/qrules/io/_mermaid.py Outdated
Comment on lines +317 to +338
def __init__(
self,
*,
render_node: bool | None = None,
render_final_state_id: bool = True,
render_resonance_id: bool = False,
render_initial_state_id: bool = False,
strip_spin: bool = False,
collapse_graphs: bool = False,
figure_style: dict[str, Any] | None = None,
edge_style: dict[str, Any] | None = None,
node_style: dict[str, Any] | None = None,
) -> None:
self.render_node = render_node
self.render_final_state_id = render_final_state_id
self.render_resonance_id = render_resonance_id
self.render_initial_state_id = render_initial_state_id
self.strip_spin = strip_spin
self.collapse_graphs = collapse_graphs
self.figure_style = dict(figure_style) if figure_style else {}
self.edge_style = dict(edge_style) if edge_style else {}
self.node_style = dict(node_style) if node_style else {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to declare this class with @attrs.define to reduce boilerplate code, just like GraphPrinter, which is declared with @define(on_setattr=_check_booleans).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this definition satisfies this?
Also AI mentioned, that in the definition of the GraphvizPrinter class has the weakness, that it also accepts invalid constructor combinations.
Should this also be fixed? A shared attrs validator was a recommendation.

Comment thread src/qrules/io/_mermaid.py
Comment thread src/qrules/io/_mermaid.py Outdated
Comment thread src/qrules/io/_mermaid.py Outdated
Comment thread src/qrules/io/_mermaid.py Outdated
Comment thread src/qrules/io/_mermaid.py Outdated
Comment on lines +163 to +168
def __extract_priority(description: str) -> str:
matches = re.match(r".* \- ([0-9]+|NA)$", description)
if matches is None:
msg = f"{description} does not contain a priority number"
raise ValueError(msg)
return matches[1]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • This returns a str, and line 134 uses it directly as sorted(..., key=..., reverse=True). This makes priority 9 sort above 10, and "NA" outranks every numeric priority. The rule list in the rendered label ends up in the wrong order whenever any priority reaches double
    digits.
    Returning an int with an explicit sentinel for NA (-1, or float("-inf") if negative priorities are possible) would fix it.
  • Minor problem: in the same regex, the \- does not need escaping outside a character class.

Note that this exact same function exists under _dot.py!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed, but please review... I'm not exactly sure if the fix is what you asked for 🙃

Comment thread src/qrules/io/_mermaid.py Outdated
Comment thread src/qrules/io/_mermaid.py Outdated
@ComPWA ComPWA deleted a comment from review-notebook-app Bot Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature New feature added to the package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Render transitions as Mermaid

3 participants