This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

GUI components

Desktop applications and their responsibilities.

The desktop suite is built with PySide6 and shares a common visual language, theme and lifecycle model.

Architecture overview

The Experiment Browser is the main window: FileSelector opens experiment scripts, the central QMdiArea hosts one or more ExperimentWindow panes, and the top dock area manages the experiment queue, preparation station and looper. ExperimentManager is the execution engine that consumes tasks and drives each run through its lifecycle.

flowchart TB
    subgraph Browser[Experiment Browser - main window]
        FS[FileSelector<br/>experiment file tree]
        MDI[QMdiArea<br/>experiment pane container]
        EW[ExperimentWindow<br/>single-experiment control]
        DOCKS[Top dock area<br/>queue / preparation / looper]
        FS --> MDI
        MDI --> EW
        DOCKS --> MDI
    end

    EM[ExperimentManager<br/>execution engine]
    QUEUE[Experiment queue / scans]
    PROC[Process Manager]

    EW --> EM
    DOCKS --> EM
    EM --> QUEUE
    EM --> PROC

ExperimentWindow owns the parameter panel, submission and scan entry points. ExperimentManager does not draw the UI; it consumes tasks from the queue and tracks their run state. The Process Manager starts and supervises the independent GUI, driver and service processes.

ApplicationResponsibility
Operations ConsoleServices, tasks/processes/ports and device health in one window
Experiment BrowserExperiment selection, parameters, queue, scans, preparation and looper
DashboardInstrument defaults and parameter tuning by device group
Data ManagerHDF5 browsing, fits, image analysis and export
Stream MonitorLive data and message inspection
Image / Live / Scroll viewersCamera, ROI and real-time curve displays
TimelineFPGA/ADwin sequence visualisation
Device ManagerDevice database editing, driver catalogue and health checks
Property / Subscription / Auto-save editorsShared property tree and persistence policies
Settings HubNotifications, licence and low-frequency configuration
Task & Process MonitorRead-only task, process, endpoint and health observability

Design conventions

  • Every window can be opened independently or through the launcher.
  • Closing the launcher’s last window prompts for full application exit and stops all services.
  • Windows that create background work release it in closeEvent; hidden windows pause refresh timers rather than stopping data clients.
  • Help and About pages are per-window and bilingual.
  • The interface follows the operating system’s font scaling and light/dark appearance.

Extending the GUI

Reusable building blocks live under quatm/GUI/widgets and quatm/GUI/infra. Project-specific windows belong in the project’s GUI/ directory and are registered in configfile.json. The application identity table controls window names, icons and desktop launchers.

1 - Experiment browser

The Quatm main window: experiment browsing, queue management and a multi-window MDI workspace.

Overview

quatm/GUI/browser/main_window.py provides the experiment browser (Browser): Quatm’s main application window, built on QMainWindow + QMdiArea as a multiple-document interface. The file selector on the left browses experiment scripts, the experiment queue, preparation station and looper are docked at the top, and each experiment occupies its own sub-window in the central MDI area.

Layout

┌───────────────┬───────────────────────────────┐
│ FileSelector  │   QMdiArea (subwindow area)   │
│ (file tree)   │   ┌─────────────────────┐     │
│               │   │ ExperimentWindow    │     │
├───────────────┤   └─────────────────────┘     │
│ Queue / Prep  │                               │
│ / Looper dock │                               │
└───────────────┴───────────────────────────────┘

Core components

ComponentModuleDescription
FileSelectorbrowser/file_selector.pyExperiment directory tree; double-clicking opens the experiment or simulation window
ExperimentWindowbrowser/experiment_window.pyControl panel for a single experiment inside the central MDI area
ExperimentQueueexperiment/experiment_queue.pyTabular task queue
ExperimentManagerexperiment/experiment_manager.pyTakes tasks from the queue and executes them
PrepStationexperiment/prepstation.pyStaging and editing of tasks before they are sent to the queue
Looperlooper/ui.pyConditionally repeats a group of tasks based on measurement results

Details of each component are given on the corresponding page in this section.

Lifecycle

  • init_ui / create_dock_widgets: adapts the default geometry to the screen and creates the MDI canvas together with the two dock areas (the file selector on the left; the queue, preparation station and looper at the top).
  • open_experiment: opens an experiment window; if it is already open, restores it from minimised state and raises it.
  • closeEvent: first saves the main-window geometry and the state of all experiment sub-windows, then stops the queue/looper worker threads, and finally hands over to the base class to complete the close.
  • moveEvent / resizeEvent: debounced geometry saving, so that the window position and size are restored on the next start.

Usage

from quatm.GUI.browser.main_window import Browser

browser = Browser()
browser.show()

The experiment browser is the interface through which every experiment other than the helpers is run; it is normally started as the main process by the process manager.

2 - Experiment manager

The core experiment execution engine: takes tasks from the experiment queue and schedules them by measurement/sequence/run hierarchy.

Overview

quatm/GUI/experiment/experiment_manager.py provides the experiment manager (ExperimentManager): the engine that takes tasks from the experiment queue (ExperimentQueue) and executes them. Its queue polling runs in a worker thread, and tasks are scheduled in the hierarchy measurement → repetition → sequence/scan → run.

Execution flow

queue_fn (worker thread polls the queue continuously)
  └─→ run (task wrapper: cleanup is guaranteed however the task ends)
       ├─→ start_measurement (measurement start hook)
       ├─→ start_sequence (sequence/scan start hook)
       │     └─→ … several run calls with varying parameters …
       ├─→ end_sequence (sequence end hook)
       └─→ end_measurement (measurement end hook; clears the task table)

Key methods

MethodDescription
queue_fnContinuously polls the queue for task dictionaries: selects tasks by priority, task number and scheduled time
runTask run wrapper: finalises cleanly whether the task ends as Done/Terminated/Failed or is deleted
pausePauses the current experiment; calling it again resumes it
terminate_experimentGraceful termination: lets the current run finish naturally before stopping
start_measurement, etc.Invokes the experiment’s start/end hooks for each stage
set_dictWrites a single parameter to an attribute of the experiment instance
set_run_nr / set_rep_nrSynchronises the run/repetition index into the task dictionary and refreshes the table
due_checkDetermines whether a task has reached its scheduled execution time
start_queue / shutdownStarts / stops the resident queue worker
update_tableNotifies the GUI to refresh the displayed task table

Usage

from quatm.GUI.experiment.experiment_manager import ExperimentManager

manager = ExperimentManager(browser)   # browser supplies the queue and the UI
manager.start_queue()                  # start the resident queue worker

Tasks execute in a dedicated worker thread and do not block the GUI; when the browser closes it calls shutdown to stop the queue worker so that the process exits cleanly.

3 - Experiment queue

The task queue table panel: maintains priority ordering, status tracking and lifecycle management (pause/terminate/sleep/delete) of experiment tasks.

Overview

ExperimentQ (quatm/GUI/experiment/experiment_queue.py) is the “experiment queue” panel of the experiment browser (Browser) main window: a task table driven by the queue table model ScheduleModel (module quatm/GUI/widgets/models.py). Task dictionaries are stored with the task number as primary key; each task is one record containing everything needed to run it, and the table sorts by priority priority (lower value first) and then by task number.

Task status

The experiment manager (ExperimentManager) and the panel jointly maintain the status of each task:

StatusMeaning
QueuedEnqueued and waiting for execution
WaitingA due time has been set; not executed until that time is reached
SleepingAsleep; the manager ignores it for the moment (click again to wake it)
RunningA single run is in progress
ScanningA sequence/scan is in progress
PausedPaused; can be resumed
Terminating / Termination PendingGraceful termination in progress (lets the current run finish)
DoneExecution completed
FailedExecution failed

Operations and shortcuts

  • Button bar (created by create_buttons): icon buttons for pause/resume, terminate selected tasks, terminate all, and so on.
  • Context menu and single-key shortcuts (init_table_actions): e edits parameters, v opens a read-only preview, and delete, sleep/wake and pause are also available.
  • Deleting a running task: automatically becomes a graceful termination (delete_clicked).
  • Terminate (terminate_clicked / terminate_all): stops gracefully, letting the run currently in progress finish before ending.

Main methods

MethodFunction
submit(taskDict)The only entry point into the queue (runs on the GUI thread): assigns task numbers centrally; the looper (Looper) also reaches it through the submitItem signal
pause()Pauses/resumes the experiment currently running
set_sleeping()Marks the selected tasks as sleeping or wakes them
delete_item(k) / delete_clicked()Deletes by task number, or deletes the selected rows (a running task is terminated gracefully)
terminate_clicked() / terminate_all()Gracefully terminates the selected tasks / all tasks
update_item(k, v)Updates a model entry by task number and resets its lock
open_editor() / open_viewer()Edits / previews the parameters of the selected task read-only (shortcuts e / v)

Data model

# task dictionary structure (key = task number)
expDict = {
    1: {
        "expName": "Rabi scan",
        "filepath": "experiments/ion/rabi.py",
        "status": "Queued",
        "priority": 1,
        "args": {},
        "due": "",
    },
}

Sorting rule: priority (lower value first) → task number (first in, first out).

Relation to the looper

Task items of the looper (Looper) are also enqueued through ExperimentQ.submit(), so the desktop interface and loop scheduling share the same “central task-number assignment” entry channel.

4 - Preparation station

The staging and editing area for experiment parameters: preview, reorder and fine-tune tasks before they are pushed into the queue.

Overview

PrepStation is a tab in a top dock of the experiment browser (Browser) that acts as the “staging area” of the experiment queue: tasks that are not yet ready are kept here and are pushed into ExperimentQ for execution once confirmed. The task list is persisted in configuration/browser/prepfile.json and can be viewed and manipulated from the experiment console on the browser side (Web remote control).

Functions

OperationDescription
StageClicking the Prep button in the experiment window stages the current parameters (including the scan definition) in the task list
PushCopies the selected task into ExperimentQ (the queue retains the complete task number, priority and scan parameters)
Add to loopAdds the selected task to a Looper loop group (push_to_looper)
ReorderMoves tasks up/down to change their order
SleepMarks a task as Sleeping so that it takes no part in pushes for the time being
Edit/viewOpens the task parameter editor or a read-only view
Save/loadSaves a parameter set as JSON (experiment_params/<experiment>/<date>/)

Task data structure

Every staged task has the same structure as a queue task (generated by the experiment window’s setup_task_dict()):

task = {
    'task': 12,                 # task number
    'expName': 'Absorption',    # experiment name
    'label': 'scan: freq 2:1',  # label (includes the scan prefix)
    'priority': 0,
    'args': {'count': 5},       # experiment parameters
    'nRuns': 21,                # number of scan points
    'scanpars': ['freq'],       # scan parameters
    'scanvals': [[...]],        # scan values
    'scansequence': [...],      # scan order (after randomisation)
    'nReps': 1,
    'status': 'Queued',         # Queued / Sleeping / Waiting
    'filepath': '.../absorption.py',
}

Persistence and sharing

  • The task list is kept in configuration/browser/prepfile.json and is restored automatically when the browser restarts;
  • The desktop GUI and the Web remote control platform share the same file, so tasks staged, pushed, reordered or slept on one side are immediately visible on the other.

5 - Looper

The conditional loop executor: decides automatically, from measurement results, whether to repeat, jump or end an experiment loop.

Overview

Looper is a tab in the top dock of the experiment browser (Browser) (quatm/GUI/looper/). It manages groups of experiment tasks, executes the items of a group in order, and decides whether to jump or to stop based on the measurement results. Loop definitions are persisted in configuration/browser/looper/loopfile.json, and the same file is shared with the experiment console on the browser side (Web remote control).

Core logic

LoopManager.run_loop(): loop from the start group forever until terminate
  └─→ run the items of the group in order
       ├─ Task: submit to the experiment queue and advance after it finishes
       │        (max count / max consecutive count can be set; reaching either ends the loop)
       └─ Conditional: read a data-stream field → compare (> >= == != =< <)
                ├─ true → jump to the given item / end of group / end of loop
                └─ false → jump to the else item

Components

ComponentDescription
LoopGroupA loop group (one tab), containing the item list and the loop builder
LoopItemItem base class (delete/up/down/run counter/indicator LED)
TaskItemTask item: points to a staged task, supports max count/max consecutive/skip
ListItemTask list item: expands a task list and runs the tasks one by one
ConditionalItemData condition item: compares a field and then jumps (if/else)
ConditionalReachedItemReached-index condition item: jumps once the current time reaches the N-th cycle’s h5 save time
ConditionalDateTimeItemTime condition item
CallerItem / GroupItemInter-group jump and end-of-group items
DataManagerSubscribes to data streams and accumulates the latest measurement values
LoopManagerThe loop executor (run_loop() / terminate(), running in a background thread)
AutoSaveEditorConfiguration of the automatic HDF5 save schedule

How to use

Operate interactively through the Looper tab in the experiment browser (Browser):

  1. Add a group: create a new tab (New Tab #N), which can be renamed;
  2. Add items: each group can contain Task / List / Conditional / ConditionalDateTime / ConditionalReached / Caller and other items;
  3. Configure items: for Task, select the staged task number and set the maximum count; for Conditional, select the data field, comparison operator and threshold, and configure the if/else jump targets (item index / end box / end loop);
  4. Run: select the starting group and click run; LoopManager executes in a background thread and the terminate button stops it at any time.
# core classes (used internally by the GUI)
from quatm.GUI.looper import Looper, LoopManager

looper = Looper(parent=browser)
looper.loopManager.run_loop()      # start looping from the start group
looper.loopManager.terminate()     # terminate the loop

Persistence and sharing

  • Loop definitions are saved automatically to configuration/browser/looper/loopfile.json ({group name: [item dictionaries, ...]}) and restored automatically when the browser restarts;
  • The desktop GUI and the web remote-control platform share the same file, so changes made on either side are immediately visible on the other; the browser side likewise supports group management, Task/Conditional item editing and starting/stopping loops.

6 - Experiment window

The per-experiment control window: dynamic parameter grid, submission/scanning and parameter persistence.

Overview

quatm/GUI/browser/experiment_window.py provides the experiment window (ExperimentWindow): each experiment script corresponds to a control window carried by an ExperimentSubWindow in the browser’s MDI area. It generates a parameter grid automatically from the parameter objects declared by the experiment, and is responsible for submitting to the queue/preparer, building scans and loading/saving JSON parameters.

Components

ComponentDescription
ExperimentSubWindowGraphical container: stores the window geometry and clamps the window inside the visible area
ExperimentWindowSingle-experiment control panel: parameter grid + submit/scan/save controls
SequenceEditorScan sequence dialog: sets start, stop and step count per dimension to generate an nD scan

Key methods (ExperimentWindow)

MethodDescription
submit_to_queueSubmits the current experiment to the experiment queue for execution (the unified entry point for all submission buttons)
submit_nextSubmits with the highest priority, ahead of all existing tasks
submit_to_prepperSubmits to the preparation station (PrepStation) for staging
setup_scanBuilds the scan sequence (parameter values and randomised run order) from the scan definition
setup_task_dictBuilds the task dictionary stored in the queue/preparation station
build_argument_dictCollects values from the parameter grid controls into a complete parameter dictionary
save_params / load_paramsSaves parameters to JSON (named by date/time, optionally backed up) and loads them back
adaptive_columnsRe-flows the parameter grid columns to the window width (roughly one extra column per 200 px)
edit_sequenceOpens the scan sequence editor and applies the new sequence

Usage

from quatm.GUI.browser.experiment_window import ExperimentWindow

# normally opened by Browser.open_experiment; may also be constructed directly
win = ExperimentWindow(filepath=..., props=props, parent=subwindow, browser=browser)

The parameter objects declared by the experiment script (such as NumberValue / BoolValue / StringCombo) automatically produce editing controls with a label, unit and range; parameter sets can be saved as json and loaded again later.

7 - Parameter system

The BasicManager parameter-manager system: maps experiment properties to numeric, boolean, combo and frequency controls.

Overview

quatm/GUI/entries/dashboard.py provides a family of “parameter manager” controls: each manager maps one experiment parameter (stored in the property database, always in SI units internally) to a labelled input control, and synchronises bidirectionally between the interface and the property database.

Control class hierarchy

BasicManager (base class of numeric parameter entries)
├── IntManager        → integer spin box
├── FloatManager      → float spin box (optional unit/step/decimals)
├── BoolManager       → check box
├── ComboManager      → drop-down box (string list)
└── FrequencyManager  → DDS frequency spin box (stores Hz, shows MHz)

Usage (schematic)

from quatm.GUI.entries.dashboard import IntManager, FloatManager, BoolManager

# each manager binds the property store props and the experiment exp, reading/writing by parameter name
mgr = IntManager(props=props, exp=exp, parname="my_int")
fmgr = FloatManager(props=props, exp=exp, parName="cooling_time", unit="µs")
bmgr = BoolManager(props=props, exp=exp, parName="enable")

Changes made in the interface are converted to SI and written back to the property database; changes in the property database are likewise synchronised to the displayed values periodically by each control (updateValue / updateSpin).

See also “Experiment parameter panel”: on this basis the Dashboard main panel arranges the parameters of a whole device into an adjustable control panel.

8 - Property editor

A ParameterTree-based tool for viewing and editing properties.

Overview

quatm/GUI/entries/property_editor.py provides a property editing tool based on parametertree: it presents the key/value tree of the property database as an expandable, editable parameter tree with search filtering, and writes changes back immediately.

Components

ComponentDescription
TreeEditExtracts information from Properties and arranges it into a tree-view structure
PropEditMain property editing window (ParameterTree): subtree browsing, search, saving/deleting the selected node

Usage

from quatm.GUI.entries.property_editor import PropEdit

editor = PropEdit(name="device_status", props=props, subtree="/", parent=parent)

Note: subtree restricts the view to the properties under a given path; TreeEdit is responsible for converting the property dictionary into a tree of Parameter nodes.

9 - Live plotting

A live plot item that subscribes to data streams and keeps updating, together with its widget container.

Overview

quatm/GUI/entries/updating_plot.py provides live plotting: UpdatingPlot is a PlotItem subclass that subscribes to a data stream, periodically pulls new data and refreshes the curve; LivePlot is a widget container that embeds one UpdatingPlot, which makes it easy to dock into other windows as a panel.

Components

ComponentDescription
UpdatingPlotLive plot item: subscribes to a data stream and keeps the curve updated
LivePlotWidget container: embeds one UpdatingPlot and may carry an image stream name

Key methods (UpdatingPlot)

MethodDescription
setnewDataPeriodically pulls new data; a one-dimensional array gets an x axis automatically, then the curve is updated according to the rotation flag
updateConfigurationCancels the old subscriptions, then resubscribes and rebuilds the curves from the stream list configured in the properties
subscribe_windowOpens the subscription editor to select data streams and reapplies the subscription configuration on close
configureWindowOpens the property editor dialog to adjust settings and reapply the display configuration

Usage

from quatm.GUI.entries.updating_plot import UpdatingPlot, LivePlot

plot = UpdatingPlot(name="PMT signal")        # use directly as a plot item
host = LivePlot(name="PMT signal", parent=parent)  # or embed as a container in the UI

Subscriptions are made in the context menu of the plot item; LivePlot is also used as the container for the row/column profile plots in the image viewer.

10 - LED indicator

A status LED: green/red/cyan color schemes, radial gradients and lit/unlit appearances.

Overview

LedIndicator (quatm/GUI/widgets/qled.py) is an LED indicator button whose lit/unlit appearance can be toggled: a two-layer circular shell with a gradient centre, using highlighted colors when checked (lit) and dark colors when unchecked (dark). It is commonly used to show device connection status, experiment run status and the execution feedback of loop items.

Color modes

MethodDescription
set_green()Green scheme: bright green when checked, dark green when unchecked; usually indicates normal/ready
set_red()Red scheme: bright red when checked, dark red when unchecked; usually indicates an error/warning
set_cyan()Cyan scheme: used by looper condition items while they wait for data

The lit/unlit (checked) state is controlled with setChecked(True/False); the onColor1/onColor2 and offColor1/offColor2 properties customise the primary/secondary colors of the on and off states.

Usage

from quatm.GUI.widgets.qled import LedIndicator

led = LedIndicator(parent=parent)
led.set_green()      # device ready
led.setChecked(True) # switch on
# ...
led.set_red()        # device fault

11 - GUI base classes

BWidget, BMainWindow and BFrame: Qt base classes with geometry persistence and property communication.

Overview

quatm/GUI/widgets/quatmQt.py defines the base classes and common controls of the Quatm GUI components: it provides window geometry persistence, the Properties property namespace, and a combo box with completion.

Class hierarchy

QWidget  → BWidget
QFrame   → BFrame
QMainWindow → BMainWindow

Base classes and mixins

ComponentDescription
GeometrySaveMixinPersists window geometry to QSettings (keyed by window name); saves on close, move and resize (debounced)
BWidgetQuatm widget base class: carries the Properties namespace and geometry persistence
BFrameBase class corresponding to QFrame, with the same behaviour as BWidget
BMainWindowMain-window base class with geometry persistence and a property handle
from quatm.GUI.widgets.quatmQt import BWidget, BMainWindow

widget = BWidget(name="my_widget", parent=None)
window = BMainWindow(name="MainWindow", parent=None)

Search and completion controls

ComponentDescription
CustomCompleterCompleter with match modes (contains = substring anywhere / begins = prefix)
SearchComboBoxCombo box with autocompletion and type-ahead search; add_if_new() / find_or_add() maintain entries conveniently
SearchLineEditLine edit for search boxes: selects all on focus, records on focus-out/Enter, restores on Escape
from quatm.GUI.widgets.quatmQt import SearchComboBox

box = SearchComboBox(parent=parent)
box.add_if_new("my_stream")

12 - Image monitor

A self-updating image display control: image/mask stream subscription, denoising and spot detection, level and ROI configuration.

Overview

quatm/GUI/entries/image_monitor.py provides the automatically updating image display window (ImageDisplay): it periodically pulls the latest frame from the image stream subscribed in the properties, transforms it by resolution and offset and refreshes the display, optionally overlaying a mask stream in sync. It has built-in denoising, spot detection, saving of the current frame and property configuration (display levels, ROI, etc.).

Methods

MethodDescription
update_imagePeriodically pulls the image stream and refreshes the display frame by frame after resolution/offset transforms
update_maskPulls the mask stream and updates the overlay geometry from the mask resolution/offset
noise_filterDenoises with a bilateral filter plus a median filter according to the property parameters
spot_detectorBinarises the image by threshold to detect bright spots
saveCurrentImageSaves the currently displayed frame as PNG (named by time)
subscribe_windowOpens the subscription dialog to select image streams and resubscribes
subscribe_maskOpens the subscription dialog to select mask streams and resubscribes
configureWindowOpens the property editing dialog to adjust display levels, ROI and other parameters

Usage

from quatm.GUI.entries.image_monitor import ImageDisplay

view = ImageDisplay(imagestreams=["camera/image"], parent=parent)
view.configureWindow()   # adjust display levels, ROI, etc.

Note: ImageDisplay is both the central display of ImageWindow and can be embedded on its own in other interfaces. The image and mask stream lists are stored in the properties, and the context menu provides entries for subscription, mask subscription and configuration.

13 - Analysis manager

A tree-view panel: manages the start, stop, status monitoring and automatic restart of analysis scripts.

Overview

quatm/GUI/entries/analysismanager.py provides the analysis manager: it lists the analysis scripts in a checkable tree table (name / script / category / input stream) and is responsible for starting and stopping subprocesses, monitoring and automatic restart, as well as adding, deleting and configuring analysis entries.

Components

ComponentDescription
AnalysisManagerMain panel: loads and organises the analysis entries, and provides delete/configure entry points
TreeViewWidgetAnalysis script management tree: checking starts and stops, monitoring restarts automatically, add/delete/edit
addAnalysisWidgetToolbar for adding an analysis entry (name / category / script / input stream)

Functions

OperationDescription
Check to startChecking an entry starts the corresponding analysis subprocess; unchecking stops it
StopendProcess: terminates first and waits briefly for exit, then forces the end on timeout
Status refreshupdateStatus: periodically checks whether the process is still running
Clean up stray processeskillVagabonding: terminates leftover processes of the same script from the previous round
Add / configure / deleteThe toolbar registers new entries; a selected row can be configured or deleted

Usage

from quatm.GUI.entries.analysismanager import AnalysisManager

mgr = AnalysisManager(name="AnalysisManager", parent=parent)

Analysis scripts are independent processes: once an entry is checked, the manager launches the script with the current interpreter and injects the project environment variables into the child process, so analysis code and the main program are isolated from each other and a script crash cannot affect experiments.

14 - Stream monitor

Stream monitoring: multi-tab data/image/command/message monitoring and single-stream panels.

Overview

quatm/GUI/streammonitor/ provides the stream monitor: MainWindow uses tabs to hold monitors for data streams (Data), image streams (Image), commands (Command), message logs (Message) and history (History), among others; each monitor tab is a StreamMonitor that subscribes to a single data stream and displays it in real time.

Components

ComponentDescription
MainWindowMonitoring main window: multi-tab container + menu
StreamMonitorSingle-stream monitoring panel: subscribes to one data stream and displays it in real time
MessageTableModelMessage log table model (timestamp/source/level/content, colored by level)
ImageTableModelImage stream metadata table (fixed time/source columns + dynamic key columns)
AutoSortProxyModelAuto-sorting proxy model ordered by descending timestamp

Monitoring types

TabContent
DataReal-time curves/tables of numeric data streams
ImageScientific image streams and their metadata
CommandCommand / instruction streams
MessageMessage log (timestamp/source/level/content)
HistoryHistorical records

Usage

from quatm.GUI.streammonitor import MainWindow, StreamMonitor

win = MainWindow(parent=parent)   # multi-tab monitoring main window
panel = StreamMonitor(name="PMT", stream_type="Data", parent=parent)  # single-stream panel

This monitoring interface is normally started as a standalone process; the single-stream StreamMonitor panel can also be embedded in other windows.

15 - Sequence editor

Experiment code editing and sequence simulation: syntax highlighting, parsing and output-channel timing visualisation.

Overview

quatm/GUI/editors/editor_sequencer.py provides the edit and simulate tool (formerly Combi / “open simulation window”): the CodeEditorParser composite main window combines the CodeEditor on the left with the sequence visualisation on the right: after editing an experiment script you can simulate a run with a single click, drawing the timing of each output channel as a step plot, which makes experiment sequences easier to debug.

Components

ComponentDescription
CodeEditorSimple code editor: line numbers, Python highlighting, automatic indentation and completion
PythonHighlighterLightweight Python syntax highlighter
LineNumberAreaLine-number margin widget on the left of the editor
ExperimentParserParses an experiment: buildExperiment / simulateExperiment return the command stack
ExperimentSequencerDraws a sequence as a step plot of each output channel against time
CodeEditorParserComposite main window: Save / Simulate / Clear toolbar + dock layout

Key methods

MethodDescription
saveFile (CodeEditor)Saves the current text to a file (returns True on success)
simulateExperiment (CodeEditorParser)Simulates the current version of the experiment and hands the command stack to the sequence visualisation
buildExperiment / simulateExperiment (ExperimentParser)Builds / simulates the experiment and returns the command stack
plotSequence (ExperimentSequencer)Draws the sequence dictionary as a per-channel timing step plot

Usage

from quatm.GUI.editors.editor_sequencer import CodeEditorParser

win = CodeEditorParser(parent=parent, filename="experiments/my_experiment.py")

Note: parameter scans (nD scans, randomisation, etc.) are edited through the Edit button of the experiment window (SequenceEditor, see Experiment window); the scan definition is stored in the experiment property tree and shared with the remote-control platform.

16 - Process manager

A distributed process panel: starts and stops background processes grouped as Servers/Driver/GUI/Viewer/Monitor.

Overview

quatm/GUI/entries/processmanager.py provides the process manager: it reads the configuration by category (Servers / Driver / GUI / Viewer / Monitor) and generates a SingleProcess start/stop button panel for each script entry, so the whole experiment software suite is managed from one place. Processes are launched with the current interpreter, either as a script or as a module (python -m), carrying the project root and the parent-process watchdog environment.

Process categories

CategoryDescriptionTypical processes
ServersCommunication / property / data servicesData centre, property service, etc.
DriverHardware driver processesFPGA and other device drivers
GUIGraphical interface processesExperiment browser, data manager, etc.
ViewerData viewing processesLive plotting, scroll window, image viewer, etc.
MonitorMonitoring / checking processesProperty checker, message monitor, etc.

Components

ComponentDescription
ProcessManagerCategory panel: reads the configuration and generates start/stop buttons for each entry
SingleProcessSingle-entry panel: start / asynchronous termination / status polling with coloring
resolve_scriptResolves the script entry from the configuration into a launch target (file path or module)

Key methods (SingleProcess)

MethodDescription
startProcessStops the old instance and then starts the subprocess with the current interpreter
stopProcessTerminates the subprocess asynchronously without blocking the GUI thread
updateStatusPeriodically polls the exit status and colors it (running / exited normally / crashed)

Usage

from quatm.GUI.entries.processmanager import ProcessManager

pm = ProcessManager(parent=parent)
pm.show()

The entries to manage are defined by the scripts in the configuration file; each entry is started and stopped through its own button panel.

17 - Device manager

PyVISA device discovery and driver binding: enumerate, query and select instruments and associate driver files.

Overview

quatm/GUI/entries/device_manager.py provides the device manager (VISADeviceLister): it scans the VISA instruments on the system through PyVISA, queries the device identity (*IDN?) and selects a driver file to bind, then adds the device to the selected list as a DeviceInfo record for use in device configuration.

Components

ComponentDescription
VISADeviceListerVISA device list tool: two columns (enumeration/query + selected devices/driver files)
DeviceInfoDevice description: name, type, driver file and additional parameters

Workflow

1. refresh_devices()      → scan the VISA bus and fill the device list
2. query_device_info()    → send an *IDN? query to the selected device
3. select_driver_file()   → choose and bind a driver file
4. add_device_to_selected() → add to the selected device list (de-duplicated)

Usage

from quatm.GUI.entries.device_manager import VISADeviceLister

dl = VISADeviceLister(parent=parent)
dl.refresh_devices()   # list the connected USB/GPIB/LAN and other VISA devices

18 - Data storage

HDF5 data management: subscription, scheduled/manual saving and history read-back, with integrated plotting panels.

Overview

quatm/GUI/h5storage/ provides the HDF5 data storage GUI (a package split out of the former single file, with its public symbols re-exported at package level): three kinds of data manager — aggregate, single-stream and image — subscribe to data and save it automatically at a scheduled time, periodically, or on a Looper command; the current snapshot can also be written to an .h5 file in the background, and historical measurements read back from a file.

Components

ComponentModuleDescription
H5StorageGuimain_window.pyMain window: data tabs, save/scheduled-save controls and plot management
H5StorageDataMgrdata_manager.pyHost for the three data managers: subscription management, save/read-back, clearing
H5SaveWorkerworkers.pyWorker thread that writes the .h5 file, keeping disk I/O off the Qt event loop
H5DataPlotter / EventPlotterplotters.pyPlotting tabs for measurement data / event data
XAxisWidget / YAxisWidgetaxes.pyData selection and filter-chain configuration for the x axis and each y axis
BinningWidget / FilterWidget / FittingWidgetwidgets.py / fitting.pybinning, filtering and ODR fitting processing chain

Saving modes (H5StorageDataMgr)

MethodDescription
toggle_scheduled_saveToggles saving at a scheduled time (saves automatically and notifies when the time arrives)
toggle_regular_saveToggles periodic automatic saving every N hours
scheduled_save_by_looperResponds to save commands from the Looper (final / intermittent)
savetoFileWrites the current data snapshot to an .h5 file in the background
loadFromFileLoads historical measurements from an existing .h5 file and refreshes the interface
selectDatadirChooses the target h5 file manually (to avoid falling back to the daily default name)
clearClears the entire cache of the three data managers

Usage

from quatm.GUI.h5storage import H5StorageGui   # package-level re-export

win = H5StorageGui(parent=parent)
win.show()

Data saving is performed by the background H5SaveWorker: the GUI thread copies the data snapshot first and then hands it to the worker, so writing to HDF5 on disk never blocks the interface.

19 - Live scroll plot

Live scrolling plots: ring buffers, running averages and data-stream subscription.

Overview

quatm/GUI/entries/live_plot.py provides live scrolling plots: ScrollWindow is a multi-subplot main window in which each ScrollPlot subplot subscribes to several channels of one data stream, maintains a ring buffer and scrolls scatter/curve data and a running average; PlotDataEditor provides the data-source drop-down panel.

Components

ComponentDescription
ScrollWindowMulti-subplot scrolling main window: restores or creates subplots from the properties; the toolbar can append subplots
ScrollPlotScrolling subplot: ring buffer, scatter and running-average curves, context-menu operations
PlotDataEditorData-source selection panel: drop-down candidates written back to the properties/parent plot

Key methods (ScrollPlot)

MethodDescription
feedDataPushes a new data block into the buffer array
setnewDataPeriodically pulls new data into the buffer and refreshes the curves
updatePlotFlushes the valid data in the buffer to the scatter and running-average curves
running_meanComputes an N-point running average efficiently from cumulative sums and differences
dataSelectDialogSelects the data channels displayed in this plot
subscribe_windowOpens the subscription editor to resubscribe the data stream
configureWindowPauses refreshing and edits this plot’s properties inline
deletePlotRemoves this plot from the parent window and clears its properties

Usage

from quatm.GUI.entries.live_plot import ScrollWindow

host = ScrollWindow(name="PMT scroll monitor", parent=parent)
host.addPlot()   # append a scrolling subplot

Afterwards, subscribe to data streams, select channels and adjust the display from the context menu of a subplot. Configurations such as the buffer length, the running-average switch and the window size are stored in the properties and restored automatically after a restart.

20 - Auto-save editor

Editor for the list of automatic save times: configures a set of periodic save instants (checkbox + date-time).

Overview

AutoSaveEditor (quatm/GUI/editors/auto_save_editor.py) is a pop-up editor used to maintain the “time list” of periodic h5 automatic saves: each row = one (checkbox + date-time), and a checked row triggers one automatic save at the corresponding time. It is invoked by the data-storage panels.

Components

ComponentDescription
AutoSaveEditorDialog for editing the list: loads/writes back the properties, adds, deletes and edits rows, and confirms (Accept)
DateTimeWidgetEditing row for a single automatic save time: index + checkbox + date-time picker

Main methods

MethodFunction
load_AutoSaveEditor_props(props, prop_name)Reads the saved date-times and check marks from the properties, padding them up to the maximum number of items
update_datetime(idx, datetime_save)Saves a new date-time for a row
update_ticked(idx, ticked)Saves the checked state of a row
accept()Confirms: writes the list back to the properties and closes

Usage

from quatm.GUI.editors.auto_save_editor import AutoSaveEditor

editor = AutoSaveEditor(props=props, max_items=24, parent=parent)
editor.load_AutoSaveEditor_props(props, "H5Storage/auto_save_times")

21 - Experiment helpers

Optical-tweezer alignment and stray-field compensation: a toolkit for automated calibration and optimisation.

Overview

Quatm wraps routine experiment calibration tasks as alignment/helper tools. The modules live in quatm/GUI/alignment/, together with a number of standalone entry-point widgets, and provide one-click runs and automatic optimisation.


ODT alignment helper — OdtAlignmentHelper

quatm/GUI/alignment/odt_helper.py — builds a single-axis control block for each piezo mirror axis of xODT/cODT, and provides overall run/terminate together with compensation voltage and BA laser parameter settings. The complete alignment sequence for each axis is: full-range scan with the laser off → fine scan near the ion → publish the fit result → move to the target position.

from quatm.GUI.alignment.odt_helper import OdtAlignmentHelper

helper = OdtAlignmentHelper(parent=parent)
helper.run_all()   # run the full alignment sequence (thread pool keeps axes sequential)
helper.terminate_all()   # safely stop all axes

Stray-field compensation — CompensationHelper

quatm/GUI/alignment/comp_helper.py — obtains the compensation voltage from a voltage scan along each trap axis as the intersection of two fitted lines, minimising the stray field automatically.

ComponentDescription
PlotWidgetPlot widget with one tab per trap axis
ControlWidgetControl area for each axis plus a shared parameter area
SingleAxisWidgetScan parameters and “find compensation voltage” (intersection of the two fit lines)
CompVoltageScanPerforms the voltage scan at the high and low rf confinement
from quatm.GUI.alignment.comp_helper import CompensationHelper

comp = CompensationHelper(parent=parent)

Piezo mirror control — PiezoMirrorControl

quatm/GUI/entries/piezo_mirror_controler.py — a simple panel that steers the direction of the mirror driven by a linear actuator using arrow keys/buttons; W/A/S/D correspond to up/left/down/right.

from quatm.GUI.entries.piezo_mirror_controler import PiezoMirrorControl

mirror = PiezoMirrorControl()   # standalone window; control with WASD or the arrow keys
mirror.show()

22 - Data models

DictSyncModel/ListSyncModel: maps Python dictionaries/lists onto Qt tables automatically.

Overview

quatm/GUI/widgets/models.py provides the base classes that map Python dictionaries / lists onto Qt table models (derived from ARTIQ’s models). The table interfaces of the experiment queue, preparation station and looper are all built on them.

Core classes

ClassDescription
_SyncSubstructHelper wrapping dictionary operations on the underlying container: triggers the refresh callback after append/insert/pop
DictSyncModelDictionary→table model base class: maps backing_store through the headers/dataNames columns
ListSyncModelList→table model base class (the backing store is a list)
ScheduleModelModel for the experiment queue (ExperimentQueue): tasks sorted by priority and then by task number
PrepModelModel for the preparation station / looper: the backing store is a list whose order can be changed freely

Usage

from quatm.GUI.widgets.models import DictSyncModel

model = DictSyncModel(
    headers=["Name", "Value", "Unit"],
    dataNames=["name", "value", "unit"],
    init={"name": "param1", "value": 100, "unit": "µs"},
)

Concrete business models customise their behaviour by implementing three hooks in a subclass: convert turns a key/value/column into cell content, sort_key returns the sort key, and flags decides per-cell flags such as whether a cell is editable.

23 - Collapsible components

CollapsibleDialog: a collapsible/expandable tree dialog.

Overview

quatm/GUI/widgets/theexpandables.py provides the collapsible/expandable tree dialog CollapsibleDialog: each “section” consists of a tree item with an expand/collapse button and a content widget, which suits configuration interfaces and advanced parameter settings.

Components

ComponentDescription
SectionExpandButtonButton that expands/collapses a section
CollapsibleDialogDialog container; subclasses override define_sections() to define all panels

CollapsibleDialog provides add_section(title, widget) to add a panel directly; subclasses may also override define_sections() to organise the tree structure in detail with add_button / add_widget.

Usage

from quatm.GUI.widgets.theexpandables import CollapsibleDialog

class SetupDialog(CollapsibleDialog):
    def define_sections(self):
        self.add_section("Camera settings", some_widget)
        self.add_section("Trigger settings", trigger_widget)

24 - Parameter boxes

Input controls bound to experiment parameters: float, boolean and combo parameter boxes that write changes back immediately.

Overview

quatm/GUI/widgets/arg_boxes.py provides widgets that bind experiment parameter classes to Qt input controls: when the user changes a value it is written back to the experiment parameter (stored internally in SI units, converted for display as needed). They are usually created automatically by the “experiment parameter panel / parameter system” according to the parameter type.

Controls

ControlParameter typeDescription
FloatBoxNumeric parameterFloating-point input; converts units via unit and display_multiplier before writing back
BoolBoxBoolean parameterCheckbox; the value is written back as a boolean
ComboBoxList of stringsCombo box; takes the value from the string list by the selected index

Usage (schematic)

from quatm.GUI.widgets.arg_boxes import FloatBox, BoolBox, ComboBox

# numeric parameter: shown in kHz in the UI, stored in SI (Hz) underneath
fbox = FloatBox(argument=param_freq, unit="kHz", display_multiplier=1e3)

bcheck = BoolBox(parName="enable", value=param_enable)
cbox = ComboBox(parName="source", argument=param_source)  # the parameter class holds a stringlist

These controls are normally generated automatically by the parameter system from the experiment’s declarations, so there is no need to instantiate them by hand.

25 - Experiment parameter panel

DefaultExp + Dashboard: a whole-device parameter control panel built automatically from the device database.

Overview

The Dashboard (quatm/GUI/entries/dashboard.py) is the “control panel” main widget driven by the default experiment (DefaultExp): DefaultExp assembles the parameters of the whole machine from the device database automatically, and Dashboard then arranges these parameters in sections by integer/float/boolean and as a grouped grid, forming an adjustable parameter control interface.

Class hierarchy

DefaultExp (experiment base class: auto-assembles device properties and groups them)
     └─ Dashboard (control panel: sections + grouped grid + adaptive column count)
            └─ manager widgets (IntManager / FloatManager / BoolManager / ComboManager …)

Key features

  • Automatic assembly: DefaultExp.build() walks the device library and creates a parameter object for every attr/generic_attr device, classifying it by its group.
  • Sections by type: the interface is split into integer / float / boolean sections, and the parameters are grouped within each section.
  • Adaptive column count: adaptive_columns() reflows according to the window width (starting at 4 columns, adding one column per ~200 px), so that narrow windows are not squeezed.
  • Immediate effect: changing a spin box writes back to the properties and straight through to the hardware (the run body run() is empty, which suits purely manual tuning).

Usage (schematic)

from quatm.GUI.entries.dashboard import Dashboard, DefaultExp

# DefaultExp auto-assembles the device parameters; Dashboard handles layout and grouping
page = Dashboard(parent=parent)

The “Parameter system” page describes the manager control classes behind it.

26 - FPGA DAC control

A simple manual control interface for the FPGA: 16 DAC voltages and 32 TTL bitmask settings.

Overview

quatm/GUI/entries/fpga_controller.py provides simple manual FPGA control for debugging and calibration: each DAC voltage is set with a labelled -10 … +10 V spin box, and the 32 TTL outputs are set with a grid of checkboxes.

Components

ComponentDescription
dacv(v)Converts -10..+10 V into the 16-bit raw DAC code used by the FPGA
DACsingleA single DAC channel: a labelled -10..+10 V spin box, effective as soon as it is written
DACvaluesAll 16 DAC channels stacked vertically
TTLQWThe 32 TTL outputs: an 8×4 grid of checkboxes, written as a single 32-bit mask
simple_pageThe DAC + TTL manual control page
centralWidget / mainQMWTab container and simple main window (with a File/quit menu)

Usage

from quatm.GUI.entries.fpga_controller import DACvalues, TTLQW

# obtain the low-level FPGA driver handle (controller) from the device database
page = DACvalues(controller)

# TTL: checkbox states are combined into a mask by the "Apply/state change" callback and written to the FPGA
ttl = TTLQW(controller)

If the hardware is missing or a write fails, it only prints an error instead of crashing, which makes the interface easy to debug without hardware.

27 - Background worker threads

Worker/WorkerSignals: a generic QRunnable background-task wrapper.

Overview

quatm/GUI/widgets/browser_workers.py and helper_workers.py provide a generic background-thread wrapper based on QRunnable: time-consuming tasks are executed in a thread pool, and results/exceptions/progress are passed back to the GUI thread through signals.

Signals

SignalDescription
finishedTask completed (no data)
error(tuple)(exception type, value, traceback string)
result(object)The result returned by processing, of any type
progress(int)Progress percentage

Usage

from quatm.GUI.widgets.browser_workers import Worker

worker = Worker(callback=my_long_task, arg1, kw=...)   # passed through to the callback
worker.signals.finished.connect(on_done)
worker.signals.error.connect(on_error)
QThreadPool.globalInstance().start(worker)

The two implementations are largely the same: helper_workers.py is reused for helper/analysis background tasks, while browser_workers.py is reused for browser-style panels.

28 - Experiment timeline

FPGA experiment timing visualisation: a chart viewer for DAC and TTL output channels against time.

Overview

quatm/GUI/entries/experiment_timeline.py provides the experiment timeline (Timeline): it loads an experiment timing JSON file (experiment.json), draws the variation of each DAC/TTL output channel over time as step subplots, and provides a checkbox panel of output channels to decide which curves are visible, which makes experiment timing logic easier to debug and verify.

Components

ComponentDescription
TimelineTimeline viewer main window: file loading, plotting and channel control
TimelinePlotterTiming visualisation widget: plots the state of each active output against time
SelectorWidgetOutput-channel checkbox panel: select all / select none decides the visible curves

Key methods (Timeline)

MethodDescription
load_fileLoads and parses the timing JSON, constructs the time series and refreshes the channel selector
plot_experimental_sequenceCreates a separate subplot for each output according to the channel selection and draws a step plot
decode_ttl_bitmaskSplits the 32-bit TTL bitmask into set/clear commands for the individual channels
construct_time_sequencesConverts the step-wise timing into times/vals sequences organised per channel
reverse_device_db_transformationDevice-database reverse transformation: maps internal names back to readable names (including the gauge calibration table)

Usage

from quatm.GUI.entries.experiment_timeline import Timeline

tl = Timeline()
tl.load_file("experiment.json")   # load a timeline file and plot it
tl.show()

29 - Scroll window

A multi-channel real-time scrolling data viewer window: subplot buffers, data-stream subscription and dynamic refreshing.

Overview

quatm/GUI/entries/scrollwindow.py provides the scroll window (ScrollWindow): a BMainWindow subclass that acts as a multi-channel real-time scrolling data viewer main window. It lays out ScrollPlot subplots in the requested number (two per row), distributes data blocks to the corresponding subplots and refreshes them uniformly; PlotDataEditor provides the data/image stream selection drop-down.

Components

ComponentDescription
ScrollWindowMain window: creates subplots by count, distributes data and refreshes
ScrollPlotScrolling subplot: subscribes to a data stream, ring buffer + periodic refresh
PlotDataEditorData-source selection panel: drop-down candidates written back to the property ydata

Key methods

MethodDescription
initPlotsCreates the scrolling subplots by count and places them in the layout (two per row)
feedDataFeeds a new data block into the buffer data array
updatePlotBatch-refreshes the filled interval of the buffer into the curves of each subplot
setnewData (ScrollPlot)Timer-driven data pull and curve refresh
dataSelectDialog (ScrollPlot)Opens a dialog to select the data channels to plot
subscribe_window (ScrollPlot)Opens the subscription editor to change the data stream
configureWindow (ScrollPlot)Pauses refreshing and edits this plot’s configuration inline

Usage

from quatm.GUI.entries.scrollwindow import ScrollWindow

win = ScrollWindow(name="PMT scroll monitor", parent=parent, n_plots=2)

Data-stream subscription, data-channel selection and display configuration are performed on each subplot through its context menu; the window can also be started as a standalone process.

30 - Subscription editor

Manages the subscription list of data/image streams: adds, deletes and hot-updates subscribed sources.

Overview

SubscriptionEditor (quatm/GUI/editors/subscription_editor.py) manages the program’s subscriptions to data streams/image streams: it loads the stored subscriptions from the property database, lists the available streams for selection, supports adding/deleting, and hot-updates the list when properties change. It is commonly used as the data-source selection component of live plotting/monitoring panels.

Main methods

MethodFunction
loadSubscriptions()Reads the saved subscriptions from the property database and loads them into the list
update_streamlist()Rebuilds the drop-down candidates from the currently available data streams
add()Adds the stream selected in the combo box to the subscription list and synchronises the properties
deletemarked()Removes the subscription items marked for deletion and synchronises the properties
handle_property_changes(changes)Listens for property changes, refreshes the list and broadcasts the change

Usage

from quatm.GUI.editors.subscription_editor import SubscriptionEditor

editor = SubscriptionEditor(props=props, category="Data", parent=parent)
editor.loadSubscriptions()

31 - Table parameter

A QTableWidget-based editor for numpy structured arrays, used in parameter trees.

Overview

quatm/GUI/widgets/table_parameter.py provides a table editing node for ParameterTree: the table_parameter parameter type works together with the table_parameterItem widget item to edit numpy structured arrays (such as calibration tables and scan sequences) directly in the parameter tree.

Components

ComponentDescription
table_parameterParameter type: accepts a numpy structured array as its value
table_parameterItemCorresponding widget item: creates a QTableWidget as the editor from the array dtype

table_parameterItem creates columns from the array dtype (including field name/type), and cell edits are written back to the array immediately; valueIsDefault() is used to decide whether the value needs to be persisted separately.

Usage

from quatm.GUI.widgets.table_parameter import table_parameter
import numpy as np

dt = np.dtype([("freq", float), ("amp", float)])
param = table_parameter(name="scan_table", value=np.zeros(10, dtype=dt))

32 - Remote ROI

An ROI component that publishes color/position/size through the central property database and can be synchronised remotely.

Overview

quatm/GUI/widgets/ROI.py provides ROI: it inherits ROI and communicates its color, position and size through the central property database under a unique name, so that remote clients can view and adjust the ROI region in sync.

Methods

MethodDescription
update_from_propertiesRefreshes the ROI pen color and geometry from the color/position/size stored in the properties

Usage

from quatm.GUI.widgets.ROI import ROI

roi = ROI(name="analysis_roi", parent=view)   # name must be unique; duplicate names share properties
roi.update_from_properties()

Note: name is the key of this ROI in the central property database, so make sure it does not clash with any name in the property dictionary; after a property change, calling update_from_properties refreshes the ROI appearance and position in sync.

33 - Image viewer

The scientific image viewing main window: a central image display with row/column profile and histogram LUT dock panels.

Overview

quatm/GUI/entries/image_group.py provides the image viewing window (ImageWindow): the central ImageDisplay is the main widget, with panels such as the row/column profiles and the histogram LUT docked around it, for real-time monitoring and analysis of imaging experiments.

Layout

Dock areaWidgetPurpose
CentralImageDisplaySubscribes to and automatically refreshes an image stream; can overlay a mask
TopLivePlot (row profile)Intensity profile of an image row
RightLivePlot (column profile)Intensity profile of an image column
LeftHistogramLUTWidgetHistogram color scale: level range and false-color mapping

Each profile plot is a LivePlot container in which an UpdatingPlot subscribes to the corresponding data stream and refreshes in real time (see Live plotting for details).

Display parameter persistence

Display parameters are stored in the Viewer/ namespace of the property database; they are restored from the properties at construction time and saved automatically on close:

PropertyMeaning
Viewer/minlevels / Viewer/maxlevelsHistogram display level range
Viewer/gradientFalse-color gradient preset (such as magma)
Viewer/tick_positionColor scale tick positions (0–1 normalised list)

After dragging the histogram levels or the color scale ticks, the current values are written back to the properties through update_min_max and get_tick_position respectively, and closeEvent saves the view range and ticks uniformly before the window closes.

Methods

MethodDescription
update_min_maxWrites the current histogram level range back to the properties (min/max levels)
get_tick_positionWalks the color scale ticks and returns them normalised to the 0–1 range
closeEventSaves the view range and color scale ticks to the properties before closing

Usage

from quatm.GUI.entries.image_group import ImageWindow

win = ImageWindow(name="absorption_imaging")   # standalone top-level window; parent may be omitted
win.show()

This window is often started as a standalone process, but can also be embedded in other interfaces as a BMainWindow instance. The image stream and the row/column profile streams are subscribed from the context menus of the individual sub-panels (image display / profile plots).

34 - Property checker

A property-distribution watchdog: verifies that the Properties hub is really broadcasting updates.

Overview

PropertiesChecker (quatm/GUI/entries/properties_checker.py) is a property-distribution watchdog: it sets a marker through one property handle and reads it back through a second handle; if the hub has not propagated the change, it raises an alert indicating that the property service may have stalled. The check runs periodically on a timer, so the window is displayed normally and the GUI event loop stays responsive.

Usage

from quatm.GUI.entries.properties_checker import PropertiesChecker

checker = PropertiesChecker(parent=parent)
checker.check_once()   # run one watchdog check manually

The panel itself calls check_once() periodically (each time setting the marker true and then false and reading it back to verify).

35 - Data plotter

A general-purpose measurement data plotting component: data source/multiple y axes, filtering, binning and fitting.

Overview

quatm/GUI/alignment/plotter.py provides the data plotter (DataPlotterWidget): it subscribes to and plots data acquired during a measurement. It supports switching the data source, an x-axis selector and multiple y-axis selectors; each y axis is processed through a configurable data chain (scaling factor → filter → binning/fitting) before being drawn in the plot area, and the result can be exported to PDF.

Components

ComponentDescription
DataPlotterWidgetMain plot: data source drop-down, x-axis selector and several y-axis selectors (right-click toggles the configuration panel)
YAxisWidgetHelpery-axis data chain: scaling factor, filter, binning and fitting

Key methods

MethodDescription
setDataSourceSets or changes the data source
checkForNewData / updateDatasourcesChecks for new data/new data sources and refreshes
plotDataAdds a set of x/y data to the plot area as a new curve
toggleConfigToggles the data source and y-axis configuration panels
exportpdfExports the current plot as a PDF suitable for archiving
clearClears the data summary and all curves in the plot area

Y-axis chain (YAxisWidgetHelper): updateYscale sets the scaling factor, the context menu offers addBinning for binning and addFitting for fitting (such as Gaussian/linear), and reevaluateData re-runs the whole data chain after a filter or similar change.

Usage

from quatm.GUI.alignment.plotter import DataPlotterWidget

plotter = DataPlotterWidget(
    axis_name="myaxis",
    prop_root="...",
    datastream_names=[".../data"],
    n_yaxis=1,
    parent=parent,
)
plotter.toggleConfig()   # expand the data-source / x, y axis selection config