Hey John,
The code to plot via ZPL is relatively simple:
- Create 1D numeric arrays for the independent (x-axis) and depenedent (y-axis) variables
- Populate the variables as needed inside a
for loop - Use the PLOT commands to format & execute the plot
For the field curvature information, I would use FCGS and FCGT to get the sagittal and tangential field curvature plots. I would then use PETZ to calculate the Petzval radius. A sample code would be below:
# calculates the tan & sag field curvature for a given wavelength
# and plots these curves along with the petzval surface
# user defined variables
wave = 2
max_steps = 50
# close the output window so only the plot will appear
CLOSEWINDOW
# determine the petzval curvature
pc = OPEV(OCOD("PETZ"), 0, wave, 0, 0, 0, 0)
IF pc != 0 THEN pc = 1 / pc
# declare the arrays to plot later
DECLARE s, DOUBLE, 1, max_steps + 1
DECLARE t, DOUBLE, 1, max_steps + 1
DECLARE sag, DOUBLE, 1, max_steps + 1
DECLARE y, DOUBLE, 1, max_steps + 1
# determine the maximum FOV
mfov = OPEV(OCOD("REAB"), 0, wave, 0, 1, 0, 0) / OPEV(OCOD("REAC"), 0, wave, 0, 1, 0, 0)
mfov = ATAN(mfov) * 90 / ACOS(0)
FOR i, 0, max_steps, 1
# normalize the field coordinate
hy = i / max_steps
# get the field curvature
s(i + 1) = OPEV(OCOD("FCGS"), 0, wave, 0, hy, 0, 0)
t(i + 1) = OPEV(OCOD("FCGT"), 0, wave, 0, hy, 0, 0)
# get the y-coordinate of the ray (note this only works for rotationally symmetric systems)
h = OPEV(OCOD("REAY"), NSUR(), wave, 0, hy, 0, 0)
# get the sag of the petzval surface
sag(i + 1) = pc * h / (1 + SQRT(1 - h*h * (pc*pc)))
# store the independent variable for plotting
y(i + 1) = mfov * hy
NEXT
# plot the arrays
PLOT NEW
PLOT TITLE, "FC & Petzval Radius"
PLOT TITLEX, "Millimeters"
PLOT TITLEY, "+Y"
PLOT FORMATX, "%4.2f"
PLOT FORMATY, "%2.0f"The
PLOT DATA, s, y, max_steps + 1, 2, 1, 0
PLOT DATA, t, y, max_steps + 1, 2, 0, 0
PLOT DATA, sag, y, max_steps + 1, 0, 0, 0
PLOT GO
As for using an LLM to help with the ZPL, I don’t have experience with this. Without learning the Zemax Programming Language and creating a schema (like MCP) to feed into your LLM, I think the best you can do is copy & paste existing ZPL files (Documents/Zemax/Macros) as additional context.