Skip to main content

Hi there again friends from the Zemax community, 

I want to use the ZOS-API interface to run a non sequential ray tracing analysis. I have managed to run a batch ray tracing analysis using OpenBatchRayTrace() and CreateNormUnpol(), however, as far as I understand it, these two tools work just for a sequential system.

I found that for the non-sequential case, I would need to use a different approach. I found the following guide on how to run the non-sequential case:

 

 

However, it seems that in this case I would need to first execute the non-sequential ray-tracing, save the results into a file and then extract the data associated to the rays with a ZRDReader object.

 

Having said this, I have a few questions:

-From the data available to the ZRDReader I notice that there is no information on the surface normals as in the sequential sequential batch ray tracing case. Is it possible to obtain the surface normals in this case? Or should I try to determine these directly from the incident and transmitted ray directions? (l m n direction cosines)

-Is there any other way to perform the non-sequential “batch” tracing by setting the rays directions and origin “in-place” as is done in the sequential ray-tracing situation? Also, I would prefer if I dont have to save the ray data information to a file, how can I extract all ray information directly on the same function call? 

 

In advance, thanks for the comments!

 

Hello again,

I noticed that I can use OpenBatchRayTrace instead of calling the standard non-sequential ray tracing routine from python.

The only thing that I need to do is to use a CreateNSC interface which returns a TraceNSCData object. Then I can apply the same procedure as with the batch based ray-tracing approach for sequential systems.

Of course there are a few differences, with the most important one being the fact that in non-sequential mode there is no concept of pupil and field coordinates. Instead I need to define the X,Y,Z and L,M,N vectors associated to the rays I want to trace through the nonsequential system.

In general, I think this works (please let me know if there is something that I might be missing?), however, I noticed that I have to be pulling the results ray by ray (even though the tracing is all done in a batch).

I was wondering if there could be a better way to retrieve the results without having to go ray by ray and instead pull all of the results related to a specific segment of the non-sequential tracing sequence? 

Also, as I mentioned in my first post, the results obtained from NSCData.ReadNextSegment() do not provide information on the surface normal at the intersection points. I could obtain the surface normal information from the retrieved L,M,N vectors for each ray at each interface. However, just to be clear, these L,M,N vectors are expressed in the global coordinate system basis right ?(the L,M,N vectors before and after an interface). If this is the case I would obtain the surface normals (also expressed in global coordinates) by using Snell’s law in vector form. What do you think about this? 

Here is a copy of the code that I am using at the moment (ZOS-API via python)

zos = PythonStandaloneApplication()
# Load local variables
ZOSAPI = zos.ZOSAPI
TheApplication = zos.TheApplication
TheSystem = zos.TheSystem

TheSystem.LoadFile(path, False)
print ("number of surfaces")
print (TheSystem.LDE.NumberOfSurfaces)

raytrace = TheSystem.Tools.OpenBatchRayTrace()



sysInt = Int32(1)
sysDbl = Double(1.0)
sysDbl2 = Double(0.0)

Nx = 100
Ny = 100
nrays = Nx*Ny

NSCData = raytrace.CreateNSC(Nx*Ny,5,0)

NSCData.ClearData()

theta = np.linspace(0,np.deg2rad(60.0),Nx)
phi = np.linspace(0,np.deg2rad(360.0),Ny)
thetat, phip = np.meshgrid(theta, phi)

l = np.sin(thetat)*np.cos(phip)
m = np.sin(thetat)*np.sin(phip)
n = np.cos(thetat)

l = l.flatten()
m = m.flatten()
n = n.flatten()


for i in range(0,l.shapes0],1):
NSCData.AddRay(sysInt,1,Enum.Parse(ZOSAPI.Tools.RayTrace.NSCTraceOptions,"None"),Double(0.0),Double(0.0),Double(0.0),l.i],m[i],n[i],sysInt,0.0,0.0,sysDbl2,sysDbl2,sysDbl2,sysDbl2)

print ("How many rays we have??")
print (NSCData.NumberOfRays)

raytrace.RunAndWaitForCompletion()
print ("Non sequential ray tracing completed")

NSCData.StartReadingResults()

x_coordinates = np.empty((nrays,5))
y_coordinates = np.empty((nrays,5))
z_coordinates = np.empty((nrays,5))

results2 = NSCData.ReadNextResult(1,sysInt,sysInt,sysInt)

while results2u0]:
# print ("Results for ray number: {}".format(results2u1]))
# print (results2)

results = NSCData.ReadNextSegment()
# print ("Results associated to ray number:{}".format(results2u1]))
while resultss0]: # success
# print ("These are the results")
# print (results)
x_coordinatesnresults2u1]-1,resultss1]] = resultss5]
y_coordinatesnresults2u1] - 1, resultss1]] = resultss6]
z_coordinatesnresults2u1] - 1, resultss1]] = resultss7]
results = NSCData.ReadNextSegment()
results2 = NSCData.ReadNextResult(1,sysInt,sysInt,sysInt)

print ("This worked")
print ("type of NSCData")
print (type(NSCData))

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.scatter(x_coordinatesn:,4],y_coordinatesn:,4],z_coordinatesn:,4])
plt.title("Ray intersection with first surface")
plt.show()


raytrace.Close()

del zos
zos = None

Any comments or thoughts?

 

 


Reply