Skip to content

Commit db19ff4

Browse files
sbryngelsonclaude
andcommitted
Add LaTeX label lookup for MFC variable names in plots
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3d10bb9 commit db19ff4

1 file changed

Lines changed: 66 additions & 7 deletions

File tree

toolchain/mfc/viz/renderer.py

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import math
1010
import os
11+
import re
1112
import tempfile
1213

1314
import numpy as np
@@ -24,14 +25,70 @@
2425
'font.family': 'serif',
2526
})
2627

28+
# LaTeX-style labels for known MFC variable names
29+
_LABEL_MAP = {
30+
'pres': r'$p$',
31+
'rho': r'$\rho$',
32+
'E': r'$E$',
33+
'T': r'$T$',
34+
'D': r'$D$',
35+
'c': r'$c$',
36+
'gamma': r'$\gamma$',
37+
'pi_inf': r'$\pi_\infty$',
38+
'pres_inf': r'$p_\infty$',
39+
'heat_ratio': r'$\gamma$',
40+
'schlieren': r'$|\nabla \rho|$',
41+
'psi': r'$\psi$',
42+
'n': r'$n$',
43+
'qm': r'$q_m$',
44+
'Bx': r'$B_x$', 'By': r'$B_y$', 'Bz': r'$B_z$',
45+
'voidFraction': r'void fraction',
46+
'liutex_mag': r'$|\lambda|$',
47+
'damage_state': r'damage',
48+
}
49+
50+
_INDEXED_PATTERNS = [
51+
(r'^vel(\d+)$', lambda m: [r'$u$', r'$v$', r'$w$'][int(m.group(1)) - 1]
52+
if int(m.group(1)) <= 3 else rf'$v_{m.group(1)}$'),
53+
(r'^mom(\d+)$', lambda m: rf'$\rho {["u", "v", "w"][int(m.group(1)) - 1]}$'
54+
if int(m.group(1)) <= 3 else rf'$m_{m.group(1)}$'),
55+
(r'^alpha(\d+)$', lambda m: rf'$\alpha_{m.group(1)}$'),
56+
(r'^alpha_rho(\d+)$', lambda m: rf'$\alpha_{m.group(1)}\rho_{m.group(1)}$'),
57+
(r'^alpha_rho_e(\d+)$', lambda m: rf'$\alpha_{m.group(1)}\rho_{m.group(1)}e_{m.group(1)}$'),
58+
(r'^omega(\d+)$', lambda m: rf'$\omega_{m.group(1)}$'),
59+
(r'^tau(\d+)$', lambda m: rf'$\tau_{m.group(1)}$'),
60+
(r'^xi(\d+)$', lambda m: rf'$\xi_{m.group(1)}$'),
61+
(r'^flux(\d+)$', lambda m: rf'$F_{m.group(1)}$'),
62+
(r'^liutex_axis(\d+)$', lambda m: rf'$\lambda_{m.group(1)}$'),
63+
(r'^rho(\d+)$', lambda m: rf'$\rho_{m.group(1)}$'),
64+
(r'^Y_(.+)$', lambda m: rf'$Y_{{\mathrm{{{m.group(1)}}}}}$'),
65+
(r'^nR(\d+)$', lambda m: rf'$nR_{{{m.group(1)}}}$'),
66+
(r'^nV(\d+)$', lambda m: rf'$nV_{{{m.group(1)}}}$'),
67+
(r'^nP(\d+)$', lambda m: rf'$nP_{{{m.group(1)}}}$'),
68+
(r'^nM(\d+)$', lambda m: rf'$nM_{{{m.group(1)}}}$'),
69+
(r'^color_function(\d+)$', lambda m: rf'color $f_{m.group(1)}$'),
70+
]
71+
72+
73+
def pretty_label(varname):
74+
"""Map an MFC variable name to a LaTeX-style label for plots."""
75+
if varname in _LABEL_MAP:
76+
return _LABEL_MAP[varname]
77+
for pattern, formatter in _INDEXED_PATTERNS:
78+
m = re.match(pattern, varname)
79+
if m:
80+
return formatter(m)
81+
return varname
82+
2783

2884
def render_1d(x_cc, data, varname, step, output, **opts): # pylint: disable=too-many-arguments,too-many-positional-arguments
2985
"""Render a 1D line plot and save as PNG."""
3086
fig, ax = plt.subplots(figsize=opts.get('figsize', (10, 6)))
87+
label = pretty_label(varname)
3188
ax.plot(x_cc, data, linewidth=1.5)
3289
ax.set_xlabel(r'$x$')
33-
ax.set_ylabel(varname)
34-
ax.set_title(f'{varname} (step {step})')
90+
ax.set_ylabel(label)
91+
ax.set_title(f'{label} (step {step})')
3592
ax.grid(True, alpha=0.3)
3693
ax.ticklabel_format(axis='y', style='sci', scilimits=(-3, 4), useMathText=True)
3794

@@ -67,7 +124,7 @@ def render_1d_tiled(x_cc, variables, step, output, **opts): # pylint: disable=t
67124
row, col = divmod(idx, ncols)
68125
ax = axes[row][col]
69126
ax.plot(x_cc, variables[vn], linewidth=1.2)
70-
ax.set_ylabel(vn, fontsize=9)
127+
ax.set_ylabel(pretty_label(vn), fontsize=9)
71128
ax.tick_params(labelsize=8)
72129
ax.grid(True, alpha=0.3)
73130

@@ -125,10 +182,11 @@ def render_2d(x_cc, y_cc, data, varname, step, output, **opts): # pylint: disab
125182
# data shape is (nx, ny), pcolormesh expects (ny, nx) when using x_cc, y_cc
126183
pcm = ax.pcolormesh(x_cc, y_cc, data.T, cmap=cmap, vmin=vmin, vmax=vmax,
127184
norm=norm, shading='auto')
128-
fig.colorbar(pcm, ax=ax, label=varname)
185+
label = pretty_label(varname)
186+
fig.colorbar(pcm, ax=ax, label=label)
129187
ax.set_xlabel(r'$x$')
130188
ax.set_ylabel(r'$y$')
131-
ax.set_title(f'{varname} (step {step})')
189+
ax.set_title(f'{label} (step {step})')
132190
ax.set_aspect('equal', adjustable='box')
133191

134192
fig.tight_layout()
@@ -197,11 +255,12 @@ def render_3d_slice(assembled, varname, step, output, slice_axis='z', # pylint:
197255
# sliced shape depends on axis: need to transpose appropriately
198256
pcm = ax.pcolormesh(x_plot, y_plot, sliced.T, cmap=cmap, vmin=vmin,
199257
vmax=vmax, norm=norm, shading='auto')
200-
fig.colorbar(pcm, ax=ax, label=varname)
258+
label = pretty_label(varname)
259+
fig.colorbar(pcm, ax=ax, label=label)
201260
ax.set_xlabel(xlabel)
202261
ax.set_ylabel(ylabel)
203262
slice_coord = coord_along[idx]
204-
ax.set_title(f'{varname} (step {step}, {slice_axis}={slice_coord:.4g})')
263+
ax.set_title(f'{label} (step {step}, {slice_axis}={slice_coord:.4g})')
205264
ax.set_aspect('equal', adjustable='box')
206265

207266
fig.tight_layout()

0 commit comments

Comments
 (0)