Warning

There is an issue with the generation of documentation from notebooks, such as this page, that causes interactive plots generated using the Plot3D function to appear incorrect. The examples should produce correct 3D plots when executed directly in Jupyter Lab.

Binocular design

This example has been inspired by the book Fischer, Tadic-Galeb, Yoder. Optical system design. Second edition; chapter 22, p642 where the design of a binocular is studied. Although the book does not provide any specific optical component to be used in the design, it does provide guidelines on how to choose and locate the optical components.

The binocular proposed in the book is a 7 \times 50 binocular. It is recommended to use an achromatic doublet of 200mm of focal length and 50mm of diameter as an objective and a double Porro prism of SK5 glass. It is suggested to leave at least 40mm from the exit surface of the second prism to the image plane. A symmetrical eyepiece, composed of two achromatic doublets, is suggested. The suggested eyepiece focal length is f is 30mm.

The example is developed step by step. The binocular has been designed using pyOpTools predefined components and lenses from the Edmund Optics Inc catalogue.

[1]:
from pyoptools.all import *
from math import pi
[2]:
# Lenses choice: We look in the catalogue for the appropriate objective lens

L1=library.Edmund.get("45179") # f=200 r= 25

OA=Ray(pos=(0,0,-10000),dir=(0,0,1),wavelength=.55) # Optical axis

C=CCD(size=(10,10))

S=System(complist=[(L1,(0,0,100),(0,pi,0)), (C,(0,0,320.053),(0,0,0))],n=1)

PB=parallel_beam_c(origin=(0,0,50),direction=(0,0,0),size=(15,15),num_rays=(5,5),wavelength=.55)

S.ray_add(PB)

S.propagate()

display(Plot3D(S,center=(0,0,180),size=(250,70),scale=4,rot=[(0,pi/2,0)]))

f=(nearest_points(PB[7].get_final_rays()[0],PB[8].get_final_rays()[0])[0][2])-(find_ppp(S, OA)[2])
print(f)
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/pyoptools-0.2.0-py3.7-linux-x86_64.egg/pyoptools/raytrace/library/library.py:159: DeprecationWarning: This method is deprecated, you can use dictionary-style accessinstead
  DeprecationWarning,
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/ipywidgets/widgets/widget.py:501: DeprecationWarning: Passing unrecognized arguments to super(MeshPhongMaterial).__init__(ambient='#050505').
object.__init__() takes exactly one argument (the instance to initialize)
This is deprecated in traitlets 4.2.This error will be raised in a future release of traitlets.
  super().__init__(**kwargs)
nan
[3]:
#Placing the objective and the Porro prism

L1=library.Edmund.get("45179") #f=200 r= 25

RP1=RightAnglePrism(width=55,height=55,material=material.schott["N-SK5"])
RP2=RightAnglePrism(width=40,height=40,material=material.schott["N-SK5"])

CC=CCD(size=(50,50))

S=System(complist=[(L1,(0,0,100),(0,0,0)), (RP1,(0,-22.5,150),(pi,-pi/4,pi/2)), (RP2,(-20,-40,140),(0,pi/4,0)),
                   (CC,(-40,-46.41421356,  195.64187845),(0,0,0))],n=1)

PB=parallel_beam_c(origin=(0,0,0),direction=(0,0,0),size=(15,15),num_rays=(5,5),wavelength=.55)

S.ray_add(PB)
S.propagate()

display(Plot3D(S,center=(0,-30,140),size=(250,150),scale=5,rot=[(0,pi/2.,0),(pi/6,0,0)]))

# Calculating the coordinates of the paraxial focal point
nearest_points(PB[10].get_final_rays()[0],PB[15].get_final_rays()[0])
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/pyoptools-0.2.0-py3.7-linux-x86_64.egg/pyoptools/raytrace/library/library.py:159: DeprecationWarning: This method is deprecated, you can use dictionary-style accessinstead
  DeprecationWarning,
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/ipywidgets/widgets/widget.py:501: DeprecationWarning: Passing unrecognized arguments to super(MeshPhongMaterial).__init__(ambient='#050505').
object.__init__() takes exactly one argument (the instance to initialize)
This is deprecated in traitlets 4.2.This error will be raised in a future release of traitlets.
  super().__init__(**kwargs)
[3]:
(array([-40.        , -45.00001128, 195.64006397]),
 array([-40.        , -45.00000001, 195.64006439]),
 1.1281287765385155e-05,
 False)
[4]:
# Looking for the right eyepiece configuration

L2=library.Edmund.get("45175") # f=30 ; r=10

CC=CCD(size=(50,50))
S=System(complist=[(L2,(0,0,89.84),(0,pi,0)), (L2,(0,0,100),(0,0,0)), (CC,(0,0,1.18656541e+02),(0,0,0))],n=1)

## The distance between the two doublets is equal to the total lense thickness

PB=parallel_beam_c(origin=(0,0,0),direction=(0,0,0),size=(10,10),num_rays=(5,5),wavelength=.55)

S.ray_add(PB)
S.propagate()

display(Plot3D(S,center=(0,0,90),size=(100,50),scale=5,rot=[(0,pi/2,0)]))

#Distance between the center of the lense and the paraxial focal point
nearest_points(PB[7].get_final_rays()[0],PB[8].get_final_rays()[0])

/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/pyoptools-0.2.0-py3.7-linux-x86_64.egg/pyoptools/raytrace/library/library.py:159: DeprecationWarning: This method is deprecated, you can use dictionary-style accessinstead
  DeprecationWarning,
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/ipywidgets/widgets/widget.py:501: DeprecationWarning: Passing unrecognized arguments to super(MeshPhongMaterial).__init__(ambient='#050505').
object.__init__() takes exactly one argument (the instance to initialize)
This is deprecated in traitlets 4.2.This error will be raised in a future release of traitlets.
  super().__init__(**kwargs)
[4]:
(array([-3.34259427e-02,  0.00000000e+00,  1.13920118e+02]),
 array([-4.23616191e-04,  4.23616191e-04,  1.13914704e+02]),
 0.03344612357265831,
 False)
[5]:
## Placing the eyepiece: Binocular 7x50

L1=library.Edmund.get("45179") #f=200 r= 25
L2=library.Edmund.get("45175") # f=30 ; r=10


RP1=RightAnglePrism(width=55,height=55,material=material.schott["N-SK5"])
RP2=RightAnglePrism(width=40,height=40,material=material.schott["N-SK5"])


CC=CCD(size=(50,50))

S=System(complist=[(L1,(0,0,100),(0,0,0)), (RP1,(0,-22.5,150),(pi,-pi/4,pi/2)), (RP2,(-20,-40,140),(0,pi/4,0)),
                   #(L2,(-40,-46.41421356,195.64187847+12.32427176),(0,pi,0)),
                   #(L2,(-40,-46.41421356,195.64187847+12.32427176+10.16),(0,0,0)),
                   (L2,(-40,-44.99,195.64187847+12.32427176),(0,pi,0)),
                   (L2,(-40,-44.99,195.64187847+12.32427176+10.16),(0,0,0)),
                   (CC,(-40,-44.99,260),(0,0,0))],n=1)

OA=Ray(pos=(0,0,100),dir=(0,0,10),intensity=100, wavelength=.55) # Optical axis
PB=parallel_beam_c(origin=(0,0,0),direction=(0,0,0),size=(15,15),num_rays=(5,5),wavelength=.55)

S.ray_add(OA)
S.ray_add(PB)
S.propagate()

%pylab inline
display(Plot3D(S,center=(0,-20,170),size=(250,130),scale=2,rot=[(0,pi/2.,0),(0,0,0)]))
figure()
spot_diagram_c(CC)

/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/pyoptools-0.2.0-py3.7-linux-x86_64.egg/pyoptools/raytrace/library/library.py:159: DeprecationWarning: This method is deprecated, you can use dictionary-style accessinstead
  DeprecationWarning,
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/pyoptools-0.2.0-py3.7-linux-x86_64.egg/pyoptools/raytrace/library/library.py:159: DeprecationWarning: This method is deprecated, you can use dictionary-style accessinstead
  DeprecationWarning,
Populating the interactive namespace from numpy and matplotlib
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/IPython/core/magics/pylab.py:160: UserWarning: pylab import has clobbered these variables: ['Polygon', 'cross', 'pi', 'f', 'unwrap', 'sqrt']
`%matplotlib` prevents importing * from pylab and numpy
  "\n`%matplotlib` prevents importing * from pylab and numpy"
/home/docs/checkouts/readthedocs.org/user_builds/pyoptools/envs/latest/lib/python3.7/site-packages/ipywidgets/widgets/widget.py:501: DeprecationWarning: Passing unrecognized arguments to super(MeshPhongMaterial).__init__(ambient='#050505').
object.__init__() takes exactly one argument (the instance to initialize)
This is deprecated in traitlets 4.2.This error will be raised in a future release of traitlets.
  super().__init__(**kwargs)
../../_images/notebooks_basic_Binocular_5_4.png
[ ]: