In the last few weeks, I have received questions regarding how we can use the ZOS-API to pull single ray trace information. For convenience, I will post my answers here in a single post. I pulled together three different methods for extracting single ray trace data. Below I will list the methods with sample code in Python and Mathematica. I’m happy to provide samples in other languages if needed!
If you have other methods you use for this kind of analysis, feel free to add them as a reply!
Method 1 - Use the Single Ray Trace analysis
This method can be used to pull the results of the Single Ray Trace analysis window.
The benefit of this method is that the results are pulled for all surfaces at once. The drawback of this method is that the data is provided in text form. The output is a TXT file which must be parsed back into the program you are using. This is discussed in a bit more detail here: How to set RayInfo.Vignetted in ZOS-API_Python
Python
########### Define the constants across all methods
hx = 0.0
hy = 1.0
px = 0.0
py = 0.0
wave = 2
surf = TheSystem.LDE.NumberOfSurfaces
########### Method 1: Single Ray Trace analysis window
# Open the analysis
singleTrace = TheSystem.Analyses.New_Analysis(ZOSAPI.Analysis.AnalysisIDM.RayTrace)
# Access the settings
traceSettings = singleTrace.GetSettings()
traceSettings.Hx = hx
traceSettings.Hy = hy
traceSettings.Px = px
traceSettings.Py = py
traceSettings.Wavelength.SetWavelengthNumber(wave)
# Apply the settings
singleTrace.ApplyAndWaitForCompletion();
# Pull the results
results = singleTrace.GetResults()
# This analysis does not have a native matrix or array built in so we must pull the text file
results.GetTextFile(r'C:\...\singleRay.txt')
Mathematica
(*Define the constants across all methods*)
hx = 0.0;
hy = 1.0;
px = 0.0;
py = 0.0;
wave = 2;
surf = theSystem@LDE@NumberOfSurfaces;
(*Open the analysis*)
LoadNETTypeo"ZOSAPI.Analysis.AnalysisIDM"];
singleTrace = theSystem@Analyses@NewUAnalysiswAnalysisIDM`RayTrace];
(*Access and change the settings*)
traceSettings = singleTrace@GetSettingse];
traceSettings@Hx = hx;
traceSettings@Hy = hy;
traceSettings@Px = px;
traceSettings@Py = py;
traceSettings@Wavelength@SetWavelengthNumbernwave];
(*Apply the settings and run the analysis*)
singleTrace@ApplyAndWaitForCompletionC];
(*Extract the results to a text file. This is required as there is no DataGrid or DataSeries method for the IAS_RayTrace interface*)
results = singleTrace@GetResultsG];
results@GetTextFilee"C:\\...\\results.txt"];
Method 2 - Use optimization operands
This method can be used to pull the values of particular ray trace operands. This is advantageous if you are interested in a single value, such as the Y-intercept of a ray at a particular surface for a given ray. This is disadvantageous if you are interested in the full ray trace results (X, Y, Z, l, m, n, etc).
In this example, we will pull the Y-intercept data for the final surface in the system using the REAY operand. The inputs will match what we see here:
Extracting the operand values will not affect the Merit Function. This is equivalent to the OPEV numeric function in ZPL.
Python
########### Define the constants across all methods
hx = 0.0
hy = 1.0
px = 0.0
py = 0.0
wave = 2
surf = TheSystem.LDE.NumberOfSurfaces
# Access the Merit Function Editor interface
TheMFE = TheSystem.MFE
# Pull the operand value. This will pull the value without affecting the Merit Function
opVal = TheMFE.GetOperandValue(ZOSAPI.Editors.MFE.MeritOperandType.REAY, surf, wave, hx, hy, px, py, 0, 0)
# Print this value. This is the Y-value for a single surface and ray. Will need to loop for more
print(opVal)
Mathematica
(*This method requests the values of optimization operands without including them in the Merit Function.Similar to OPEV within the ZPL.Useful for a small handful of operands or for a loop*)
(*Step 1:Access the Merit Function Editor object and declare the required enumerations for this call*)
theMFE = theSystem@MFE;
LoadNETType;"ZOSAPI.Editors.MFE.MeritOperandType"];
(*Step 2:Define the inputs. We are after REAY so the inputs are as follows...*)
hx = 0.0;
hy = 1.0;
px = 0.0;
py = 0.0;
wave = 2;
surf = theSystem@LDE@NumberOfSurfaces;
(*Step 3:Get the value*)
opVal = theMFE@GetOperandValueFMeritOperandType`REAY, surfNum, wave, hx, hy, px, py, 0, 0]
Method 3 - Run a single ray trace through the Batch Ray Trace tool
This method will pull a full set of ray data into your program of choice as native double or integer values, similar to the full Batch Ray Trace. This is particularly useful if you are extracting data into an array or matrix, as you will not need to parse any external files. This method will also report errors and vignetting as part of the ray trace. The downside of this method is that the data is pulled for a single surface. In other words, the rays are traced from the Object to the input surface.
This method makes use of “out double” values. Each language handles these a bit differently. You can read more about how to identify these in this post: What is an "out double" value in the ZOS-API?.
Note: The Batch Ray Trace interface is categorized as a tool. Only one tool-type item may be open at a time.
Python
########### Import modules to read the data
from System import Enum, Int32, Double
########### Define the constants across all methods
hx = 0.0
hy = 1.0
px = 0.0
py = 0.0
wave = 2
surf = TheSystem.LDE.NumberOfSurfaces
########### Method 3: Run a single ray trace through the Batch tool
# Open the tool
raytrace = TheSystem.Tools.OpenBatchRayTrace()
# Run a single unpolarized ray trace with real rays
# This tool accepts inputs and provides OUT-variable outputs
# We must pre-define the output variables
sysInt = Int32(1)
sysDbl = Double(1.0)
# Now run for a single ray
output = raytrace.SingleRayNormUnpol(ZOSAPI.Tools.RayTrace.RaysType.Real, surf, wave, hx, hy, px, py, False, sysInt, sysInt, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl, sysDbl)
# The values for the OUT variables are then stored in an array of name output
# The value for Y is 4 when we index at 0
print(outputw4])
# Close the tool. This is HUGELY important. In the API, only one Tool-type object may be open at a time
raytrace.Close()
Mathematica
(*Single ray trace method.Best method for reading one ray at a time and extracting its data*)
(*For this,we could use the Single Ray Trace analysis,or the Batch Ray Trace tool.The Batch Ray Trace is ideal here because the results will be extracted as native double/int/etc values in Mathematica*)
(*Step 1:Open the tool*)
raytrace = theSystem@Tools@OpenBatchRayTracet];
LoadNETTypeB"ZOSAPI.Tools.RayTrace.RaysType"];
LoadNETTyper"ZOSAPI.Tools.RayTrace.OPDMode"];
(*Step 2:Define our inputs*)
hx = 0.0;
hy = 1.0;
px = 0.0;
py = 0.0;
wave = 2;
surf = theSystem@LDE@NumberOfSurfaces;
calcOPD = False;
(*Step 3:Call the single ray trace and retrieve the OUT variables*)
raytrace@SingleRayNormUnpol raytrace@RunAndWaitForCompletion>];
(*Step 4:Check if the ray traced successfully.If so,read the data*)
Ifl((errCode == 0) && (vigCode == 0)), Print&"X = ", x];
Print)"Y = ", y]]
(*Step 5: Close the tool. This is REQUIRED as only one "tool" can be opened at a time*)
raytrace@Closed];