Test: add fixed PSF image references
This commit is contained in:
1 parent
ab56e23fc9
commit
4953775cdd
8 files changed
+165
No files matched your search
@@ -123,3 +123,4 @@ clean:
|
||||
rm -rf build
|
||||
|
||||
-include $(RENDER_DEPS)
|
||||
include mk/reference_images.mk
|
||||
@@ -0,0 +1,70 @@
|
||||
# PSF event-sink image references
|
||||
|
||||
Run date: 2026-09-04
|
||||
|
||||
Purpose: fixed pixel-comparison references before replacing the sink consumer
|
||||
with HIP. The renderer used the default CPU `PSF_EVENT_SINK=1` path. There
|
||||
was no adaptive refinement. The catalog is the repository test catalog, not
|
||||
an all-sky tile snapshot. This is not a performance benchmark.
|
||||
|
||||
Environment:
|
||||
|
||||
- Git `HEAD`: `ab56e23` (worktree contains the uncommitted event-sink change)
|
||||
- Build: `BUILD_TYPE=Release`, `ENABLE_HDR=1`, `ENABLE_PNG=1`, OpenMP
|
||||
- Host worker setting: `OMP_NUM_THREADS=16`
|
||||
- Images: 640 x 360 px; Moffat FWHM 2.7 px, beta 4.5
|
||||
- Observer: radius 30, inward speed 0; ICRS look direction RA 1 deg, Dec 1 deg
|
||||
|
||||
The explicit `1e300` magnification cap is the practical command-line spelling
|
||||
of the normal unlimited default. `--draw-mesh` and `--psf-direct` are absent,
|
||||
therefore disabled. All refinement thresholds are included even though level
|
||||
zero prevents refinement, so later default changes cannot affect this run.
|
||||
|
||||
## Minkowski
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
make -B SPACETIME=minkowski ENABLE_HDR=1 PSF_EVENT_SINK=1 backend
|
||||
```
|
||||
|
||||
Render:
|
||||
|
||||
```bash
|
||||
OMP_NUM_THREADS=16 build/Release/minkowski_sky --catalog assets/sky_grid_5deg.csv --output tests/data/psf_event_sink_reference/minkowski_ra1_dec1_640x360.png --hdr-output --width 640 --height 360 --fov-deg 30 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-inward-speed 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
|
||||
```
|
||||
|
||||
Result: 35 images from 5,654 catalog stars; 35 cached, 0 wing-clipped, 0 direct
|
||||
fallback, 0 min-Y discarded.
|
||||
|
||||
Versioned reference outputs:
|
||||
|
||||
- `tests/data/psf_event_sink_reference/minkowski_ra1_dec1_640x360.png`
|
||||
- `tests/data/psf_event_sink_reference/minkowski_ra1_dec1_640x360_HDR.fits`
|
||||
|
||||
## Analytic Schwarzschild
|
||||
|
||||
This reference uses a 60 deg horizontal field of view. At radius 30, the
|
||||
former 30 deg framing mostly contained the shadow and high-order images inside
|
||||
the Einstein ring, without enough field to test the first-image star field.
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
make -B SPACETIME=schwarzschild ENABLE_HDR=1 PSF_EVENT_SINK=1 backend
|
||||
```
|
||||
|
||||
Render:
|
||||
|
||||
```bash
|
||||
OMP_NUM_THREADS=16 build/Release/schwarzschild_sky --catalog assets/sky_grid_5deg.csv --output tests/data/psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360.png --hdr-output --width 640 --height 360 --fov-deg 60 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-inward-speed 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
|
||||
```
|
||||
|
||||
Result: 5,206 images from 5,654 catalog stars; 5,206 cached, 0 wing-clipped,
|
||||
0 direct fallback, 0 min-Y discarded. This is a visual regression reference,
|
||||
not a performance result.
|
||||
|
||||
Versioned reference outputs:
|
||||
|
||||
- `tests/data/psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360.png`
|
||||
- `tests/data/psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits`
|
||||
@@ -0,0 +1,16 @@
|
||||
REFERENCE_DIR := tests/data/psf_event_sink_reference
|
||||
REFERENCE_TMP_DIR := /tmp/gr_psf_event_sink_reference
|
||||
FLOATDIFF_SCRIPT := scripts/fits_floatdiff.py
|
||||
|
||||
.PHONY: test-reference-images
|
||||
|
||||
test: test-reference-images
|
||||
|
||||
test-reference-images: $(FLOATDIFF_SCRIPT) $(REFERENCE_DIR)/minkowski_ra1_dec1_640x360_HDR.fits $(REFERENCE_DIR)/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits
|
||||
$(MAKE) SPACETIME=minkowski ENABLE_HDR=1 backend
|
||||
mkdir -p $(REFERENCE_TMP_DIR)
|
||||
OMP_NUM_THREADS=16 $(BUILD_DIR)/minkowski_sky --catalog assets/sky_grid_5deg.csv --output $(REFERENCE_TMP_DIR)/minkowski_ra1_dec1_640x360.png --hdr-output --width 640 --height 360 --fov-deg 30 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-inward-speed 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
|
||||
python3 $(FLOATDIFF_SCRIPT) $(REFERENCE_DIR)/minkowski_ra1_dec1_640x360_HDR.fits $(REFERENCE_TMP_DIR)/minkowski_ra1_dec1_640x360_HDR.fits
|
||||
$(MAKE) SPACETIME=schwarzschild ENABLE_HDR=1 backend
|
||||
OMP_NUM_THREADS=16 $(BUILD_DIR)/schwarzschild_sky --catalog assets/sky_grid_5deg.csv --output $(REFERENCE_TMP_DIR)/schwarzschild_ra1_dec1_fov60_640x360.png --hdr-output --width 640 --height 360 --fov-deg 60 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-inward-speed 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
|
||||
python3 $(FLOATDIFF_SCRIPT) $(REFERENCE_DIR)/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits $(REFERENCE_TMP_DIR)/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare primary-image IEEE float values in two simple FITS files.
|
||||
|
||||
The renderer writes a single 32-bit RGB primary HDU. Keeping this dependency-
|
||||
free tool in the repository makes HDR reference comparisons available on the
|
||||
minimal Gentoo installation as well as in CI.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import math
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
def read_fits(path):
|
||||
with open(path, "rb") as stream:
|
||||
cards = []
|
||||
while True:
|
||||
block = stream.read(2880)
|
||||
if len(block) != 2880:
|
||||
raise ValueError(f"{path}: truncated FITS header")
|
||||
cards.extend(block[i:i + 80].decode("ascii") for i in range(0, 2880, 80))
|
||||
if any(card.startswith("END") for card in cards[-36:]):
|
||||
break
|
||||
values = {}
|
||||
for card in cards:
|
||||
if card[8:10] == "= ":
|
||||
values[card[:8].strip()] = card[10:30].strip()
|
||||
if values.get("BITPIX") != "-32" or values.get("NAXIS") != "3":
|
||||
raise ValueError(f"{path}: expected a 32-bit, three-axis primary image")
|
||||
shape = tuple(int(values[f"NAXIS{axis}"]) for axis in (1, 2, 3))
|
||||
count = math.prod(shape)
|
||||
payload = stream.read(count * 4)
|
||||
if len(payload) != count * 4:
|
||||
raise ValueError(f"{path}: truncated image payload")
|
||||
return shape, payload
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("reference")
|
||||
parser.add_argument("candidate")
|
||||
parser.add_argument("--abs-tolerance", type=float, default=0.0)
|
||||
parser.add_argument("--rel-tolerance", type=float, default=0.0)
|
||||
args = parser.parse_args()
|
||||
if args.abs_tolerance < 0 or args.rel_tolerance < 0:
|
||||
parser.error("tolerances must be non-negative")
|
||||
ref_shape, ref_payload = read_fits(args.reference)
|
||||
candidate_shape, candidate_payload = read_fits(args.candidate)
|
||||
if ref_shape != candidate_shape:
|
||||
print(f"shape mismatch: {ref_shape} != {candidate_shape}", file=sys.stderr)
|
||||
return 1
|
||||
maximum_abs = maximum_rel = 0.0
|
||||
mismatch_count = 0
|
||||
worst_index = 0
|
||||
for index, (reference, candidate) in enumerate(
|
||||
zip(struct.iter_unpack(">f", ref_payload),
|
||||
struct.iter_unpack(">f", candidate_payload))):
|
||||
reference, candidate = reference[0], candidate[0]
|
||||
if not math.isfinite(reference) or not math.isfinite(candidate):
|
||||
equal = reference == candidate
|
||||
absolute = relative = math.inf if not equal else 0.0
|
||||
else:
|
||||
absolute = abs(candidate - reference)
|
||||
relative = absolute / max(abs(reference), 1.0e-30)
|
||||
equal = absolute <= args.abs_tolerance or relative <= args.rel_tolerance
|
||||
if absolute > maximum_abs:
|
||||
maximum_abs, worst_index = absolute, index
|
||||
maximum_rel = max(maximum_rel, relative)
|
||||
mismatch_count += not equal
|
||||
print(f"floatdiff: shape={ref_shape} samples={math.prod(ref_shape)} "
|
||||
f"mismatches={mismatch_count} max_abs={maximum_abs:.9g} "
|
||||
f"max_rel={maximum_rel:.9g} worst_sample={worst_index}")
|
||||
return 1 if mismatch_count else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
Binary file not shown.
Reference in new issue
Block a user