Repository navigation
Outline the beam on any surface of a sequential system - #258
Merged
Merged
Conversation
`AbstractSequentialSystem.beam_footprint(index, wavelength, samples_field_stop, samples_pupil_stop)` gives the convex hull of where the light which reaches the end of the system crosses one of its surfaces, as a `PolygonalAperture` in the local coordinates of that surface. The hull is that of the rays which graze the edges of both stops, solved for as they are for `rayfunction_stops` and traced through the whole system with both stops left open, since rounding would block about half of the rays on their edges. A grid of rays finds the corners of the hull only to within its spacing, which shrinks as the fourth root of the number of rays, against the square root along the edges. The logic which opens a surface moves from `_surfaces_open` into `_surfaces_opened`, which both use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
`beam_footprint` needs `na.geometry.convex_hull`, from sun-data/named-arrays#270, which is not released yet. Go back to `named-arrays~=2.15` once it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #258 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 129 129
Lines 10031 10181 +150
==========================================
+ Hits 10031 10181 +150
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
So that the transformation of a stop's own aperture is carried into the outline on it, and the branch of the test which applies it runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
It was released with sun-data/named-arrays#270, so `pyproject.toml` no longer needs to take named-arrays from that PR's branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
- The outline is the hull of the rays of the default grid as well as of the rays along the edges of the stops. The rays along the edges missed a corner of another aperture which lies inside the beam, and an aperture smaller than the beam everywhere blocked all of them, which left an outline of NaN although light reached the end. The grid fills both in, to within its spacing, so the outline now holds every ray of the grid which reaches the end, and is NaN only where none does. - With more than one surface marked as either stop, the stops left open are the pair the solve finishes on, which `_pairs_stops` now gives to both. They used to be the last surface marked as each, which can be a different pair, so the stop the rays were solved on stayed closed and another was opened. - The docstring says the outline is in the local coordinates of the surface, which differ from those an aperture with a transformation of its own gives its vertices in. - `_surfaces_opened` is renamed `_surfaces_with_open`, and takes the surfaces its caller has already built. - The tests allow for the chords between the samples along the edge of a round stop by their sagitta, rather than by a tolerance smaller than it which passed only because the default grid's rays on the edges land on samples. A new test traces a grid whose rays fall between the samples. - The abstract test requires every outline to be a number, rather than allowing NaN for every system. - New tests cover a corner of the sensor inside the beam, a second pupil stop, and outlines at other wavelengths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
roytsmart
marked this pull request as ready for review
October 12, 2026 21:11
roytsmart
added a commit
to esis-mission/esis-instrument-paper
that referenced
this pull request
Oct 12, 2026
The footprints on the primary mirror were the hull of a grid of 1.2 million rays, which fell short of their true outline by up to 2 mm and rounded off its corners. `beam_footprint` (sun-data/optika#258, released in optika 3.2) outlines them from the rays along the edges of the field stop and the grating, which converge to within 0.1 mm for about as many rays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP
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.
Adds
AbstractSequentialSystem.beam_footprint(index, wavelength=None, samples_field_stop=401, samples_pupil_stop=401). It returns the outline of the beam on one surface of a system, meaning the convex hull of where the light that reaches the end of the system crosses that surface. The result is aPolygonalAperturein the surface's local coordinates. An aperture with a transformation of its own gives its vertices before that transformation, so on a stop the outline matchesaperture.transformation(aperture.vertices).The ESIS instrument paper needs it to draw each channel's footprint on the primary mirror (esis-mission/esis-instrument-paper#18). Baffles need the same outline at each baffle.
The hull comes from
na.geometry.convex_hull(sun-data/named-arrays#270), released in named-arrays 2.15, sopyproject.tomlnow requiresnamed-arrays~=2.15.f1d2e83 fixes what a review found.
How
The outline is the hull of two sets of rays, each traced through the whole system, keeping only those that reach its end:
rayfunction_stopssolves them, at as many samples along each edge as asked for.grid_input, atwavelength, traced asraytracetraces them.Why both:
Where the stops bound the beam, every ray that reaches the end passes inside both stops, and the outermost of them pass through both edges. So the rays along the edges find the outline, much more sharply than a grid (see below).
Clipping: where another aperture cuts the beam, the corners it makes where its edge crosses the outline of the beam are found from the rays along the edges too, to within the spacing of the samples.
What the edges miss, the grid fills in, to within its spacing:
So the outline always holds every ray of the grid that reaches the end, and its vertices are NaN only where no ray arrives.
Rounding at the edges: each ray along the edges lies on the edge of both stops, where rounding would block about half of them. Both stops are therefore left open for that trace, the way
_surfaces_openleaves the field stop open._surfaces_with_open(surfaces, indices), which both use;_surfaces_openis unchanged._pairs_stops(surfaces)gives the pairs, and the solve in_calc_rayfunction_stops_onlynow iterates over them, so the two can't disagree.Why not a grid of rays alone
A grid over the field and the pupil finds the corners of the hull only to within its spacing. That spacing shrinks as the fourth root of the number of rays; along the edges of the stops it shrinks as the square root. For the ESIS footprints on the primary mirror:
The grid's hull falls short of the true one. The edge outline reaches 0.3–0.5 mm beyond the billion-ray hull, which is about what that hull's own convergence implies it is short by. Between 401 × 401 and 401 × 1001 edge samples, the outline moves by less than 0.08 mm.
Limitations
TestSequentialSystemis like this: its object aperture, 10 mm, is inside the ±20 mm field of its marked field stop.na.geometry.convex_hulldoesn't support uncertain components yet, so neither does this. That belongs in named-arrays.Tests
test_beam_footprint(abstract, every test system), on every surface:test_beam_footprint_holds_rays_between_the_samples: this runs on the four systems in which nothing but the stops blocks a ray. On every surface, the outline holds every ray of a 6² field × 30² pupil grid that reaches the end. The tolerance is the sagitta of the chords that 21 samples cut across a round stop. This grid's rays on and near the edges fall between the samples, where the default grid's land on them.test_beam_footprint_on_a_stop_is_the_stop: this uses a system with rectangular stops and no other apertures, one stop off its center. On both stops, the outline equals the stop, compared by support function over a fan of directions. The system is moved rigidly first, so an outline left in the wrong frame fails.test_beam_footprint_is_cut_by_an_aperture_with_straight_edges: this uses the Newtonian test telescope, with a straight-edged obscuration that cuts off one side of the beam.test_beam_footprint_holds_a_corner_inside_the_beam: this moves the Newtonian telescope's sensor so that its corner lies at the center of the image. The outline on the sensor then holds every ray of the default grid, including those at the corner.test_beam_footprint_opens_the_stops_the_solve_finishes_on: this marks the Newtonian telescope's primary as a pupil stop too, and shrinks the last-marked pupil stop to 5 mm. The outline on that stop stays inside it.test_beam_footprint_at_other_wavelengths: this uses the grazing spectrograph. Outlines at three wavelengths along an axis of their own each match the outline of the same system with its default grid at that wavelength, and the grating moves them across the sensor.ruffandblackpass, and the optika suite passes against named-arrays 2.15.0.🤖 Generated with Claude Code
https://claude.ai/code/session_01BYjDL98znSud1yFh9chnkP