This example demonstrates the feasibility of integrating Lumerical tools with Python. This interoperability is made possible using Application Programming Interface (API). Users will learn how to write a simple Python script and use some automation API functions to drive Lumerical simulations and data processing. There are two parts in this example:
- driving Lumerical simulations within Python
- producing figures in Python, e.g., PNG format.
Requirements: Lumerical products R2019a or newer
The example files were created using Lumerical 2019a, Python 3.7 (and numpy), matplotlib 0.99.1.1, scipy 1.1.0 (interpolate), collections 1.0.1 (OrderedDict) and CentOS 6.8 (Final)
It should be possible to store the files in any working directory. However, it is recommended to put the Lumerical and Python files in the same folder in order for the above script files to work properly. It is also important to check the Lumerical working directory has the correct path to run the .lsf script file, see here for instructions to change the Lumerical working directory.
A lumapi.py file is the key to enable Lumerical-Python API connection. Once the lumapi module is imported to Python, the integration should be ready. See this page for instructions for setting up Python API.
Starting a session
This is as simple as calling the relevant constructor for the Lumerical product and storing it in a variable.
fdtd = lumapi.FDTD()
You can create multiple sessions of the same product and different products at once, as long as they all have unique names.
mode1 = lumapi.MODE()
mode2 = lumapi.MODE()
device = lumapi.DEVICE()
Each of the product's constructor supports the following named optional parameters:
- hide (default to False): Hides the main window on startup
- filename (default empty): Launches the application and loads the provided project file or loads and runs the provided script file
# loads and runs script.lsf while hiding the application window
inc = lumapi.INTERCONNECT(filename="script.lsf", hide=True)
Closing a session
Since Python will automatically delete variables once they go out of scope, most times you will not need to close a session manually. However, if you need to, you can call the close function
inc.close() #inc is the name of the active session
Advanced session management
When the variables local to the function or context manager go out of scope, they will be deleted automatically, and a Lumerical session will automatically close when all variable references pointing to it are deleted.
Wrapping the session in a function
While we do not support function in Lumerical scripting language, you can use this Python feature to make your code more usable:
fdtd = lumapi.FDTD()
Using the "with" context manager
We support Python "with" statement by giving well-defined entrance and exit behaviour to Lumerical session objects in Python. If there was any error within the "with" code block, the session still closes successfully (unlike in a function). Also note that any error message you typically see in a Lumerical script environment would be displayed in the Python exception.
with lumapi.FDTD(hide=True) as fdtd:
fdtd.setnamed("bad name") ## you will see
LumApiError: "in setnamed, no items matching the name 'bad name' can be found."
## fdtd still successfully closes
Lumerical Script Commands as Python Session Methods
Almost all of the script commands in the Lumerical script language can be used as methods on your session object in Python. The method names and the Lumerical script commands share the same name and can be called directly on the session once it's been created. For example,
fdtd.addrect() # Note the added brackets since this is a method in Python.
For more details please see attached pyapi_example.py script file.
We also support Python docstrings for Lumerical session object methods which contain similar information that can be found on The Alphabetical List of Script Commands. You can view the docstring by using the Python built-in function "help" or most ways rich interactive Python shells display docstrings (e.g. IPython, Jupyter Notebook):
Help on method addfdtd in module lumapi:
addfdtd(self, *args) method of lumapi.FDTD instance
Adds an FDTD solver region to the simulation environment. The extent of
the solver region determines the simulated volume/area in FDTD
| Syntax | Description |
| o.addfdtd() | Adds an FDTD solver region to the |
| | simulation environment. |
| | |
| | This function does not return any |
| | data. |
|Note: We still support previous version of the Python API, that can be found here. However, with the modifications in the recent API, available in 2018a R4 and newer versions, we strongly recommend to use the newer Python API.|
Since release 2019a, Python API starts to support adding objects using a constructor and getting sim-object from a constructor.
Adding objects using a constructor
When adding an object, its constructor can be used to set the values of properties at creation.
fdtd.addfdtd(dimension="2D", x=0.0e-9, y=0.0e-9, x_span=3.0e-6, y_span=1.0e-6)
In python, dict ordering is not guaranteed, so if there are properties that depend on other properties, an ordered dict is necessary. For example, in the below line of python, 'override global monitor settings' must be true before 'frequency points' can be set.
props = OrderedDict([("name", "power"),("override global monitor settings", True),("x", 0.),("y", 0.4e-6),
("monitor type", "linear x"),("frequency points", 10.0)])
Getting sim-object from a constructor
When adding a new object to a lumerical product, an object is returned that respresents it. That object can be used to make changes to the object in the lumerical product.
rectangle = fdtd.addrect()
rectangle.x = -1
rectangle.x_span = 10
Since release 2019a, in addition to the standard object access style, the Python API also supports dict-like access and parent/children access.
The below line of python code shows an example of the dict-like access of parameters in a FDTD rectangle object.
rectangle = fdtd.addrect()
rectangle["x"] = -1
rectangle["x span"] = 10
Parent and children access
The tree of objects in a Lumerical product can be traversed using the parent or children of an object.
bRect = device.addrect(name="in B")
# Go up two parents from the rectangle in "B" group
aGroup = bRect.getParent().getParent()
# Print the names of all members of "A" group
for child in aGroup.getChildren():
Driving Lumerical Tools within Python
This example involves running a Lumerical "parameter sweep" in Python. The Python script loops over the material index of an object, then it runs a simulation and records the transmission data for each index. It also records time monitor and profile monitor data to be plotted. Note that this is not using the Lumerical built-in Parameter Sweep tool.
Users can run the pyapi_example.py script file to automate the simulations in Lumerical. Although this is a similar idea with the built-in Parameter Sweep tool, this is just an example to demonstrate the feasibility only. It is expected that the users may expand the use of this feature based on their requirements.
The results, returned in Python, are printed in the Terminal, and also saved to a .npy file.
T results, index = 2
[0.62071068 0.65759588 0.69757707 0.73969429 0.78241551 0.82379468
0.86173885 0.89432665 0.92010975 0.93833142]
T results, index =3
[0.63151639 0.61975685 0.63662256 0.67232229 0.67939735 0.66418428
0.62840731 0.56812109 0.49615073 0.42200023]
Producing figures in Python
This part is to demonstrate data extraction from Lumerical to Python, and make use of the matplotlib module for visualization, please see matplotlb's website for installation and documentation. It is possible to produce plots in the formats supported by the module, e.g., PNG, PS, SVG, etc.
Making figures with subplots
The figure below shows E(t) returned by a time monitor when material index is 3. The subplots are zoomed into the regions where a) the transient fields are dominant, and b) the fields decay steadily. This figure is for demonstration only, users should produce their own figures based on their requirements.
Making image plots
The figure below shows the abs(Ex(x,y)) returned by a profile DFT monitor. The colormap and colourbar of this plot can be set in the Python file. The arrow indicates the location of the local maximum. This figure is for demonstration only, users should produce their own figures based on their requirements.
|Note: that it is also possible to save Lumerical simulation results to a text file using the write command. Users can then import the text file to Python without having to using API. Exporting plot data to MATLAB is also supported, see here.|