Feat: Add post-tone-map mesh diagnostics with RGBA overlays
Color antialiased half-edges by ray outcome with configurable Catppuccin colors and default opacity 0.5. Rasterize premultiplied RGBA8 overlays on the producer and composite in place after writing the clean image. Keep single-frame, movie, and replay output consistent. Add overlay, CLI, and queue ownership regressions and document the final output architecture.
This commit is contained in:
1 parent
4053d5d0c8
commit
80f9dcb3a3
17 files changed
+1873
-182
No files matched your search
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Production CLI regression for post-tone-map mesh settings and replay."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
BUILD = Path(sys.argv[1] if len(sys.argv) > 1 else 'build/Release').resolve()
|
||||
BINARY = BUILD / 'minkowski_sky'
|
||||
ENV = dict(os.environ, OMP_NUM_THREADS='4')
|
||||
TMP = Path('/tmp/opencode')
|
||||
TMP.mkdir(parents=True, exist_ok=True)
|
||||
COLORS = ['escape', 'dark', 'unresolved', 'incomplete', 'untraced']
|
||||
COMMON = ['--catalog', 'assets/sky_grid_5deg.csv', '--width', '32', '--height',
|
||||
'24', '--coarse-cell-pixels', '8', '--refine-max-level', '0',
|
||||
'--exposure', '1e-3', '--psf-relative-tail', '1e-4']
|
||||
|
||||
|
||||
def run(*args, ok=True):
|
||||
result = subprocess.run([str(BINARY), *map(str, args)], env=ENV,
|
||||
capture_output=True, text=True)
|
||||
assert (result.returncode == 0) == ok, (args, result.stdout, result.stderr)
|
||||
return result
|
||||
|
||||
|
||||
help_text = run('--help').stdout
|
||||
ext = 'png' if '.png' in help_text else 'ppm'
|
||||
for category in COLORS:
|
||||
assert f'--mesh-color-{category}' in help_text
|
||||
for value in ['red', '123456', '#12345', '#1234567', '#GG1122', '']:
|
||||
result = run(f'--mesh-color-{category}', value, ok=False)
|
||||
assert result.stderr and 'Rendered' not in result.stdout
|
||||
run(f'--mesh-color-{category}', ok=False)
|
||||
for value in ['nan', 'inf', '-inf', '-0.1', '1.1', 'junk']:
|
||||
run('--mesh-opacity', value, ok=False)
|
||||
run('--mesh-opacity', ok=False)
|
||||
|
||||
custom = []
|
||||
for category, color in zip(COLORS, ['#123ABC', '#ABC123', '#AA5533',
|
||||
'#1122EE', '#112233']):
|
||||
custom += [f'--mesh-color-{category}', color]
|
||||
custom += ['--mesh-opacity', '0.85']
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix='mesh-cli-', dir=TMP) as directory:
|
||||
tmp = Path(directory)
|
||||
baseline = tmp / f'baseline.{ext}'
|
||||
run(*COMMON, '--output', baseline)
|
||||
configured = tmp / f'configured.{ext}'
|
||||
run(*COMMON, *custom, '--output', configured)
|
||||
assert baseline.read_bytes() == configured.read_bytes()
|
||||
assert not (tmp / f'configured_mesh.{ext}').exists()
|
||||
|
||||
for opacity in [0, 1]:
|
||||
output = tmp / f'opacity{opacity}.{ext}'
|
||||
run(*COMMON, *custom, '--mesh-opacity', opacity, '--draw-mesh',
|
||||
'--output', output)
|
||||
assert output.read_bytes() == baseline.read_bytes()
|
||||
mesh = tmp / f'opacity{opacity}_mesh.{ext}'
|
||||
assert (mesh.read_bytes() == baseline.read_bytes()) == (opacity == 0)
|
||||
|
||||
single_map = tmp / 'single.grlens'
|
||||
single = tmp / f'single.{ext}'
|
||||
run(*COMMON, *custom, '--draw-mesh', '--lens-map-output', single_map,
|
||||
'--output', single)
|
||||
replay = tmp / f'replay.{ext}'
|
||||
run('--catalog', 'assets/sky_grid_5deg.csv', '--exposure', '1e-3',
|
||||
'--psf-relative-tail', '1e-4', *custom, '--draw-mesh',
|
||||
'--lens-map-input', single_map, '--output', replay)
|
||||
assert single.read_bytes() == replay.read_bytes()
|
||||
assert (tmp / f'single_mesh.{ext}').read_bytes() == (tmp / f'replay_mesh.{ext}').read_bytes()
|
||||
|
||||
track = tmp / 'track.csv'
|
||||
run('--write-minkowski-accel-track', track, '--duration', 2, '--fps', 4,
|
||||
'--proper-acceleration', 0.1)
|
||||
movie_dir, replay_dir = tmp / 'movie', tmp / 'movie_replay'
|
||||
movie_dir.mkdir()
|
||||
replay_dir.mkdir()
|
||||
movie_map = tmp / 'movie.grlens'
|
||||
run(*COMMON, *custom, '--draw-mesh', '--observer-track', track,
|
||||
'--duration', 1, '--fps', 1, '--frames-dir', movie_dir,
|
||||
'--frames-prefix', 'frame', '--lens-map-output', movie_map)
|
||||
run('--catalog', 'assets/sky_grid_5deg.csv', '--exposure', '1e-3',
|
||||
'--psf-relative-tail', '1e-4', *custom, '--draw-mesh',
|
||||
'--lens-map-input', movie_map, '--frames-dir', replay_dir,
|
||||
'--frames-prefix', 'frame')
|
||||
expected_names = {f'frame_{i:06d}{suffix}.{ext}'
|
||||
for i in range(2) for suffix in ['', '_mesh']}
|
||||
assert {p.name for p in movie_dir.iterdir()} == expected_names
|
||||
assert {p.name for p in replay_dir.iterdir()} == expected_names
|
||||
for name in expected_names:
|
||||
assert (movie_dir / name).read_bytes() == (replay_dir / name).read_bytes(), name
|
||||
|
||||
print('mesh-overlay CLI checks passed: colors/opacity, clean fidelity, single/movie replay')
|
||||
Reference in new issue
Block a user