1.1 MiB
1.1 MiB
In [1]:
%matplotlib widget isdark = False from rayoptics.environment import *
In [2]:
opm = OpticalModel() sm = opm['seq_model'] osp = opm['optical_spec'] pm = opm['parax_model'] osp['pupil'] = PupilSpec(osp, key=['object', 'pupil'], value=16) osp['fov'] = FieldSpec(osp, key=['object', 'angle'], value=0.5, flds=[0., 0.707, 1.], is_relative=True) osp['wvls'] = WvlSpec([('F', 0.5), (587.5618, 1.0), ('C', 0.5)], ref_wl=1) opm.radius_mode = True sm.gaps[0].thi=1e10 def calc_curvature(n, fl): return (n-1)*fl n_bk7 = 1.5168 n_lasf9 = 1.85025 n_f2 = 1.62005 v_bk7 = 64.17 v_lasf9 = 32.16 v_f2 = 36.43 # try for chaining a 3x telescope setup with a second 3x telescope setup f0 = 150 f0_0 = (v_bk7-v_f2)*f0/v_bk7 f0_1 = -f0_0*v_bk7/v_f2 f0_actual = 1/(1/f0_0+1/f0_1) f1 = 60 # 1/f = 1/f0 + 1/f1 = 1/f0 - v2/(f0*v1) = (v1-v2)/(v1*f0) # f0 = (v1-v2)*f/v1 f1_0 = (v_bk7-v_f2)*f1/v_bk7 f1_1 = -f1_0*v_bk7/v_f2 f2 = 150 f3 = 50 f1_stacked = 2*f1 r0 = calc_curvature(n_lasf9, f0) r0_0 = calc_curvature(n_bk7, f0_0) r0_1 = calc_curvature(n_f2, f0_1) r1 = calc_curvature(n_lasf9, f1) r1_0 = calc_curvature(n_bk7, f1_0) r1_1 = calc_curvature(n_f2, f1_1) r2 = calc_curvature(n_lasf9, f2) r3 = calc_curvature(n_lasf9, f3) #sm.add_surface([r0_0, 2, 'N-BK7', 'Schott', 42/2]) #sm.add_surface([1e9, 2, 'N-F2', 'Schott', 42/2]) #sm.add_surface([-r0_1, 180+2*f1]) #sm.add_surface([-r0_1, 180+2*36.]) sm.add_surface([r1_0, 4, 'N-BK7', 'Schott', 16]) sm.add_surface([1e9, 2, 'N-F2', 'Schott', 16]) sm.add_surface([-r1_1, 30]) #sm.add_surface([1e9, 2, 'N-LASF9', 'Schott', 16]) #sm.add_surface([-r1, f2+f3]) #sm.add_surface([r2, 2, 'N-LASF9', 'Schott', 16]) #sm.add_surface([1e9, f2+f3]) #sm.add_surface([1e9, 2, 'N-LASF9', 'Schott', 16]) #sm.add_surface([-r3, f3])
In [3]:
opm.update_model() opm.seq_model.gaps[-1].thi = opm.optical_spec.parax_data.fod.bfl opm.update_model() layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm, is_dark=isdark).plot()
Figure
In [4]:
pm.first_order_data()
efl 50.17 ffl -54.42 pp1 -4.251 bfl 42.68 ppk 7.488 f/# 3.135 m -5.017e-09 red -1.993e+08 obj_dist 1e+10 obj_ang 0.5 enp_dist -0 enp_radius 8 na obj 8e-10 n obj 1 img_dist 42.68 img_ht 0.4378 exp_dist -3.569 exp_radius 7.375 na img -0.1575 n img 1 optical invariant 0.06981
In [5]:
abr_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='Ray', scale_type=Fit.All_Same).plot()
Figure
In [6]:
spot_plt = plt.figure(FigureClass=SpotDiagramFigure, opt_model=opm, is_dark=isdark).plot()
Figure
In [7]:
layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm, is_dark=isdark).plot()
Figure
In [8]:
def dump_dist(p, wi, ray_pkg, fld, wvl, foc): if ray_pkg is not None: image_pt = fld.ref_sphere[0] ray = ray_pkg[0] dist = foc / ray[-1][1][2] defocused_pt = ray[-1][0] + dist*ray[-1][1] t_abr = defocused_pt - image_pt return np.sqrt(np.sum(t_abr*t_abr)) def spot_rms(sm): return np.sqrt(np.mean(np.square(sm.trace_grid(dump_dist, 0, form='list', append_if_none=False)[0]), axis=1)) spot_rms(sm)
Out[8]:
array([0.71394997, 0.69072105, 0.67781734])
In [9]:
import rayoptics.optical.model_constants as mc old_gap = opm.seq_model.gaps[-1].thi offsets = np.linspace(-40, 40, 2000) opm.seq_model.gaps[-1].thi = opm.optical_spec.parax_data.fod.bfl opm.update_model() def dump_rays(p, wi, ray_pkg, fld, wvl, foc): if ray_pkg is not None: image_pt = fld.ref_sphere[0] ray = ray_pkg[mc.ray] v = ray[-1][mc.d][0:2] / ray[-1][mc.d][2] return [ray[-1][mc.p][0:2] - image_pt[0:2], v] vals, colors = sm.trace_grid(dump_rays, 0, form='list', append_if_none=False) v1, v2, v3 = vals v1_p = v1[:,0] v1_v = v1[:,1] v2_p = v2[:,0] v2_v = v2[:,1] v3_p = v3[:,0] v3_v = v3[:,1] v1_rms = np.zeros(offsets.size) v2_rms = np.zeros(offsets.size) v3_rms = np.zeros(offsets.size) for i in range(offsets.size): v1_rms[i] = np.sqrt(np.mean(np.square(v1_p+v1_v*offsets[i]))) v2_rms[i] = np.sqrt(np.mean(np.square(v2_p+v2_v*offsets[i]))) v3_rms[i] = np.sqrt(np.mean(np.square(v3_p+v3_v*offsets[i]))) opm.seq_model.gaps[-1].thi = old_gap opm.update_model() plt.figure() plt.plot(offsets, v1_rms, color=colors[0]) plt.plot(offsets, v2_rms, color=colors[1]) plt.plot(offsets, v3_rms, color=colors[2]) plt.show() min_b, min_g, min_r = (offsets[np.argmin(v1_rms)], offsets[np.argmin(v2_rms)], offsets[np.argmin(v3_rms)]) min_b, min_g, min_r
Figure
Out[9]:
(-5.142571285642823, -4.9824912456228105, -4.902451225612808)
In [10]:
opm.seq_model.gaps[-1].thi = opm.optical_spec.parax_data.fod.bfl + (min_r*0.25 + min_g*0.5 + min_b*0.25) opm.update_model() spot_plt = plt.figure(FigureClass=SpotDiagramFigure, opt_model=opm, is_dark=isdark).plot() print(spot_rms(sm))
[0.21615536 0.21605082 0.21695656]
Figure
In [11]:
abr_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='Ray', scale_type=Fit.All_Same).plot()
Figure
In [12]:
# let's try chaining the two lenses together and seeing how that looks # first let's wrap that focus calculation code into a function def dump_rays(p, wi, ray_pkg, fld, wvl, foc): if ray_pkg is not None: image_pt = fld.ref_sphere[0] ray = ray_pkg[mc.ray] v = ray[-1][mc.d][0:2] / ray[-1][mc.d][2] return [ray[-1][mc.p][0:2] - image_pt[0:2], v] def get_focus(sm, weights=np.array([0.25, 0.5, 0.25])): offsets = np.linspace(-40, 40, 2000) vals, colors = sm.trace_grid(dump_rays, 0, form='list', append_if_none=False) rms = np.zeros((offsets.size, len(vals)), dtype=float) for i in range(offsets.size): for j in range(len(vals)): rms[i][j] = np.sqrt(np.mean(np.square(vals[j][:,0]+vals[j][:,1]*offsets[i]))) return offsets[np.argmin(np.sum(rms*weights, axis=1))] get_focus(sm)
Out[12]:
-0.020010005002504272
In [13]:
opm2 = OpticalModel() sm2 = opm2['seq_model'] osp2 = opm2['optical_spec'] pm2 = opm2['parax_model'] osp2['pupil'] = PupilSpec(osp2, key=['object', 'pupil'], value=16) osp2['fov'] = FieldSpec(osp2, key=['object', 'angle'], value=0.5, flds=[0., 0.707, 1.], is_relative=True) osp2['wvls'] = WvlSpec([('F', 0.5), (587.5618, 1.0), ('C', 0.5)], ref_wl=1) opm2.radius_mode = True sm2.gaps[0].thi=1e10 sm2.add_surface([r0_0, 2, 'N-BK7', 'Schott', 42/2]) sm2.add_surface([1e9, 2, 'N-F2', 'Schott', 42/2]) sm2.add_surface([-r0_1, f0]) opm2.update_model() sm2.gaps[-1].thi += get_focus(sm2) opm2.update_model() layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm2, is_dark=isdark).plot()
Figure
In [14]:
#use the gap from sm sm2.gaps[-1].thi += sm.gaps[-1].thi sm2.add_surface([r1_1, 2, 'N-F2', 'Schott', 16]) sm2.add_surface([1e9, 4, 'N-BK7', 'Schott', 16]) sm2.add_surface([-r1_0, sm.gaps[-1].thi]) opm2.update_model() layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm2, is_dark=isdark).plot()
Figure
In [15]:
pm2.first_order_data()
efl 951.4 ffl 2559 pp1 3510 bfl -280.2 ppk 1232 f/# 59.46 m -9.514e-08 red -1.051e+07 obj_dist 1e+10 obj_ang 0.5 enp_dist -0 enp_radius 8 na obj 8e-10 n obj 1 img_dist -280.2 img_ht 8.303 exp_dist -244.4 exp_radius 2.974 na img -0.008409 n img 1 optical invariant 0.06981
In [16]:
sm2.insert_surface_and_gap() cur = sm2.cur_surface sm2.ifcs[cur] = ThinLens(power=1/30.) sm2.gaps[cur].thi = 30. opm2.update_model() layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm2, is_dark=isdark).plot()
Figure
In [17]:
spot_plt = plt.figure(FigureClass=SpotDiagramFigure, opt_model=opm2, is_dark=isdark).plot() print(spot_rms(sm2))
[0.33087284 0.03391144 0.26097283]
Figure
In [18]:
adjust = get_focus(sm2) sm2.gaps[-1].thi += adjust opm2.update_model() spot_plt = plt.figure(FigureClass=SpotDiagramFigure, opt_model=opm2, is_dark=isdark).plot() adjust, spot_rms(sm2)
Out[18]:
(-0.3801900950475243, array([0.35119223, 0.02588293, 0.23321615]))
Figure
In [ ]: