PythonStandalone_11_Basic_Seq
Last update: 17.07.2025 1import clr, os, winreg
2from itertools import islice
3
4from shutil import copyfile
5
6class PythonStandaloneApplication(object):
7 class LicenseException(Exception):
8 pass
9 class ConnectionException(Exception):
10 pass
11 class InitializationException(Exception):
12 pass
13 class SystemNotPresentException(Exception):
14 pass
15
16 def __init__(self, path=None):
17 # determine location of ZOSAPI_NetHelper.dll & add as reference
18 aKey = winreg.OpenKey(winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER), r"Software\Zemax", 0, winreg.KEY_READ)
19 zemaxData = winreg.QueryValueEx(aKey, 'ZemaxRoot')
20 NetHelper = os.path.join(os.sep, zemaxData[0], r'ZOS-API\Libraries\ZOSAPI_NetHelper.dll')
21 winreg.CloseKey(aKey)
22 clr.AddReference(NetHelper)
23 import ZOSAPI_NetHelper
24
25 # Find the installed version of OpticStudio
26 if path is None:
27 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize()
28 else:
29 # Note -- uncomment the following line to use a custom initialization path
30 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize(path)
31
32 # determine the ZOS root directory
33 if isInitialized:
34 dir = ZOSAPI_NetHelper.ZOSAPI_Initializer.GetZemaxDirectory()
35 else:
36 raise PythonStandaloneApplication.InitializationException("Unable to locate Zemax OpticStudio. Try using a hard-coded path.")
37
38 # add ZOS-API referencecs
39 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI.dll"))
40 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI_Interfaces.dll"))
41 import ZOSAPI
42
43 # create a reference to the API namespace
44 self.ZOSAPI = ZOSAPI
45
46 # create a reference to the API namespace
47 self.ZOSAPI = ZOSAPI
48
49 # Create the initial connection class
50 self.TheConnection = ZOSAPI.ZOSAPI_Connection()
51
52 if self.TheConnection is None:
53 raise PythonStandaloneApplication.ConnectionException("Unable to initialize .NET connection to ZOSAPI")
54
55 self.TheApplication = self.TheConnection.CreateNewApplication()
56 if self.TheApplication is None:
57 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
58
59 if self.TheApplication.IsValidLicenseForAPI == False:
60 raise PythonStandaloneApplication.LicenseException("License is not valid for ZOSAPI use")
61
62 self.TheSystem = self.TheApplication.PrimarySystem
63 if self.TheSystem is None:
64 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
65
66 def __del__(self):
67 if self.TheApplication is not None:
68 self.TheApplication.CloseApplication()
69 self.TheApplication = None
70
71 self.TheConnection = None
72
73 def OpenFile(self, filepath, saveIfNeeded):
74 if self.TheSystem is None:
75 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
76 self.TheSystem.LoadFile(filepath, saveIfNeeded)
77
78 def CloseFile(self, save):
79 if self.TheSystem is None:
80 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
81 self.TheSystem.Close(save)
82
83 def SamplesDir(self):
84 if self.TheApplication is None:
85 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
86
87 return self.TheApplication.SamplesDir
88
89 def ExampleConstants(self):
90 if self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusType.PremiumEdition:
91 return "Premium"
92 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeProfessionalEdition:
93 return "Professional"
94 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeStandardEdition:
95 return "Standard"
96 else:
97 return "Invalid"
98
99 def reshape(self, data, x, y, transpose = False):
100 """Converts a System.Double[,] to a 2D list for plotting or post processing
101
102 Parameters
103 ----------
104 data : System.Double[,] data directly from ZOS-API
105 x : x width of new 2D list [use var.GetLength(0) for dimension]
106 y : y width of new 2D list [use var.GetLength(1) for dimension]
107 transpose : transposes data; needed for some multi-dimensional line series data
108
109 Returns
110 -------
111 res : 2D list; can be directly used with Matplotlib or converted to
112 a numpy array using numpy.asarray(res)
113 """
114 if type(data) is not list:
115 data = list(data)
116 var_lst = [y] * x;
117 it = iter(data)
118 res = [list(islice(it, i)) for i in var_lst]
119 if transpose:
120 return self.transpose(res);
121 return res
122
123 def transpose(self, data):
124 """Transposes a 2D list (Python3.x or greater).
125
126 Useful for converting mutli-dimensional line series (i.e. FFT PSF)
127
128 Parameters
129 ----------
130 data : Python native list (if using System.Data[,] object reshape first)
131
132 Returns
133 -------
134 res : transposed 2D list
135 """
136 if type(data) is not list:
137 data = list(data)
138 return list(map(list, zip(*data)))
139
140if __name__ == '__main__':
141 zos = PythonStandaloneApplication()
142
143 # load local variables
144 ZOSAPI = zos.ZOSAPI
145 TheApplication = zos.TheApplication
146 TheSystem = zos.TheSystem
147 if not os.path.exists(TheApplication.SamplesDir + "\\API\\Python"):
148 os.makedirs(TheApplication.SamplesDir + "\\API\\Python")
149
150 #! [e11s01_py]
151 # Create New Sequential File
152 TheSystem.New(False)
153 # Name File
154 fileName = TheApplication.SamplesDir + "\\API\\Python\\e11_basic_seq.zos"
155 TheSystem.SaveAs(fileName)
156 #! [e11s01_py]
157
158 #! [e11s02_py]
159 # Changing System Explorer Settings
160 # Set Aperture
161 TheSystemData = TheSystem.SystemData
162 TheSystemData.Aperture.ApertureValue = 20
163 TheSystem.SystemData.MaterialCatalogs.AddCatalog('SCHOTT')
164
165 # Set Apodization Type to Gaussian, and set apodization factor to 1
166 TheSystemData.Aperture.ApodizationType = 1 # ApodizationType 0 = uniform; 1 = gaussian; 2 = Cosine Cubed
167 TheSystemData.Aperture.ApodizationFactor = 1
168 # Set Wavelength
169 TheSystemData.Wavelengths.SelectWavelengthPreset(ZOSAPI.SystemData.WavelengthPreset.FdC_Visible)
170 #! [e11s02_py]
171
172 #! [e11s03_py]
173 # Insert and Track New Surfaces, set STOP to surface 1
174 TheLDE = TheSystem.LDE
175 TheLDE.InsertNewSurfaceAt(1)
176 TheLDE.InsertNewSurfaceAt(1)
177 TheLDE.InsertNewSurfaceAt(1)
178 Surf_1 = TheLDE.GetSurfaceAt(1)
179 Surf_2 = TheLDE.GetSurfaceAt(2)
180 Surf_3 = TheLDE.GetSurfaceAt(3)
181 Surf_4 = TheLDE.GetSurfaceAt(4)
182 Surf_1.IsStop = 1
183 # Set some baseline parameters
184 Surf_1.Thickness = 5
185 Surf_2.Thickness = 5
186 Surf_2.Radius = 100
187 Surf_2.Material = "N-BK7"
188 Surf_3.Thickness = 3
189 Surf_3.Radius = -30
190 Surf_3.Material = "F2"
191 Surf_4.Radius = -80
192 #! [e11s03_py]
193
194 #! [e11s04_py]
195 # Set system lens units to inches, scale all values with Scale Lens tool
196 unit = TheSystemData.Units.LensUnits # For demonstration only. This file is new, so it has default units mm.
197 ScaleLens = TheSystem.Tools.OpenScale() # Open Scale Lens tool
198 # Apply Tool Settings
199 ScaleLens.ScaleByUnits = True
200 ScaleLens.ScaleToUnit = 2 # 0=millimeters; 1=centimeters; 2=inches; 3=meters
201 # Cast to ISystemTool interface to gain access to Run
202 ScaleLens.RunAndWaitForCompletion()
203 ScaleLens.Close()
204 #! [e11s04_py]
205
206 #! [e11s05_py]
207 # Add Rectangular Aperture to Surface 1
208 # Get surface 1, create aperture settings
209 Surf_1 = TheSystem.LDE.GetSurfaceAt(1)
210 rAperture = Surf_1.ApertureData.CreateApertureTypeSettings(ZOSAPI.Editors.LDE.SurfaceApertureTypes.RectangularAperture)
211 # Set aperture size
212 rAperture._S_RectangularAperture.XHalfWidth = .1
213 rAperture._S_RectangularAperture.YHalfWidth = .1
214 # Apply aperture settings to surface 1
215 Surf_1.ApertureData.ChangeApertureTypeSettings(rAperture)
216 #! [e11s05_py]
217
218 #! [e11s06_py]
219 # Run Quick Focus
220 QuickFocus = TheSystem.Tools.OpenQuickFocus()
221 QuickFocus.RunAndWaitForCompletion()
222 QuickFocus.Close()
223 #! [e11s06_py]
224
225 #! [e11s07_py]
226 # Open Universal Plot of RMS Spot Size vs Surface3 Thickness
227 UnivPlot = TheSystem.Analyses.New_Analysis(ZOSAPI.Analysis.AnalysisIDM.UniversalPlot1D)
228 UnivPlot_Settings = UnivPlot.GetSettings()
229 print("Universal Plot has analysis specific settings? ", UnivPlot.HasAnalysisSpecificSettings)
230 # Above is False; Universal Plot Settings must be changed via ModifySettings (changing a config (.cfg) file)
231 cfg = TheApplication.ZemaxDataDir + "\\Configs\\UNI.CFG"
232 UnivPlot_Settings.Save() # Create new .cfg file, named "UNI.CFG" in \Configs\ folder
233 UnivPlot_Settings.ModifySettings(cfg, 'UN1_SURFACE', str(TheSystem.LDE.NumberOfSurfaces - 2))
234 UnivPlot_Settings.ModifySettings(cfg, 'UN1_STARTVAL', str(Surf_4.Thickness - 0.4 / 25.4)) # Change universal plot settings
235 UnivPlot_Settings.ModifySettings(cfg, 'UN1_STOPVAL', str(Surf_4.Thickness + 0.1 / 25.4))
236 UnivPlot_Settings.ModifySettings(cfg, 'UN1_STEPS', str(20))
237 UnivPlot_Settings.ModifySettings(cfg, 'UN1_PAR1', str(10))
238 UnivPlot_Settings.ModifySettings(cfg, 'UN1_OPERAND', "RSRE")
239 # For ModifySettings keycodes (UN1_STARTVAL, UN1_STEPS, etc.), see MODIFYSETTINGS page in ZPL>keywords help files
240 # LoadFrom allows you to load any CFG file, not just default; not available via GUI
241 UnivPlot_Settings.LoadFrom(cfg)
242 #! [e11s07_py]
243
244 #! [e11s08_py]
245 # Open Spot Diagram to See Result!
246 newSpot = TheSystem.Analyses.New_StandardSpot()
247 print("Spot has analysis specific settings? ", newSpot.HasAnalysisSpecificSettings) # True; no ModifySettings
248 newSettings = newSpot.GetSettings()
249 newSettings.RayDensity = 15
250 newSpot.ApplyAndWaitForCompletion()
251 #! [e11s08_py]
252
253 # save!
254 TheSystem.Save()
255
256
257 # This will clean up the connection to OpticStudio.
258 # Note that it closes down the server instance of OpticStudio, so you for maximum performance do not do
259 # this until you need to.
260 del zos
261 zos = None
Definition: ZemaxService.cs:198