Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion docs/run_ribasim.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,57 @@
That way we can run this version on CI but it looks like we run the Ribasim Python version.
"""

import os
import re
import sys
import tempfile
from pathlib import Path

from juliacall import Main as jl

jl.seval("import Ribasim")

_ANSI_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")


def _filter_output(raw: str) -> str:
"""Remove blank lines and progress bar repetitions from Ribasim output."""
lines = raw.splitlines()
filtered = []
for line in lines:
plain = _ANSI_RE.sub("", line)
# Skip lines that are only whitespace or invisible braille blanks (U+2800)
if all(c in " \t\u2800" for c in plain):
continue
# Skip progress bar log lines from OrdinaryDiffEqCore
if "@ OrdinaryDiffEqCore" in plain:
continue
if plain.lstrip().startswith("\u250c") and "Simulating" in plain:
continue
filtered.append(line)
return "\n".join(filtered)


def run_ribasim(toml_path: str | Path) -> None:
"""Run a Ribasim simulation via juliacall."""
retcode = jl.Ribasim.main(str(toml_path))
# Redirect stderr at the fd level to capture Julia output
# (logo, log messages, progress bar) which all go to stderr.
sys.stderr.flush()
old_fd = os.dup(2)
try:
with tempfile.TemporaryFile(mode="w+b") as tmp:
os.dup2(tmp.fileno(), 2)
try:
retcode = jl.Ribasim.main(str(toml_path))
finally:
os.dup2(old_fd, 2)
tmp.seek(0)
raw = tmp.read().decode("utf-8", errors="replace")
finally:
os.close(old_fd)

output = _filter_output(raw)
if output:
print(output, file=sys.stderr)

assert retcode == 0, f"Simulation failed: {toml_path}"
2 changes: 1 addition & 1 deletion python/ribasim/ribasim/geometry/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def plot(self, ax=None, zorder=None) -> plt.Axes:
if self.df is None:
return ax

NODE_ICON_SIZE = 17.0 # display-points per icon
NODE_ICON_SIZE = 25.0 # display-points per icon
for nodetype, df in self.df.groupby("node_type"):
assert isinstance(nodetype, str)
for x, y in zip(df.geometry.x, df.geometry.y, strict=True):
Expand Down
Loading