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
@@ -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())
|
||||
Reference in new issue
Block a user