ZEMAX (also known as OpticStudio), a leading tool for design and analysis of optical systems, provides an in-built DDE server that enables access to ZEMAX’s features externally using any Windows application. The ability to access and control ZEMAX externally allows it to be used in many interesting and powerful ways, some of which has been documented in the “ZEMAX Extensions” chapter of the ZEMAX manual. An excellent toolbox called MZDDE, developed by Derek Griffith at CSIR, already exists for users of MATLAB. When I tried to look for an equivalent toolbox in Python, I couldn’t find one, so I decided to write one myself.
PyZDDE is a Python-based toolbox for communicating with ZEMAX using the DDE messaging protocol. It is similar to MZDDE and very much inspired by it. Currently PyZDDE is not as extensive as MZDDE as it is a work in progress. However, it has some distinguishing features — it can be used with regular Python scripts and also in an interactive environment such as an IPython shell, QtConsole or IPython notebook. The ability to interact with ZEMAX from an IPython notebook using PyZDDE can be a powerful tool for both teaching and documentation. Please visit the github repository for downloading and using the code. The github repository also contains an accompanying wiki page which describes briefly on how to use the PyZDDE toolbox.
import pyzdde.zdde as pyz link = pyz.createLink() print(&amp;amp;quot;Hello Zemax version: &amp;amp;quot;, link.zGetVersion()) link.close()
Zemax maintains a separate copy of a lens in the DDE server and all processing/modifications using any external application is done on this lens residing in the DDE server. The lens (if any) in the LDE is not modified by the DDE calls. One can of course move the lens in the DDE server to the LDE (using
zPushLens) or move the lens in the LDE to the DDE server (using
- Start the ZEMAX application.
- Import the pyzdde module (
import pyzdde.zdde as pyz) and create a DDE communication object object (
link = pyz.createLink()) in a Python script, IPython QtConsole (interactive environment) or IPython notebook.
- Now, if you want to work with a lens in the LDE, use
link.zGetRefresh()to copy the lens from the LDE to the DDE server. Else, load a ZEMAX lens file directly into the DDE server using the function
link.zLoadFile(). You can of course build an optical system from scratch entirely through PyZDDE.
- Once all calculations (depending on the application) have completed, use
link.close()to terminate the DDE communication.
- A separate module called arraytrace has been added for performing array ray tracing.
- Functions for accessing ZEMAX using the data items as defined in the “ZEMAX EXTENSIONS” chapter of the ZEMAX manual. These functions’ names start with “z” and the rest of the function-names match the corresponding data-item defined by Zemax. For example
- Helper functions to enhance the toolbox functionality beyond just the data items, such as
zSpiralSpot. Also, there are other helper functions which increase the capability of the toolbox such as
zSetWaveTuple, etc. More functions are expected to be added over time.
- Few functions, which start with “ipz“, such as
ipzGetTextWindowcan be used to embed analysis, graphic windows and text files from Zemax into an IPython Notebook or IPython QtConsole.
- There are several other functions which can be used independent of a running Zemax session. Examples include
findZButtonCode, etc. More functions are expected to be added over time.
import pyzdde.zdde as pyz ln = pyz.createLink() # create a DDE communication link
Helper functions of type 4 can be accessed the the `zdde` module directly.
pyz.zo.findZOperand(&amp;amp;amp;quot;decenter&amp;amp;amp;quot;) # same as calling pyz.findZOperand(&amp;amp;amp;quot;decenter&amp;amp;amp;quot;)
- PUSH LENS PERMISSION: All operations through the DDE affect the lens in the DDE server. In order to copy the lens the lens from the DDE server to the main application/LDE, you need to “push” the lens from the server to the LDE. TO do so, please enable the option “Allow Extensions to Push Lenses”, under File->Preferences->Editors tab.
- ANSI/UNICODE TEXT ENCODING: PyZDDE supports both ANSI and UNICODE text from Zemax. Please set the appropriate text encoding in PyZDDE to by calling module function
pyz.setTextEncoding(text_encoding)(assuming that PyZDDE was imported as
import pyzdde.zdde as pyz). By default, ANSI text encoding is set in PyZDDE. You can check the current text encoding by calling
pyz.getTextEncoding()function. Please note that you need to do this only when you change the text setting in Zemax and not for every session.
- PURE NSC MODE: If want to work on an optical design in pure NSC mode, please start ZEMAX in pure NSC mode before initiating the communication with PyZDDE. There is no way to switch the ZEMAX mode using external interfaces.
For getting started, please refer to the Getting started page at github wiki.
from __future__ import print_function import sys import os import matplotlib.pyplot as plt import pyzdde.zdde as pyz # The ZEMAX file path zmxfp = cd + '\\ZMXFILES\\' zmxfile = 'Cooke 40 degree field.zmx' filename = zmxfp + zmxfile # Create a DDE comm link ln = pyz.createLink() # Load a lens file into the ZEMAX DDE server ln.zLoadFile(filename) hx, hy = 0.0, 0.4 spirals, rays = 100, 6000 xb, yb, _, _, = ln.zSpiralSpot(hx, hy, 1, spirals, rays) xg, yg, _, _, = ln.zSpiralSpot(hx, hy, 2, spirals, rays) xr, yr, _, _, = ln.zSpiralSpot(hx, hy, 3, spirals, rays) fig = plt.figure(facecolor='w') ax = fig.add_subplot(111) ax.set_aspect('equal') ax.scatter(xr, yr, s=5, c='red' , linewidth=0.35, zorder=20) ax.scatter(xg, yg, s=5, c='lime', linewidth=0.35, zorder=21) ax.scatter(xb, yb, s=5, c='blue', linewidth=0.35, zorder=22) ax.set_xlabel('x') ax.set_ylabel('y') fig.suptitle('Spiral Spot') ax.grid(color='lightgray', linestyle='-', linewidth=1) ax.ticklabel_format(scilimits=(-2,2)) # close the communication channel pyz.closeLink() plt.show()
Output of the above Python script.
I have also written a Zemax knowledge-base article called “Talking to ZEMAX from Python using PyZDDE”. That article gives a more complete overview of the toolbox. The link to the knowledge-base article is http://www.zemax.com/support/knowledgebase/talking-to-zemax-from-python-using-pyzdde [updated on 02.24.2015]
Is there anything missing? The short answer is yes! At this time you cannot perform bulk/ array ray tracing with PyZDDE. I hope that in the near future, this issue will be resolved. UPDATE [02/24/2015]: As of today, there is a way to do array ray tracing. The code is still in a separate branch, as I am testing the code. It will soon be integrated into the master branch.
PyZDDE is now feature complete with array ray tracing feature added to it.