ZEMAX features a built-in DDE (Dynamic Data Exchange) server that allows other Windows applications access to ZEMAX functions. Programming DDE applications can be somewhat complex if you are working in a compiled language such as C++. An alternative is to use one of the scripting languages such as Tcl, Python or Matlab. Matlab is a great choice since it is much more than a scripting language. Matlab provides a wealth of functions for processing and visualizing scientific and engineering data and there are toolboxes for Matlab that extend the basic capabilities into a wide variety of more specialized areas and disciplines.
What is DDE ?
DDE is a facility and a protocol provided by Windows to allow applications to communicate.
There are a few modes of DDE interaction, the simplest being the exchange of text strings of data. One of the applications must set itself up as a server. ZEMAX is the DDE server in this case, so you don’t have to do anything except start ZEMAX. Once you have started ZEMAX, the DDE server is ready and waiting for a client to connect and make requests for services. The client application in this case is Matlab.
If you look in the ZEMAX manual in the chapter on “ZEMAX Extensions” in the section called “The Data Items”, you will see the various request strings you can send to ZEMAX from Matlab (or from other DDE clients). The manual also documents the reply that ZEMAX will send back to the client application. The requests can be for ZEMAX to perform a particular function or computation, or simply to send back data on the lens currently stored in the ZEMAX DDE server.
Now here is an important point to note. ZEMAX always maintains a separate copy of the lens data in the DDE server memory to that available to the user in the ZEMAX Lens Data Editor (LDE). This is a very good policy, since you don’t want some DDE client coming in unexpectedly and altering your lens data. There are functions that explicitly copy the lens in the LDE to the DDE server or the other way around. The PushLens item instructs ZEMAX to copy the lens data in the ZEMAX DDE server into the LDE, and the GetRefresh item will copy the lens data in the LDE into the DDE server. As you develop your application in Matlab, it is important to keep track of your data and take care how you use the PushLens and GetRefresh items.
From the ZEMAX Preferences dialog, you have control over whether extensions (Matlab in this case) are allowed to tell ZEMAX to push lens data from the DDE server into the LDE. Go to the Editors tab on the Preferences dialog and look for a check box labeled “Allow Extensions to Push Lenses”.
Matlab has a few basic functions for performing DDE client operations. They include the following.
ddeinit – This function is used to initiate a DDE conversation
ddereq – Used to request data from the DDE server
ddeterm – Terminates the DDE link
The basic sequence for accessing ZEMAX from Matlab is
Start ZEMAX and Matlab.
Initiate the DDE link from Matlab using the ddeinit function.
Send requests and obtain replies from ZEMAX using the ddereq function.
Terminate the link to ZEMAX using the ddeterm function.
The ddereq function is used in the text mode, that is, you send data to ZEMAX in the form of a text string and the answer is returned in the form of another string. To get the strings into object classes that are more useful in Matlab (floats, doubles, integers etc.) you will use the sscanf function or other functions for string data conversion e.g. str2num.
The ZEMAX DDE Toolbox for Matlab
You can save yourself some effort by downloading the ZEMAX DDE toolbox from the Mathworks Central File Exchange. This toolbox is open source under the GPL and implements a Matlab function for each of the data items documented in the ZEMAX manual in the chapter on ZEMAX Extensions. The corresponding Matlab function in the toolbox has the same name as the data item, but prefixed with “z”. To get started, perform the following steps.
Download the toolbox archive (.zip file).
Unzip the archive to a sub-directory called MZDDE anywhere on your local disk.
Start ZEMAX and Matlab.
Add the directory MZDDE to your Matlab path to enable Matlab to find the new functions (go to the File menu and select Set Path …)
If you type help mzdde at the Matlab prompt, you should get a list of all the functions in the toolbox and a short description of each function. If so, you are ready to use the toolbox.
Use the function zDDEInit to open the DDE link to ZEMAX. This step is important. If you don’t do this before trying to execute other calls in the toolbox, Matlab will issue a verbose error message suggesting that something terrible has happened and that you should contact the Mathworks. If this happens, just ignore the error and make the call to zDDEInit.
Call other functions in the toolbox as required, making judicious use of zPushLens and zGetRefresh if you need to interact with the ZEMAX user interface. Of course, you can call the functions from the Matlab command line, or incorporate them into your Matlab functions and scripts.
Finish off by calling zDDEClose. This is not important in most cases, and you can just terminate Matlab and ZEMAX without closing the DDE link.
Note that the toolbox function names are capitalized for readability. Matlab function names are case insensitive under Windows, so that zddeinit is equivalent to zDDEInit. This is convenient at the Matlab command line, but the capitalization helps for readability in functions and scripts. The source code for all of the functions is available for modification and reuse, and you can examine the source to see how the basic Matlab DDE calls are used.
Every DDE call made by Matlab to ZEMAX is subject to a timeout limit. The default is set in the zDDEInit function to 3 seconds. That is, if ZEMAX does not respond to the DDE request within 3 seconds, the Matlab call will return empty-handed. You will want to increase the timeout limit if you are calling on ZEMAX to do time-consuming computations. This can be done using the zSetTimeout function call.
Here is a simple example of an interaction with ZEMAX at the Matlab prompt. Having started ZEMAX in the usual way, enter the following commands in Matlab.
>> zLoadFile('C:\ZEMAX\Samples\Sequential\Objectives\Cooke 40 degree field.zmx')
>> [x, y] = SpiralSpot(0.4, 0, 1, 10, 10000);
You should get a plot something like this …
Firstly the DDE link was initialized and the result of 0 indicated success, then ZEMAX was asked to load a lens into the DDE server with the zLoadFile function call. Now, a pretty way of representing a spot diagram is to trace a spiral of rays through the lens pupil and to plot the ray intercepts at the image plane. This is implemented in a toolbox function called SpiralSpot. Get help for the function by typing help spiralspot at the Matlab prompt. Because SpiralSpot acts on the lens in the LDE by starting out with a zGetRefresh, it is necessary to perform a zPushLens before calling SpiralSpot. A timeout of 1 second was specified for zPushLens to complete in this case.
Note that in this example you would get the same result if you had loaded the same lens into ZEMAX from the ZEMAX File menu rather than using the zLoadFile call.
Tracing Large Numbers of Rays
The standard text mode of the DDE call is adequate for many purposes, but not when large amounts of data have to be exchanged between the client and the server. This situation arises when you need to trace a large number of rays. Unfortunately, at the time of writing the toolbox, Matlab did not allow DDE modes other than text. To circumvent this problem, it was necessary to write some C code in mex (Matlab executable) format. He resulting .dll is called zArrayTrace.
Type help zArrayTrace to get more information on bulk ray tracing. It will also be useful to consult the corresponding section in the ZEMAX manual. To help set up the ray input data for zArrayTrace mode 0, there is a function called genRayDataMode0.
If you have the Matlab compiler, it is possible to compile your Matlab scripts written using the toolbox to standalone extensions that can be run from the ZEMAX Extensions menu. There are a few traps that must be avoided when attempting this. Firstly, there are a few Matlab functions that cannot be compiled, and you will have to think of workarounds for such functions (fortunately not many). Secondly, while your standalone extension should run fine on a machine on which Matlab is installed, it will not run on a machine that does not have the Matlab runtime libraries. You must therefore package your extension together with the Matlab runtime libraries to make it fully portable. The Mathworks makes this easier by packaging most of the required runtime libraries in a self-extracting archive called mglinstaller.exe (typically found in C:\MATLAB\extern\lib\win32 or thereabouts). The final trap is that the regular Matlab runtime libraries do not contain the code for the DDE functions mentioned above. These .dll files can be found by searching your Matlab installation for files matching dde*.dll (typically C:\MATLAB\toolbox\matlab\winfun or thereabouts). The runtime libraries, including the DDE libraries, must be installed to a directory that is on the Windows search path.
Things to Remember when using the Toolbox
Your first call after starting up ZEMAX and Matlab must be to zDDEInit.
Timeouts can be a problem. Increase the DDE timeout limit using zSetTimeout if necessary.
ZEMAX has two copies of the lens data, one displayed in the Lens Data Editor, and the other stored in the DDE server. Your can copy the one to the other using the zPushLens and zGetRefresh functions. zPushLens always requires a single parameter giving the timeout in seconds.
zPushLens will only work if you have granted ZEMAX extensions permission to push lenses by checking the box on the Editors tab of the ZEMAX Preferences dialog.