Optics: cache pixel-area Moffat kernels

This commit is contained in:
wyj committed 2026-08-28 13:53:06 -04:00
1 parent a71180706f
commit 80b891d2c8
10 files changed
+693 -56

No files matched your search

+54 -4
View File
@@ -27,7 +27,7 @@ int main(void) {
goto done;
const size_t images =
frame_splat_catalog(&mesh, &catalog, hdr, width, height, test_exposure,
&psf, 1, NULL);
&psf, NULL, 1, NULL, NULL);
if (images != 1 || hdr[3 * (50 * width + 50)] <= 0.0) {
fputs("flat-space inverse lens-map regression failed\n", stderr);
goto done;
@@ -44,10 +44,10 @@ int main(void) {
omp_set_dynamic(0);
omp_set_num_threads(1);
const size_t serial_images = frame_splat_catalog(
&mesh, &catalog, serial_hdr, width, height, test_exposure, &psf, 1, NULL);
&mesh, &catalog, serial_hdr, width, height, test_exposure, &psf, NULL, 1, NULL, NULL);
omp_set_num_threads(4);
const size_t parallel_images = frame_splat_catalog(
&mesh, &catalog, parallel_hdr, width, height, test_exposure, &psf, 1, NULL);
&mesh, &catalog, parallel_hdr, width, height, test_exposure, &psf, NULL, 1, NULL, NULL);
omp_set_num_threads(original_threads);
for (int value = 0; value < width * height * 3; ++value)
if (fabs(serial_hdr[value] - parallel_hdr[value]) >
@@ -83,6 +83,56 @@ int main(void) {
fputs("Moffat normalization or wing regression failed\n", stderr);
goto done;
}
/* The cache stores 4-point pixel-area integrals over a 64x64 sub-pixel
* lattice. Compare its bilinear interpolation with the independent 8-point
* direct reference at phases on both sides of a pixel boundary. */
PsfKernelCache cache = {0};
double *cached_hdr = calloc((size_t)width * height * 3, sizeof *cached_hdr);
double *reference_hdr = calloc((size_t)width * height * 3, sizeof *reference_hdr);
if (cached_hdr == NULL || reference_hdr == NULL ||
psf_kernel_cache_init(&cache, &psf)) {
free(cached_hdr);
free(reference_hdr);
psf_kernel_cache_destroy(&cache);
fputs("PSF cache construction regression failed\n", stderr);
goto done;
}
const double phases[][2] = {{0.01, 0.99}, {0.499, 0.501}, {0.999, 0.001}};
for (size_t phase = 0; phase < sizeof phases / sizeof *phases; ++phase) {
memset(cached_hdr, 0, (size_t)width * height * 3 * sizeof *cached_hdr);
memset(reference_hdr, 0, (size_t)width * height * 3 * sizeof *reference_hdr);
if (splat_moffat_cached(cached_hdr, width, height, 50.0 + phases[phase][0],
50.0 + phases[phase][1], (LinearRgb){1.0, 1.0, 1.0},
1.0, &psf, &cache) != 0) {
fputs("ordinary PSF cache unexpectedly fell back\n", stderr);
free(cached_hdr); free(reference_hdr); psf_kernel_cache_destroy(&cache);
goto done;
}
splat_moffat_direct(reference_hdr, width, height,
50.0 + phases[phase][0], 50.0 + phases[phase][1],
(LinearRgb){1.0, 1.0, 1.0}, 1.0, &psf);
double peak = 0.0, max_error = 0.0;
for (int value = 0; value < width * height * 3; ++value) {
peak = fmax(peak, reference_hdr[value]);
max_error = fmax(max_error, fabs(cached_hdr[value] - reference_hdr[value]));
}
if (peak <= 0.0 || max_error > 4e-5 * peak) {
fputs("PSF cache interpolation accuracy regression failed\n", stderr);
free(cached_hdr); free(reference_hdr); psf_kernel_cache_destroy(&cache);
goto done;
}
}
/* A bright event must avoid a cached hard cutoff by selecting the direct
* reference path when the requested support exceeds the cache. */
if (splat_moffat_cached(cached_hdr, width, height, 50.5, 50.5,
(LinearRgb){1.0, 1.0, 1.0}, 1000.0, &psf, &cache) != 1) {
fputs("bright PSF direct-fallback regression failed\n", stderr);
free(cached_hdr); free(reference_hdr); psf_kernel_cache_destroy(&cache);
goto done;
}
free(cached_hdr);
free(reference_hdr);
psf_kernel_cache_destroy(&cache);
frame_draw_mesh(&mesh, hdr, width, height, 0.5, 0.5);
if (hdr[3 * (10 * width + 20)] != 0.25) {
fputs("mesh diagnostic overlay regression failed\n", stderr);
@@ -102,7 +152,7 @@ int main(void) {
if (frame_lens_mesh_build_coarse(&fine_mesh, width, height, 1, 0.1) ||
frame_lens_mesh_trace(&fine_mesh, &spacetime, &observer, &trace) ||
frame_splat_catalog(&fine_mesh, &fine_catalog, hdr, width, height,
test_exposure, &psf, 1, NULL) != 1) {
test_exposure, &psf, NULL, 1, NULL, NULL) != 1) {
fputs("fine source-triangle containment regression failed\n", stderr);
frame_lens_mesh_destroy(&fine_mesh);
goto done;