How to create a ZOS-API User Extension to convert from Chebyshev to Extended polynomial

This article is part of the Getting Started with ZOS-API free tutorial.

This article describes how to create a User Extension using the ZOS-API to convert from a Chebyshev polynomial surface to an Extended polynomial surface. The conversion will work up to a 14th order Chebyshev surface, which is currently the maximum allowed in OpticStudio.

Authored By Sandrine Auriol, Katsumoto Ikeda


Article Attachments


Chebyshev polynomials for optical design are becoming increasingly popular, but are difficult to manufature on-site. These polynomials may not be implemented in the tooling CAM (Computer-Aided Manufacturing) equations, the mold correction, and mold shrinkage compensation during injection molding. However, the Extended polynomial surface can be. So, it is useful to have a method to convert the Chebyshev polynomials into Extended polynomials, and vice versa.

What is a User Extension?

In the built-in Help file under The Programming Tab…About the ZOS-API…Plug-In/Extension, a ZOS-API Extension is defined as follows. It is "conceptually very similar to a ZPL Macro – the Extension controls the active OpticStudio instance, blocks user interaction with the UI while it is running and can change virtually any aspect of the active lens system. Initial setup and connection to OpticStudio is identical to the User Operand and User Analysis modes.”

For an extension, the PrimarySystem (found on TheApplication) is always the lens system displayed in OpticStudio. The Extension author can control whether or not changes to PrimarySystem are displayed ‘live’ in the user interface:

// Make all changes (i.e. loading a new lens file) immediately

// display in the User interface

TheApplication.ShowChangesInUI = true;

// Do some work

// Do not show any changes in the User interface

TheApplication.ShowChangesInUI = false;

// Do some more work

This setting can be very important when performing a task that results in many rapid changes – such as inserting a large number of rows in the Merit Function Editor. Note that regardless of this setting, the UI will always display the final system when the Extension completes. There are also three additional properties available via the API that are specific to Extensions:

  • TheApplication.TerminateRequested:  this will be true when the user clicks on the Cancel button.
  • TheApplication.ProgressMessage:  sets the current message displayed in the Extension dialog.
  • TheApplication.ProgressPercent:  sets the current progress (0-100%) in the Extension dialog.

Thus, the User-Extension mode gives the user a full control over the lens design and user interface. User extensions can be written using either C++ (COM) or C# (.NET). The User Extension of this article is written in C#.

Open new boilerplate template

Let’s create a User Extension in C#. Navigate to Programming…C#...User Extension:

User Extension New

A Windows Explorer opens with the solution folder {Zemax}\ZOS-API Projects\CSharpUserExtensionApplication1. Visual Studio also opens with a new solution. The solution contains a boilerplate code - a template that can be used as the basis for any User Extension. In Visual Studio, the User Extension is then compiled as an executable. The executable is then copied to the {Zemax)\ZOS-API\Extensions folder so that OpticStudio can use it. 

Open the Chebyshev freeform mirror example

The file “ChebyshevMirror_optimized.zar” is attached to this article. It contains a Chebyshev polynomial acting as a freeform mirror that focuses light coming within +/-10 o field of view in X and Y.

Chebyshev mirror

For more information about the Chebyshev polynomials, see our white paper: Design & Implementation of a New Freeform Surface Based on Chebyshev Polynomials.

The system is optimized and toleranced. Before sending the drawing of the freeform mirror to a manufacturer, we will convert the Chebyshev polynomials into Extended polynomials so that the design can be implemented in the tooling CAM (Computer-Aided Manufacturing) equations, the mold correction, and mold shrinkage compensation during injection molding.

While OpticStudio has an aspheric conversion tool built in, it does not have a tool to convert one freeform surface into another. Luckily, the ZOS-API allows us to build our own tool for that purpose.

Converting from Chebyshev polynomials to Extended polynomials

Chebyshev polynomials

Chebyshev polynomials are represented by products of X and Y, making them especially useful as a rectangular orthogonal polynomial.

Chebyshev Equation

Extended polynomials

The main differences between the definition of an Extended and Chebyshev polynomial are:

  • The conic constant k
  • The Extended polynomials contains one normalization factor per coefficient, whereas Chebyshev has x0 and y0
  • The coefficients vary with “i

Extended Equation


Using Mathematica and the above definitions, we can compute each Extended polynomial term as being equal to an equation containing Chebyshev polynomials terms. The results are shown below:


With the above results, we have generated a User-Extension that will automate the conversion by reading the coefficients of the Chebyshev polynomial surface and computing the coefficients of the Extended polynomial surface.

The User-Extension will add after the Chebyshev polynomial an Extended polynomial surface with the computed coefficients as well as a Grid Sag surface containing the sag difference between the two polynomial surfaces. That will give the quality of the fit.

File converted

Code of the User-Extension


Code explained

The code of the User-Extension can be found in the attachments. It contains:

  • A loop to find the Chebyshev polynomial surface

// Loop to find the Chebyshev polynomial surface                
                int i = 1;
                    TheApplication.ProgressMessage = "Chebyshev Surface at line : " + i.ToString();
                    if (TheSystem.LDE.GetSurfaceAt(i).Type == ZOSAPI.Editors.LDE.SurfaceType.ChebyShv)
                } while (i <= TheSystem.LDE.NumberOfSurfaces);

  • A check for the Chebyshev surface. If a Chebyshev polynomial surface is found at row i, then the code will call a conversion function called ConvertChebyshevToExtended(TheApplication, i). The conversion function will fill 2 data arrays: an array of Chebyshev coefficients and an array of computed Extended coefficients. Once the conversion is done, the function will add a new Extended polynomial surface just after the Chebyshev polynomial surface filled with the newly computed coefficients.

//Call the conversion function
ConvertChebyshevToExtended(TheApplication, i);

  • A call to a function Sag(TheApplication, i) that will return an array of the sag. It will be called twice: once for the Chebyshev polynomial surface and once for the Extended polynomial surface.

//Measure the sag of Chebyshev, Extended       
double[,] chebysag = Sag(TheApplication, i);
double[,] extendedsag = Sag(TheApplication, i + 1);

  • A call to a function called SagDifference(chebysag, extendedsag) which will return an array containing the sag difference between the Chebyshev polynomial surface and the Extended polynomial surface.

    //Make the difference and add a "difference" grid sag surface
    double[,] chebyExtendedsagdiff = SagDifference(chebysag, extendedsag);
  • A call to a function called RMS_PV_function(chebyExtendedsagdiff, out RMSConversion, out PVConversion) which will return the RMS (RootMean-Square) and PV (Peak-to-Valley) of the sag difference.

    //Calculate the RMS and PV of a matrix
    RMS_PV_function(chebyExtendedsagdiff, out RMSConversion, out PVConversion);
  • And finally, a call to a function called CreateGridSag that will create a Grid Sag surface with the sag difference. This will be the quality of the fit.

    //Make a grid sag of the difference
    //The arguments are the semi-diameter because we need to know the spacing / interval between the sag points
    //the surface number is also an argument: we will add a grid sag below the extended surface
    double semidiameter = TheSystem.LDE.GetSurfaceAt(i).SemiDiameter;
    CreateGridSag(TheApplication, chebyExtendedsagdiff, semidiameter, i);

Save, build, and move executable

The solution can then be built in Release Mode. To distribute the User-Extension as a plug-in, set it in Release mode, because the Debug libraries are not redistributable.


The executable can then be copied from the solution folder (in {Zemax}\ZOS-API Projects\...) to {Zemax}\ZOS-API\User Extension.

Run User Extension

To check the ConvertChebyToExtended User Extension, start OpticStudio and open the lens file “ChebyshevMirror_optimized.zar”.

Open a Wavefront Map under Analyze…Wavefront. We will use this to compare the results before and after the conversion. To start, the Wavefront Map shows an RMS of 1.7423 waves and PV of 6.9820 waves.

Under Programming…User Extensions, there should now be the newly created extension.

Run Extension

Running the extension computes the Extended polynomial coefficients:

Extension running

The extension displays the quality of the fit:

Fit Quality

Then two new surfaces are added to the file after the Chebyshev polynomial surface: an Extended Polynomial and a Grid Sag surface containing the difference.


On the Wavefront map, the results after the conversion show an RMS of 1.7423 waves and PV of 6.9820 waves. The conversion runs properly!

Things to know about the User Extension: speed, settings and other tips

  • Can the UserExtension change the Preferences file so that the software does not save a file after each coefficient is converted?


Currently the Preferences file cannot be changed from the User Extension. When running the User-Extension and namely converting the coefficients, OpticStudio saves each step of the conversion if in Project Preferences > General > Undo is set to “Disk Multi-Step”. So, every time a new coefficient is changed (and there are more than 200) the software saves an UNDO file. That slows down the execution. The only workaround is to change that setting manually before running the extension.

  • Is there anything to speed up the UserExtension?


  1. Set IZOSAPI_Application.ShowChangesInUI to ‘false’.  That doesn’t affect the undo behavior but can make extensions run significantly faster as calling the Sag analysis for example will not mean displaying the analysis.
  2. Set the IOpticalSystem.UpdateMode to ‘LensUpdateMode.EditorsOnly’
  3. Manually change Project Preferences…General…Undo to None
  • Can the UserExtension have settings, to select the surface to convert?

The user extension is an executable, so it is possible to display a setting window. 

The easiest to add settings is to create a new empty Windows Forms project, then integrate in the user extension code. A STA thread attribute will need to be added to the entry point for a UI to work. Check the "How to create a Time-Of-Flight User Analysis using ZOS-API" article for more information on settings.

  • When I run the UserExtension, a black window pops up with the format of console application. Can I remove it?


For User Extensions, the default output format is console application. This can be changed to windows application.

Project Properties


Windows Application


This article is part of the Getting Started with ZOS-API free tutorial.

Previous article: Interactive Extension: FAQ
Next article: How to create a User-Analysis: Time-of-flight analysis


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



Article is closed for comments.