Skip to content

Add grazing-incidence soft X-ray spectrograph tutorial#166

Open
jacobdparker wants to merge 7 commits into
mainfrom
tutorials/grazing-spectrometer
Open

Add grazing-incidence soft X-ray spectrograph tutorial#166
jacobdparker wants to merge 7 commits into
mainfrom
tutorials/grazing-spectrometer

Conversation

@jacobdparker

@jacobdparker jacobdparker commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new docs tutorial, docs/tutorials/grazing_spectrograph.ipynb, that designs a slitless grazing-incidence soft X-ray spectrograph end-to-end in optika:

  • a Wolter Type-I telescope — paraboloid (ParabolicSag) + confocal hyperboloid (ConicSag, k < −1), illuminated at large radius for grazing incidence;
  • a 5000 line/mm transmission grating (ConstantRulingSpacing) placed in the converging beam; and
  • a 2k × 4k CMOS detector (10 µm pixels) that records the zero-order direct image and the first-order spectrum side by side.

The design is driven by a 1 arcsec/pixel spatial plate scale (→ f ≈ 2.06 m) and a 15–20 Å first-order range. It's also a workout for parts of optika that hadn't been exercised before: grazing-incidence conic optics and transmission gratings.

Sections

  • Focal length from plate scale; aperture → grazing angle (≈0.5°)
  • Paraboloid and confocal-hyperboloid construction (with the subtlety that the hyperboloid's far focus must match the parabola's true focus at F_p − f_p for zero on-axis aberration)
  • Transmission grating + dispersion check (≈0.86 mm/Ã…, zero order on-chip)
  • Layout in the cross-dispersion plane, plus a dispersion-plane layout tracing m=0 and m=1 to show the spectral mapping onto the detector
  • Spot diagrams (on-axis near-perfect; off-axis coma sets the usable field)
  • Spatial plate-scale check
  • Au/Ir grazing reflectivity sidebar (CXRO optical constants)

Notes for reviewers

  • Independent of the in-flight FZP tutorial branch; based directly on main.
  • Notebook executes end-to-end against main (jupyter nbconvert --execute) and outputs are stripped (nbstripout).
  • Registered in the docs toctree (docs/index.rst).

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.35%. Comparing base (9d38b2c) to head (70c6dfb).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #166   +/-   ##
=======================================
  Coverage   99.34%   99.35%           
=======================================
  Files         116      116           
  Lines        5967     6045   +78     
=======================================
+ Hits         5928     6006   +78     
  Misses         39       39           
Flag Coverage Δ
unittests 99.35% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jacobdparker jacobdparker changed the title Add grazing-incidence soft X-ray spectrometer tutorial Add grazing-incidence soft X-ray spectrograph tutorial Jun 10, 2026
jacobdparker and others added 7 commits June 10, 2026 16:15
A new docs tutorial that designs a slitless grazing-incidence soft X-ray
spectrometer end-to-end: a Wolter Type-I telescope (paraboloid + confocal
hyperboloid), a 5000 line/mm transmission grating in the converging beam, and
a 2k x 4k CMOS detector. Driven by a 1 arcsec/pixel plate scale and a 15-20 A
first-order range, it exercises grazing-incidence conic optics and
transmission gratings (both new territory for optika) and includes layout,
dispersion, spot-diagram, plate-scale, and grazing-reflectivity sections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add optika.apertures.AnnularAperture: a ring-shaped aperture defined by an
inner and outer radius, with optional angle_start/angle_stop arguments that
restrict it to an annular sector (full ring by default). This is the natural
stop for a grazing-incidence mirror, which is physically a thin ring with a
central obscuration. Includes a full parametrized test class.

Use it for the telescope mirror stops in the grazing-spectrometer tutorial
(sized to pass the full beam, so the imaging analysis is unchanged), and draw
the mirrors in the layout plots as their meridional sag profiles. system.plot
draws each surface's aperture rim, which on these near-cylindrical grazing sags
falls hundreds of mm apart in z and does not depict the optic faithfully.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Place the solar source at z = -0.7 m instead of -0.2 m: the paraboloid's outer
illuminated radius lies near z = -0.3 m on the steep grazing flank, so the
previous position left those rays travelling backwards to reach the mirror.

Add an "Aperture footprints" section that traces the full field and pupil and
scatters the ray intercepts on each optic (both mirrors and the grating) over
its clear-aperture outline, confirming the annular footprints sit inside the
annular stops and the beam under-fills the grating.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This instrument records the full dispersed spectrum on the detector array in a
single exposure, which is properly a spectrograph rather than a spectrometer.
Rename the notebook (and its toctree entry) and update the title, intro, and
summary text accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The primary and secondary mirrors overlapped in z: because the grazing flank is
so steep, each mirror is hundreds of mm long axially, and with the secondary
near z = 250 mm part of the converging beam could only reach it by travelling
backward. Those rays imaged correctly (a conic images its foci from any point on
the sheet) but were unphysical and showed up as backward segments in the layout.

Separate the mirrors axially: shorten the mirror (and fix a factor-of-two in the
annulus half-width, L*tan(a)/2) and move the secondary to z_intercept = 500 mm,
with the grating just downstream at z = 800 mm. Every segment now advances in z
and the layout shows a clean two-bounce fold. The longer telescope shifts the
principal plane and shortens the grating lever arm, so the plate scale
(~1.16"/pix) and dispersion (~0.63 mm/A) are a bit coarser; the narrative and
summary now explain this trade-off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The same grating diffracts the 15-20 A band into every order. Add the second
order (m=2) to the dispersion section: it lands at x ~ -7 to -13 mm (sensor
local), still on the 4k axis, at twice the deflection — so twice the dispersion
and a separate, higher-resolution copy of the spectrum. The dispersion-layout
zoom now traces m = 0, 1, 2 (grey / solid / dashed), and the printout reports
the first- and second-order positions; the narrative notes the order overlap
inherent to a slitless spectrograph.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Diffraction orders are now a single named "order" axis on one grating
  (dataclasses.replace + diffraction_order=na.ScalarArray([0,1,2])), so the
  dispersion layout and the centroid table come from one vectorized ray trace
  each instead of rebuilding a SequentialSystem per order.
- Replace manual `.ndarray.value` extraction + boolean masking with
  named-array `.mean(axis=..., where=unvignetted)` for the order centroids and
  the plate-scale image shift (also more correct: averages only unvignetted
  rays rather than nanmean over all).
- Clarify the "Building the system" note: normalized field/pupil coordinates
  are not usable here because the normalization's backward raytrace does not
  converge for this grazing geometry (Max iterations exceeded), independent of
  the conic-intercept fix in #167.

Outputs unchanged (centroids, plate scale, and all figures identical).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant