Skip to main content

ZOS-API interface 2025 R2

PythonStandalone_02_NSC_ray_trace

Last update: 16.07.2025
1import clr, os, winreg
2from itertools import islice
3
4import matplotlib.pyplot as plt
5import numpy as np
6
7class PythonStandaloneApplication(object):
8 class LicenseException(Exception):
9 pass
10 class ConnectionException(Exception):
11 pass
12 class InitializationException(Exception):
13 pass
14 class SystemNotPresentException(Exception):
15 pass
16
17 def __init__(self, path=None):
18 # determine location of ZOSAPI_NetHelper.dll & add as reference
19 aKey = winreg.OpenKey(winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER), r"Software\Zemax", 0, winreg.KEY_READ)
20 zemaxData = winreg.QueryValueEx(aKey, 'ZemaxRoot')
21 NetHelper = os.path.join(os.sep, zemaxData[0], r'ZOS-API\Libraries\ZOSAPI_NetHelper.dll')
22 winreg.CloseKey(aKey)
23 clr.AddReference(NetHelper)
24 import ZOSAPI_NetHelper
25
26 # Find the installed version of OpticStudio
27 if path is None:
28 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize()
29 else:
30 # Note -- uncomment the following line to use a custom initialization path
31 isInitialized = ZOSAPI_NetHelper.ZOSAPI_Initializer.Initialize(path)
32
33 # determine the ZOS root directory
34 if isInitialized:
35 dir = ZOSAPI_NetHelper.ZOSAPI_Initializer.GetZemaxDirectory()
36 else:
37 raise PythonStandaloneApplication.InitializationException("Unable to locate Zemax OpticStudio. Try using a hard-coded path.")
38
39 # add ZOS-API referencecs
40 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI.dll"))
41 clr.AddReference(os.path.join(os.sep, dir, "ZOSAPI_Interfaces.dll"))
42 import ZOSAPI
43
44 # create a reference to the API namespace
45 self.ZOSAPI = ZOSAPI
46
47 # create a reference to the API namespace
48 self.ZOSAPI = ZOSAPI
49
50 # Create the initial connection class
51 self.TheConnection = ZOSAPI.ZOSAPI_Connection()
52
53 if self.TheConnection is None:
54 raise PythonStandaloneApplication.ConnectionException("Unable to initialize .NET connection to ZOSAPI")
55
56 self.TheApplication = self.TheConnection.CreateNewApplication()
57 if self.TheApplication is None:
58 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
59
60 if self.TheApplication.IsValidLicenseForAPI == False:
61 raise PythonStandaloneApplication.LicenseException("License is not valid for ZOSAPI use")
62
63 self.TheSystem = self.TheApplication.PrimarySystem
64 if self.TheSystem is None:
65 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
66
67 def __del__(self):
68 if self.TheApplication is not None:
69 self.TheApplication.CloseApplication()
70 self.TheApplication = None
71
72 self.TheConnection = None
73
74 def OpenFile(self, filepath, saveIfNeeded):
75 if self.TheSystem is None:
76 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
77 self.TheSystem.LoadFile(filepath, saveIfNeeded)
78
79 def CloseFile(self, save):
80 if self.TheSystem is None:
81 raise PythonStandaloneApplication.SystemNotPresentException("Unable to acquire Primary system")
82 self.TheSystem.Close(save)
83
84 def SamplesDir(self):
85 if self.TheApplication is None:
86 raise PythonStandaloneApplication.InitializationException("Unable to acquire ZOSAPI application")
87
88 return self.TheApplication.SamplesDir
89
90 def ExampleConstants(self):
91 if self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusType.PremiumEdition:
92 return "Premium"
93 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeProfessionalEdition:
94 return "Professional"
95 elif self.TheApplication.LicenseStatus == self.ZOSAPI.LicenseStatusTypeStandardEdition:
96 return "Standard"
97 else:
98 return "Invalid"
99
100 def reshape(self, data, x, y, transpose = False):
101 """Converts a System.Double[,] to a 2D list for plotting or post processing
102
103 Parameters
104 ----------
105 data : System.Double[,] data directly from ZOS-API
106 x : x width of new 2D list [use var.GetLength(0) for dimension]
107 y : y width of new 2D list [use var.GetLength(1) for dimension]
108 transpose : transposes data; needed for some multi-dimensional line series data
109
110 Returns
111 -------
112 res : 2D list; can be directly used with Matplotlib or converted to
113 a numpy array using numpy.asarray(res)
114 """
115 if type(data) is not list:
116 data = list(data)
117 var_lst = [y] * x;
118 it = iter(data)
119 res = [list(islice(it, i)) for i in var_lst]
120 if transpose:
121 return self.transpose(res);
122 return res
123
124 def transpose(self, data):
125 """Transposes a 2D list (Python3.x or greater).
126
127 Useful for converting mutli-dimensional line series (i.e. FFT PSF)
128
129 Parameters
130 ----------
131 data : Python native list (if using System.Data[,] object reshape first)
132
133 Returns
134 -------
135 res : transposed 2D list
136 """
137 if type(data) is not list:
138 data = list(data)
139 return list(map(list, zip(*data)))
140
141if __name__ == '__main__':
142 zos = PythonStandaloneApplication()
143
144 #use http://matplotlib.org/ to plot 2D graph
145 # need to install this package before running this code
146
147 # load local variables
148 ZOSAPI = zos.ZOSAPI
149 TheApplication = zos.TheApplication
150 TheSystem = zos.TheSystem
151 sampleDir = TheApplication.SamplesDir
152
153 #! [e02s01_py]
154 # Open file
155 testFile = os.path.join(os.sep, sampleDir, r'Non-sequential\Miscellaneous\Digital_projector_flys_eye_homogenizer.zos')
156 TheSystem.LoadFile(testFile, False)
157 #! [e02s01_py]
158
159 # ! [e02s02_py]
160 # Create ray trace
161 NSCRayTrace = TheSystem.Tools.OpenNSCRayTrace()
162 NSCRayTrace.SplitNSCRays = True
163 NSCRayTrace.ScatterNSCRays = False
164 NSCRayTrace.UsePolarization = True
165 NSCRayTrace.IgnoreErrors = True
166 NSCRayTrace.SaveRays = False
167 NSCRayTrace.Run()
168 # ! [e02s02_py]
169
170 lastValue = []
171 lastValue.append(0)
172 print('Beginning ray trace:')
173 while NSCRayTrace.IsRunning:
174 currentValue = NSCRayTrace.Progress
175 if currentValue % 2 == 0:
176 if lastValue[len(lastValue) - 1] != currentValue:
177 lastValue.append(currentValue)
178 print(currentValue)
179 NSCRayTrace.WaitForCompletion()
180 NSCRayTrace.Close()
181
182 # Non-sequential component editor
183 TheNCE = TheSystem.NCE
184
185 DetObj = 4
186 obj = TheSystem.NCE.GetObjectAt(DetObj);
187 numXPixels = obj.ObjectData.NumberXPixels;
188 numYPixels = obj.ObjectData.NumberYPixels;
189 pltWidth = 2 * obj.ObjectData.XHalfWidth;
190 pltHeight = 2 * obj.ObjectData.YHalfWidth;
191
192 pix = 0
193
194 #! [e02s03_py]
195 # Get detector data
196 detectorData = [[0 for x in range(numYPixels)] for x in range(numXPixels)]
197 for x in range(0,numYPixels,1):
198 for y in range(0,numXPixels,1):
199 ret, pixel_val = TheNCE.GetDetectorData(DetObj, pix, 1, 0)
200 pix += 1
201 if ret == 1:
202 detectorData[y][x] = pixel_val
203 else:
204 detectorData[x][y] = -1
205 #! [e02s03_py]
206
207 # end of default code
208 # everything below here is based on numpy/matplotlib and is not supported by ZOSAPI or Zemax
209 # https://docs.scipy.org/doc/numpy/index.html
210 # http://matplotlib.org/
211
212 # This will clean up the connection to OpticStudio.
213 # Note that it closes down the server instance of OpticStudio, so you for maximum performance do not do
214 # this until you need to.
215
216 detectorData = zos.transpose(detectorData)
217
218 del zos
219 zos = None
220
221 # text output & FOR loops for OpticStudio will invert the vertical image
222 # place plt.show() after clean up to release OpticStudio from memory
223 plt.imshow(detectorData)
224 plt.show()
Definition: ZemaxService.cs:198

Connect with Ansys