How to call a ZPL macro from within a ZPL macro

It is generally good programming practice to perform each step of a calcution in a separate piece of code  This article explains how to call a ZPL macro from within another macro, and how data are passed back and forth between macros.

Article Attachments

Introduction

When writing a ZPL macro in which many steps are performed, it is generally good programming practice to perform each step in a separate piece of code. This may be done with ZPL subroutines, using the GOSUB, SUB, RETURN, and END keywords. However, there are cases where it may be easier to perform each step in a separate macro, and then call each of these individual (“child”) macros from a main (“parent”) macro. For instance, if the same calculation is to be performed in many different macros, it would be much more efficient to perform this calculation in a child macro which is subsequently called by various parent macros. This can be done in OpticStudio by using the CALLMACRO keyword.

Calling a macro from within another macro

A description of the CALLMACRO keyword and its implementation may be found in the Help System by navigating to The Programming Tab...About the ZPL...Calling a Macro from within a Macro

An example of a parent macro which calls two separate child macros may be found in the .ZIP file attached to this article. These macros should be placed in the {Zemax}\Macros directory, and are meant to be used with the file "Cooke 40 degree field.zmx", located in the {Zemax}\Samples\Objectives directory.

The parent macro (CALLMACRO_TEST_PARENT.ZPL) starts by defining arrays to hold data which will be returned by the child macros. The parent macro then fills the master macro buffer with both numeric values using the CALLSETDBL keyword and string values using the CALLSETSTR keyword:

n_vals = 49 DECLARE x, DOUBLE, 1, n_vals    # Variables to store OPD data DECLARE y, DOUBLE, 1, n_vals

FOR i, 1, n_vals, 1

CALLSETDBL i, 2*i   # Test values to demonstrate use of CALLSETDBL, CALLSETSTR keywords A$= call_str$ + $STR(i) CALLSETSTR i, A$

NEXT i

In this case the numeric and string values are simple test values used to demonstrate the method of passing data back and forth between parent and child macros.

The parent macro then calls the first child macro (CALLMACRO_TEST_CHILD1.ZPL) using the CALLMACRO keyword. In the child macro, values stored in the macro buffer are printed to the output window using the CALD and $CALLSTR numeric functions: ! Print values passed from parent macro n_vals = 49 FOR i, 1, n_vals, 1 FORMAT 6.4 PRINT "Doule precision value = ", CALD(i) FORMAT 2 INT A$ = $CALLSTR(i) PRINT A$

NEXT i

The macro then calculates the optical path difference for various tangential pupil coordinates (Py) at fixed sagittal pupil coordinate (Px = 0) and fixed field coordinates (Hx = Hy = 0) using the RAYTRACE keyword and the OPDC function:

! Calculate OPD

DECLARE x, DOUBLE, 1, n_vals # Variables to store OPD data DECLARE y, DOUBLE, 1, n_vals

FOR i, 1, n_vals, 1

py = 0.04166*i-1.04166 RAYTRACE 0, 0, 0, py, 1 x(i) = py y(i) = OPDC()

NEXT i

In this child macro, the values for the pupil coordinate (stored in the x array) are passed back to the parent macro using CALLSETDBL:

! Reset values to normalized pupil coordinates and pass them back to parent macro

call_str$= "This is the string for variable number " FOR i, 1, n_vals, 1 CALLSETDBL i, x(i) A$ = call_str$+$STR(i+50) CALLSETSTR i, A$ NEXT i New string values are also placed in the macro buffer as a test to ensure that this data is passed back to the parent. Once the child macro is finished, OpticStudio returns to the parent macro, and values for the pupil coordinate are stored in the appropriate array: CALLMACRO CALLMACRO_TEST_CHILD1.ZPL ! Save values passed back from child macro 1 FOR i, 1, n_vals, 1 x(i) = CALD(i) A$ = $CALLSTR(i) PRINT A$

NEXT i

The parent macro then calls the second child macro (CALLMACRO_TEST_CHILD2.ZPL). This macro is identical to the first child macro – the only difference is that in this case, the OPD data (stored in the y array) are passed back to the parent macro rather than the pupil coordinates:

! Print values passed from parent macro

n_vals = 49

FOR i, 1, n_vals, 1

FORMAT 6.4 PRINT "Doule precision value = ", CALD(i) FORMAT 2 INT A$=$CALLSTR(i) PRINT A$ NEXT i ! Calculate OPD DECLARE x, DOUBLE, 1, n_vals # Variables to store OPD data DECLARE y, DOUBLE, 1, n_vals FOR i, 1, n_vals, 1 py = 0.04166*i-1.04166 RAYTRACE 0, 0, 0, py, 1 x(i) = py y(i) = OPDC() NEXT i ! Reset values to OPD results and pass them back to parent macro call_str$ = "This is the string for variable number "

FOR i, 1, n_vals, 1

CALLSETDBL i, y(i) A$= call_str$ + $STR(i+100) CALLSETSTR i, A$

NEXT i

New string values are again placed in the macro buffer as a test to ensure that this data is passed back to the parent. The numeric OPD data are then stored into an array in the parent macro:

CALLMACRO CALLMACRO_TEST_CHILD2.ZPL

! Save values passed back from child macro 2

FOR i, 1, n_vals, 1

y(i) = CALD(i) A$=$CALLSTR(i) PRINT A\$

NEXT i

Finally, the parent macro plots the OPD vs. pupil coordinate data using the PLOT keyword:

! Plot data

PLOT NEW PLOT TITLE, "OPD FOR FIELD POINT 1, WAVELENGTH 1" PLOT TITLEX, "NORMALIZED PUPIL COORDINATE" PLOT TITLEY, "OPTICAL PATH DIFFERENCE (WAVES)" PLOT RANGEX, -1.0, 1.0 PLOT RANGEY, -1.0, 1.0 PLOT DATA, x, y, n_vals, 1, 1, 1 PLOT GO

More information on this keyword may be found in the Help System section The Programming Tab...About the ZPL...KEYWORDS (about the zpl), and in the Knowledgebase article: “How to use the PLOT keyword in ZPL”. Results are then plotted to a graphics window:

KA-01473