.. currentmodule:: rayoptics.optical
###############
Triplet example
###############
This triplet design, used in Jose Sasian's `Lens Design OPTI 517 `_ course at the Univ. of Arizona, is attributed to Geiser.
.. code:: ipython3
%matplotlib inline
.. code:: ipython3
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.
.. code:: ipython3
from rayoptics.environment import *
Create a new model
------------------
Create a new :class:`~opticalmodel.OpticalModel` instance and set up some convenient aliases to important constituents of the model.
.. code:: ipython3
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 ``epd``, ``f/#`` or ``NA``, where ``epd`` is the pupil
diameter.
.. code:: ipython3
osp['pupil'] = PupilSpec(osp, key=['object', 'epd'], 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``
.. code:: ipython3
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.
.. code:: ipython3
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
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
----------------
.. code:: ipython3
opm.update_model()
List the sequential model
-------------------------
.. code:: ipython3
sm.list_model()
.. parsed-literal::
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
List the optical specifications
-------------------------------
Use the :func:`~.listobj` function to get formatted output of an object's contents.
.. code:: ipython3
listobj(osp)
.. parsed-literal::
aperture: object epd; value= 12.5000
field: object angle; value= 20.0000
y = 0.000 ( 0.00) vlx= 0.000 vux= 0.000 vly= 0.000 vuy= 0.000
y = 14.140 ( 0.71) vlx= 0.000 vux= 0.000 vly= 0.000 vuy= 0.000
y = 20.000 ( 1.00) vlx= 0.000 vux= 0.000 vly= 0.000 vuy= 0.000
is_relative=True, is_wide_angle=False
central wavelength= 587.5618 nm
wavelength (weight) = 486.1327 (0.500), 587.5618 (1.000)*, 656.2725 (0.500)
focus shift=0.0
List the first order properties
-------------------------------
.. code:: ipython3
pm.first_order_data()
.. parsed-literal::
efl 50
f 50
f' 50
ffl -37.1
pp1 12.9
bfl 41.24
ppk -8.763
pp sep -2.047
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.125
n img 1
optical invariant 2.275
Draw a lens picture
-------------------
.. code:: ipython3
layout_plt = plt.figure(FigureClass=InteractiveLayout, opt_model=opm, is_dark=isdark).plot()
.. image:: output_25_0.png
.. code:: ipython3
em.list_model()
.. parsed-literal::
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')
.. code:: ipython3
pm.list_model()
.. parsed-literal::
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 |ybar| diagram
---------------------
.. code:: ipython3
yybar_plt = plt.figure(FigureClass=InteractiveDiagram, opt_model=opm, dgm_type='ht',
do_draw_axes=True, do_draw_frame=True, is_dark=isdark).plot()
.. image:: output_29_0.png
Plot the transverse ray aberrations
-----------------------------------
.. code:: ipython3
abr_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='Ray', scale_type=Fit.All_Same, is_dark=isdark).plot()
.. image:: output_31_0.png
Plot the wavefront aberration
-----------------------------
.. code:: ipython3
wav_plt = plt.figure(FigureClass=RayFanFigure, opt_model=opm, data_type='OPD', scale_type=Fit.All_Same, is_dark=isdark).plot()
.. image:: output_33_0.png
List the paraxial model
-----------------------
.. code:: ipython3
pm.list_model()
.. parsed-literal::
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
.. code:: ipython3
pm.list_lens()
.. parsed-literal::
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
to_pkg = compute_third_order(opm)
to_pkg
.. raw:: html
|
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
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()
.. image:: output_40_0.png
convert aberration sums to transverse measure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
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)
.. parsed-literal::
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
central_wv = opm.nm_to_sys_units(sm.central_wavelength())
to.seidel_to_wavefront(to_pkg.loc['sum',:], central_wv).T
.. parsed-literal::
W040 2.334457
W131 -0.776108
W222 -9.218154
W220 10.834770
W311 -3.911650
dtype: float64
compute Petzval, sagittal and tangential field curvature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: ipython3
to.seidel_to_field_curv(to_pkg.loc['sum',:], n_last, fod.opt_inv)
.. parsed-literal::
TCV 0.000734
SCV 0.004921
PCV 0.007014
dtype: float64
Save the model
--------------
.. code:: ipython3
opm.save_model('Sasian Triplet')