Feat: Add single-frame observer coordinate time option
This commit is contained in:
1 parent
b3f1e837d5
commit
69a8cb5647
4 files changed
+69
-11
No files matched your search
@@ -115,14 +115,15 @@ def map_vertices(path):
|
||||
return values, data[offset:offset + triangles * MAP_TRIANGLE_SIZE]
|
||||
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix='gr-camera-cli-') as directory:
|
||||
with tempfile.TemporaryDirectory(prefix='gr-camera-cli-', dir='/tmp/opencode') as directory:
|
||||
tmp = Path(directory)
|
||||
for backend in ('minkowski', 'schwarzschild'):
|
||||
binary = BUILD / f'{backend}_sky'
|
||||
help_text = run(binary, '--help').stdout
|
||||
ext = 'png' if '.png' in help_text else 'ppm'
|
||||
hdr_available = '--hdr-output' in help_text
|
||||
for option in ('--observer-position', '--observer-velocity', '--camera-roll-deg'):
|
||||
hdr_available = any(line.startswith(' --hdr-output ')
|
||||
for line in help_text.splitlines())
|
||||
for option in ('--observer-time', '--observer-position', '--observer-velocity', '--camera-roll-deg'):
|
||||
assert option in help_text
|
||||
assert '--tone-map' in help_text and '--tone-map-p' in help_text
|
||||
assert '--sensor-bloom-limit' in help_text
|
||||
@@ -162,6 +163,15 @@ with tempfile.TemporaryDirectory(prefix='gr-camera-cli-') as directory:
|
||||
assert pole == render('pole_explicit', '--observer-position', 0, 0, 30,
|
||||
'--look-ra-deg', 0, '--look-dec-deg', -90)
|
||||
default = render('default')
|
||||
# Stationary backends are time-translation invariant; the event time
|
||||
# must nevertheless survive in lens-map metadata, including negatives.
|
||||
for time in (0, 12.5, -12.5):
|
||||
timed_map = tmp / f'{backend}_time_{time}.grlens'
|
||||
assert default == render('timed', '--observer-time', time,
|
||||
'--lens-map-output', timed_map)
|
||||
saved_time, proper_time = struct.unpack_from(
|
||||
'<dd', timed_map.read_bytes(), MAP_FRAME_HEADER_START + 8)
|
||||
assert saved_time == time and proper_time == 0
|
||||
pos = (0, 0, 0) if backend == 'minkowski' else (0, 0, 30)
|
||||
assert default == render('default_explicit', '--observer-position', *pos,
|
||||
'--look-ra-deg', 90, '--look-dec-deg', -90)
|
||||
@@ -221,6 +231,15 @@ with tempfile.TemporaryDirectory(prefix='gr-camera-cli-') as directory:
|
||||
assert 'PSF cache ready' not in too_long.stderr
|
||||
|
||||
errors = [
|
||||
(['--observer-time'], None),
|
||||
(['--observer-time', ''], None),
|
||||
(['--observer-time', 'bad'], None),
|
||||
(['--observer-time', 'nan'], None),
|
||||
(['--observer-time', 'inf'], None),
|
||||
(['--observer-time', '-inf'], None),
|
||||
(['--observer-track', 'missing.csv', '--observer-time', 0], 'cannot be combined'),
|
||||
(['--frames-dir', tmp, '--observer-time', 0], 'cannot be combined'),
|
||||
(['--lens-map-input', 'missing.grlens', '--observer-time', 0], 'cannot be combined'),
|
||||
(['--observer-position', 1, 2], None),
|
||||
(['--observer-position', 1, 2, 'nan'], None),
|
||||
(['--observer-velocity', 0, 0, 'inf'], None),
|
||||
@@ -443,3 +462,30 @@ with tempfile.TemporaryDirectory(prefix='gr-camera-cli-') as directory:
|
||||
f'movie lens map changed with {threads} threads'
|
||||
print('schwarzschild: movie lens map identical with 1, 4 and 16 threads', flush=True)
|
||||
print(f'{backend}: CLI checks passed; single/movie image identical, map max error {max_error:.3g}', flush=True)
|
||||
|
||||
# In the moving bubble, (t, x) -> (t+T, x+v_s*T) preserves the
|
||||
# metric and physical ray endpoints. This detects a stale t=0 in either
|
||||
# camera metric evaluation or ray initialization, not just map metadata.
|
||||
alc = BUILD / 'alcubierre_sky'
|
||||
if alc.exists():
|
||||
reference = None
|
||||
for time in (0, 12.5, -12.5):
|
||||
path = tmp / f'alcubierre_time_{time}.grlens'
|
||||
run(alc, *common, '--alcubierre-vs', 0.3,
|
||||
'--alcubierre-radius', 1, '--observer-time', time,
|
||||
'--observer-position', 0.3 * time, 0, 0,
|
||||
'--observer-velocity', 0.3, 0, 0,
|
||||
'--look-ra-deg', 0, '--look-dec-deg', 0,
|
||||
'--lens-map-output', path, '--output', tmp / 'alcubierre.png')
|
||||
assert struct.unpack_from('<d', path.read_bytes(),
|
||||
MAP_FRAME_HEADER_START + 8)[0] == time
|
||||
vertices, triangles = map_vertices(path)
|
||||
if reference is None:
|
||||
reference = vertices, triangles
|
||||
continue
|
||||
expected, expected_triangles = reference
|
||||
assert len(vertices) == len(expected) and triangles == expected_triangles
|
||||
for actual, baseline in zip(vertices, expected):
|
||||
assert actual[9:12] == baseline[9:12]
|
||||
assert max(abs(a - b) for a, b in zip(actual[:9], baseline[:9])) < 1e-8
|
||||
print('alcubierre: nonzero camera-time translation checks passed', flush=True)
|
||||
Reference in new issue
Block a user