Skip to content

Commit a84b3f3

Browse files
sbryngelsonclaude
andcommitted
Move viz deps to optional extra; install on first ./mfc.sh viz
pyproject.toml: matplotlib, seaborn, h5py, imageio, imageio-ffmpeg, plotext, textual, textual-plotext, dash, plotly, and tqdm moved from [project.dependencies] to [project.optional-dependencies] viz = [...]. None of these are imported by any toolchain command other than viz. viz.py: _ensure_viz_deps() runs at the top of viz() before any viz imports. It checks for matplotlib as a sentinel; if absent, installs the local toolchain[viz] extra via uv (or pip fallback) using the same UV_LINK_MODE=copy strategy as bootstrap/python.sh. On first run the user sees a one-time "Installing viz dependencies..." message; subsequent runs are instant (sentinel import succeeds immediately). This means ./mfc.sh build, run, test, etc. no longer pull in ~700 MB of visualization packages that most HPC users never need. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 85c715e commit a84b3f3

2 files changed

Lines changed: 67 additions & 15 deletions

File tree

toolchain/mfc/viz/viz.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,50 @@
55
"""
66

77
import os
8+
import importlib
9+
import shutil
10+
import subprocess
11+
import sys
812

913
from mfc.state import ARG
10-
from mfc.common import MFCException
14+
from mfc.common import MFC_ROOT_DIR, MFCException
1115
from mfc.printer import cons
1216

1317

18+
def _ensure_viz_deps() -> None:
19+
"""Install the [viz] optional extras on first use.
20+
21+
Checks for matplotlib as the sentinel package. If it is missing the
22+
whole viz extra is assumed to be absent and gets installed via uv (or pip
23+
as a fallback) from the local toolchain directory.
24+
"""
25+
try:
26+
import matplotlib # noqa: F401 # pylint: disable=import-outside-toplevel,unused-import
27+
return # already installed
28+
except ImportError:
29+
pass
30+
31+
toolchain_path = os.path.join(MFC_ROOT_DIR, "toolchain")
32+
cons.print("[bold]Installing viz dependencies[/bold] "
33+
"(first run — this may take a minute)...")
34+
35+
env = {**os.environ, "UV_LINK_MODE": "copy"}
36+
if shutil.which("uv"):
37+
cmd = ["uv", "pip", "install", f"{toolchain_path}[viz]"]
38+
else:
39+
cmd = [sys.executable, "-m", "pip", "install", f"{toolchain_path}[viz]"]
40+
41+
result = subprocess.run(cmd, env=env, check=False)
42+
if result.returncode != 0:
43+
raise MFCException(
44+
"Failed to install viz dependencies. "
45+
f"Try manually: pip install '{toolchain_path}[viz]'"
46+
)
47+
48+
importlib.invalidate_caches()
49+
cons.print("[bold green]Viz dependencies installed.[/bold green]\n")
50+
51+
1452
_CMAP_POPULAR = (
1553
'viridis, plasma, inferno, magma, turbo, '
1654
'coolwarm, RdBu_r, bwr, hot, jet, gray, seismic'
@@ -82,6 +120,8 @@ def _parse_steps(step_arg, available_steps):
82120

83121
def viz(): # pylint: disable=too-many-locals,too-many-statements,too-many-branches
84122
"""Main viz command dispatcher."""
123+
_ensure_viz_deps()
124+
85125
from .reader import discover_format, discover_timesteps, assemble # pylint: disable=import-outside-toplevel
86126
from .renderer import render_1d, render_1d_tiled, render_2d, render_3d_slice, render_mp4 # pylint: disable=import-outside-toplevel
87127

toolchain/pyproject.toml

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,6 @@ dependencies = [
3333
"numpy",
3434
"pandas",
3535

36-
# Plotting
37-
"seaborn",
38-
"matplotlib",
39-
40-
# Visualization
41-
"h5py",
42-
"imageio>=2.33",
43-
"imageio-ffmpeg>=0.5.0",
44-
"plotext>=5.2.0",
45-
"textual>=0.47.0",
46-
"textual-plotext>=0.2.0",
47-
4836
# Chemistry
4937
"cantera>=3.1.0",
5038
#"pyrometheus == 1.0.5",
@@ -53,16 +41,40 @@ dependencies = [
5341
# Frontier Profiling
5442
"astunparse==1.6.2",
5543
"colorlover",
56-
"dash>=2.0",
5744
"pymongo",
5845
"tabulate",
59-
"tqdm",
6046
"dash-svg",
6147
"dash-bootstrap-components",
6248
"kaleido",
6349
"plotille"
6450
]
6551

52+
[project.optional-dependencies]
53+
viz = [
54+
# 2D/3D plotting (renderer, TUI)
55+
"matplotlib",
56+
"seaborn",
57+
58+
# Silo-HDF5 reader
59+
"h5py",
60+
61+
# MP4 export
62+
"imageio>=2.33",
63+
"imageio-ffmpeg>=0.5.0",
64+
65+
# Terminal UI (--tui)
66+
"plotext>=5.2.0",
67+
"textual>=0.47.0",
68+
"textual-plotext>=0.2.0",
69+
70+
# Interactive web UI (--interactive)
71+
"dash>=2.0",
72+
"plotly",
73+
74+
# Progress bar (PNG/MP4 batch rendering)
75+
"tqdm",
76+
]
77+
6678
[tool.hatch.metadata]
6779
allow-direct-references = true
6880

0 commit comments

Comments
 (0)