- Home
- Programming ZEMAX
- ZPL
- How to Use the PLOT2D keyword in ZPL
How to Use the PLOT2D keyword in ZPL
- By Sanjay Gangadhara
- Published 24 June 2008
- ZPL
- Unrated
Through-focus PSF plots
An interesting use of the PLOT2D keyword is to generate through-focus PSF plots. An example macro (PLOT2D_PSF.ZPL) illustrating how this is done is also provided in the .ZIP file located at the end of this article. This macro is intended to be used with the Cooke triplet sample file (Cooke 40 degree field.zmx) provided with the ZEMAX installation (in the \ZEMAX\Samples\Sequential\Objectives\ directory).
Through-focus results are generated by obtaining results for the XY PSF at various values of the back focal length (BFL). The macro starts by defining
settings for the PSF calculation, as well as arrays to hold the resultant data:
! Define the settings for the PSF data to obtain (e.g.
! for the primary wavelength, at the on-axis field
! point, ...)
wavnum = PWAV() # Primary wavelength number
fldnum = 1 # Field point number for on-
axis field point
samnum = 2 # Sampling (1 = 32x32, 2 =
64x64, ...)
unflag = 1 # Unnormalized flag (0 =
normalized, 1 =
unnormalized)
phflag = 0 # Flag for data to return (0 =
intensity, 1 = phase)
imdelt = 0 # Image delta (0 = default)
n = 2*32*samnum # Number of PSF data points in
each direction
vsize = n*n + 1000 # Vector size
SETVECSIZE vsize # Set vector size
! Set up an array to hold XYZ PSF data
nz = n # Number of Z planes at which
calculation is done
DECLARE xyz_psf, DOUBLE, 3, n, n, nz # Full 3D array of
XYZ PSF data
DECLARE psf_data, DOUBLE, 2, n, n # 2D array to hold
XY PSF data at
each Z value
DECLARE psf_size, DOUBLE, 1, nz # Spacing between
data points
Calculations for the PSF are then performed for a number of Z locations, using a FOR loop. The first step in the loop is to change the BFL of the system, using the SURP keyword:
! Loop over all Z planes
bf_surf = NSUR() - 1 # Last surface before image
plane
bf_thic = THIC(bf_surf) # Thickness of last surface
before image plane
deltaz = 0.12 # Total range for back focal
length
bf_inc = deltaz/(nz - 1) # Incremental thickness change
cent_indx = 0.5*(nz + 1) # Index value corresponding to
nominal thickness
FOR i, 1, nz, 1
! Change the thickness of the last surface before
! image plane
new_thic = bf_thic + bf_inc*(i - cent_indx)
SURP bf_surf, 3, new_thic
UPDATE ALL
At each new value of the BFL, the XY PSF is obtained using the GETPSF keyword. Tests are conducted to ensure that the data were obtained successfully:
! Get the PSF data for this system
GETPSF wavnum, fldnum, samnum, 1, unflag, phflag, imdelt
! Test that the data was obtained successfully
np = vec1(0)
IF (np == 0)
PRINT "PSF Computation aborted."
GOTO 1
ENDIF
IF (np == -1)
PRINT "SETVECSIZE too small for PSF data."
GOTO 1
ENDIF
IF (np == -2)
PRINT "Not enough system RAM for PSF data."
GOTO 1
ENDIF
IF (np == -3)
PRINT "A general error occured while computing the PSF."
GOTO 1
ENDIF
The PSF data are then written into a 3D array, as well as into a 2D array that is used to generate plots of the XY PSF data at each value of the BFL:
! Write PSF data into the 3D array, as well as into
! a 2D array for plotting
FOR j, 1, n, 1
FOR k, 1, n, 1
pos = n*(j-1) + k
xyz_psf(k,j,i) = vec1(pos)
psf_data(k,j) = vec1(pos)
NEXT k
NEXT j
! Determine the grid spacing for the PSF calculation
psf_size(i) = vec1(np+1)
! Plot the XY results at different planes, if desired
xy_plot = 0
IF (xy_plot == 1)
PLOT2D NEW
PLOT2D TITLE, "XY PSF"
PLOT2D COMM1, $STR(WAVL(wavnum))+" MICRONS AT (X,Y) =
("+$STR(FLDX(fldnum))+", "+$STR(FLDY(fldnum))+")"
PLOT2D COMM2, "THICKNESS OF THE LAST SURFACE =
"+$STR(new_thic)
PLOT2D DATA, psf_data
PLOT2D GO
ENDIF
LABEL 1
NEXT i
The grid spacing for the PSF calculation is also read into a variable. This data is used to check that calculations are performed with the same spacing at each value of the BFL:
! Make sure that the spacing between points was the same
! for all focal planes
psf_temp = psf_size(1)
psf_flag = 1
FOR i, 2, nz, 1
psf_delta = psf_size(i)
IF (psf_delta != psf_temp)
PRINT "Array sizes do not agree!"
psf_flag = 0
GOTO 2
ELSE
psf_temp = psf_delta
ENDIf
NEXT i
psf_totsiz = n*psf_delta # Total size of
the image in
X and Y, in
microns
psf_totsiz = psf_totsiz/1000.0 # Convert size
to lens units
(assumes lens
units = mm)
psf_ratio = psf_totsiz/deltaz # Ratio of X/Y-
width to Z-width
Finally, separate 2D arrays are created for plotting the XZ PSF data at Y=0 and the YZ PSF data at X=0:
! Plot XZ PSF data at Y = 0, false color
DECLARE xz_psf, DOUBLE, 2, n, nz
ypos = n/2 # Index value for y = 0
FOR i, 1, nz, 1
FOR j, 1, n, 1
xz_psf(j,i) = xyz_psf(j,ypos,i)
NEXT j
NEXT i
PLOT2D NEW
PLOT2D TITLE, "XZ PSF"
PLOT2D COMM1, "SURFACE: Y = 0"
PLOT2D COMM2, $STR(WAVL(wavnum))+" MICRONS AT (X,Y) =
("+$STR(FLDX(fldnum))+", "+$STR(FLDY(fldnum))+")"
PLOT2D COMM3, "TOTAL X-SIZE (X-AXIS), LENS UNITS = "+
$STR(psf_totsiz)
PLOT2D COMM4, "TOTAL Z-SIZE (Y-AXIS), LENS UNITS = "+
$STR(deltaz)
PLOT2D ASPECT, psf_ratio
PLOT2D DISPLAYTYPE, 5
PLOT2D HIDEADDRESS, 1
PLOT2D DATA, xz_psf
PLOT2D GO
! Plot YZ PSF data at X = 0, false color
DECLARE yz_psf, DOUBLE, 2, n, nz
xpos = n/2 # Index value for x = 0
FOR i, 1, nz, 1
FOR j, 1, n, 1
yz_psf(j,i) = xyz_psf(xpos,j,i)
NEXT j
NEXT i
PLOT2D NEW
PLOT2D TITLE, "YZ PSF"
PLOT2D COMM1, "SURFACE: X = 0"
PLOT2D COMM2, $STR(WAVL(wavnum))+" MICRONS AT (X,Y) =
("+$STR(FLDX(fldnum))+", "+$STR(FLDY(fldnum))+")"
PLOT2D COMM3, "TOTAL Y-SIZE (X-AXIS), LENS UNITS = "+
$STR(psf_totsiz)
PLOT2D COMM4, "TOTAL Z-SIZE (Y-AXIS), LENS UNITS = "+
$STR(deltaz)
PLOT2D ASPECT, psf_ratio
PLOT2D DISPLAYTYPE, 5
PLOT2D HIDEADDRESS, 1
PLOT2D DATA, yz_psf
PLOT2D GO
! Plot YZ PSF data at X = 0, surface
PLOT2D NEW
PLOT2D TITLE, "YZ PSF"
PLOT2D COMM1, "SURFACE: X = 0"
PLOT2D COMM2, $STR(WAVL(wavnum))+" MICRONS AT (X,Y) =
("+$STR(FLDX(fldnum))+", "+$STR(FLDY(fldnum))+")"
PLOT2D COMM3, "TOTAL Y-SIZE (X-AXIS), LENS UNITS = "+
$STR(psf_totsiz)
PLOT2D COMM4, "TOTAL Z-SIZE (Y-AXIS), LENS UNITS = "+
$STR(deltaz)
PLOT2D DISPLAYTYPE, 1
PLOT2D HIDEADDRESS, 1
PLOT2D DATA, yz_psf
PLOT2D GO
The number of iterations in the loop, as given by the variable nz, is the number of BFL values for which the 3D XYZ PSF data were calculated. For the above case, nz =128, while the BFL varies by a total distance of 120 mm (nz was chosen according to the sampling used to generate the XY PSF at each Z plane; the values for nz and for the range of BFL values ensure that there are the same number of points in X, Y, and Z and that they cover the same physical space). For such a large number of calculations, the computation will be slow, so be sure to exercise some patience while running the macro! However, once the PSF calculations are complete, PLOT2D may be used to plot the data in multiple formats if you like, without any noticeable change to the computational time. In other words, the computational time is determined by the time required perform the PSF calculations, and not the time required to perform the plotting. To demonstrate this fact, the macro uses PLOT2D to generate both a false color plot and a surface plot of the YZ PSF data. For the Cooke triplet on-axis, the results are the same for both the XZ and YZ PSF:
