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.
Authored By Sanjay Gangadhara
Downloads
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
Comments
Please sign in to leave a comment.