# the-devil-8/q-diamond architecture

> Architecture diagram of the GitHub repository the-devil-8/q-diamond, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/the-devil-8/q-diamond
- Repository: https://github.com/the-devil-8/q-diamond

## Overview

1. **What this repository is**
   - Q-Diamond is a desktop measurement suite for NV-centre experiments.
   - It combines confocal scanning, ODMR, pulsed measurements, time traces, and optimization into one application.
   - The same codebase runs either against simulated instruments or real NI-DAQ / microwave hardware.

2. **Top-level application shape**
   - `main.py` is the entry point.
   - The app is organized around a GUI front end in `gui_env`, a control/experiment layer in `logic`, a hardware abstraction layer in `interface`, and concrete device backends in `drivers`.
   - `core` provides shared infrastructure used across the app: configuration, logging, module lifecycle, and event routing.

3. **Presentation layer**
   - `gui_env/main_window.py` is the main container window.
   - Feature-specific panels live beside it: `confocal_widget.py`, `odmr_widget.py`, `pulsed_widget.py`, `time_trace_widget.py`, and `log_widget.py`.
   - These widgets are the user-facing controls and displays; they do not appear to own hardware logic directly.

4. **Experiment/control layer**
   - The `logic` package contains the measurement workflows and analysis flows.
   - Key modules include `scan_logic.py`, `odmr_logic.py`, `pulsed_logic.py`, `time_trace_logic.py`, `zscan_logic.py`, and `optimizer_logic.py`.
   - Supporting logic such as `sequence_generator.py`, `fit_logic.py`, and `data_manager.py` handle waveform/sequence creation, fitting/analysis, and persistence of acquired data.

5. **Hardware abstraction boundary**
   - The `interface` package defines the contracts for the physical subsystems:
     - `scanner_interface.py`
     - `counter_interface.py`
     - `mw_interface.py`
     - `pulse_interface.py`
   - These interfaces form the boundary between experiment logic and device-specific implementations, so the logic layer can stay independent of whether hardware is real or simulated.

6. **Device backends**
   - `drivers/dummy_scanner.py` provides simulation behavior for running without hardware.
   - `drivers/ni_scanner.py` is the real scanner backend for NI-based acquisition.
   - `drivers/mw_smiq.py` connects to the microwave source.
   - The README’s “one line” switch in `config/hardware.yaml` indicates that backend selection is configuration-driven, not code-driven.

7. **Shared application infrastructure**
   - `core/base_module.py` and `core/modular_manager.py` suggest a plugin-like module lifecycle and registration model.
   - `core/signal_bus.py` is the central event channel for decoupled communication between GUI, logic, and possibly hardware-facing components.
   - `core/config_loader.py` reads configuration from the YAML files under `config/`.
   - `core/logger.py` provides centralized logging, likely feeding both console/file output and the GUI log widget.

8. **Data flow**
   - User actions start in a GUI widget.
   - The widget triggers a logic module through the shared app infrastructure.
   - Logic modules call hardware interfaces, which route to either dummy or real drivers.
   - Measurements and status updates propagate back through signals/bus events to the widgets and log panel.
   - Analysis and data saving are handled by the logic layer, not the widgets.

9. **Measurement pipelines**
   - Confocal and scan-oriented workflows likely flow through the scanner/counter interfaces and `scan_logic` / `zscan_logic`.
   - ODMR and pulsed experiments involve the microwave and pulse interfaces, with `sequence_generator.py` defining timing/control sequences.
   - `time_trace_logic.py` handles single-point fluorescence monitoring, and `optimizer_logic.py` likely adjusts scan position or experimental settings based on measured signal quality.

10. **Configuration and runtime mode**
    - `config/hardware.yaml` controls whether dummy or real hardware is used.
    - `config/scan_config.yaml` appears to define scan-related defaults and acquisition parameters.
    - This makes the runtime environment declarative: hardware selection and key acquisition parameters are externalized from code.

11. **Outputs and analysis**
    - Data is not just displayed; it is also processed by `fit_logic.py` and managed by `data_manager.py`.
    - The architecture implies a clear separation between raw acquisition, derived analysis, and presentation.
    - That separation matters for the diagram because analysis is part of the experiment pipeline, not a GUI-only concern.

12. **External dependencies that matter architecturally**
    - The presence of NI scanner and SMIQ microwave drivers means the app integrates with lab hardware.
    - The project is explicitly designed to tolerate missing hardware by swapping in dummy implementations.
    - No external network or cloud services are indicated; the main integration boundary is instrument control.

13. **Good diagram boundaries**
    - Draw four main zones: GUI, logic/analysis, hardware interfaces, and device drivers.
    - Show `core` as shared infrastructure spanning all zones.
    - Show configuration files feeding `core/config_loader.py`, and logging/events flowing through `core/logger.py` and `core/signal_bus.py`.

Main entry points: [`gui_env/main_window.py`](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/main_window.py) (Main window), [`logic/scan_logic.py`](https://github.com/the-devil-8/q-diamond/blob/master/logic/scan_logic.py) (Scan logic), [`logic/data_manager.py`](https://github.com/the-devil-8/q-diamond/blob/master/logic/data_manager.py) (Data manager), [`logic/odmr_logic.py`](https://github.com/the-devil-8/q-diamond/blob/master/logic/odmr_logic.py) (ODMR logic)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_group_gui["GUI"]
  node_main_window["Main window<br/>GUI shell<br/>[main_window.py]"]
  node_confocal_widget["Confocal<br/>panel<br/>[confocal_widget.py]"]
  node_odmr_widget["ODMR<br/>panel<br/>[odmr_widget.py]"]
  node_pulsed_widget["Pulsed<br/>panel<br/>[pulsed_widget.py]"]
  node_time_trace_widget["Time trace<br/>panel"]
  node_log_widget["Log panel<br/>[log_widget.py]"]
end

subgraph group_group_logic["Logic"]
  node_scan_logic["Scan logic<br/>workflow<br/>[scan_logic.py]"]
  node_zscan_logic["Z scan<br/>workflow<br/>[zscan_logic.py]"]
  node_odmr_logic["ODMR logic<br/>workflow<br/>[odmr_logic.py]"]
  node_pulsed_logic["Pulsed logic<br/>workflow<br/>[pulsed_logic.py]"]
  node_time_trace_logic["Time trace logic<br/>workflow"]
  node_optimizer_logic["Optimizer<br/>workflow<br/>[optimizer_logic.py]"]
  node_sequence_generator["Sequences<br/>generator"]
  node_fit_logic["Fitting<br/>analysis<br/>[fit_logic.py]"]
  node_data_manager[("Data manager<br/>persistence<br/>[data_manager.py]")]
end

subgraph group_group_core["Core"]
  node_base_module["Base module<br/>lifecycle<br/>[base_module.py]"]
  node_modular_manager["Module manager<br/>registry<br/>[modular_manager.py]"]
  node_signal_bus(("Signal bus<br/>event bus<br/>[signal_bus.py]"))
  node_config_loader["Config loader<br/>[config_loader.py]"]
  node_logger["Logger<br/>logging<br/>[logger.py]"]
end

subgraph group_group_iface["Interfaces"]
  node_scanner_iface["Scanner API<br/>hardware contract"]
  node_counter_iface["Counter API<br/>hardware contract"]
  node_mw_iface["MW API<br/>hardware contract<br/>[mw_interface.py]"]
  node_pulse_iface["Pulse API<br/>hardware contract<br/>[pulse_interface.py]"]
end

subgraph group_group_drivers["Drivers"]
  node_dummy_scanner["Dummy scanner<br/>sim backend<br/>[dummy_scanner.py]"]
  node_ni_scanner["NI scanner<br/>device backend<br/>[ni_scanner.py]"]
  node_mw_smiq["SMIQ driver<br/>device backend<br/>[mw_smiq.py]"]
end

subgraph group_group_config["Config"]
  node_hardware_yaml["hardware.yaml<br/>config file<br/>[hardware.yaml]"]
  node_scan_yaml["scan_config.yaml<br/>config file<br/>[scan_config.yaml]"]
end

node_main_py(("main.py<br/>entrypoint<br/>[main.py]"))

node_main_py -->|"starts"| node_main_window
node_main_py -->|"loads"| node_config_loader
node_main_py -->|"initializes"| node_modular_manager
node_main_window -->|"hosts"| node_confocal_widget
node_main_window -->|"hosts"| node_odmr_widget
node_main_window -->|"hosts"| node_pulsed_widget
node_main_window -->|"hosts"| node_time_trace_widget
node_main_window -->|"hosts"| node_log_widget
node_confocal_widget -->|"drives"| node_scan_logic
node_confocal_widget -->|"drives"| node_zscan_logic
node_odmr_widget -->|"drives"| node_odmr_logic
node_pulsed_widget -->|"drives"| node_pulsed_logic
node_time_trace_widget -->|"drives"| node_time_trace_logic
node_log_widget -->|"subscribes"| node_signal_bus
node_scan_logic -->|"uses"| node_scanner_iface
node_scan_logic -->|"uses"| node_counter_iface
node_zscan_logic -->|"uses"| node_scanner_iface
node_odmr_logic -->|"uses"| node_mw_iface
node_pulsed_logic -->|"uses"| node_pulse_iface
node_pulsed_logic -->|"builds"| node_sequence_generator
node_time_trace_logic -->|"uses"| node_counter_iface
node_optimizer_logic -->|"adapts"| node_scan_logic
node_fit_logic -->|"writes"| node_data_manager
node_scan_logic -->|"writes"| node_data_manager
node_odmr_logic -->|"writes"| node_data_manager
node_pulsed_logic -->|"writes"| node_data_manager
node_time_trace_logic -->|"writes"| node_data_manager
node_scan_logic -->|"analyzes"| node_fit_logic
node_odmr_logic -->|"analyzes"| node_fit_logic
node_modular_manager -->|"manages"| node_base_module
node_modular_manager -->|"routes"| node_signal_bus
node_config_loader -->|"reads"| node_hardware_yaml
node_config_loader -->|"reads"| node_scan_yaml
node_config_loader -->|"configures"| node_logger
node_logger -->|"feeds"| node_log_widget
node_hardware_yaml -->|"selects"| node_dummy_scanner
node_hardware_yaml -->|"selects"| node_ni_scanner
node_hardware_yaml -->|"selects"| node_mw_smiq
node_scanner_iface -->|"implemented by"| node_dummy_scanner
node_scanner_iface -->|"implemented by"| node_ni_scanner
node_mw_iface -->|"implemented by"| node_mw_smiq
node_base_module -->|"emits"| node_signal_bus

click node_main_py "https://github.com/the-devil-8/q-diamond/blob/master/main.py"
click node_main_window "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/main_window.py"
click node_confocal_widget "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/confocal_widget.py"
click node_odmr_widget "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/odmr_widget.py"
click node_pulsed_widget "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/pulsed_widget.py"
click node_time_trace_widget "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/time_trace_widget.py"
click node_log_widget "https://github.com/the-devil-8/q-diamond/blob/master/gui_env/log_widget.py"
click node_scan_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/scan_logic.py"
click node_zscan_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/zscan_logic.py"
click node_odmr_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/odmr_logic.py"
click node_pulsed_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/pulsed_logic.py"
click node_time_trace_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/time_trace_logic.py"
click node_optimizer_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/optimizer_logic.py"
click node_sequence_generator "https://github.com/the-devil-8/q-diamond/blob/master/logic/sequence_generator.py"
click node_fit_logic "https://github.com/the-devil-8/q-diamond/blob/master/logic/fit_logic.py"
click node_data_manager "https://github.com/the-devil-8/q-diamond/blob/master/logic/data_manager.py"
click node_base_module "https://github.com/the-devil-8/q-diamond/blob/master/core/base_module.py"
click node_modular_manager "https://github.com/the-devil-8/q-diamond/blob/master/core/modular_manager.py"
click node_signal_bus "https://github.com/the-devil-8/q-diamond/blob/master/core/signal_bus.py"
click node_config_loader "https://github.com/the-devil-8/q-diamond/blob/master/core/config_loader.py"
click node_logger "https://github.com/the-devil-8/q-diamond/blob/master/core/logger.py"
click node_scanner_iface "https://github.com/the-devil-8/q-diamond/blob/master/interface/scanner_interface.py"
click node_counter_iface "https://github.com/the-devil-8/q-diamond/blob/master/interface/counter_interface.py"
click node_mw_iface "https://github.com/the-devil-8/q-diamond/blob/master/interface/mw_interface.py"
click node_pulse_iface "https://github.com/the-devil-8/q-diamond/blob/master/interface/pulse_interface.py"
click node_dummy_scanner "https://github.com/the-devil-8/q-diamond/blob/master/drivers/dummy_scanner.py"
click node_ni_scanner "https://github.com/the-devil-8/q-diamond/blob/master/drivers/ni_scanner.py"
click node_mw_smiq "https://github.com/the-devil-8/q-diamond/blob/master/drivers/mw_smiq.py"
click node_hardware_yaml "https://github.com/the-devil-8/q-diamond/blob/master/config/hardware.yaml"
click node_scan_yaml "https://github.com/the-devil-8/q-diamond/blob/master/config/scan_config.yaml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main_window,node_confocal_widget,node_odmr_widget,node_pulsed_widget,node_time_trace_widget,node_log_widget toneBlue
class node_scan_logic,node_zscan_logic,node_odmr_logic,node_pulsed_logic,node_time_trace_logic,node_optimizer_logic,node_sequence_generator,node_fit_logic,node_data_manager toneAmber
class node_base_module,node_modular_manager,node_signal_bus,node_config_loader,node_logger toneMint
class node_scanner_iface,node_counter_iface,node_mw_iface,node_pulse_iface toneRose
class node_dummy_scanner,node_ni_scanner,node_mw_smiq toneIndigo
class node_hardware_yaml,node_scan_yaml toneTeal
class node_main_py toneNeutral
```

## Components

### GUI

User-facing windows and measurement panels

- [Main window](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/main_window.py): GUI shell · Top-level application container · `gui_env/main_window.py`
- [Confocal](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/confocal_widget.py): panel · Confocal scan controls and display · `gui_env/confocal_widget.py`
- [ODMR](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/odmr_widget.py): panel · ODMR experiment controls and display · `gui_env/odmr_widget.py`
- [Pulsed](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/pulsed_widget.py): panel · Pulsed measurement controls and display · `gui_env/pulsed_widget.py`
- [Time trace](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/time_trace_widget.py): panel · Time trace monitoring panel · `gui_env/time_trace_widget.py`
- [Log panel](https://github.com/the-devil-8/q-diamond/blob/master/gui_env/log_widget.py): panel · UI log viewer · `gui_env/log_widget.py`

### Logic

Measurement workflows, analysis, and persistence

- [Scan logic](https://github.com/the-devil-8/q-diamond/blob/master/logic/scan_logic.py): workflow · Confocal and scan acquisition flow · `logic/scan_logic.py`
- [Z scan](https://github.com/the-devil-8/q-diamond/blob/master/logic/zscan_logic.py): workflow · Axial scan workflow · `logic/zscan_logic.py`
- [ODMR logic](https://github.com/the-devil-8/q-diamond/blob/master/logic/odmr_logic.py): workflow · Frequency sweep and resonance acquisition · `logic/odmr_logic.py`
- [Pulsed logic](https://github.com/the-devil-8/q-diamond/blob/master/logic/pulsed_logic.py): workflow · Pulse-based measurement workflow · `logic/pulsed_logic.py`
- [Time trace logic](https://github.com/the-devil-8/q-diamond/blob/master/logic/time_trace_logic.py): workflow · Single-point fluorescence monitoring · `logic/time_trace_logic.py`
- [Optimizer](https://github.com/the-devil-8/q-diamond/blob/master/logic/optimizer_logic.py): workflow · Adaptive tuning and positioning · `logic/optimizer_logic.py`
- [Sequences](https://github.com/the-devil-8/q-diamond/blob/master/logic/sequence_generator.py): generator · Pulse and timing sequence construction · `logic/sequence_generator.py`
- [Fitting](https://github.com/the-devil-8/q-diamond/blob/master/logic/fit_logic.py): analysis · Curve fitting and derived analysis · `logic/fit_logic.py`
- [Data manager](https://github.com/the-devil-8/q-diamond/blob/master/logic/data_manager.py): persistence · Acquisition storage and data handling · `logic/data_manager.py`

### Core

Shared runtime infrastructure

- [Base module](https://github.com/the-devil-8/q-diamond/blob/master/core/base_module.py): lifecycle · Common module lifecycle base · `core/base_module.py`
- [Module manager](https://github.com/the-devil-8/q-diamond/blob/master/core/modular_manager.py): registry · Registers and coordinates modules · `core/modular_manager.py`
- [Signal bus](https://github.com/the-devil-8/q-diamond/blob/master/core/signal_bus.py): event bus · Decoupled app-wide event routing · `core/signal_bus.py`
- [Config loader](https://github.com/the-devil-8/q-diamond/blob/master/core/config_loader.py): config · Loads runtime configuration · `core/config_loader.py`
- [Logger](https://github.com/the-devil-8/q-diamond/blob/master/core/logger.py): logging · Centralized application logging · `core/logger.py`

### Interfaces

Hardware abstraction contracts

- [Scanner API](https://github.com/the-devil-8/q-diamond/blob/master/interface/scanner_interface.py): hardware contract · Scanner abstraction boundary · `interface/scanner_interface.py`
- [Counter API](https://github.com/the-devil-8/q-diamond/blob/master/interface/counter_interface.py): hardware contract · Photon counter abstraction boundary · `interface/counter_interface.py`
- [MW API](https://github.com/the-devil-8/q-diamond/blob/master/interface/mw_interface.py): hardware contract · Microwave source abstraction boundary · `interface/mw_interface.py`
- [Pulse API](https://github.com/the-devil-8/q-diamond/blob/master/interface/pulse_interface.py): hardware contract · Pulse control abstraction boundary · `interface/pulse_interface.py`

### Drivers

Concrete simulated and real instrument backends

- [Dummy scanner](https://github.com/the-devil-8/q-diamond/blob/master/drivers/dummy_scanner.py): sim backend · Simulated scanner implementation · `drivers/dummy_scanner.py`
- [NI scanner](https://github.com/the-devil-8/q-diamond/blob/master/drivers/ni_scanner.py): device backend · NI-based scanner implementation · `drivers/ni_scanner.py`
- [SMIQ driver](https://github.com/the-devil-8/q-diamond/blob/master/drivers/mw_smiq.py): device backend · Microwave source driver · `drivers/mw_smiq.py`

### Config

Runtime configuration files

- [hardware.yaml](https://github.com/the-devil-8/q-diamond/blob/master/config/hardware.yaml): config file · Hardware backend selection · `config/hardware.yaml`
- [scan_config.yaml](https://github.com/the-devil-8/q-diamond/blob/master/config/scan_config.yaml): config file · Scan defaults and acquisition parameters · `config/scan_config.yaml`

### Other components

- [main.py](https://github.com/the-devil-8/q-diamond/blob/master/main.py): entrypoint · Application startup and wiring · `main.py`

## Connections

- main.py → Main window: starts · Launches the GUI application
- main.py → Config loader: loads · Initial runtime configuration
- main.py → Module manager: initializes · Sets up module lifecycle coordination
- Main window → Confocal: hosts · Contains measurement panels
- Main window → ODMR: hosts · Contains measurement panels
- Main window → Pulsed: hosts · Contains measurement panels
- Main window → Time trace: hosts · Contains measurement panels
- Main window → Log panel: hosts · Contains log display
- Confocal → Scan logic: drives · Triggers scan workflows
- Confocal → Z scan: drives · Triggers axial scan workflows
- ODMR → ODMR logic: drives · Triggers ODMR workflows
- Pulsed → Pulsed logic: drives · Triggers pulsed workflows
- Time trace → Time trace logic: drives · Triggers monitoring workflows
- Log panel → Signal bus: subscribes · Displays application events and logs
- Scan logic → Scanner API: uses · Reads position-controlled acquisition data
- Scan logic → Counter API: uses · Reads count data during scans
- Z scan → Scanner API: uses · Controls axial scanner motion
- ODMR logic → MW API: uses · Sweeps microwave source
- Pulsed logic → Pulse API: uses · Programs pulse timing and control
- Pulsed logic → Sequences: builds · Generates pulse sequences
- Time trace logic → Counter API: uses · Monitors fluorescence counts
- Optimizer → Scan logic: adapts · Uses scan feedback for optimization
- Fitting → Data manager: writes · Stores processed results and fits
- Scan logic → Data manager: writes · Persists acquired scan data
- ODMR logic → Data manager: writes · Persists ODMR results
- Pulsed logic → Data manager: writes · Persists pulsed measurement data
- Time trace logic → Data manager: writes · Persists trace data
- Scan logic → Fitting: analyzes · Uses fitting for derived metrics
- ODMR logic → Fitting: analyzes · Uses fitting for resonance analysis
- Module manager → Base module: manages · Coordinates module lifecycle
- Module manager → Signal bus: routes · Dispatches decoupled events
- Config loader → hardware.yaml: reads · Loads hardware mode and backend choice
- Config loader → scan_config.yaml: reads · Loads scan defaults and parameters
- Config loader → Logger: configures · Initializes application logging
- Logger → Log panel: feeds · Supplies log messages to UI
- hardware.yaml → Dummy scanner: selects · Chooses simulated scanner backend
- hardware.yaml → NI scanner: selects · Chooses real scanner backend
- hardware.yaml → SMIQ driver: selects · Chooses microwave backend
- Scanner API → Dummy scanner: implemented by · Simulation backend implementation
- Scanner API → NI scanner: implemented by · Real scanner backend implementation
- MW API → SMIQ driver: implemented by · Microwave backend implementation
- Base module → Signal bus: emits · Modules publish state changes and results
