Zemax → LensBench Mapping
A quick reference for Zemax users. ✅ implemented, 🚧 planned. Since 2026-10-17, the conventions of analyses and operands have been aligned with Zemax; for how far the numbers can be trusted, see the validation report.
Editors
| Zemax | LensBench | Status |
|---|---|---|
| Lens Data Editor | surf lines in .lens; the GUI table | ✅ |
| System Explorer | title / units / aperture / field / wave / catalogs / ray_aim in .lens | ✅ |
| Merit Function Editor | op / default lines in .lens (Zemax operand names); lb merit shows the table | ✅ |
| Multi-Configuration Editor | config / mc lines in .lens (references are written like var), zmx round trip; lb mc-set changes a single value | ✅ Editing, import/export, per-configuration analysis and plots (--config), multi-configuration merit function and optimization |
| Tolerance Data Editor | tol / comp lines in .lens; lb tolerance sensitivity analysis + tornado chart | ✅ TRAD / TFRN / TTHI / TIND / TCON / TPAR (aspheric coefficients, tol aN) / TSDX / TSDY / TSTX / TSTY / TEDX / TEDY / TETX / TETY + COMP + TWAV, sensitivity and Monte Carlo (--mode montecarlo); Monte Carlo distributions follow STAT (tol stat normal / uniform / parabolic, sigma=, and a per-line stat= at the end of the line); zmx TOL lines import and export (including TCON, TPAR, STAT; the STAT layout follows the manual and has not been checked against a Zemax file, and STAT 3, the user-defined distribution, is not imported); tol abbe (Abbe number, %) is supported, but the zmx unit of TABB is still to be verified, so it is neither imported nor exported yet; irregularity (TIRR / TEZI / TEXI) 🚧: it needs non-rotationally-symmetric surface-form terms — the Zernike sag surface (type=zernike) now exists, the tolerance layer is not wired to it yet; inverse tolerancing (Inverse Limit / Inverse Increment): `lb tolerance-inverse --limit … |
| ZPL macros / ZOS-API | CLI commands + --json, Python, MCP | ✅ |
LDE columns
| Zemax column | .lens | Notes |
|---|---|---|
| Surface Type | type=standard / evenasph / oddasph / toroidal / paraxial / tilted / binary2 / grating / zernike / zernike_fringe / coordbreak | Irregular surfaces, grid sag, Zernike phase surfaces (Zernike Fringe / Standard Phase), freeform surfaces such as Chebyshev, Binary 1 / 3, holographic surfaces, etc. 🚧 (reported as E-ZMX-TYPE on import); GRIN (gradient index) is not planned for now; USERSURF (depends on a user DLL) is not supported |
| Tilted: X / Y Tangent | type=tilted tanx= tany= | Tilted plane z = tanx·x + tany·y |
| Toroidal: Radius of Rotation / Coeff on y^2… | type=toroidal rx= a2= a4=… (R and k refer to the YZ section) | Omit rx for a cylinder |
| Paraxial: Focal Length | type=paraxial f= | Ideal thin lens; if the incoming beam has no aberration, it images perfectly for any field and any conjugate, as in Zemax |
| Paraxial: OPD Mode | opd_mode=0 / opd_mode=1 | 0 uses a fixed conjugate (default), 1 integrates ray by ray; Modes 2 / 3 are not supported and are treated as 0 on import |
| Binary 2: Diffract Order / Norm Radius / Coeff on p^2, p^4… | type=binary2 m= norm= p2= p4=… (base R, k, a2 a4 … as for the even asphere) | p2 is A1; the phase-term variable is var p2@3 |
| Zernike Standard Sag / Zernike Fringe Sag: Extrapolate, Par 1–8, Zernike Decenter X / Y, Number of Terms, Norm Radius, Zernike 1, 2 … | type=zernike / type=zernike_fringe, extrapolate=0 (default 1), a2= … a16=, zdx= zdy=, norm=, z1= z2= … (base R, k as for the even asphere) | Zernike coefficients are lengths (mm); Standard uses the Zernike Standard numbering and normalization (Noll, RMS = 1 on the unit circle — the same set as lb zernike and the ZERN operand), up to z231; Fringe is unnormalized, up to z37. Zernike terms do not enter the paraxial quantities or Seidel (base only, I-ZERN-PARAXIAL). Variables var z5@3. zmx SZERNSAG / FZERNSAG import and export (the meaning of PARM 0 / 9 / 10 follows the Zemax manual, still to be checked against Zemax) |
| Diffraction Grating: Lines/µm / Diffract Order | type=grating lines=1.2/um m=-1 (also lines=1200/mm; the unit is required) | Grooves are parallel to the local x axis; paraxial quantities use order 0 |
| Comment | comment="..." | |
| Radius | R= | C= (curvature) also works |
| Thickness | T= | |
| Material | glass= | Exact glass name; MIRROR; model(nd, vd) |
| Clear Semi-Dia | Automatic; semi= fixes it | The automatic value uses real rays (pupil edge for every field × every wavelength, maximum radial height in local coordinates); it does not vignette |
| Surface Properties › Aperture | aperture=circular(min, max) / obscuration(…) / rectangular(xh, yh) / float, decenter dx= dy= | Clips rays; zmx CLAP / OBSC / SQAP / FLAP / OBDC |
| Coordinate Break (Par 1–6) | type=coordbreak dx= dy= tx= ty= tz= order= | |
| Surface Properties › Tilt/Decenter (single-surface decenter and tilt) | One type=coordbreak before and one after the surface (the transform before the surface, the surface itself, the transform after it; the thickness is taken after the trailing transform) | Expanded automatically on zmx import, and later surface numbers shift accordingly |
| Conic | k= | |
| Par 1..8 (EVENASPH) | a2= a4= a6= … | Named by power; Par1 = a2 |
| Extended Odd Asphere (XOSPHERE): Norm Radius / Coeff on p^1… | type=oddasph a1= a2= a3= … (aᵢ = Aᵢ / normⁱ, same surface) | zmx import/export; odd aspheres beyond r⁸ and even aspheres beyond r¹⁶ are exported as XOSPHERE |
| Cell solve type Variable | var R3 T6 a4@5 p2@3 z5@4 | |
| MFE SUMM / DIFF / PROD / DIVI / MAXX / MINN / ABSO / SQRT combinations | op EXPR expr="…" (vectorized expression that can call operands directly; see "Expressions" in optimization.md) | User-defined operands (ZPLM / UDOP) 🚧 |
| Glass Solve › Model (Vary Index / Vary Abbe) | glass=model(nd, vd) + var nd@3 vd@3 | With no bounds written, nd is 1.40–2.10 and vd is 15–100 |
| Replace a model glass with a catalog glass (Glass Substitution) | lb glass-substitute (--reoptimize optimizes again after the swap) | Picks the nearest glass by (nd, vd) distance |
| Glass catalog Status / Relative Cost | supply status and relative price in lb materials, lb glass, lb glass-map | Taken from the catalog the design actually uses (an AGF before the bundled library, which has no prices); obsolete glasses get W-GLASS-OBSOLETE in lb check |
| Switch catalog glasses to another vendor's equivalents | lb glass-replace --vendor CDGM (--refocus / --reoptimize) | Nearest by (nd, vd), ties broken by supply status, ΔPgF, dn/dT, expansion and price, obsolete grades skipped; reports before / after image quality, mass and price |
| Cell solve type Pickup | R=pickup(source_surface, scale=, offset=) | R / T / k / aN (aspheric coefficients, e.g. a4=pickup(2, scale=-1); both the source and this surface must be aspheric) |
| Glass Solve › Pickup | glass=pickup(source_surface) | Copies the source surface's medium after the surface (resolved at parse time, and follows the source surface across configurations); the source surface cannot be a coordinate break; a model-glass variable on the source or this surface cannot be used together with it for now |
| Marginal Ray Height | T=solve(marginal_height, h) | |
| Chief Ray Height | T=solve(chief_height, h) | |
| Marginal Ray Angle | R=solve(marginal_angle, u) | u is the global slope dy/dz; can also be solved on a mirror (after a mirror, using the global slope is an inference, still to be verified against Zemax) |
| Chief Ray Angle | R=solve(chief_angle, u) | Same as above |
| F Number | R=solve(fnum, F) | The marginal ray converges after leaving this surface, |u′| = 1/(2F); can also be solved on a mirror (even numbers of reflections have been checked against results stored by Zemax; after an odd number of reflections, such as a single concave mirror, it is an inference still to be verified against Zemax) |
| Quick Focus (tool) | T=solve(focus) | Always-on best focus |
| Edge Thickness | T=solve(edge_thickness, edge_thickness, radial_height) | At the radial height, T + next-surface sag − this-surface sag = target (sag taken along y); with no radial height it uses this surface's fixed semi (Zemax uses the semi-diameter for radial height 0; not yet supported when the semi-diameter is automatic) |
| Position | T=solve(position, length, reference_surface) | Distance from the reference surface vertex to the next surface vertex = length; the reference surface is before this surface or is this surface (the semantics of a reference surface after it have not been verified, so it is not supported for now) |
| Aplanatic | R=solve(aplanatic) | Marginal ray u′/n′ = u/n (this surface contributes no spherical aberration, coma, or astigmatism); refracting surfaces only |
| Concentric of Surface | R=solve(concentric_surface, reference_surface) | The center of curvature falls on the vertex of the reference surface |
| Concentric with Radius | R=solve(concentric_radius, reference_surface) | Coincides with the center of curvature of the reference surface (when the reference surface is a plane, this surface is a plane too) |
| Remaining solves (Marginal / Chief Ray Normal, Element Power, Optical Path Difference, Semi-Diameter Pickup, ZPL Macro …) | 🚧 | Taken as plain values on zmx import |
System Explorer
| Zemax | .lens |
|---|---|
| Aperture Type: Entrance Pupil Diameter / Image Space F/# / Object Space NA / Float By Stop Size | aperture EPD 10 / aperture FNO 4 / aperture NA 0.1 / aperture float |
| Fields: Angle / Object Height / Paraxial Image Height / Real Image Height | field angle … / field object_height … / field paraxial_image_height … / field real_image_height … |
| Field Weight / VDX VDY VCX VCY | w= vdx= vdy= vcx= vcy= |
| Fields › Normalization: Radial / Rectangular | Radial by default; for rectangular write norm=rect (on any field line, e.g. field angle (0, 0), (10, 7.5) norm=rect): Hx is normalized by the largest |x| field and Hy by the largest |y| field (the fifth number of zmx FTYP; imported and exported) |
| Wavelengths + Primary | wave F, d*, C or wave 0.55* |
| Material Catalogs | catalogs SCHOTT, CDGM. For versioned library names in a zmx GCAT (the AGF version the user installed at the time, such as CDGM-ZEMAX201806, CDGM20160415, CDGM-202111): if an AGF with the same name exists (the file agf points to, or one in the Glasscat directory), it is used; otherwise "vendor name + a suffix starting with -, _, or a digit" is looked up in that vendor's current library, glass names are still matched exactly, and W-CATALOG-VERSION is reported (that version's data may differ slightly). The library name is kept as is, and exporting back to zmx writes it unchanged |
| Load an .AGF glass library | agf "glass/SCHOTT.AGF" (a single file: that vendor is searched before catalogs); agf "C:/…/Glasscat" (a whole directory: in catalogs order, same as GCAT) |
| Ray Aiming: Off / Paraxial | ray_aim off / ray_aim real (or robust, which tolerates a few vignetted rays better): both iterate to aim at the stop, with the stop size set paraxially, equivalent to Zemax's Paraxial |
| Ray Aiming: Real (stop size set by the real marginal ray) | ray_aim real_stop: the real marginal ray of the on-axis field exactly meets the aperture in object space (EPD/2, object-space NA), and its height at the stop is the stop radius; with a floating aperture it is the same as Paraxial. The second number of zmx RAIM, 0 / 1 / 2, imports as off / robust / real_stop, and export does the reverse |
| Aperture › Telecentric Object Space | aperture NA 0.1 telecentric or aperture float telecentric (finite object distance, non-angle fields, NA or float aperture only; the second number of zmx FTYP). With the stop exactly at the rear focal plane of the front group (entrance pupil at infinity) the entrance pupil diameter / position are inf and the image-space F/# is not applicable; the other first-order quantities are computed as usual |
Analysis
| Zemax | LensBench | Status |
|---|---|---|
| System Data (EFFL, BFL, F/#, ENPP, EXPP, TOTR…) | lb paraxial; conventions as in Zemax (image-space F/#, entrance / exit pupil diameters taken positive, total length as Total Track), checked against Zemax's System Data | ✅ |
| Cardinal Points | The "Cardinal points" table of lb paraxial (primary wavelength): object- and image-space focal lengths, focal points, principal points (principal planes), nodal points, anti-principal points (anti-principal planes), and anti-nodal points; same default start and end surfaces as Zemax (surface 1 → image plane): object-space positions are relative to the vertex of surface 1 and image-space positions relative to the image-plane vertex, along the optical axis with right positive; object-space focal length −n/φ, image-space n′/φ; when image space is not air the nodal points are not at the principal points. Computed with paraxial matrices, and not yet checked item by item against Zemax's report | ✅ |
| Standard Spot Diagram | lb spot (RMS/GEO, µm), lb spot-diagram (plot) | ✅ |
| Geometric Image Analysis (point source, to see the energy distribution) | lb spot-density (RMS, 99.5 % energy radius); lb plot x.lens spot_density (pseudo-color density) | ✅ |
| Single Ray Trace | lb ray Hx Hy Px Py | ✅ |
| 2D Layout | lb layout (PNG) | ✅ |
| Prescription Data | lb show | ✅ |
| Ray Fan | lb ray-fan (µm, relative to the primary-wavelength chief ray) | ✅ |
| OPD Fan | lb opd-fan (waves) | ✅ |
| Wavefront Map / Interferogram | lb wavefront --field 3 (RMS, P-V); lb plot x.lens wavefront (pseudo-color + interferogram) | ✅ |
| Image Simulation | lb image-sim (patch: Strehl, lateral color; full: distortion, relative illumination); lb plot x.lens image_sim | ✅ |
| Grid Distortion | lb grid-distortion (maximum distortion, SMIA TV distortion); lb plot x.lens grid_distortion | ✅ |
| Through Focus MTF | lb through-focus-mtf [frequency] (best focus for each field); lb plot x.lens through_focus_mtf | ✅ |
| FFT MTF vs. Field | lb mtf-vs-field [frequency…]; lb plot x.lens mtf_vs_field | ✅ |
| Relative Illumination | lb relative-illumination (minimum value, effective F-number); lb plot x.lens relative_illumination | ✅ |
| Diffraction / Geometric Encircled Energy | lb encircled-energy (50 / 80 / 90 % energy radius); lb plot x.lens encircled_energy | ✅ |
| FFT PSF / FFT PSF Cross Section | lb psf --field 3 (Strehl, peak position, Airy radius); lb plot x.lens psf (pseudo-color + cross section, scale=log); polychromatic by default, --wave k for a single wavelength | ✅ |
| Huygens PSF / Huygens PSF Cross Section | lb huygens-psf --field 3 (--sampling pupil sampling, --pixels image grid, --delta pixel pitch in µm); lb plot x.lens huygens_psf; pixels lie on the real image plane (tilted / curved image planes) | ✅ |
| Glass Map | lb glass-map (--catalogs all); lb plot x.lens glass_map; hover in the desktop app to read the glass name | ✅ |
| Sag Table | lb sag 3 (--num); lb plot x.lens sag --view "surface=3"; BFS takes the sphere through the vertex and the edge | ✅ |
| Full-Field Aberration / RMS Field Map | lb field-map (--area sensor, --data wavefront); lb plot x.lens field_map | ✅ |
| RMS vs. Field (Spot Radius / Wavefront) | lb rms-field (--data wavefront, --ref chief, --num, --rings, --arms); lb plot x.lens rms_field; Gaussian quadrature, same as RSCE / RWCE (arms default to 2 × rings, azimuths as in Zemax) | ✅ |
| Zernike Fringe / Standard Coefficients | lb zernike --field 3 (--kind standard, --terms, --grid); lb plot x.lens zernike; coefficients in waves, relative to the chief-ray reference sphere | ✅ |
| Huygens MTF | lb huygens-mtf 20 40 (--sampling pupil sampling); lb plot x.lens huygens_mtf; computed on the real image plane, so it differs from FFT MTF when the image plane is tilted / curved; polychromatic combination follows the same convention as FFT MTF | ✅ |
| FFT MTF | lb mtf [frequency…]; polychromatic as in Zemax: the complex OTFs of the wavelengths are added with their weights and then the modulus is taken, referenced to the primary-wavelength chief ray (lateral color is included); includes the polychromatic diffraction limit | ✅ |
| Field Curvature / Distortion | lb field-curvature; distortion is F-Tan(θ), computed in image-plane local coordinates | ✅ |
| Seidel Coefficients | lb seidel (S1…S5, C1, C2, W040…); the operands SPHA / COMA / ASTI / FCUR / DIST use Zemax's wavefront aberration coefficients (in waves), so target values for these operands in old files need converting, and opening such a file shows I-OP-SEIDEL-W | ✅ |
| Strehl (Huygens/FFT PSF) | lb strehl | ✅ |
| Chromatic Focal Shift | lb focal-shift; lb plot x.lens focal_shift | ✅ |
| Longitudinal Aberration | lb longitudinal; lb plot x.lens longitudinal | ✅ |
| Lateral Color | lb lateral-color; lb plot x.lens lateral_color | ✅ |
| Through Focus Spot Diagram | lb through-focus; lb plot x.lens through_focus | ✅ |
| Footprint Diagram | lb footprint 4 / lb footprint all; lb plot x.lens footprint | ✅ |
| Value of a single operand (MFE Value column, ZPL OPEV) | lb calc "OPDC(wave=2, Hy=1, Py=1)" (vectorized, e.g. Hy=0:0.25:1) | ✅ |
| Operands PARX / PARY / PARA / PARB, CENX / CENY, TRAC, OSCD, DISC, GMTA, MNSD / MXSD | op PARY 3 Hy=1 Py=0.5 (paraxial ray: linear superposition of the marginal and chief rays), op CENY field=3 (spot centroid, same sampling as RSCE), op TRAC Hy=1 Py=1 (relative to the centroid, the centroid being the same as in the default merit function), op OSCD (offense against the sine condition, the OSC′ of Conrady / Welford), op DISC <= 0.5 (calibrated F-θ distortion, focal length fixed by least squares), op GMTA freq=30 field=2 >= 0.5 (geometric MTF, not multiplied by the diffraction limit), op MNSD 1..6 >= 3 (semi-diameter boundary); for conventions and parameters see the operand reference; zmx import/export (the parameter layouts of CENX / CENY, OSCD, DISC, GMTA are inferred from the manual and not checked against Zemax files); a design that uses them is optimized entirely in Python | ✅ |
| Materials Catalog (look up a glass) | lb glass N-SF* --catalogs SCHOTT | ✅ |
| System Explorer › Afocal Image Space (and Units › Afocal Mode Units) | afocal image [unit=mrad]: spot diagram, ray fans, RMS spot, TRAX / TRAY / TRAR / TRAC / RSCE / RSCH and the default merit function in angle (difference of image-space direction cosines; units urad / mrad / rad / arcsec / arcmin / deg), wavefront analyses referenced to a plane wave at the exit pupil, MTF in cycles/mrad, field curvature in diopters, distortion from the image-space chief-ray angle; lb paraxial gives the angular magnification (op AMAG); length-only analyses are refused; zmx FTYP field 7 and UNIT field 6 are imported and exported, and an Angular Radius default merit function imports as default angular | ✅ (direction-cosine angles, the vergence sign convention and the reference plane follow the manual and geometry, not yet checked against Zemax runs) |
| Optimization Wizard (default merit function) | default spot centroid rings=3 arms=6 …; Obscuration → obscuration=0.33; total weight (π × mean of field / wavelength weights) and quadrature azimuths as in Zemax | ✅ |
| Local Optimization (DLS) | lb optimize (Levenberg-Marquardt) | ✅ |
| Hammer | lb optimize --mode hammer --seconds N | ✅ |
| Save/Load Merit Function (.MF) | lb mf-export / lb mf-import (also reads Zemax's text .MF; a merit function embedded in a zmx is imported with lb import-zmx and written back with lb export-zmx); when writing for Zemax only lines whose operands Zemax has are written, and LensBench-only ones such as op EXPR are left out and listed | ✅ |
Files
| Zemax | LensBench |
|---|---|
.zmx import | lb import-zmx x.zmx (own parser, supports UTF-8/UTF-16); variable flags on curvature, thickness, conic, and aspheric coefficients (CURV type 1, VDSZ, VCON, VPAR) → var; marginal / chief ray angle, F-number, aplanatic, concentric, and pickup → solve; thickness marginal-ray-height solve (MAZH) → T=solve(marginal_height, h), chief-ray-height solve (CHZH) → T=solve(chief_height, h), edge-thickness solve (EDGE) → T=solve(edge_thickness, …) (after building, the values are checked against those stored by Zemax, and any that do not match are frozen to values); thickness pickup (PZUP), glass pickup (GLAS solve type 2), conic-coefficient pickup (PKUP), and aspheric-coefficient pickup (PPAR) → pickup (the values in the file are checked first); all other solves are taken as values only, with a notice. When a glass name in the file cannot be found in the bundled material library (mostly discontinued glasses), or a versioned library name in GCAT has a same-named AGF in the local Zemax Glasscat, a line agf "<local Glasscat>" is added to the .lens automatically (written explicitly in the text, matched exactly, with notice I-ZMX-GLASSCAT); unparsed surface directives are combined into a single notice |
.zmx export | lb export-zmx x.lens x.zmx (angle / F-number / aplanatic / concentric solves on curvature, ±1× curvature pickup, thickness pickup, thickness solves on marginal-ray height / chief-ray height / edge thickness, pickups of glass / conic / aspheric coefficients, and variables on curvature / thickness / conic / aspheric coefficients / diffractive phase terms / Zernike coefficients are written as they are (without bounds, since Zemax variables have none); the merit function, multi-configuration data, and tolerances are written along with them; other solves are frozen at their current values, and nd / vd variables of model glasses are not written, with a notice) |
On export, a check sheet x_zemax_check.md / .csv is attached next to the file by default: "the numbers this design should show in Zemax" — System Data (focal length, back focal length, image-space F/#, entrance / exit pupils, total length, paraxial magnification), the RMS of each field in the Standard Spot Diagram, FFT MTF (T / S of each field at 10 / 20 / 30 cycles/mm), maximum distortion, and the totals of the Seidel terms. Each row states which Zemax window to look in, the unit, and the LensBench evidence id, and the sheet ends with the sampling settings (Ray Density, Sampling, ray aiming, glass library version). Open the exported .zmx in Zemax and go through it item by item; checking takes about half a minute. --no-check skips this sheet.