|
| 1 | +#------------------------------------------------------------------------------- |
| 2 | +# Name: systems.py |
| 3 | +# Purpose: Simple optical systems for quick setup with PyZDDE. |
| 4 | +# Copyright: (c) Indranil Sinharoy, Southern Methodist University, 2012 - 2014 |
| 5 | +# Licence: MIT License |
| 6 | +# This file is subject to the terms and conditions of the MIT License. |
| 7 | +# For further details, please refer to LICENSE.txt |
| 8 | +# Revision: 0.8.0 |
| 9 | +#------------------------------------------------------------------------------- |
| 10 | +"""simple optical systems for quick setup with PyZDDE & Zemax. The docstring |
| 11 | +examples assume that PyZDDe is imported as ``import pyzdde.zdde as pyz``, |
| 12 | +a PyZDDE communication object is then created as ``ln = pyz.createLink()`` |
| 13 | +or ``ln = pyz.PyZDDE(); ln.zDDEInit()`` and ``systems`` (this module) is |
| 14 | +imported as ``import pyzdde.systems as optsys`` |
| 15 | +""" |
| 16 | +from __future__ import division |
| 17 | +from __future__ import print_function |
| 18 | + |
| 19 | +def zMakeIdealThinLens(ddeLn, fl=50, fn=5, stop_pos=0, stop_shift=0, opd_mode=1, |
| 20 | + zmx_mode=0): |
| 21 | + """Creates an ideal thin lens of the given specification consisting of |
| 22 | + a STOP and a PARAXIAL surface in the zemax server. |
| 23 | +
|
| 24 | + Parameters |
| 25 | + ---------- |
| 26 | + ddeLn : object |
| 27 | + pyzdde object |
| 28 | + fl : float, optional |
| 29 | + focal length (measured in air of unity index) in lens units |
| 30 | + fn : float, optional |
| 31 | + f-number (image space f/#) |
| 32 | + stop_pos : integer (0/1), optional |
| 33 | + use 0 to place STOP before (to the left of) the paraxial |
| 34 | + surface, 1 to place STOP after (to the right) |
| 35 | + stop_shift : integer, optional |
| 36 | + axial distance between STOP and paraxial surface |
| 37 | + opd_mode : integer (0, 1, 2 or 3), optional |
| 38 | + the OPD mode, which indicates how Zemax should calculate the |
| 39 | + optical path difference for rays refracted by the paraxial lens. |
| 40 | +
|
| 41 | + * ``opd_mode=0`` is fast and accurate if the aberrations are not |
| 42 | + severe. Zemax uses parabasal ray tracing in this mode. |
| 43 | + * ``opd_mode=1`` is the most accurate. |
| 44 | + * ``opd_mode=2`` assumes that the lens is used at infinite |
| 45 | + conjugates. |
| 46 | + * ``opd_mode=3`` is similar to ``opd_mode=0``, except that zemax |
| 47 | + traces paraxial rays instead of paraxial rays. |
| 48 | +
|
| 49 | + zmx_mode : integer (0, 1, or 2), optional |
| 50 | + zemax mode. 0 for sequential, 1 for hybrid, 2 for mixed. Currently |
| 51 | + ignored. |
| 52 | +
|
| 53 | + Returns |
| 54 | + ------- |
| 55 | + None |
| 56 | +
|
| 57 | + Examples |
| 58 | + -------- |
| 59 | + >>> import pyzdde.zdde as pyz |
| 60 | + >>> ln = pyz.createLink() |
| 61 | + >>> optsys.zMakeIdealThinLens(ln) |
| 62 | + >>> optsys.zMakeIdealThinLens(ln, fl=100, fn=5, opd_mode=0) |
| 63 | + >>> optsys.zMakeIdealThinLens(ln, stop_shift=5) |
| 64 | + >>> optsys.zMakeIdealThinLens(ln, stop_pos=1, stop_shift=5) |
| 65 | +
|
| 66 | + Notes |
| 67 | + ----- |
| 68 | + 1. For more information see "Paraxial" under "Sequential surface type |
| 69 | + definitions" in the Zemax manual. |
| 70 | + 2. Use ``ln.zPushLens(1)`` update lens into the LDE |
| 71 | + """ |
| 72 | + if stop_pos < 0 or stop_pos > 1: |
| 73 | + raise ValueError("Expecting stop_pos to be either 0 or 1") |
| 74 | + epd = fl/fn |
| 75 | + stop_surf = 2 if stop_pos else 1 |
| 76 | + para_surf = 1 if stop_pos else 2 |
| 77 | + ddeLn.zNewLens() |
| 78 | + ddeLn.zInsertSurface(para_surf) |
| 79 | + ddeLn.zSetSystemAper(aType=0, stopSurf=stop_surf, apertureValue=epd) |
| 80 | + if stop_pos: |
| 81 | + ddeLn.zSetSurfaceData(para_surf, code=3, value=stop_shift) |
| 82 | + else: |
| 83 | + ddeLn.zSetSurfaceData(stop_surf, code=3, value=stop_shift) |
| 84 | + ddeLn.zSetSurfaceData(para_surf, code=0, value='PARAXIAL') |
| 85 | + ddeLn.zSetSurfaceParameter(para_surf, parameter=1, value=fl) # focallength |
| 86 | + ddeLn.zSetSurfaceParameter(para_surf, parameter=2, value=opd_mode) |
| 87 | + surf_beforeIMA, thickness_code = 2, 1 |
| 88 | + solve_type, height, pupil_zone = 2, 0, 0 # Marginal ray height |
| 89 | + ddeLn.zSetSolve(surf_beforeIMA, thickness_code, solve_type, height, pupil_zone) |
| 90 | + |
| 91 | +def zMakeIdealCollimator(ddeLn, fl=50, fn=5, ima_dist=10, opd_mode=1, zmx_mode=0): |
| 92 | + """Creates a collimator using an ideal thin lens of the given |
| 93 | + specification. |
| 94 | +
|
| 95 | + The model consists of just 3 surfaces in the LDE -- OBJ, STOP |
| 96 | + (paraxial surface) and IMA plane. |
| 97 | +
|
| 98 | + Parameters |
| 99 | + ---------- |
| 100 | + ddeLn : object |
| 101 | + pyzdde object |
| 102 | + fl : float, optional |
| 103 | + focal length (measured in air of unity index) in lens units |
| 104 | + fn : float, optional |
| 105 | + f-number (image space f/#) |
| 106 | + ima_dist : integer, optional |
| 107 | + axial distance the paraxial surface and IMA (observation plane) |
| 108 | + opd_mode : integer (0, 1, 2 or 3), optional |
| 109 | + the OPD mode, which indicates how Zemax should calculate the |
| 110 | + optical path difference for rays refracted by the paraxial lens. |
| 111 | +
|
| 112 | + * ``opd_mode=0`` is fast and accurate if the aberrations are not |
| 113 | + severe. Zemax uses parabasal ray tracing in this mode. |
| 114 | + * ``opd_mode=1`` is the most accurate. |
| 115 | + * ``opd_mode=2`` assumes that the lens is used at infinite |
| 116 | + conjugates. |
| 117 | + * ``opd_mode=3`` is similar to ``opd_mode=0``, except that zemax |
| 118 | + traces paraxial rays instead of paraxial rays. |
| 119 | +
|
| 120 | + zmx_mode : integer (0, 1, or 2), optional |
| 121 | + zemax mode. 0 for sequential, 1 for hybrid, 2 for mixed. Currently |
| 122 | + ignored. |
| 123 | +
|
| 124 | + Returns |
| 125 | + ------- |
| 126 | + None |
| 127 | +
|
| 128 | + Examples |
| 129 | + -------- |
| 130 | + >>> optsys.zMakeIdealCollimator(ln) |
| 131 | + >>> optsys.zMakeIdealCollimator(ln, fl=100, fn=5, opd_mode=0) |
| 132 | + >>> optsys.zMakeIdealThinLens(ln, stop_shift=5) |
| 133 | + >>> optsys.zMakeIdealThinLens(ln, stop_pos=1, stop_shift=5) |
| 134 | +
|
| 135 | + Notes |
| 136 | + ----- |
| 137 | + 1. For more information see "Paraxial" under "Sequential surface type |
| 138 | + definitions" in the Zemax manual. |
| 139 | + 2. Use ``ln.zPushLens(1)`` update lens into the LDE |
| 140 | + """ |
| 141 | + epd = fl/fn |
| 142 | + ddeLn.zNewLens() |
| 143 | + ddeLn.zSetSystemAper(aType=0, stopSurf=1, apertureValue=epd) |
| 144 | + ddeLn.zSetSystemProperty(code=18, value1=1) # Afocal Image Space |
| 145 | + ddeLn.zSetSurfaceData(surfaceNumber=0, code=3, value=fl) |
| 146 | + ddeLn.zSetSurfaceData(surfaceNumber=1, code=0, value='PARAXIAL') |
| 147 | + ddeLn.zSetSurfaceData(surfaceNumber=1, code=3, value=ima_dist) |
| 148 | + ddeLn.zSetSurfaceParameter(surfaceNumber=1, parameter=1, value=fl) # focallength |
| 149 | + ddeLn.zSetSurfaceParameter(surfaceNumber=1, parameter=2, value=opd_mode) |
0 commit comments