Triplet example

This triplet design, used in Jose Sasian’s Lens Design OPTI 517 course at the Univ. of Arizona, is attributed to Geiser.

%matplotlib widget
isdark = False

Setup the rayoptics environment

The environment.py module imports many useful classes and functions. All the symbols defined in the module are intended to be imported into a rayoptics interactive session.

from rayoptics.environment import *

Create a new model

Create a new OpticalModel instance and set up some convenient aliases to important constituents of the model.

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']

Define first order aperture and field for system

The pupil and field specifications can be specified in a variety of ways. The key keyword argument takes a list of 2 strings. The first string indicates whether the specification is in object or image space. The second one indicates which parameter is the defining specification.

The PupilSpec can be defined in object or image space. The defining parameters can be pupil, f/# or NA, where pupil is the pupil diameter.

osp['pupil'] = PupilSpec(osp, key=['object', 'pupil'], value=12.5)

The FieldSpec can be defined in object or image space. The defining parameters can be height or angle, where angle is given in degrees. The is_relative keyword argument may be used to specify fields as a fraction of the maximum value

osp['fov'] = FieldSpec(osp, key=['object', 'angle'], value=20.0, flds=[0., 0.707, 1.], is_relative=True)

The WvlSpec defines the wavelengths and weights to use when evaluating the model. The wavelength values can be given in either nanometers or a spectral line designation.

osp['wvls'] = WvlSpec([('F', 0.5), (587.5618, 1.0), ('C', 0.5)], ref_wl=1)

Define interface and gap data for the sequential model

opm.radius_mode = True

sm.gaps[0].thi=1e10

sm.add_surface([23.713, 4.831, 'N-LAK9', 'Schott'])
sm.add_surface([7331.288, 5.86])
sm.add_surface([-24.456, .975, 'N-SF5,Schott'])
sm.set_stop()
sm.add_surface([21.896, 4.822])
sm.add_surface([86.759, 3.127, 'N-LAK9', 'Schott'])
sm.add_surface([-20.4942, 41.2365])

Update the model

opm.update_model()

List the sequential model

sm.list_model()
             r            t        medium     mode   zdr      sd
 Obj:     0.000000  1.00000e+10       air             1  3.6397e+09
   1:    23.713000      4.83100    N-LAK9             1      10.009
   2:  7331.288000      5.86000       air             1      8.9482
Stop:   -24.456000     0.975000     N-SF5             1      4.7919
   4:    21.896000      4.82200       air             1      4.7761
   5:    86.759000      3.12700    N-LAK9             1      8.0217
   6:   -20.494200      41.2365       air             1      8.3321
 Img:     0.000000      0.00000                       1      18.217

Draw a lens picture

layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm, is_dark=isdark).plot()
Figure
em.list_model()
0: Object (DummyInterface): Surface(lbl='Obj', profile=Spherical(c=0.0), interact_mode='dummy')
1: E1 (Element): Element: Spherical(c=0.042170961076202926), Spherical(c=0.00013640168003221264), t=4.8310, sd=10.0087, glass: N-LAK9
2: E2 (Element): Element: Spherical(c=-0.04088976120379457), Spherical(c=0.04567044208987943), t=0.9750, sd=4.7919, glass: N-SF5
3: E3 (Element): Element: Spherical(c=0.011526181721781025), Spherical(c=-0.04879429301948844), t=3.1270, sd=8.3321, glass: N-LAK9
4: Image (DummyInterface): Surface(lbl='Img', profile=Spherical(c=0.0), interact_mode='dummy')
pm.list_model()
          ax_ht        pr_ht       ax_slp       pr_slp         power          tau        index    type
0:            0  -3.6397e+09     6.25e-10      0.36397             0        1e+10      1.00000    dummy
1:         6.25     -4.25088    -0.182126     0.487842    0.02914022      2.85689      1.69100    transmit
2:      5.72969     -2.85718    -0.181586     0.487573 -9.425384e-05         5.86      1.00000    transmit
3:      4.66559  3.53405e-07   -0.0532508     0.487573   -0.02750683     0.582887      1.67271    transmit
4:      4.63455       0.2842    0.0891357     0.496304   -0.03072283        4.822      1.00000    transmit
5:      5.06436      2.67738       0.0488      0.47498   0.007964615       1.8492      1.69100    transmit
6:       5.1546      3.55571    -0.124998     0.355092    0.03371696      41.2365      1.00000    transmit
7:  0.000143648      18.1985    -0.124998     0.355092             0            0      1.00000    dummy

Draw a \(y-\overline{y}\) diagram

yybar_plt = plt.figure(FigureClass=InteractiveDiagram, opt_model=opm, dgm_type='ht',
                       do_draw_axes=True, do_draw_frame=True, is_dark=isdark).plot()
Figure

Plot the transverse ray aberrations

abr_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='Ray', scale_type=Fit.All_Same, is_dark=isdark).plot()
Figure

Plot the wavefront aberration

wav_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='OPD', scale_type=Fit.All_Same, is_dark=isdark).plot()
Figure

List the optical specifications

pm.first_order_data()
efl                  50
ffl               -37.1
pp1                12.9
bfl               41.24
ppk               8.763
f/#                   4
m                -5e-09
red              -2e+08
obj_dist          1e+10
obj_ang              20
enp_dist          11.68
enp_radius         6.25
na obj         6.25e-10
n obj                 1
img_dist          41.24
img_ht             18.2
exp_dist         -10.01
exp_radius        6.406
na img           -0.124
n img                 1
optical invariant        2.275

List the paraxial model

pm.list_model()
          ax_ht        pr_ht       ax_slp       pr_slp         power          tau        index    type
0:            0  -3.6397e+09     6.25e-10      0.36397             0        1e+10      1.00000    dummy
1:         6.25     -4.25088    -0.182126     0.487842    0.02914022      2.85689      1.69100    transmit
2:      5.72969     -2.85718    -0.181586     0.487573 -9.425384e-05         5.86      1.00000    transmit
3:      4.66559  3.53405e-07   -0.0532508     0.487573   -0.02750683     0.582887      1.67271    transmit
4:      4.63455       0.2842    0.0891357     0.496304   -0.03072283        4.822      1.00000    transmit
5:      5.06436      2.67738       0.0488      0.47498   0.007964615       1.8492      1.69100    transmit
6:       5.1546      3.55571    -0.124998     0.355092    0.03371696      41.2365      1.00000    transmit
7:  0.000143648      18.1985    -0.124998     0.355092             0            0      1.00000    dummy
pm.list_lens()
      ax_ray_ht    ax_ray_slp
0:            0      6.25e-10
1:         6.25     -0.182126
2:      5.72969     -0.181586
3:      4.66559    -0.0532508
4:      4.63455     0.0891357
5:      5.06436        0.0488
6:       5.1546     -0.124998
7:  0.000143648     -0.124998

      pr_ray_ht    pr_ray_slp
0:  -3.6397e+09       0.36397
1:     -4.25088      0.487842
2:     -2.85718      0.487573
3:  3.53405e-07      0.487573
4:       0.2842      0.496304
5:      2.67738       0.47498
6:      3.55571      0.355092
7:      18.1985      0.355092

           power           tau        index    type
0:             0         1e+10      1.00000    dummy
1:    0.02914022        2.8569      1.69100    transmit
2: -9.425384e-05          5.86      1.00000    transmit
3:   -0.02750683       0.58289      1.67271    transmit
4:   -0.03072283         4.822      1.00000    transmit
5:   0.007964615        1.8492      1.69100    transmit
6:    0.03371696        41.236      1.00000    transmit
7:             0             0      1.00000    dummy

Third Order Seidel aberrations

Computation and tabular display

to_pkg = compute_third_order(opm)
to_pkg
S-I S-II S-III S-IV S-V
1 0.027654 0.019379 0.013581 0.089174 0.072010
2 0.022082 -0.059501 0.160327 -0.000288 -0.431229
3 -0.105156 0.137692 -0.180295 -0.085097 0.347506
4 -0.045358 -0.076796 -0.130024 -0.095046 -0.381069
5 0.007942 0.028382 0.101431 0.024373 0.449596
6 0.103810 -0.050068 0.024148 0.103180 -0.061411
sum 0.010973 -0.000912 -0.010832 0.036297 -0.004597

Bar chart for surface by surface third order aberrations

fig, ax = plt.subplots()
ax.set_xlabel('Surface')
ax.set_ylabel('third order aberration')
ax.set_title('Surface by surface third order aberrations')
to_pkg.plot.bar(ax=ax, rot=0)
ax.grid(True)
fig.tight_layout()
Figure

convert aberration sums to transverse measure

ax_ray, pr_ray, fod = ar['parax_data']
n_last = pm.sys[-1][mc.indx]
u_last = ax_ray[-1][mc.slp]
to.seidel_to_transverse_aberration(to_pkg.loc['sum',:], n_last, u_last)
TSA   -0.043893
TCO    0.010944
TAS   -0.015198
SAS   -0.101860
PTB   -0.145190
DST    0.018387
dtype: float64

convert sums to wavefront measure

central_wv = opm.nm_to_sys_units(sm.central_wavelength())
to.seidel_to_wavefront(to_pkg.loc['sum',:], central_wv).T
W040     2.334457
W131    -0.776108
W222    -9.218154
W220    10.834770
W311    -3.911650
dtype: float64

compute Petzval, sagittal and tangential field curvature

to.seidel_to_field_curv(to_pkg.loc['sum',:], n_last, fod.opt_inv)
TCV    0.000734
SCV    0.004921
PCV    0.007014
dtype: float64

Save the model

opm.save_model('Sasian Triplet')