Skip to main content

Hello! I’m trying to run batch ray traces from Python and have encountered some difficulties. Originally I didn’t use this feature because it was quite slow - since each ray needed to be traced individually in a for loop. But after discovering this Knowledgebase article: Batch Processing of Ray Trace Data using ZOS-API in MATLAB or Python – Knowledgebase (zemax.com) I got excited to try the new Raytrace DLL.
|
I started by getting the MATLAB example file working, which was pretty trivial. It basically ran as soon as I downloaded it. 

However, I need the raytracing to be done in Python - so I tried to translate from the MATLAB example file, which did not work very well. First I encountered this error:

  • module ‘clr’ has no attribute ‘AddReference’

Which I fixed by uninstalling clr and installing pythonnet (woops, that’s on me). I had to downgrade to Python3.8 to install pythonnet. The next error I encountered after I finally got the code running seems more fundamental, when trying to run NET.addAssembly(pwd+’\Raytrace.dll’) it says

  • NameError: name ‘NET’ is not defined.

Where is NET supposed to be imported? I don’t see it explicitly earlier in the script, or the accompanying script “PythonNET_ZRDLoaderFull.py”. 

Alternatively, if someone could just point me to an example of sequential raytracing using the Raytrace.dll that would be very helpful.

Thanks!

Hi Jaren,

Yes, as you discovered, pythonnet is only supported up to 3.8 (https://github.com/pythonnet/pythonnet); when pythonnet upgrades to 3.10 then you can also upgrade to the latest version of Python and still access the ZOS-API.

As for adding references via pythonnet, you need import clr and clr.AddReference() methods (I’m not sure where NET.AddReference is coming from).  When you first download the file, make sure you unblock the file so you can actually access it via Python (by default, Windows will block the execution of code from unsigned sources).  After downloading & extracting the ZIP file, you will need to right click on it, select Properties and then check the Unblock option at the bottom of the General tab:

 

As for sample Python code, refer to the below code for running a Normalized Unpolarized raytrace (it traces the 4 marginal rays at full field for the Double Gauss 28 degree field sample file):

--------------------------------------------------------

import zosapi
from System import Enum, Int32, Double

# add the raytrace.dll from the current directory
import clr, os
dll = os.path.join(os.path.dirname(os.path.realpath(__file__)), r'RayTrace.dll')

clr.AddReference(dll);

# import the raytrace namespace
import BatchRayTrace;

# load the double gauss
zos = zosapi.App()
TheSystem = zos.TheSystem
ZOSAPI = zos.ZOSAPI
TheSystem.LoadFile(os.path.join(zos.TheApplication.SamplesDir, r'Sequential\Objectives\Double Gauss 28 degree field.zmx'), False)

# check to make sure the file was loaded
if TheSystem.LDE.NumberOfSurfaces < 4:
    print('did not load the file properly')
    exit()

# run a sequential ray trace
maxrays = 4;        # let's trace the 4 marginal rays
tool = TheSystem.Tools.OpenBatchRayTrace();
normUnpol = tool.CreateNormUnpol(maxrays, ZOSAPI.Tools.RayTrace.RaysType.Real, TheSystem.LDE.NumberOfSurfaces - 1)

# pass raytracer to dll
reader = BatchRayTrace.ReadNormUnpolData(tool, normUnpol)
reader.ClearData();

# initialize the output (the number of indices in the output array is maxseg*maxseg
maxseg = 2;
rays = reader.InitializeOutput(maxseg);

# add the 4 full field marginal rays
reader.AddRay(2, 
    d0, 0, 0, 0], 
    1, 1, 1, 1], 
    1, -1, 0, 0], 
    /0, 0, 1, -1], Enum.Parse(ZOSAPI.Tools.RayTrace.OPDMode, 'None'));

# read the segments (array length is maxsegs * max segs)
isfinished = False
while not isfinished:
    segments = reader.ReadNextBlock(rays)
    if segments == 0:
        isfinished = True

# print the rays
print(list(rays.X))
print(list(rays.Y))

# always close your tools
tool.Close();


Hi Michael,

Thanks for your reply, I was able to get your example file working! Just had to install zos-api from pip

I didn’t see the option to Unblock the raytrace.dll file. I thought I was on my administrator account so I expected to see something similar, but my Properties window did not have this option:


I had another question if you don’t mind enlightening me - I see the line where the dll is loaded, and where the clr package adds it as a reference. But I don’t see any lines where the dll is used by the raytracer.

Does the OpenBatchRayTrace method implicitly use the Raytrace.dll when it is imported?


Hi Jaren,

The DLL is loaded with the lines:

# import the raytrace namespace
import BatchRayTrace;

And the DLL is first used with the lines:

# pass raytracer to dll
reader = BatchRayTrace.ReadNormUnpolData(tool, normUnpol)
reader.ClearData();

The OpenBatchRayTrace doesn’t use the RayTrace.dll; rather the RayTrace.dll uses the OpenBatchRayTrace interface.  The tool argument that is passed into the BatchRayTrace.ReadNormUnpolData is actually a reference to the OpenBatchRayTrace interface.


Reply