How to write a ZPL macro: Computing Zonal Transverse Chromatic Aberration

This article is part of the ZPL Programming free tutorial.

This article describes how to use the Zemax Programming Language (ZPL) to create a macro calculating and plot user defined peformance metric. In this case the zonal transverse chromatic aberration (ZTCA) of a system. After explaining the basic algorithm to be used, the article describes how the macro can be generalized to allow for a more flexible use, including user input and error trapping.

Authored By Alessandra Croce


Article Attachments


Suppose we want to calculate the zonal transverse chromatic aberration (ZTCA) of a system. ZTCA is the difference in ray height between two wavelengths at the image plane, as a function of pupil zone


Here is the basic algorithm:

  1. Step over the pupil zones
  2. Trace zonal marginal ray at each wavelength
  3. Subtract y-coordinates
  4. Print results

To make the macros easy to read, we will adopt the following programming etiquette, which we recommend for every ZPL macro:

  • Write all variables as lower case
  • Write all ZPL functions and keywords as upper case
  • Indent text inside IF and FOR loops
  • Give variables meaningful names (e.g. ray_angle instead of a)
  • Use descriptive comments (e.g. using ! or #)

To make macros even easier to read, OpticStudio has a built-in text editor with syntax highlighting:


First cut macro

For this example, we will use sample file <Documents>\Zemax\Samples\Sequential\Objectives\Doublet.zmx. Load this file in OpticStudio then click Programming…New Macro:


Enter the following code to calculate the ZTCA as per the algorithm previously described:


Use the second button on the ribbon to save the macro as “ZTCA1.zpl” in the <Documents>\Zemax\Macros folder.


Then, from the Programming tab, select the saved macro from the Macro List drop-down menu, or select it from Edit/Run and then click Run


When the macro runs, a new text window will appear with the output of the macro, in this case the ZTCA as a function of pupil zones:


Note that this macro works as expected on this file, but is based on many assumptions:

  • Extreme wavelengths are 1 and 3
  • Number of steps across pupil is 10
  • It only calculates the ZTCA for the on-axis field position
  • There is no error checking 
    • what if there is only one wavelength?

Let’s improve the macro so that it can be used with other files. 

Generalized macro

User defined number of steps

We can use the INPUT keyword to prompt the user for the number of pupil steps, rather than using a fixed value of 10. At the beginning of the macro, remove assignment “numsteps = 10” and use the INPUT as follows:


This will make a ZPL Macro Input window appear when the macro is run:


The IF statement tests whether numsteps is a positive integer through function INTE(), which rounds a decimal number down.

The GOTO command tells OpticStudio to jump to a line (forward or backward) with a specified LABEL command. In this case we jump to the end of the program:


While END is only strictly necessary when using subroutines, it is a good habit to use it to indicate where execution of the macro terminates

Adapt for different wavelengths

Next, we can ask the macro to determine the extreme wavelengths (min and max) and use them for the ray trace. We can also ask to return an error message if only one wavelength is defined in the file:


The wavelengths to use for the ray trace are now minwav and maxwav, so inside the FOR loop, replace lines:

RAYTRACE 0, 0, 0, py, 1

RAYTRACE 0, 0, 0, py, 3

Respectively with:

RAYTRACE 0, 0, 0, py, minwav

RAYTRACE 0, 0, 0, py, maxwav

Error checking

Finally, we can use RAYE() to check for errors during the ray trace. The code therefore becomes:


Save the macro as ZTCA2.ZPL and test its behaviour, ensuring you test each error condition:

  • User defined steps < 1 or non-integers
  • Only 1 wavelength
  • Ray errors

Below is the macro output for 20 pupil zones:


Plotting the data

Instead of printing out the data, we can plot it using the PLOT keyword. PLOT supports one independent and one dependent variable, while PLOT2D supports two independent and one dependent variable. Both keywords allow users full control of the plot formatting, such as:

  • Title, axis legends
  • X,Y axis scales
  • Comments
  • Data points and fit line: color, style, size
  • Window aspect ratio

In order to be able to plot the data, first you need to declare two array variables, one for the pupil coordinate and one for the ZTCA. Add the array declarations after the user input and error checking code:

DECLARE pupil, double, 1, (numsteps + 1)

DECLARE ztca, double, 1, (numsteps + 1)

Then, inside the main loop, you need to store the values in the previously declared arrays instead of printing them to screen. This means replacing this line:

PRINT "Pupil zone = ", py, " ZTCA = ", yf-yc

With these lines:

pupil(i+1) = py

ztca(i+1) = yf-yc

Finally, immediately after main loop, add the code to create the plot:



PLOT TITLE, "Zonal Transverse Chromatic Aberration"

PLOT TITLEX, "Normalized Pupil Coordinate (Py)"



PLOT RANGEY, -0.005, 0.005

PLOT DATA, pupil, ztca, (numsteps + 1), 1, 2, 0


PLOT DATA is used to define the series of data points to be plotted. It requires the following arguments:

  •  x_array, y_array, #points, color, style, options

In this case Color 1 = blue, style 2 = dashed, option 0 = no data point markers

The complete description of PLOT syntax can be found in help file section The Programming Tab > About the ZPL > KEYWORDS (about the zpl) > PLOT

Now save the macro as ZTCA3.zpl and run it. The macro will produce the plot below:


This article is part of the ZPL Programming free tutorial.

Previous article: Introduction to Zemax Programming Language
Next article:
How to create a user-defined solve


Was this article helpful?
4 out of 4 found this helpful



Article is closed for comments.