Open yohann95 opened 3 months ago
Hello @yohann95, You're correct that ray-optics doesn't match OSLO. I looked into this some and I think OSLO has the correct answer. The underlying data and calculations are correct; the issue was calculating the NA from the paraxial data.
from rayoptics.environment import *
opm = OpticalModel()
sm = opm['seq_model']
osp = opm['optical_spec']
pm = opm['parax_model']
em = opm['ele_model']
pt = opm['part_tree']
ar = opm['analysis_results']
opm.system_spec.dimensions = 'mm'
opm.radius_mode = True
osp['pupil'] = PupilSpec(osp, key=['object', 'epd'], value=2*12.)
osp['fov'] = FieldSpec(osp, key=['object', 'angle'], value=0.)
osp['wvls'] = WvlSpec([(800., 1.)], ref_wl=0)
sm.gaps[0].thi=1e10
sm.add_surface([1e10, 0.])
sm.set_stop()
sm.add_surface([11.325, 9.45, 1.755])
sm.ifcs[sm.cur_surface].profile = EvenPolynomial(
r=11.325,cc=-0.63,coefs=[0., 5.0056e-06, -2.968e-08, -2.3959e-10, -6.0923e-13])
sm.add_surface([1e10, 9.6154])
opm.update_model()
layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm, is_dark=False).plot()
listobj(osp)
aperture: object epd; value=24.0
field: object angle; value=1.0
x,y=0.0 vlx= 0.000 vux= 0.000 vly= 0.000 vuy= 0.000
y=1.0 vly= 0.000 vuy= 0.000 vlx= 0.000 vux= 0.000
central wavelength= 800.0000 nm
wavelength (weight) = 800.0000 (1.000)*
focus shift=0.0
pm.first_order_data()
efl 15
f 15
f' 15
ffl -15
pp1 -6.098e-09
bfl 9.615
ppk -5.385
pp sep 4.065
f/# 0.625
m -1.5e-09
red -6.667e+08
obj_dist 1e+10
obj_ang 1
enp_dist -0
enp_radius 12
na obj 1.2e-09
n obj 1
img_dist 9.615
img_ht 0.2618
exp_dist -5.385
exp_radius 12
na img -0.6247
n img 1
optical invariant 0.2095
pm.list_model()
ax_ht pr_ht ax_slp pr_slp power tau index type
0: 0 -1.74551e+08 1.2e-09 0.0174551 0 1e+10 1.00000 dummy
1: 12 0 1.2e-09 0.0174551 0 0 1.00000 transmit
2: 12 0 -0.8 0.0174551 0.06666667 5.38462 1.75500 transmit
3: 7.69231 0.0939888 -0.8 0.0174551 -7.55e-11 9.6154 1.00000 transmit
4: -1.22841e-05 0.261826 -0.8 0.0174551 0 0 1.00000 dummy
The paraxial slope in image space is 0.8, in agreement with Oslo. The NA is defined as
NA = n sin(theta)
ray-optics calculates the (paraxial) NA by converting the slope to an angle and taking the sine of that. For high NA systems, such as yours, the sine and tangent differ substantially.
slope = pm.ax[-1][mc.slp]
angle = math.atan(slope)
NA = math.sin(angle)
print(f"{slope=:8.4f} {angle=:8.4f} {NA=:8.4f}")
slope= -0.8000 angle= -0.6747 NA= -0.6247
While this may have some logic to it, it may not be right. I did a quick bookshelf survey and Shannon clearly states
paraxial NA = n * slp
I'll change ray-optics to match OSLO's and Shannon's definition of paraxial NA.
To calculate the real ray NA, trace an axial marginal ray.
f0 = osp['fov'].fields[0]
wvl = osp['wvls'].central_wvl
marg_ray, err = trace_ray(opm, [0, 1], f0, wvl,
output_filter=None, rayerr_filter=None)
list_ray(marg_ray)
X Y Z L M N Len
0: 0.00000 12.00000 0 0.000000 0.000000 1.000000 1e+10
1: 0.00000 12.00000 7.2e-09 0.000000 0.000000 1.000000 7.0803
2: 0.00000 12.00000 7.0803 0.000000 -0.426858 0.904319 2.6205
3: 0.00000 10.88143 5.9203e-09 0.000000 -0.749136 0.662417 14.516
4: 0.00000 0.00725 0 0.000000 -0.749136 0.662417 0
The "real" NA is the sine of the image space marginal ray angle. For the axial marginal ray, this is equal to the M direction consine.
print(f"real ray NA={marg_ray.ray[-1].d[1]:8.4f}")
real ray NA= -0.7491
The transverse ray aberration curves show high order coma, so the system isn't aplanatic.
ta_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='Ray',
scale_type=Fit.All_Same, dpi=130).plot()
Hope this helps. Feel free to ask further questions.
Mike Hayford
Hello Mike, Thank you very much for your return. That completely answers my question. There is still a little mismatch between the Oslo NA (=0.80) and the ray-optics NA (=0.75), but this time I think Oslo is wrong. The value of NA=0.80 is not consistent with the Oslo graphical representation... I have a second question but not related to this one so I open another issue. Yohann
Hello Mike, First thank you for your return by email. I ask my next question here.
I have noticed a big difference between the NA given by ray-optics and given by Oslo for high NA aspheric lenses. I the example here, Oslo gives 0.8 and ray-optics gives 0.67. What is the reason for that ?
from rayoptics.environment import OpticalModel, PupilSpec, FieldSpec, WvlSpec, EvenPolynomial
opm = OpticalModel() opm.system_spec.dimensions = 'mm' opm.radius_mode = True
sm = opm['seq_model'] osp = opm['optical_spec'] pm = opm['parax_model'] ar = opm['analysis_results']
osp['pupil'] = PupilSpec(osp, key=['object', 'epd'], value=2*12.) osp['fov'] = FieldSpec(osp, key=['object', 'angle'], value=0.) osp['wvls'] = WvlSpec([(800., 1.)], ref_wl=0)
sm.gaps[0].thi=1e10 sm.add_surface([1e10, 0.]) sm.set_stop() sm.add_surface([11.325, 9.45, 1.755]) sm.ifcs[sm.cur_surface].profile = EvenPolynomial( \ r=11.325,cc=-0.63,coefs=[0., 5.0056e-06, -2.968e-08, -2.3959e-10, -6.0923e-13]) sm.add_surface([1e10, 9.6154])
opm.update_model()
print('NA = %.3f'%abs(ar['parax_data'].fod.img_na))