Skip to main content
Solved

What is the ZOS-API-solution of ZPL-RAYTRACE


Hans-Jürgen Feige

So far I haven't found a way to calculate many rays through to the image surface and read out the ray data on each surface.
In ZPL, the "RAYTRACE hx, hy, px, py, wavelength" provides ray data on all surfaces (RAY*(surface)).
Have I overlooked a solution using ZOS API?

Many Thanks!

Hans

Best answer by MichaelH

Hi Hans, 

There is not a 100% equivalent method with the simplicity of RAYTRACE in the ZPL.  The closest method is the SingleRayNormUnpol under the IOpticalSystemTools interface.  The 2 biggest differences is:

  1. SingleRayNormUnpol will only trace to a single surface, so if you want all the surfaces you’ll need to call this method inside a for loop
  2. All results are in local coordinates, so if you want something like RAG*, then you’ll need to get the Global Rotation Matrix for the given surface.

Some pseudo code would look like the following:

// open batch ray trace
var tool = TheSystem.Tools.OpenBatchRayTrace();

// run raytrace across all surfaces
for (int surf = 1; surf < TheSystem.LDE.NumberOfSurfaces; surf++)
{
	// run the actual raytrace
		var raytrace = tool.SingleRayNormUnpol(RaysType.Real, surf, wavenumber, hx, hy, px, py, true,
			out int errorCode, out int vignetteCode,
			out double x, out double y, out double z,
			out double l, out double m, out double n,
			out double nx, out double ny, out double nz,
			out double opd, out double intensity);

	// convert to global corrdinates
	if (useGlobal){
		TheSystem.LDE.GetGlobalMatrix(surf,
			out double r11, out double r12, out double r13,
			out double r21, out double r22, out double r23,
			out double r31, out double r32, out double r33,
			out double xo, out double yo, out double zo);

		double xg = xo + r11 * x + r12 * y + r13 * z;
		double yg = yo + r21 * x + r22 * y + r23 * z;
		double zg = zo + r31 * x + r32 * y + r33 * z;

		x = xg;
		y = yg;
		z = zg;
	}
}

// always close your tool
tool.Close();

 

View original
Did this topic help you find an answer to your question?

11 replies

MichaelH
Luminary
Forum|alt.badge.img+2
  • Luminary
  • 336 replies
  • Answer
  • July 16, 2024

Hi Hans, 

There is not a 100% equivalent method with the simplicity of RAYTRACE in the ZPL.  The closest method is the SingleRayNormUnpol under the IOpticalSystemTools interface.  The 2 biggest differences is:

  1. SingleRayNormUnpol will only trace to a single surface, so if you want all the surfaces you’ll need to call this method inside a for loop
  2. All results are in local coordinates, so if you want something like RAG*, then you’ll need to get the Global Rotation Matrix for the given surface.

Some pseudo code would look like the following:

// open batch ray trace
var tool = TheSystem.Tools.OpenBatchRayTrace();

// run raytrace across all surfaces
for (int surf = 1; surf < TheSystem.LDE.NumberOfSurfaces; surf++)
{
	// run the actual raytrace
		var raytrace = tool.SingleRayNormUnpol(RaysType.Real, surf, wavenumber, hx, hy, px, py, true,
			out int errorCode, out int vignetteCode,
			out double x, out double y, out double z,
			out double l, out double m, out double n,
			out double nx, out double ny, out double nz,
			out double opd, out double intensity);

	// convert to global corrdinates
	if (useGlobal){
		TheSystem.LDE.GetGlobalMatrix(surf,
			out double r11, out double r12, out double r13,
			out double r21, out double r22, out double r23,
			out double r31, out double r32, out double r33,
			out double xo, out double yo, out double zo);

		double xg = xo + r11 * x + r12 * y + r13 * z;
		double yg = yo + r21 * x + r22 * y + r23 * z;
		double zg = zo + r31 * x + r32 * y + r33 * z;

		x = xg;
		y = yg;
		z = zg;
	}
}

// always close your tool
tool.Close();

 


Hans-Jürgen Feige

Hi Michael,

thanks, I do as I use ZOS API.

But I can't believe this is an "internal" solution.

For n surfaces, n rays must be tracesd!?
If we trace a ray to the image (like in ZPL) all information must be available on ALL surfaces.

A huge advantage of BatchRayTrace is missed.

All the Best

Hans


David.Nguyen
Luminary
Forum|alt.badge.img+2

@Hans-Jürgen Feige

 

In addition to what @MichaelH suggested, I can see two other potential solutions:

  1. Convert your file to Non-Sequential and use the Non-Sequential Batch Raytrace, which returns the rays by segments (one should be careful as the rays might not travel sequentially anymore).
  2. Put RAYTRACE in a ZPLM and manipulate the Merit Function with the ZOS-API.

I haven’t fully tested 2. but here’s what I had in mind. Make a macro ZPL05.ZPL like so:

RAYTRACE PVHX(), PVHY(), PVPX(), PVPY()

FOR ii, 1, NSUR(), 1
	OPTRETURN ii-1, RAYY(ii)
NEXT

I’m using RAYY for this example. In my dummy lens, the Merit Function looks like so:

Remember that with ZPLM, the operand is executed only once and returns all the possible Data values at once. In ZOS-API you can create these operands, run the Merit Function and retrieve the operands Value.

I hope this helps and take care,


David


Hans-Jürgen Feige

Hi David,

thanks, and yes I am currently doing that too, without!! changes in system and editors.

An indSUR loop with

… zosMFE.GetOperandValue(MeritOperandType_REAR, indSUR, ...
… zosMFE.GetOperandValue(MeritOperandType_RAID, indSUR, ...
… zosMFE.GetOperandValue(MeritOperandType_RAED, indSUR, …
and so on.

But it is a pity about the BatchRayTrace tool advantage!

BR Hans


David.Nguyen
Luminary
Forum|alt.badge.img+2

@Hans-Jürgen Feige

 

If you use individual operands such as REAR, RAID, and RAED with GetOperandValue(), you still need one operand per surface. You might see a performance improvement by using the ZPLM approach, even though there’s a small overhead for the call of the first ZPLM operand, all other ZPLM operands with the same Mac# are calculated simultaneously, i.e. you get all surfaces in one call.

Take care,

 

David


Hans-Jürgen Feige

Hi David,

ok, got it. thanks.

I’ll check and try ...

BR


Hans-Jürgen Feige

Hi All,

we are still surprised about all this (ZOS API not as convenient as ZPL), especially since we know that ZPL is no longer the focus of developments at ZEMAX.

Hopefully, zemax's core code works differently.

 

BR


Hans-Jürgen Feige

… The best solution would be to pass arrays to .ReadNextResult() and get the values ...


David.Nguyen
Luminary
Forum|alt.badge.img+2

@Hans-Jürgen Feige 

 

ZOS-API and ZPL have different applications. I wouldn’t say one is more convenient than the other, they are just different. While I agree it would be nice to have a similar functionality in ZOS-API, it is also a matter of priority. At least for this issue you have several workarounds already. In the past you could contact Zemax to make a feature request for such functionality, and it would be implemented based on popularity, existence of workarounds, etc. Perhaps you can try to do that?

Take care,


David

 


Juan_Reto_Reynal

Hi ​@Hans-Jürgen Feige, I encountered the same limitation on an application I’m working on.

‘In ZPL, the "RAYTRACE hx, hy, px, py, wavelength" provides ray data on all surfaces (RAY*(surface)).
Have I overlooked a solution using ZOS API?’

If you need to use RAYTRACE as a step of many in a ZOS-API application, perhaps the following might be useful, if not disregard.

For me, what worked in the end was to call the ZPL script -which calls RAYTRACE several times- within a python script, then get the output text file of that ZPL and continue with the flow of my application using ZOS-API as always, all within python environment.

 

import subprocess #python standard library, don’t need to install anything

opticstudio_path = r"C:\Program Files\..\Zemax OpticStudio\OpticStudio.exe"

macro_path = r"C:\Users\..l\Documents\Zemax\Macros\your_macro.ZPL" #it can be saved anywhere


command = [opticstudio_path, f'-zpl={macro_path}']

result = subprocess.run(command) 

This will open Zemax GUI and run your .ZPL file. Zemax GUI will automatically close after running the .ZPL macro.

Your .ZPL macro should ask to open the desired Zemax model, where the .ZPL macro will run.
For that use (within the .ZPL macro, probably the first line of code):

LOADLENS “your_model.zos”

After you run the .ZPL macro, you can start/continue with your ZOS-API application if that is what you wanted.


Hans-Jürgen Feige

Hello Juan, thank you for your effort.
We also use a similar workaround.
Your suggestion is unsuitable for a long running application - it runs unattended for hours.

And for users, the applications should remain "black boxes" without them having to select special macros.

But this should still force our demands on the developers of ZEMAX with ZOS API.
1. Ray trace with provision of all ray data on all surfaces.
2. Start of ZPL macros from the ZOS API environment.

Best regards
Hans-Jürgen


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings