Fix real-ray stop radius for decentered stops (#654)#684
Open
manuelFragata wants to merge 1 commit into
masteroptiland/optiland:masterfrom
fix/ray-aiming-654-decentered-stopoptiland/optiland:fix/ray-aiming-654-decentered-stopCopy head branch name to clipboard
Open
Fix real-ray stop radius for decentered stops (#654)#684manuelFragata wants to merge 1 commit intomasteroptiland/optiland:masterfrom fix/ray-aiming-654-decentered-stopoptiland/optiland:fix/ray-aiming-654-decentered-stopCopy head branch name to clipboard
manuelFragata wants to merge 1 commit into
masteroptiland/optiland:masterfrom
fix/ray-aiming-654-decentered-stopoptiland/optiland:fix/ray-aiming-654-decentered-stopCopy head branch name to clipboard
Conversation
The entrance pupil is the image of the stop, so a decentered stop has a decentered entrance pupil. RealReferenceStrategy probed the pupil edge by launching at (0, EPD/2) -- on the axis -- and reported the distance from the stop centre to wherever that ray landed. For a stop decentered off axis the probe never goes near the pupil, so the reported radius is unrelated to the stop. On the system reported in #654, this returned 4.04 against a true radius of ~1.0. The aimer then targeted the full pupil at a radius four times too large: the outer rays missed the stop surface entirely (NaN) and the rest were vignetted by its physical aperture, leaving only the chief ray. Solve for the pupil centre first -- the axial ray landing on the stop's own origin, which needs no stop radius -- then offset EPD/2 from there. The solve is seeded with the first-order pupil decenter (stop decenter times pupil magnification). For a centered system the seed is zero and the solve is a no-op, so the measured radius is unchanged on every system that already worked. Refs #654
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #678, which fixed the tilted-stop, back-surface-stop and folded cases but left the offset-stop case out. That case is a real solver bug, not the system-definition inconsistency the earlier file suggested.
The bug
The entrance pupil is the image of the stop, so a decentered stop has a decentered entrance pupil.
RealReferenceStrategymeasured the stop radius by launching a probe aty = EPD/2, on the axis, and reporting where it landed relative to the stop centre. When the pupil is off axis that probe never goes near it, so the reported radius is unrelated to the stop.On the system reported in the follow-up comment (a small R=5 lens,
r_max1.0, decentered to y=+5 behind a singlet):So
r_stopcame out 4.039 against a true radius of ~1.0. The aimer then targeted the full pupil four times too wide: the outer rays missed the stop surface (NaN) and the rest were vignetted by its physical aperture, leaving only the chief ray. That is the degenerate spot in the report.Note the aperture is self-consistent here: EPD 2.2622 puts the paraxial marginal ray at exactly 1.0, which is the stop's
r_max. The system is correctly defined, unlike the earlier file (EPD 20 against a radius-5 stop) that #678 set aside.The fix
Solve for the pupil centre first, the axial ray landing on the stop's own origin, which needs no stop radius, then offset
EPD/2from there. The solve reusesIterativeRayAimer._solve_coreagainst target (0, 0) and is seeded with the first-order pupil decenter (stop decenter times pupil magnification), which predicts 5.6555 against the true 5.6727 and converges immediately.For a centered system the seed is zero and the solve is a no-op, so the measured radius is unchanged by construction.
After the fix
Aimed rays land at local stop y
[-0.977, -0.489, 0.000, 0.489, 0.977]: linear inPy, centred on the stop to 1e-9, all insider_max1.0. The full disk pupil traces unvignetted.r_stopis bit-identical on every system that already worked:No system falls back to the paraxial path, so the real-ray measurement is exercised throughout.
Tests
Two regression tests in
tests/test_ray_aiming.py, on both backends: the real-ray radius must match the paraxial reference for a decentered stop, and every pupil ray must aim inside the stop's clear aperture and reach the image unvignetted. Both fail on master and pass here. The existing ray-aiming, initialization, cached-aimer and image-simulation suites are unchanged (226 passing).Refs #654