Skip to content

Commit 5b8d16e

Browse files
sbryngelsonclaude
andcommitted
viz: make TUI the default mode, add --png flag for image output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent adfcdc7 commit 5b8d16e

File tree

4 files changed

+51
-50
lines changed

4 files changed

+51
-50
lines changed

docs/documentation/visualization.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@ MFC includes a built-in visualization command that renders images and videos dir
1414
### Basic usage
1515

1616
```bash
17-
# Plot pressure at the last available timestep (--step defaults to 'last')
18-
./mfc.sh viz case_dir/ --var pres
17+
# Launch the terminal UI (default mode)
18+
./mfc.sh viz case_dir/
1919

20-
# Plot density at all available timesteps
21-
./mfc.sh viz case_dir/ --var rho --step all
20+
# Launch with a specific variable pre-selected
21+
./mfc.sh viz case_dir/ --var pres
2222
```
2323

2424
The command auto-detects the output format (binary or Silo-HDF5) and dimensionality (1D, 2D, or 3D).
25-
Output images are saved to `case_dir/viz/` by default.
26-
The default colormap is `viridis`, default DPI is 150, and `--step` defaults to `last`.
25+
By default it launches an interactive terminal UI that works over SSH.
26+
Use `--interactive` for a browser-based UI (supports 3D), `--png` to save images, or `--mp4` for video.
2727

2828
### Exploring available data
2929

@@ -54,13 +54,13 @@ Customize the appearance of plots:
5454

5555
```bash
5656
# Custom colormap and color range
57-
./mfc.sh viz case_dir/ --var rho --step 1000 --cmap RdBu --vmin 0.5 --vmax 2.0
57+
./mfc.sh viz case_dir/ --var rho --step 1000 --png --cmap RdBu --vmin 0.5 --vmax 2.0
5858

5959
# Higher resolution
60-
./mfc.sh viz case_dir/ --var pres --step 500 --dpi 300
60+
./mfc.sh viz case_dir/ --var pres --step 500 --png --dpi 300
6161

6262
# Logarithmic color scale
63-
./mfc.sh viz case_dir/ --var schlieren --step 1000 --log-scale
63+
./mfc.sh viz case_dir/ --var schlieren --step 1000 --png --log-scale
6464
```
6565

6666
| Option | Description | Default |
@@ -84,13 +84,13 @@ By default, it slices at the midplane along the z-axis.
8484
8585
```bash
8686
# Default z-midplane slice
87-
./mfc.sh viz case_dir/ --var pres --step 500
87+
./mfc.sh viz case_dir/ --var pres --step 500 --png
8888

8989
# Slice along the x-axis at x=0.25
90-
./mfc.sh viz case_dir/ --var pres --step 500 --slice-axis x --slice-value 0.25
90+
./mfc.sh viz case_dir/ --var pres --step 500 --png --slice-axis x --slice-value 0.25
9191

9292
# Slice by array index
93-
./mfc.sh viz case_dir/ --var pres --step 500 --slice-axis y --slice-index 50
93+
./mfc.sh viz case_dir/ --var pres --step 500 --png --slice-axis y --slice-index 50
9494
```
9595

9696
### Video generation
@@ -117,10 +117,10 @@ For 1D cases, omitting `--var` (or passing `--var all`) renders all variables in
117117

118118
```bash
119119
# Tiled plot of all variables at the last timestep
120-
./mfc.sh viz case_dir/ --step last
120+
./mfc.sh viz case_dir/ --step last --png
121121

122122
# Equivalent explicit form
123-
./mfc.sh viz case_dir/ --var all --step last
123+
./mfc.sh viz case_dir/ --var all --step last --png
124124
```
125125

126126
Each variable gets its own subplot with automatic LaTeX-style axis labels.
@@ -147,13 +147,13 @@ The interactive viewer provides a Dash web UI with:
147147
148148
### Terminal UI (TUI)
149149

150-
For environments without a browser — such as SSH sessions or HPC login nodes — use `--tui` to launch a live terminal UI:
150+
The default mode launches a live terminal UI that works over SSH with no browser or port-forwarding needed:
151151

152152
```bash
153-
./mfc.sh viz case_dir/ --tui
153+
./mfc.sh viz case_dir/
154154

155155
# Start with a specific variable pre-selected
156-
./mfc.sh viz case_dir/ --var pres --tui
156+
./mfc.sh viz case_dir/ --var pres
157157
```
158158

159159
The TUI loads all timesteps and renders plots directly in the terminal using Unicode block characters.

toolchain/mfc/cli/commands.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -867,19 +867,19 @@
867867
description=(
868868
"Render post-processed MFC output as PNG images or MP4 video, or explore "
869869
"interactively. Supports 1D line plots, 2D colormaps, 3D midplane slices, "
870-
"and tiled all-variable views. PNG files are saved to case_dir/viz/ by default.\n\n"
870+
"and tiled all-variable views.\n\n"
871871
"Output modes:\n"
872-
" (default) Save PNG image(s) to case_dir/viz/\n"
873-
" --mp4 Encode frames into an MP4 video\n"
872+
" (default) Launch a terminal UI (works over SSH, no browser needed)\n"
874873
" --interactive Launch a Dash web UI in your browser\n"
875-
" --tui Launch a terminal UI (works over SSH, no browser needed)\n\n"
874+
" --png Save PNG image(s) to case_dir/viz/\n"
875+
" --mp4 Encode frames into an MP4 video\n\n"
876876
"Variable selection:\n"
877877
" --var NAME Plot a single variable\n"
878878
" (omit --var) 1D/2D: tiled layout of all variables; 3D: first variable\n\n"
879879
"Quick-start workflow:\n"
880880
" 1. ./mfc.sh viz case_dir/ --list-steps\n"
881881
" 2. ./mfc.sh viz case_dir/ --list-vars --step 0\n"
882-
" 3. ./mfc.sh viz case_dir/ --var pres --step 1000"
882+
" 3. ./mfc.sh viz case_dir/"
883883
),
884884
positionals=[
885885
Positional(
@@ -927,15 +927,15 @@
927927
Argument(
928928
name="output",
929929
short="o",
930-
help="Directory for saved PNG images or MP4 video (default: case_dir/viz/).",
930+
help="Directory for saved PNG images or MP4 video.",
931931
type=str,
932932
default=None,
933933
metavar="DIR",
934934
completion=Completion(type=CompletionType.DIRECTORIES),
935935
),
936936
Argument(
937937
name="cmap",
938-
help="Matplotlib colormap name (default: viridis).",
938+
help="Matplotlib colormap name.",
939939
type=str,
940940
default='viridis',
941941
metavar="CMAP",
@@ -981,14 +981,14 @@
981981
),
982982
Argument(
983983
name="dpi",
984-
help="Image resolution in DPI (default: 150).",
984+
help="Image resolution in DPI.",
985985
type=int,
986986
default=150,
987987
metavar="DPI",
988988
),
989989
Argument(
990990
name="slice-axis",
991-
help="Axis for 3D slice: x, y, or z (default: z).",
991+
help="Axis for 3D slice.",
992992
type=str,
993993
default='z',
994994
choices=["x", "y", "z"],
@@ -1019,7 +1019,7 @@
10191019
),
10201020
Argument(
10211021
name="fps",
1022-
help="Frames per second for MP4 output (default: 10).",
1022+
help="Frames per second for MP4 output.",
10231023
type=int,
10241024
default=10,
10251025
metavar="FPS",
@@ -1058,38 +1058,36 @@
10581058
),
10591059
Argument(
10601060
name="port",
1061-
help="Port for the interactive web server (default: 8050).",
1061+
help="Port for the interactive web server.",
10621062
type=int,
10631063
default=8050,
10641064
metavar="PORT",
10651065
),
10661066
Argument(
10671067
name="host",
1068-
help="Host/bind address for the interactive web server (default: 127.0.0.1).",
1068+
help="Host/bind address for the interactive web server.",
10691069
default="127.0.0.1",
10701070
metavar="HOST",
10711071
),
10721072
Argument(
1073-
name="tui",
1073+
name="png",
10741074
help=(
1075-
"Launch an interactive terminal UI (1D/2D only). "
1076-
"Works over SSH with no browser required. "
1077-
"Use arrow keys to step through timesteps."
1075+
"Save PNG image(s) to the output directory instead of "
1076+
"launching the terminal UI."
10781077
),
10791078
action=ArgAction.STORE_TRUE,
10801079
default=False,
10811080
),
10821081
],
10831082
examples=[
1083+
Example("./mfc.sh viz case_dir/", "Launch terminal UI (default mode)"),
10841084
Example("./mfc.sh viz case_dir/ --list-steps", "Discover available timesteps"),
10851085
Example("./mfc.sh viz case_dir/ --list-vars --step 0", "Discover available variables at step 0"),
1086-
Example("./mfc.sh viz case_dir/ --var pres --step 1000", "Save pressure PNG at step 1000 → case_dir/viz/"),
1087-
Example("./mfc.sh viz case_dir/ --step 1000", "Save tiled PNG of all variables (1D/2D) at step 1000"),
1088-
Example("./mfc.sh viz case_dir/ --var schlieren --step 0:10000:500 --mp4", "Encode schlieren MP4 from range"),
1089-
Example("./mfc.sh viz case_dir/ --step 0,100,200,...,1000", "Render all steps 0–1000 (stride inferred)"),
1090-
Example("./mfc.sh viz case_dir/ --var pres --step 500 --slice-axis x", "3D: x-plane slice of pressure"),
10911086
Example("./mfc.sh viz case_dir/ --var pres --interactive", "Browser UI — scrub timesteps and switch vars"),
1092-
Example("./mfc.sh viz case_dir/ --var pres --tui", "Terminal UI over SSH (1D/2D, no browser)"),
1087+
Example("./mfc.sh viz case_dir/ --var pres --step 1000 --png", "Save pressure PNG at step 1000"),
1088+
Example("./mfc.sh viz case_dir/ --var schlieren --step 0:10000:500 --mp4", "Encode schlieren MP4 from range"),
1089+
Example("./mfc.sh viz case_dir/ --step 0,100,200,...,1000 --png", "Render all steps 0–1000 as images"),
1090+
Example("./mfc.sh viz case_dir/ --var pres --step 500 --slice-axis x --png", "3D: x-plane slice of pressure"),
10931091
],
10941092
key_options=[
10951093
("-- Discovery --", ""),
@@ -1099,10 +1097,10 @@
10991097
("--var NAME", "Variable to plot (omit for tiled all-vars layout)"),
11001098
("--step STEP", "last (default), int, start:stop:stride, list, or 'all'"),
11011099
("-- Output modes --", ""),
1102-
("(default)", "Save PNG to case_dir/viz/; use -o DIR to change"),
1103-
("--mp4", "Encode frames into an MP4 video"),
1100+
("(default)", "Terminal UI — works over SSH, no browser needed (1D/2D)"),
11041101
("--interactive / -i", "Dash web UI in browser (supports 1D/2D/3D)"),
1105-
("--tui", "Terminal UI over SSH — no browser needed (1D/2D)"),
1102+
("--png", "Save PNG image(s) to case_dir/viz/; use -o DIR to change"),
1103+
("--mp4", "Encode frames into an MP4 video"),
11061104
("-- Appearance --", ""),
11071105
("--cmap NAME", "Matplotlib colormap (default: viridis)"),
11081106
("--vmin / --vmax", "Fix color-scale limits"),

toolchain/mfc/viz/tui.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
Terminal UI (TUI) for MFC visualization using Textual + plotext.
33
4-
Launched via ``./mfc.sh viz <dir> --tui [--var VAR] [--step STEP]``.
4+
Launched via ``./mfc.sh viz <dir> [--var VAR] [--step STEP]``.
55
Opens a full-terminal interactive viewer that works over SSH with no
66
browser or port-forwarding required.
77
@@ -688,7 +688,7 @@ def run_tui(
688688
"""Launch the Textual TUI for MFC visualization (1D/2D only)."""
689689
if ndim not in (1, 2):
690690
raise MFCException(
691-
f"--tui only supports 1D and 2D data (got ndim={ndim}). "
691+
f"Terminal UI only supports 1D and 2D data (got ndim={ndim}). "
692692
"Use --interactive for 3D data."
693693
)
694694

toolchain/mfc/viz/viz.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,10 @@ def viz(): # pylint: disable=too-many-locals,too-many-statements,too-many-branc
265265
step_arg = ARG('step')
266266
tiled = varname is None or varname == 'all'
267267

268-
if ARG('interactive') or ARG('tui') or ARG('mp4'):
268+
# TUI is the default mode; --interactive, --png, and --mp4 are explicit.
269+
use_tui = not ARG('interactive') and not ARG('png') and not ARG('mp4')
270+
271+
if ARG('interactive') or use_tui or ARG('mp4'):
269272
# Load all steps by default; honour an explicit --step so users can
270273
# reduce the set for large 3D cases before hitting the step limit.
271274
if step_arg == 'last':
@@ -313,7 +316,7 @@ def viz(): # pylint: disable=too-many-locals,too-many-statements,too-many-branc
313316

314317
# Load all variables when tiled, interactive, or TUI; filter otherwise.
315318
# TUI needs all vars loaded so the sidebar can switch between them.
316-
load_all = tiled or interactive or ARG('tui')
319+
load_all = tiled or interactive or use_tui
317320

318321
def read_step(step):
319322
if fmt == 'silo':
@@ -334,7 +337,7 @@ def read_step(step):
334337
f"(limit is {_3d_limit}). Use --step with a range or stride to reduce.")
335338

336339
# Tiled mode works for 1D and 2D. For 3D, auto-select the first variable.
337-
if tiled and not interactive and not ARG('tui'):
340+
if tiled and not interactive and not use_tui:
338341
if test_assembled.ndim == 3:
339342
varname = avail[0] if avail else None
340343
if varname is None:
@@ -343,7 +346,7 @@ def read_step(step):
343346
cons.print(f"[dim]Auto-selected variable: [bold]{varname}[/bold]"
344347
" (use --var to specify)[/dim]")
345348

346-
if not tiled and not interactive and not ARG('tui') and varname not in test_assembled.variables:
349+
if not tiled and not interactive and not use_tui and varname not in test_assembled.variables:
347350
# test_assembled was loaded with var_filter=varname so its variables dict
348351
# may be empty. Re-read without filter (errors only, so extra I/O is fine)
349352
# to build a useful "available variables" list for the error message.
@@ -367,10 +370,10 @@ def read_step(step):
367370
_validate_cmap(cmap_name)
368371

369372
# TUI mode — launch Textual terminal UI (1D/2D only)
370-
if ARG('tui'):
373+
if use_tui:
371374
if test_assembled.ndim == 3:
372375
raise MFCException(
373-
"--tui only supports 1D and 2D data. "
376+
"Terminal UI only supports 1D and 2D data. "
374377
"Use --interactive for 3D data."
375378
)
376379
from .tui import run_tui # pylint: disable=import-outside-toplevel

0 commit comments

Comments
 (0)