Application examples
End-to-end examples from real experiments.
The repository contains complete experiment examples. They are intended to be read together with their project configuration, not as standalone snippets.
| Example | Demonstrates |
|---|
| MOT loading optimisation | absorption imaging, MOT sequence, parameter scans and live evaluation |
| Absorption imaging | camera handling, ROI analysis and optical-density calculation |
| Optical dipole trap | trap loading, intensity ramps, calibration and lifetime measurement |
| Ion loading / state detection | ion-trap control, detection thresholds and event processing |
| Quantum-state detection | repeated readout, statistics and state assignment |
| Atom–ion interaction | combining cold-atom and ion-trap subsystems in one experiment |
| System calibration | reference measurements, fitting and calibration persistence |
Each example project includes a README.md, configuration/ and experiments/. Start with the project launcher and run it in simulation mode before connecting hardware.
Structure of an example
- Physical goal — what is measured and why.
- Device setup — the device database entries and calibration files.
- Experiment class — parameters, sequence and analysis hooks.
- Data and analysis — expected HDF5 content and fitting.
- Operational notes — safety checks, common failures and tuning advice.
1 - Atom–ion collision experiment
Study the collision dynamics between cold atoms and a single ion with Quatm’s coordinated multi-system control.
Overview
This experiment provides the class secondinteraction: it integrates the lithium-atom MOT with ion
loading, state preparation and shuttling into one atom–ion collision/interaction experiment. Each stage
is encapsulated in its own method, which makes it easy to reuse and extend.
Stage methods
| Method | Description |
|---|
load_ions | Ablation loading + laser cooling of the ions |
count_ions | Fluorescence counting to determine whether an ion is in the trap |
Ion_to_D_state / Ion_to_S_state | State preparation |
load_MOT / MOT_off | Loads / switches off the lithium MOT |
ion_state_preparation | Ion state preparation before the interaction |
run | Orchestrates the loading–state preparation–collision–detection sequence |
Parameters (build excerpt)
Loading_Time, Nr_Ablation_Pulses, Det_Time, Nr_Pictures,
loadingtime_MOT, detection_time, RF_Voltage_Final and others.
Key code (excerpt)
from quatm.experiment import Experiment, delay, realtime
class secondinteraction(Experiment):
def run(self):
self.load_ions() # ablation loading + laser cooling
self.Ion_to_S_state() # prepare in S1/2
self.load_MOT() # load the lithium MOT
# interaction … then imaging/counting
2 - Dipole-trap optimisation helper
ODT alignment with the experiment helper tool: xODT alignment + stray-field compensation.
Overview
Before an optical dipole trap (xODT/cODT) experiment, the beam has to be aligned onto the atoms/ions
with the dipole-trap optimisation helper. The experiment-helper main window odt_utils on the GUI
side (quatm/GUI/entries/odt_utils.py) aggregates two kinds of alignment tool as tabs:
| Tab | Real component | Purpose |
|---|
| xODT alignment | alignment/odt_utils.odt | piezo-mirror axis scan → Gaussian fit → publish, aligning the xODT/cODT onto the atom cloud |
| Stray-field compensation | alignment/odt_utils.compensation | find the compensation voltage along each trap axis to minimise the stray field |
Usage
from quatm.GUI.entries.odt_utils import odt_utils
helper = odt_utils() # started as a separate process, with xODT alignment and stray-field compensation tabs
For the complete description see Experiment helper in the GUI components section; for the ODT
experiment after alignment see Optical dipole trap.
3 - Electric-field offset compensation helper
Compensating the stray electric field of an ion trap: a GUI tool + a trap-axis voltage-scan script.
Overview
Ion-trap experiments are often affected by stray electric fields (ion-position offsets/micromotion). The
electric-field offset compensation helper brings together voltage scanning, data plotting and the
determination of the compensation voltage: on the GUI side it is provided by CompensationHelper in
quatm/GUI/alignment/comp_helper.py; on the experiment side Usage Example/experiments/compensation.py (class compensation) applies shim voltages to the ion and triggers multi-frame
images, scanning axes such as trap_x / trap_y.
GUI components (comp_helper)
| Component | Description |
|---|
Compensation | Compensation main panel (one plot per trap axis + controls) |
PlotWidget / TabWidget | Plot with one tab per trap axis |
ControlWidget / SingleAxisWidget | Scan controls per axis and “find the compensation voltage” (intersection of two fitted lines) |
CompVoltageScan | Executes a voltage scan on the rf confinement |
Usage
from quatm.GUI.alignment.comp_helper import CompensationHelper
comp = CompensationHelper(parent=parent)
For a fuller description see Experiment helper.
4 - Ion loading and cooling
A complete ion-loading routine from laser ablation to fluorescence detection, using Quatm’s multi-stage timing control.
Overview
This script provides the class loading_ion: it orchestrates the complete ion-loading routine from
switching on the RF trap, producing ions by ablation and laser cooling through to fluorescence
detection. The number of ablation pulses, the pulse width and the cooling/detection durations are all
GUI parameters.
Parameters (build excerpt)
Nr_Ablation_Pulses, tune_pulse_number, pulse_duration, det_time, shutter_time, V_rf (trap voltage), ion_cool_power.
Timing
Switch on the RF trap (V_rf) → ablation pulses (several) → laser cooling
→ fluorescence detection (count to decide whether the ion loaded successfully)
Key code (excerpt)
from quatm.experiment import Experiment
class loading_ion(Experiment):
def build(self):
self.setattr_argument("Nr_Ablation_Pulses", NumberValue(...))
self.setattr_argument("V_rf", NumberValue(...))
# ... remainder omitted
ablation_pulse.py (single ablation), deterministic_loading.py and
loading_deterministic.py (deterministic loading: retry on failure).
Companion
The cooling and fluorescence counting after ion loading can be combined with
quantum-state detection for state-dependent measurements; the default parameters of the RF
trap are in rf_trap.py.
5 - MOT loading optimisation
Automatically optimise the magneto-optical trap loading efficiency with Quatm’s parameter scans and multi-dimensional timing control.
Overview
This experiment script provides the class mot_settings: build() declares the full set of lithium
MOT/CMOT devices and exposes the axial / radial magnetic-field currents and the MOT/CMOT detunings as
GUI parameters, so that the magneto-optical trap loading can be optimised manually or by scanning.
run() contains an empty timing sequence, on top of which imaging/counting can be added to assess the
loading.
Devices (build excerpt)
| Device | Purpose |
|---|
li_cooling_aom / li_repump_aom / li_zeeman_aom | cooling / repump / Zeeman light switches |
li_cooling_power / li_repump_power / li_zeeman_power | power of the individual beams |
li_lock_mot / li_lock_cmot | frequency-lock references |
Parameters (build excerpt)
MOT_Axial / _Radial, CMOT_Axial /
_Radial (gradient/homogeneous-field currents), MOT_Current / CMOT_Current (trap currents),
MOT_detuning / CMOT_detuning (detunings).
Key code (excerpt)
from quatm.experiment import Experiment, NumberValue
class mot_settings(Experiment):
def build(self):
self.setattr_device("li_cooling_power")
self.setattr_argument("MOT_detuning", NumberValue(...))
# ... remaining devices/parameters omitted
Loading optimisation
After changing the magnetic-field currents and the detuning, the loading efficiency can be judged from
the atom number measured by fluorescence counting or absorption imaging (see Absorption imaging
in the same directory).
6 - System calibration
Automated applications of Quatm in routine system calibration and maintenance.
Overview
Besides physics experiments, Quatm also codes routine calibration tasks as standard experiment scripts,
giving one-click execution and automatic recording. This covers common calibration needs such as camera
dark noise, shutter response, frequency synthesiser verification and trigger-delay calibration.
Code structure
All calibration experiments follow the same structural pattern:
- subclass the
Experiment class - declare the device under test and the calibration parameters in
build() - execute the calibration procedure in
run() and record the results automatically
Typical calibration tasks
Camera dark-noise characterisation
Function: acquire image frames continuously under dark conditions and characterise the dark-current noise distribution.
Main steps:
- Switch off all light sources and set the camera exposure time
- Acquire N dark frames in a loop
- Compute the mean and the standard deviation of each pixel
- Save the noise map to HDF5
Devices involved: camera
Shutter response time measurement
Function: measure the delay of a mechanical shutter from the TTL trigger to fully open/closed.
Main steps:
- Align a photodetector with the beam behind the shutter
- Trigger the shutter open with a TTL signal and start high-speed acquisition synchronously
- Record the rise/fall edge times of the detector signal
- Repeat the measurement and average
Devices involved: shutter (TTL), photodetector
Frequency synthesiser verification
Function: verify the actual output frequency and power of a Valon 5009 or DDS frequency synthesiser.
Main steps:
- Set the frequency synthesiser to the target frequency
- Measure the actual output with a spectrum analyser
- Scan the frequency range and record the deviation
- Generate a calibration curve
Devices involved: Valon 5009/DDS (serial port), spectrum analyser
Camera trigger delay calibration
Function: measure the delay between the TTL trigger and the actual exposure window of the camera.
Main steps:
- Share the same TTL signal between the pulsed light source and the camera trigger
- Scan the trigger-delay parameter
- Detect the position at which the light pulse appears in each frame
- Calibrate the optimal delay value
Devices involved: camera, pulsed light source (TTL)
7 - Absorption imaging
Automated acquisition and analysis of atom-cloud absorption images with Quatm’s camera control and image analysis.
Overview
This experiment script provides the class absorption_imaging: build() declares the cooling/imaging
light and the camera trigger and exposes the MOT loading, the probe flash and the free-flight expansion
time as parameters; run() orchestrates the imaging sequence and provides two detection modes,
fluorescence_imaging and absorption_imaging.
Parameters (build excerpt)
Mot_loading, Flash_us (duration of the probe flash), expansiontime_ms (free-flight expansion),
image_detuning (imaging detuning), MOT_detuning.
Devices (build excerpt)
li_cooling_aom / li_repump_aom / li_zeeman_aom (cooling/repump/Zeeman),
li_absorption_h (horizontal absorption probe beam), li_imaging_valon + dds_0 (imaging frequency source),
trigger_radba (trigger).
Key code (excerpt)
from quatm.experiment import Experiment, NumberValue, delay
class absorption_imaging(Experiment):
def build(self):
self.setattr_device("li_absorption_h")
self.setattr_device("li_imaging_valon")
self.setattr_argument("expansiontime_ms", NumberValue(...))
# ... remainder omitted
def absorption_imaging(self):
# three frames with atoms / without atoms / background, computing the optical depth
...
Data analysis
The optical depth (column density) is computed and published by the analysis process ImageDivider, see
Data and analysis/Absorption imaging.
8 - Atom–ion interaction in an optical dipole trap
Example experiment on the interaction of a neutral atom with a single ion in an optical dipole trap.
Overview
In this example we combine a lithium MOT / optical dipole trap (ODT) with the cooling, shuttling and
state detection of a barium ion into one complete atom–ion interaction experiment. The experiment
class interaction_optical_trapping subclasses Experiment, and the main sequence is assembled in
stages by methods such as init_CMOT, absorption_imaging, expose_camera and run.
A typical sequence is roughly: load the MOT and pre-cool the ion and shuttle it “out of the way”, then
load the atom cloud into the CMOT and the optical dipole trap, and after evaporation and spin
polarisation move the ion back and let it interact with the atoms (loss spectroscopy or Feshbach
resonance measurements are possible); finally perform optical thermometry, absorption imaging and
detection of the ionic product state.
Main devices
| Category | Device (excerpt) | Purpose |
|---|
| Lithium MOT/CMOT | li_cooling_aom / li_repump_aom / li_zeeman_aom, dds_0/1, li_mot_det_switch | cooling/repump/Zeeman light and frequency, detuning switching |
| Magnetic field | b_quadrupole, b_homogen, quadrupole_fet_off, homogen_fet_off, Feshbach coil relays | MOT gradient, homogeneous field, Feshbach/evaporation field |
| Ba lasers and states | aom_1(_ttl), aom_2(_ttl), the shutters, trigger_cam | ion cooling, pumping, ion state detection |
| Optical dipole trap | li_odt_* (xODT/cODT), laser power | optical trap for atoms/ions |
| Imaging | li_absorption_h, li_imaging_freq, trigger_abs | absorption imaging and vertical trigger |
MOT loading → ion pre-cooling and shuttling (making room for the atom loading)
→ CMOT (optional high-gradient/power/detuning stage) → transfer into the ODT / two-colour trap
→ evaporative cooling (optional rf association) → spin polarisation
→ ion moved back into the atom cloud → interaction / loss / Feshbach measurement
→ trap-frequency measurement / time of flight (TOF) → ion optical thermometry → absorption imaging + ion state detection
Key code (excerpt)
from quatm.experiment import NumberValue, BoolValue, Experiment, delay, realtime
class interaction_optical_trapping(Experiment):
def build(self):
# devices for the lithium MOT/CMOT
self.setattr_device("li_cooling_power")
self.setattr_device("li_cooling_aom")
self.setattr_device("b_quadrupole")
self.setattr_device("b_homogen")
# ... remaining devices omitted
def run(self):
# keep the ion inside the atom cloud during the interaction
with realtime():
self.li_cooling_aom = False
delay(0.5)
# ... timing omitted
Running
After placing the script in the corresponding directory under experiments/, open it in the experiment
browser (Browser) to see the parameter panel generated by build; clicking run executes the whole
sequence according to the timing in run. The script can also serve as a template for writing custom
atom–ion interaction experiments (note the ion-shuttling ramps, the CMOT loading and the ODT transfer
stages).
9 - Quantum-state manipulation and detection
Optical pumping and state-dependent fluorescence detection of ionic quantum states, using Quatm’s precise timing and statistical analysis.
Overview
This experiment script provides the class state_prep: it optically pumps the ion into the S1/2 or
D3/2 state and can optionally apply one more cooling cycle at the end. State-dependent detection
then distinguishes the bright/dark states by fluorescence counting.
Parameters
on_s_off_d (pump to S1/2 (650 off) or to D3/2 (493 off)),
cooling_end (whether to add one cooling step before the end).
State-preparation logic
- S1/2: switch off the 650 light first → the ion falls into S1/2;
- D3/2: switch off the 493 light first → the ion is pumped into D3/2.
The same logic also appears in Ion_to_S_state / Ion_to_D_state of secondinteraction, where
count_ions fluorescence counting performs the state-dependent detection (bright = S1/2, dark = D3/2, etc.).
Key code (excerpt)
from quatm.experiment import Experiment, BoolValue
class state_prep(Experiment):
def build(self):
self.setattr_argument("on_s_off_d", BoolValue(value=False))
self.setattr_argument("cooling_end", BoolValue(value=True))
# ... remainder omitted
optical_dark_pumping.py (dark pumping, pumping_time_us), d_shelving.py
(D-state related measurements).
10 - Optical dipole trap experiment
Study the trapping and loss characteristics of cold atoms in an ODT with Quatm’s two-parameter scans and lifetime measurements.
Overview
This experiment script provides the class optical_trapping: build() declares the lithium MOT/CMOT
and the imaging devices and exposes the key timing parameters for loading / trapping / imaging as GUI
parameters; run() orchestrates the complete optical dipole trap (ODT) experiment sequence through
methods such as init_CMOT, fluorescence_imaging and absorption_imaging.
Timing stages
MOT loading (Mot_loading) → CMOT (init_CMOT: gradient/detuning/power switching)
→ ODT trapping (trapping_time_ms) → release → time of flight (time_of_flight)
→ absorption imaging / fluorescence imaging
Parameters (build excerpt)
Mot_loading, Flash_us, trapping_time_ms, resonance_shift,
image_detuning, detuning_ramp_slope_MHz_ms, time_of_flight,
MOT_detuning / CMOT_detuning, MOT_Current_Loading / CMOT_Current and the
Homogenous_Current_* series, etc.
Key code (excerpt)
from quatm.experiment import Experiment, NumberValue, delay
class optical_trapping(Experiment):
def build(self):
self.setattr_device("li_cooling_aom")
self.setattr_device("li_absorption_h")
self.setattr_argument("trapping_time_ms", NumberValue(...))
# ... remainder omitted
def init_CMOT(self):
# CMOT stage: gradient, detuning and power switching
...
Companion
The xODT/cODT beam path can be aligned with the dipole-trap optimisation helper; for imaging data
analysis see Absorption imaging and Absorption imaging in the data and analysis section.
11 - Optically trapped ion
Purely optical trapping of an ion in an optical dipole trap, with state detection.
Overview
This example uses the experiment class OpticalTrappingIon to demonstrate purely optical trapping
of a single ion in an optical dipole trap. The radio-frequency trap (rf) can optionally be switched
off in order to measure the performance of the pure optical trap, and optical trapping can also be
performed in an adjustable magnetic field; together with ion laser cooling, spin preparation and
product-state detection, the ion can also be moved into and out of the trap via the axial electrodes.
Main devices
| Category | Device (excerpt) | Purpose |
|---|
| Ba lasers | ba_493_aom(_ttl), ba_493_vert_aom, ba_650_aom(_ttl), ba_493_res_shut, ba_493_det_shut, ba_615_shut | cooling, pumping (S1/2↔P1/2, D3/2, etc.), shutters |
| Optical dipole trap | odt_power / odt_aom / odt_shut | power and on/off of the optical trapping beam |
| RF trap | rf, rf_off | radio-frequency Paul trap confinement (can be switched off for a pure optical trap) |
| Axial movement | trap_ax, trap_ax_pc, trap_ax_wall, trap_ax_offs | axial shuttling of the ion |
| Magnetic field | b_homogen, shim | quantisation field for pre-cooling/trapping |
| Detection | trigger_cam | trigger for radial ion fluorescence/state detection |
Parameters (excerpt of setattr_argument in build)
trapping_time, odtpower, rf_init and
rf_ramp_duration, opt_ramp_duration, repumpers_on, pump_d32,
ba_spin_prep, b_field_precooling(_applied) / b_field_opt_trap(_applied),
shuttle_ion / shift_voltage, shutter_time, detect_ba_product_state and others.
Timing stages
Initialisation
→ ion spin preparation
→ magnetic-field switching (optional high-field probing)
→ (optional) shuttle the ion out and back
→ linear ramp-up of the optical trapping beam power → switch off the RF confinement (pure optical trapping)
→ switch off the optical trap (release) and the magnetic field
→ product-state/fluorescence detection
Key code (excerpt)
from quatm.experiment import * # Experiment, NumberValue, BoolValue, delay, realtime ...
class OpticalTrappingIon(Experiment):
def build(self):
self.setattr_device("ba_493_aom")
self.setattr_device("odt_power")
self.setattr_device("rf")
self.setattr_argument("trapping_time", NumberValue(ndecimals=0, step=10,
value=100, unit="µs"))
# ... remaining parameters omitted
def run(self):
with realtime():
# ramp up the optical trapping beam and switch off the RF confinement for pure optical trapping
self.odt_power = self.odtpower
self.rf_trap_off = True
# ... timing omitted
Running
Once the script is placed in experiments, opening it in the experiment browser (Browser) generates
the parameter panel; adjusting odtpower and trapping_time scans the power and duration of the
optical trapping, while detect_ba_product_state reads out the ionic product state.