Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set decenter/tilt in a correct way #153

Open
TLawu opened this issue Aug 17, 2024 · 7 comments
Open

How to set decenter/tilt in a correct way #153

TLawu opened this issue Aug 17, 2024 · 7 comments

Comments

@TLawu
Copy link

TLawu commented Aug 17, 2024

Dear Mike,

I raised an issued in mjhoptics/ray-optics-notebook.
Since it didn't have other issues, then I put the link here.
mjhoptics/ray-optics-notebooks#16

Hopefully, I can get the solution.
Best regards,
Tjundewo

@mjhoptics
Copy link
Owner

Hi @TLawu,

First, I think the layout plot is misleading, if not wrong. So this is an issue. I'll look into this.

Second, I presume your intent is to "float" the 2nd lens inside of the immersing medium. In this case, the entries for the second, reverse decenter need to be modified a bit.

The reverse decenter is the correct choice for returning to the original axis. The angles are applied in reverse, making entry for this case simple.

The translation, however needs adjustment. The translation between surfaces 4 and 5 is tilted by a 5 deg angle, so the distance along the original Z axis is cos(tilt)*lens_thickness. The change in the original thickness can be input as a Z-component of the decenter.
The vertex of the 2nd lens surface, surface 5, is further from the axis than surface 4. The y decenter for surface 5 should be original_offset+sin(tilt)*lens_thickness.
The inputs, suitably parameterized, look like this:

sm.ifcs[4].decenter = srf.DecenterData('decenter')
sm.ifcs[5].decenter = srf.DecenterData('reverse')

offset=0.5
tilt=5.0
tilt_rad=np.deg2rad(tilt)
thi=sm.gaps[4].thi
sm.ifcs[4].decenter.dec = np.array([0., offset, 0.])
sm.ifcs[5].decenter.dec = np.array([0., 
                                    offset + np.sin(tilt_rad)*thi, # y decenter
                                    (np.cos(tilt_rad) - 1)*thi])   # z decenter
sm.ifcs[4].decenter.euler = np.array([tilt, 0., 0.])
sm.ifcs[5].decenter.euler = np.array([tilt, 0., 0.])
opm.update_model()

There is a method in seq_model to print all of the surface coordinates in a single, global, coordinate system. The format for each surface is the rotation matrix, following by the vertex coordinate vector.

sm.list_gbl_tfrms()
 0:    1.000000    0.000000    0.000000       0.00000
       0.000000    1.000000    0.000000       0.00000
       0.000000    0.000000    1.000000  -10000000000.00000

 1:    1.000000    0.000000    0.000000       0.00000
       0.000000    1.000000    0.000000       0.00000
       0.000000    0.000000    1.000000       0.00000

 2:    1.000000    0.000000    0.000000       0.00000
       0.000000    1.000000    0.000000       0.00000
       0.000000    0.000000    1.000000       0.55000

 3:    1.000000    0.000000    0.000000       0.00000
       0.000000    1.000000    0.000000       0.00000
       0.000000    0.000000    1.000000       3.60000

 4:    1.000000    0.000000    0.000000       0.00000
       0.000000    0.996195    0.087156       0.50000
       0.000000   -0.087156    0.996195       3.60000

 5:    1.000000    0.000000    0.000000       0.00000
       0.000000    0.996195    0.087156       0.84862
       0.000000   -0.087156    0.996195       7.58478

 6:    1.000000    0.000000    0.000000       0.00000
       0.000000    1.000000    0.000000      -0.00000
       0.000000    0.000000    1.000000      24.19655

It is also useful to use listobj() to get at all the data for an object.

listobj(sm.ifcs[5])
transmit
profile: Spherical
c=-0.16666666666666666,   r=-6.0
decenter type: reverse
decenter: [ 0.          0.84862297 -0.01522121]
euler angles: [5. 0. 0.]
surface_od=3.0

I believe the raytrace results for the decentered model are correct, but the layout clearly isn't useful as it stands. I'll look into it.
Mike

@TLawu
Copy link
Author

TLawu commented Aug 18, 2024

Dear Mike,

Thanks for the quick response.
So, in this case, I need to handle surface 5 for return dec and the problem is in the layout, but not the ray trace.

When I need to shift and tilt the pupil, is it better to shift and tilt all other components (not the STOP itself)?
Currently, I use Zemax and want to stop using it in the future.
My needs are only to calculate the optical model (eye model) in this issue (and its little modification) with dec/tilt in pupil, lens and/or cornea.
Analyses are only paraxial focus, LSA, and wavefront error. These analyses are done based on your valuable advices previously (in the discussion about constant index)
I can calculate the PSF, MTF using the resulted wavefront error.

Regards,
Tjundewo

@mjhoptics
Copy link
Owner

Tjundewo,
You should be able to decenter the stop surface directly without having to modify the rest of the model.
Mike

@TLawu
Copy link
Author

TLawu commented Aug 20, 2024

Dear Mike,

Just to confirm, to decenter the stop surface, are decenter and reverse at the same surface number?

sm.ifcs[3].decenter = srf.DecenterData('decenter')
sm.ifcs[3].decenter = srf.DecenterData('reverse')

sm.ifcs[3].decenter.dec = np.array([0., 0.5, 0.])
sm.ifcs[3].decenter.dec = np.array([0., 0.5, 0.])

Thank you.
Tjundewo

@mjhoptics
Copy link
Owner

For this situation, the 'dec and return' decenter type is the best choice.

sm.ifcs[3].decenter = srf.DecenterData('dec and return')
sm.ifcs[3].decenter.dec = np.array([0., 0.5, 0.])

This decenter type decenters and tilts the surface and then returns to the starting point and orientation.

@TLawu
Copy link
Author

TLawu commented Aug 20, 2024

Dear Mike,

Great.
This 'dec and return' solve my doubt for decentering/tilting for one surface.
I assume 'dec and return' applied also for tilt

sm.ifcs[3].decenter = srf.DecenterData('dec and return')
sm.ifcs[3].decenter.dec = np.array([0., 0.5, 0.])
sm.ifcs[3].decenter.euler = np.array([5., 0., 0.])

and since only one surface, then no need to calculate offset as explained above.

I do hope also for the improvement of the layout.

Additionally, I can set pupil float by stop using set_pupil(opm) and set entrance pupil diameter by osp['pupil'].value.
When using set_pupil(opm), then the sd value of stop is applied to trace the correct osp['pupil'].value
But when using osp['pupil'].value, the sd value of stop is remain unchanged.
How to set the correct sd value to the surface stop based on the trace result osp['pupil'].value?
I need to do this when calculating the wavefront to get the correct size.

wfe = rayoptics.raytr.analyses.eval_wavefront(opm, fld, wvl, foc, num_rays=65)

Best regards,

Tjundewo

@mjhoptics
Copy link
Owner

mjhoptics commented Aug 20, 2024 via email

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

No branches or pull requests

2 participants