Example 07: Tilt and Decenter.

Example 07: Tilt and Decenter.#

from __future__ import annotations

import os

import numpy as np

from skZemax.skZemaxClass import skZemaxClass

skZemax = skZemaxClass()
# Open file
skZemax.Utilities_OpenZemaxFile(
    skZemax.SamplesDir() + os.sep + r"Sequential\Objectives\Cooke 40 degree field.zmx",
    False,
)
# Lockdown the sample sheet to do new things with it...
skZemax.System_Lockdown(usePrecisionRounding=True, decimalPrecision=2)
# recreate the functionality of the tilt/decenter elements tool
# apply coordinate breaks around the 2nd lens element (surf 3/4)
skZemax.LDE_ChangeSurfaceType(skZemax.LDE_InsertNewSurface(3), "CoordinateBreak")
skZemax.LDE_ChangeSurfaceType(skZemax.LDE_InsertNewSurface(6), "CoordinateBreak")
skZemax.LDE_GetSurface(3).Comment = "CB1"
skZemax.LDE_GetSurface(6).Comment = "CB2"
# insert a dummy surface after 2nd CB
skZemax.LDE_InsertNewSurface(7).Thickness = skZemax.LDE_GetSurface(
    5
).Thickness  # the dummy carries the original thickness
skZemax.LDE_GetSurface(7).Comment = "Dummy"
# we're going to play with the STOP surface position, so let's put STOP on surf 1
skZemax.LDE_SetSurfaceAsStop(1)
# create position solve
skZemax.Solver_LDESurfaceProperty_ForValue(
    in_surface=5,
    property="thickness",
    solve_type="position",
    params={"FromSurface": 3, "Length": 0},
)
# create pickup solve
skZemax.Solver_LDESurfaceProperty_ForValue(
    in_surface=6,
    property="thickness",
    solve_type="surfacepickup",
    params={
        "Surface": 5,
        "ScaleFactor": -1,
        "Offset": 0,
        "Column": skZemax.LDE_GetSurfaceColumnEnum("Thickness"),
    },
)
# set pickup solves for coordinate break tilt/decenter parameter cells
# these parameters are columns 12-16 in the Lens Data Editor (parameters 1-5)
#
# Note, I convert names into parameter index with skZemax.LDE_GetSurfaceColumnEnum().
surf6 = skZemax.LDE_GetSurface(6)
surf3 = skZemax.LDE_GetSurface(3)
for prop in [
    "Decenter X",
    "Decenter Y",
    "Par3",
    "Par4",
    "Par5",
]:  # Switching to Par# notation for example, but can be "Tilt About X/Y/Z" instead.
    skZemax.Solver_LDESurfaceProperty_ForValue(
        in_surface=surf6,
        property=prop,
        solve_type="surfacepickup",
        params={
            "Surface": 3,
            "ScaleFactor": -1,
            "Offset": 0,
            "Column": skZemax.LDE_GetSurfaceColumnEnum(prop, surf3),
        },
    )  # Don't need surf3 input for 'Par#' names
# assign random tilt/decenter values (the pickups above should undo the tilt/decenter)
for par in ["Par1", "Par2", "Par3", "Par4", "Par5"]:
    surf3.GetCellAt(
        int(skZemax.LDE_GetSurfaceColumnEnum(par))
    ).DoubleValue = np.random.uniform(-0.1, 0.01)
# also, set the 'order' flag for CB#2
surf6.GetCellAt(int(skZemax.LDE_GetSurfaceColumnEnum("Order", surf6))).IntegerValue = 1

# We now get the global rotation matrix at surface 5.
_, R = skZemax.LDE_GetObjectRotationAndPositionMatrices(5)

skZemax.Visualization_SEQ_ShadedModel(
    save_image=True,
    saved_image_location=skZemax.Utilities_skZemaxExampleDir()
    + os.sep
    + r"e07_TiltDecenterAndMFOperand_Shaded.png",
)
skZemax.Utilities_SaveZemaxFileAs(
    skZemax.Utilities_skZemaxExampleDir() + os.sep + r"e07_TiltDecenterAndMFOperand.zmx"
)
del skZemax
skZemax = None
OpenZemaxFile ::  Opening Zemax file [C:\Users\dsl935\Documents\Zemax\SAMPLES\Sequential\Objectives\Cooke 40 degree field.zmx].
System_Lockdown :: Locking system down...
System_Lockdown :: Done locking system down.
SaveZemaxFileAs :: Saving Current Zemax File As [E:\_OfficerRepositories\ZemaxRepos\skZemax\docs\source\Examples\e07_TiltDecenterAndMFOperand.zmx].