Part III · Chapter 18
API Interface
3DOptix has a REST API at https://api.3doptix.com/v1 and an official Python package, threed-optix, that wraps it. This chapter describes the Python package, version 5.0.34. Use it to drive 3DOptix from your own scripts; use the MCP integration to work with an AI agent.
Getting an API key
- Sign in to the 3DOptix web app.
- Open your account menu and choose User settings.
- Open the API tab and copy the key.
Treat the key like a password: anyone who has it can use your account.
Installing
pip install threed-optix
The package needs Python 3 and installs its dependencies, among them requests, pandas, numpy, scipy and matplotlib.
Connecting
import threed_optix as tdo
client = tdo.Client('<your_api_key>')
Client checks that the server is reachable and the key is valid, and loads your setups. Pass verbose=False to skip the welcome message.
Setups
Create a setup:
setup = client.create_setup(
name="My Setup",
description="A short description",
labels=["General"],
units="mm", # "mm" or "in"
private=True,
)
Valid labels: General, Microscopy, Telescopy, Spectroscopy, Imaging, Non-linear optics, Fiber, Illumination, Light sources, Laser Optics, Diffractive Optics (also available as tdo.SETUP_LABELS). At least one label is required, and the name and description must not be empty.
Open existing setups:
client.get_setups() # every setup on the account
client.get("My Setup") # the first setup with this name
client.get("My Setup", all=True) # every setup with this name
You can also loop over the client (for setup in client:) or test membership ("My Setup" in client).
Parts
A setup exposes .parts, .optics, .light_sources and .detectors.
Add parts:
setup.add_optics(db_id="n-bk7_schott_lens_id", pose=[0, 0, 50, 0, 0, 0])
setup.add_light_source(source_type="PLANE_WAVE")
setup.add_detector(size=[10, 10])
add_optics takes a catalog db_id. All three accept further keyword settings, which are validated for that part type; an unknown keyword raises an error.
Find, move and remove parts:
part = setup.get("Lens 1") # by label
part = setup.at((0, 0, 50)) # the part nearest to a point
part.change_pose([0, 0, 55, 0, 0, 0])
setup.delete_part(part)
Save the setup object to a local file and load it again in a later session (this does not save to the cloud):
setup.save("my_setup.dill")
setup = tdo.Setup.load("my_setup.dill", api=client)
Light sources
Source types are PLANE_WAVE (the default), GAUSSIAN_BEAM, POINT_SOURCE, LED and RAY_FILE. A source can be converted in place:
light.to_gaussian(waist_x=0.05, waist_y=0.05, waist_position_x=0, waist_position_y=0)
light.to_point_source(density_pattern="...", point_source_data={...})
light.to_plane_wave(density_pattern="...", plane_wave_data={...})
Other methods: change_power, change_wavelengths, add_wavelengths, turn_on, turn_off, change_rays_direction, change_color and change_config, which also sets polarization:
ls = setup.get("light_source_id")
ls.change_config(polarization_data={"type": "USER_DEFINED", "angle": 45})
Custom optics
The client creates custom parts with create_* methods, for example client.create_spherical_lens(...) and client.create_grating(...): spherical, aspheric, biconic and conic lenses, ball lenses, gratings, mirrors of several shapes, multiplets and apertures. Each method takes the parameters of that part's geometry.
Materials
materials = client.search_materials("N-BK7")
materials[0].refractive_index(wavelength=0.55) # µm
A material exposes its dispersion equation and coefficients (Sellmeier, Modified Sellmeier, Schott, Cauchy or Conrady1) and its valid wavelength range.
Simulation and analysis
ray_table = setup.run() # ray trace only
results = setup.run(analysis=my_analysis) # run one analysis
run() without arguments returns a ray table at the ray count set in the app. With an Analysis object it returns the analysis results as a DataFrame. configurations_csv_path runs the same analysis for every row of a CSV file, one configuration per row. setup.add_analysis(...) and setup.delete_analysis(...) manage the analyses of a detector.
The older _run_async and _run_batch methods are no longer supported.
Widget links
client.get_widget_url(setup.id)
client.get_widget_url_with_live_updates(setup.id)
Both return a link that shows the setup in the web viewer. The second keeps the view in step with later changes made through the API.
Errors
Every call is a REST request that carries your key in the X-API-KEY header. A failed request raises a Python exception with the server's message. Wrap calls in try/except in unattended scripts.
client.ask() and client.feedback() exist but are not yet available. Send feedback to support@3doptix.com.
Quick reference
| Task | Call |
|---|---|
| Connect | tdo.Client(api_key) |
| List setups | client.get_setups() |
| Get a setup by name | client.get(name) |
| Create a setup | client.create_setup(name, description, labels, ...) |
| Add a part | setup.add_optics(...), setup.add_light_source(...), setup.add_detector(...) |
| Find a part | setup.get(label), setup.at((x, y, z)) |
| Move a part | part.change_pose([...]) |
| Remove a part | setup.delete_part(part) |
| Search materials | client.search_materials(name) |
| Run a trace or an analysis | setup.run(), setup.run(analysis=...) |
| Get a viewer link | client.get_widget_url(setup.id) |