Skip to content

Paraxial surfaces: fixes for tracing and rendering#514

Open
rjmoerland wants to merge 7 commits intomasterfrom
robert/f2-mirror
Open

Paraxial surfaces: fixes for tracing and rendering#514
rjmoerland wants to merge 7 commits intomasterfrom
robert/f2-mirror

Conversation

@rjmoerland
Copy link
Collaborator

@rjmoerland rjmoerland commented Mar 12, 2026

Background
While working on #382 I ran into a few issues regarding the handling of paraxial mirrors, and the backward tracing of real rays through paraxial surfaces. Those issues lead to erroneous results for the locations and magnitudes of the front and back focal plane when paraxial mirrors are involved. In addition, the RealRay interaction with paraxial surfaces was not handling backward tracing well, leading to confusing ray diagrams that did not reflect the expected outcome.

This PR hopes to address these shortcomings, and consists of two parts:

  1. Fixing the tracing of paraxial rays through the system that includes rays bouncing back from paraxial mirrors.
  2. Fixing the interaction of real rays with paraxial surfaces, in order to fix the display of the ray diagram.

Approach
The tracing of rays through real surfaces seems to be accurate regardless the direction, and also the paraxial calculations (f1, f2, etc.) seem accurate. Therefore, I've used the outcome of "real" models as the "gold standard" to compare the results with when using paraxial surfaces.

Sign convention:
For mirrors and a collimated beam coming from the left, the rays will be focused to the left of the surface when the focal length is negative. For a positive focal length, the rays will seem like coming from the right of the surface. The sign is flipped for rays coming from the right, i.e., after having reflected off an mirror earlier in the path. This sign convention seems to be in step with real mirrors: for a collimated beam coming from the left, a negative radius yields a real focus on the left, and a positive radius gives a virtual focus on the right. For rays from the right, it's vice versa.

Examples
Below I show a few examples of problematic lens systems. I tabulated the outcome of the paraxial calculations as obtained from master (at the time of writing based on this commit ), together with the outcomes obtained with the code in this PR (labeled as "This PR") and the outcome of paraxial calculations for an equivalent "real" lens system. Sometimes the results from master and this PR are identical, but then the ray diagram is off, sometimes both are off.

Below each table I plot the ray diagrams as obtained with the master branch, this branch, and the equivalent real systems. Also here, the paraxial ray diagrams obtained with this branch and the equivalent real systems are identical.

Example 1

A single paraxial mirror, with focal length -50 (real focus to the left):

f1 F1 P1 f2 F2 P2
Master 50.000 50.000 0.000 -50.000 -50.000 0.000
This PR -50.000 -50.000 0.000 -50.000 -50.000 0.000
Real mirror* -50.000 -50.000 0.000 -50.000 -50.000 0.000

*R = -100

master
image

This PR
image

Reference equivalent system
image

Example 2

A paraxial lens with f=50, followed by a flat mirror at 10 units distance, reflecting the light back through the lens:

f1 F1 P1 f2 F2 P2
Master -31.250 -18.750 12.500 -31.250 -18.750 12.500
This PR -31.250 -18.750 12.500 -31.250 -18.750 12.500
Real lens* -31.250 -18.750 12.500 -31.250 -18.750 12.500

*Lens consisting of two surfaces with R = 100 and R = -100, respectively, with n = 2 and thickness 0.

master
image

This PR
image

Reference equivalent system
image

Example 3

Two paraxial mirrors, with f = -50 and f = 50 respectively, and a gap of 20 in between:

f1 F1 P1 f2 F2 P2
Master 20.833 29.167 8.333 31.250 -1.250 -32.500
This PR -31.250 -18.750 12.500 31.250 -1.250 -32.500
Real mirrors* -31.250 -18.750 12.500 31.250 -1.250 -32.500

*Real mirrors with radius -100 and +100, respectively.

master:
image

This PR:
image

Reference equivalent system
image

Final remark
As far as my understanding goes, the paraxial ray tracer seems like it was written largely with linear optical lens systems in mind, and perhaps at a time when computing power was more limited. Optiland's real ray tracing has no issues with tracing rays through 3D space, and though I don't know what the best approach would be, I would like to see a fully vectorial approach for paraxial rays as well. Ideally, surfaces would be placed in the optical system with well-defined surface normals, and those normals would be used for paraxial ray tracing. In that case, there could be no confusion about the direction from which light is hitting the element. But, perhaps this is already considered in the non-sequential mode?

As a thought, perhaps attaching a ThinLensInteractionModel to every real surface, to be used during paraxial ray tracing only, could be a way to leverage the current RealRay tracing engine to obtain paraxial results relatively easily?

@codecov
Copy link

codecov bot commented Mar 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #514      +/-   ##
==========================================
+ Coverage   93.19%   93.28%   +0.08%     
==========================================
  Files         309      319      +10     
  Lines       18292    18849     +557     
==========================================
+ Hits        17048    17583     +535     
- Misses       1244     1266      +22     
Files with missing lines Coverage Δ
...tiland/interactions/thin_lens_interaction_model.py 94.64% <100.00%> (+1.30%) ⬆️
optiland/paraxial.py 92.73% <100.00%> (ø)
optiland/raytrace/paraxial_ray_tracer.py 98.36% <100.00%> (+3.27%) ⬆️

... and 74 files with indirect coverage changes

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

@rjmoerland rjmoerland force-pushed the robert/f2-mirror branch 2 times, most recently from 015050d to 6d13933 Compare March 14, 2026 10:08
@rjmoerland rjmoerland marked this pull request as ready for review March 15, 2026 12:15
@rjmoerland
Copy link
Collaborator Author

rjmoerland commented Mar 15, 2026

@HarrisonKramer, tangentially related to this PR: I've struggled with this much longer than one might think, based on the number of lines that are changed in the core framework. This was mostly because of the bugs with the signs described above, as now sign convention seems to be pretty consistent. I was thinking, would there be room for a tutorial on the sign conventions (if we agree on this PR)? I am thinking of putting it somewhere between the existing 1a 1b tutorials, and could deal with real (spherical) surfaces and paraxial surfaces.
Edit: and I'm volunteering to create it

@HarrisonKramer
Copy link
Owner

Hi @rjmoerland,

Thanks for this deepdive and the fix! It's clear there are flaws in the master branch implementation. Your fix looks solid, and the new sign handling makes sense. I think we can already merge this, but let me answer your questions here first.

First, you're right that paraxial raytracing logic was implemented with only simple linear systems in mind. I have come across a few cases, in which the assumptions here have failed. It very likely makes the most sense just to extend the paraxial ray tracing capability to 3D. I need to explore this in more detail, but I agree that it will effectively just be an extension of the 3D real ray tracing engine, but while using the paraxial assumptions.

Adding a ThinLensInteractionModel could also work, though my first instinct is that this might be more complex than needed. Happy to be proven wrong here though. I would like to investigate the possibilities here, then come back to it, if that's okay for you. If I create an issue (or later a PR), I will plan to reference you there too, so you can review any proposals.

And yes, a new tutorial would be great! If it's not clear for you, then it's unlikely it will be clear for the general user. Improving clarity here makes sense. Perhaps we can also update the docs if needed. For example, there's already a section on sign conventions in the cheat sheet.

Thanks again, and let me know if this PR is ready and I will merge.

Kramer

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.

2 participants