Skip to main content

ZOS-API interface 2024 R1

PythonStandalone_24_nsc_detectors

Last update: 17.07.2025
1import clr, os, winreg
2from itertools import islice
3
4import time, array
5import matplotlib.pyplot as plt
6import numpy as np
7
8class PythonStandaloneApplication(object):
9 class LicenseException(Exception):
10 pass
11 class ConnectionException(Exception):
12 pass
13 class InitializationException(Exception):
14 pass
15 class SystemNotPresentException(Exception):
16 pass
17
18 def __init__(self, path=None):
19 # determine location of ZOSAPI_NetHelper.dll & add as reference
20 aKey = winreg.OpenKey(winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER), r"Software\Zemax", 0, winreg.KEY_READ)
21 zemaxData = winreg.QueryValueEx(aKey, 'ZemaxRoot')
22 NetHelper = os.path.join(os.sep, zemaxData[0], r'ZOS-API\Libraries\ZOSAPI_NetHelper.dll')
23 winreg.CloseKey(aKey)
24 clr.AddReference(NetHelper)
25 import ZOSAPI_NetHelper
26
27 # Find the installed version of OpticStudio
28 if path is None:
29 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize()
30 else:
31 # Note -- uncomment the following line to use a custom initialization path
32 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize(path)
33
34 # determine the ZOS root directory
35 if isInitialized:
36 dir = ZOSAPI_NetHelper.ZOSAPI_Initializer.GetZemaxDirectory()
37 else:
38 raise PythonStandaloneApplication.InitializationException("Unable to locate Zemax OpticStudio. Try using a hard-coded path.")
39
40 # add ZOS-API referencecs
41 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI.dll"))
42 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI_Interfaces.dll"))
43 import ZOSAPI
44
45 # create a reference to the API namespace
46 self.ZOSAPI = ZOSAPI
47
48 # create a reference to the API namespace
49 self.ZOSAPI = ZOSAPI
50
51 # Create the initial connection class
52 self.TheConnection = ZOSAPI.ZOSAPI_Connection()
53
54 if self.TheConnection is None:
55 raise PythonStandaloneApplication.ConnectionException("Unable to initialize .NET connection to ZOSAPI")
56
57 self.TheApplication = self.TheConnection.CreateNewApplication()
58 if self.TheApplication is None:
59 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
60
61 if self.TheApplication.IsValidLicenseForAPI == False:
62 raise PythonStandaloneApplication.LicenseException("License is not valid for ZOSAPI use")
63
64 self.TheSystem = self.TheApplication.PrimarySystem
65 if self.TheSystem is None:
66 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
67
68 def __del__(self):
69 if self.TheApplication is not None:
70 self.TheApplication.CloseApplication()
71 self.TheApplication = None
72
73 self.TheConnection = None
74
75 def OpenFile(self, filepath, saveIfNeeded):
76 if self.TheSystem is None:
77 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
78 self.TheSystem.LoadFile(filepath, saveIfNeeded)
79
80 def CloseFile(self, save):
81 if self.TheSystem is None:
82 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
83 self.TheSystem.Close(save)
84
85 def SamplesDir(self):
86 if self.TheApplication is None:
87 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
88
89 return self.TheApplication.SamplesDir
90
91 def ExampleConstants(self):
92 if self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusType.PremiumEdition:
93 return "Premium"
94 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeProfessionalEdition:
95 return "Professional"
96 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeStandardEdition:
97 return "Standard"
98 else:
99 return "Invalid"
100
101 def reshape(self, data, x, y, transpose = False):
102 """Converts a System.Double[,] to a 2D list for plotting or post processing
103
104 Parameters
105 ----------
106 data : System.Double[,] data directly from ZOS-API
107 x : x width of new 2D list [use var.GetLength(0) for dimension]
108 y : y width of new 2D list [use var.GetLength(1) for dimension]
109 transpose : transposes data; needed for some multi-dimensional line series data
110
111 Returns
112 -------
113 res : 2D list; can be directly used with Matplotlib or converted to
114 a numpy array using numpy.asarray(res)
115 """
116 if type(data) is not list:
117 data = list(data)
118 var_lst = [y] * x;
119 it = iter(data)
120 res = [list(islice(it, i)) for i in var_lst]
121 if transpose:
122 return self.transpose(res);
123 return res
124
125 def transpose(self, data):
126 """Transposes a 2D list (Python3.x or greater).
127
128 Useful for converting mutli-dimensional line series (i.e. FFT PSF)
129
130 Parameters
131 ----------
132 data : Python native list (if using System.Data[,] object reshape first)
133
134 Returns
135 -------
136 res : transposed 2D list
137 """
138 if type(data) is not list:
139 data = list(data)
140 return list(map(list, zip(*data)))
141
142if __name__ == '__main__':
143 zos = PythonStandaloneApplication()
144
145 # load local variables
146 ZOSAPI = zos.ZOSAPI
147 TheApplication = zos.TheApplication
148 TheSystem = zos.TheSystem
149 if not os.path.exists(TheApplication.SamplesDir + "\\API\\Python"):
150 os.makedirs(TheApplication.SamplesDir + "\\API\\Python")
151
152 # makes system non-seqnuential and adds 2 objects (3 in total)
153 TheSystem = TheApplication.CreateNewSystem(ZOSAPI.SystemType.NonSequential)
154
155 #! [e24s01_py]
156 # Initializes NCE and loads surfaces
157 # Inserts objects
158 TheNCE = TheSystem.NCE
159 for a in range(1,5):
160 TheNCE.InsertNewObjectAt(1)
161 #! [e24s01_py]
162
163 TheSystem.SystemData.MaterialCatalogs.AddCatalog("SCHOTT")
164
165 #! [e24s02_py]
166 # Gets reference to specific object
167 o1 = TheNCE.GetObjectAt(1)
168 o2 = TheNCE.GetObjectAt(2)
169 o3 = TheNCE.GetObjectAt(3)
170 o4 = TheNCE.GetObjectAt(4)
171 o5 = TheNCE.GetObjectAt(5)
172 #! [e24s02_py]
173
174 #! [e24s03_py]
175 # Changes Object Type
176 TheNCE.GetObjectAt(1).ChangeType(o1.GetObjectTypeSettings(ZOSAPI.Editors.NCE.ObjectType.SourceEllipse))
177 o2.ChangeType(o2.GetObjectTypeSettings(ZOSAPI.Editors.NCE.ObjectType.AsphericSurface2))
178 o3.ChangeType(o3.GetObjectTypeSettings(ZOSAPI.Editors.NCE.ObjectType.StandardLens))
179 o4.ChangeType(o4.GetObjectTypeSettings(ZOSAPI.Editors.NCE.ObjectType.DetectorColor))
180 o5.ChangeType(o5.GetObjectTypeSettings(ZOSAPI.Editors.NCE.ObjectType.DetectorRectangle))
181 #! [e24s03_py]
182
183 #! [e24s04_py]
184 # Sets positions & materials
185 TheNCE.GetObjectAt(2).XPosition = 1.5
186 TheNCE.GetObjectAt(2).ZPosition = 9.99
187 TheNCE.GetObjectAt(2).Material = 'ABSORB'
188 #! [e24s04_py]
189 o3.YPosition = 1.5
190 o3.ZPosition = 8.99
191 o3.Material = 'N-BK7'
192 o4.ZPosition = 10
193 o5.RefObject = 4
194 o5.ZPosition = 1e-3
195
196 #! [e24s05_py]
197 # Sets layout rays based on parameter number
198 TheNCE.GetObjectAt(1).GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par1).IntegerValue = 100
199 # Sets analysis rays based on object data column
200 o1.ObjectData.NumberOfAnalysisRays = 1E6
201 #! [e24s05_py]
202
203 o1.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par10).DoubleValue = 50
204 o1.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par11).DoubleValue = 50
205
206 o2.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par3).DoubleValue = 0.5
207 o2.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par4).DoubleValue = 1
208 o2.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par9).IntegerValue = 1
209
210 o4.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par1).DoubleValue = 8.223
211 o4.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par2).DoubleValue = 2.565
212 o4.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par3).IntegerValue = 200
213 o4.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par4).IntegerValue = 150
214
215 o5_x = 10
216 o5_y = 12.23
217 o5.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par1).DoubleValue = o5_x
218 o5.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par2).DoubleValue = o5_y
219 o5.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par3).IntegerValue = 100
220 o5.GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par4).IntegerValue = 100
221
222 #! [e24s06_py]
223 # changes face type and coating properties
224 TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(0).FaceIs = ZOSAPI.Editors.NCE.FaceIsType.Absorbing
225 TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(1).FaceIs = ZOSAPI.Editors.NCE.FaceIsType.ObjectDefault
226 TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(1).Coating = 'I.50'
227 #! [e24s06_py]
228
229 #! [e24s07_py]
230 # changes scatter profile on face
231 o3_Scatter = TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(2).CreateScatterModelSettings(ZOSAPI.Editors.NCE.ObjectScatteringTypes.Lambertian)
232 o3_Scatter._S_Lambertian.ScatterFraction = 0.5
233 TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(2).ChangeScatterModelSettings(o3_Scatter)
234 TheNCE.GetObjectAt(3).CoatScatterData.GetFaceData(2).NumberOfRays = 2
235 #! [e24s07_py]
236
237 #! [e24s08_py]
238 # removes pixel interpolation for the detector
239 o4.TypeData.UsePixelInterpolation = False
240 #! [e24s08_py]
241
242 #! [e24s09_py]
243 # Setup and run the ray trace
244 NSCRayTrace = TheSystem.Tools.OpenNSCRayTrace()
245 NSCRayTrace.SplitNSCRays = False
246 NSCRayTrace.ScatterNSCRays = True
247 NSCRayTrace.UsePolarization = False
248 NSCRayTrace.IgnoreErrors = True
249 NSCRayTrace.SaveRays = False
250 NSCRayTrace.ClearDetectors(0)
251 NSCRayTrace.RunAndWaitForCompletion()
252 NSCRayTrace.Close()
253 #! [e24s09_py]
254
255 # saves file to disk to expose all objects
256 TheSystem.SaveAs(TheApplication.SamplesDir + '\\API\\Python\\e24_nsc_detectors.zos')
257
258 tic = time.time()
259 #! [e24s10_py]
260 # Creates a new detector viewer analysis reference, changes to TrueColor for RGB extraction
261 d4 = TheSystem.Analyses.New_Analysis(ZOSAPI.Analysis.AnalysisIDM.DetectorViewer)
262 det_settings = d4.GetSettings()
263 det_settings.ShowAs = ZOSAPI.Analysis.DetectorViewerShowAsTypes.TrueColor
264 det_settings.Detector.SetDetectorNumber(4);
265 d4.ApplyAndWaitForCompletion()
266 d4_Results = d4.GetResults()
267 d4_raw = d4_Results.GetDataGridRgb(0)
268 #! [e24s10_py]
269
270 # Reads in values from NCE for detector settings
271 obj = 4
272 x_half = TheSystem.NCE.GetObjectAt(obj).GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par1).DoubleValue
273 y_half = TheSystem.NCE.GetObjectAt(obj).GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par2).DoubleValue
274 x_pixels = TheSystem.NCE.GetObjectAt(obj).GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par3).IntegerValue
275 y_pixels = TheSystem.NCE.GetObjectAt(obj).GetObjectCell(ZOSAPI.Editors.NCE.ObjectColumn.Par4).IntegerValue
276
277 #! [e24s11_py]
278 # FillValues() method still in development for Python; need to use GetValue()
279 #! [e24s11_py]
280
281 #! [e24s12_py]
282 # FillValues() method still in development for Python
283 # creates 3D array to store normalized RGB data
284 data = np.zeros([y_pixels, x_pixels, 3])
285
286 for y in range(0, y_pixels):
287 for x in range(0, x_pixels):
288 rgb = d4_raw.GetValue(x, y)
289 data[y, x, 0] = rgb.R / 255
290 data[y, x, 1] = rgb.G / 255
291 data[y, x, 2] = rgb.B / 255
292 #! [e24s12_py]
293
294 plt.figure()
295 plt.imshow(np.flipud(data), extent=[-x_half, x_half, -y_half, y_half])
296
297 #! [e24s13_py]
298 # changes default values for Detector Viewer
299 # pltos the Incoherent Irradiance in False Color
300 d5 = TheSystem.Analyses.New_Analysis(ZOSAPI.Analysis.AnalysisIDM.DetectorViewer)
301 d5_set = d5.GetSettings()
302
303 d5_set.Detector.SetDetectorNumber(5)
304 d5_set.ShowAs = ZOSAPI.Analysis.DetectorViewerShowAsTypes.FalseColor
305 d5.ApplyAndWaitForCompletion()
306 d5_results = d5.GetResults()
307 d5_values = d5_results.GetDataGrid(0).Values
308 #! [e24s13_py]
309
310 npData = zos.reshape(d5_values, d5_values.GetLength(0), d5_values.GetLength(1))
311 #npData = (np.asarray(tuple(d5_values))).reshape(d5_values.GetLength(0), d5_values.GetLength(1));
312 plt.figure()
313 plt.imshow(np.flipud(npData), cmap='jet', extent=[-o5_x, o5_x, -o5_y, o5_y])
314 plt.colorbar()
315
316 toc = round(time.time() - tic, 3)
317 print('Elapsed time is ' + str(toc) + ' seconds.')
318
319 #! [e24s14_py]
320 # saves current system in memory
321 TheSystem.Save()
322 #! [e24s14_py]
323
324
325 # This will clean up the connection to OpticStudio.
326 # Note that it closes down the server instance of OpticStudio, so you for maximum performance do not do
327 # this until you need to.
328 del zos
329 zos = None
330
331 # place plt.show() after clean up to release OpticStudio from memory
332 plt.show()
Definition: ZemaxService.cs:198

Connect with Ansys