这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

欢迎使用Quatm

欢迎来到 Quatm 用户指南!无论你是刚开始搭建实验控制系统,还是希望从 LabView、Matlab 迁移到开源方案,这里都能帮你快速上手。

什么是 Quatm?

Quatm 是一个专为量子物理实验设计的开源控制框架。它把设备驱动、时序管理、数据采集和分析这些常见需求整合在一起,让你只需关注实验本身,而不是底层的软件细节。了解更多 →

Quatm 不提供

  • 硬件:Quatm 是纯软件框架,实验所需的仪器设备需要你自行采购和维护。
  • 实验方案:Quatm 提供控制的工具,具体的实验逻辑和物理方案由你定义。

Quatm 提供

  • 完整的控制架构:设备驱动、时序控制、参数管理和数据分析,开箱即用。
  • 灵活的部署方式:单机运行、控制端—客户端分离,随需选择。
  • 活跃的社区支持:持续迭代、问题追踪和用户交流。

Quatm 适合我吗?

如果你的实验涉及超冷原子、离子阱、量子光学、量子化学等领域,需要精确控制多个仪器设备和全自动化实验测量,Quatm 会是理想的选择。

特别适合以下场景:

  • 🧪 长期使用 LabView 或 Matlab,想迁移到开源、可定制的方案
  • 🔌 多种厂商硬件混杂,需要一个统一的控制层
  • 🚀 希望将实验流程自动化,解放科研精力

💡 提示:如果你已经在使用全套 Artiq 生态,其原生支持已非常完善,Quatm 可能不是最佳选择。

系统架构

Quatm 采用分布式微服务架构,每个组件(硬件驱动、分析例程、GUI 面板)作为独立操作系统进程运行,通过 ZeroMQ 消息进行通信:

┌─────────────────────────────────────────────────────┐
│                    GUI 层                            │
│  实验浏览器 │ 参数编辑器 │ 图像监视器 │ 数据分析管理      │
└──────────────┬──────────────────────────────────────┘
               │ ZMQ PUB/SUB + RPC
┌──────────────┼──────────────────────────────────────┐
│              通信层 (quatm.servers)                   │
│  DataClient │ ImageClient │ CommandClient │ Properties │
└──────────────┬──────────────────────────────────────┘
               │
┌──────────────┼──────────────────────────────────────┐
│     实验层                 │      分析层               │
│  Experiment 基类          │  吸收成像 │ 高斯拟合       │
│  realtime() 时序控制       │  亮斑检测 │ 图像切片       │
│  参数扫描与队列管理         │  数据平均 │ 拟合加速       │
└──────────────┬──────────────────────────────────────┘
               │
┌──────────────┴──────────────────────────────────────┐
│                    驱动层                             │
│  FPGA │ Andor │ BlackFly │ Rigol │ Valon │ Thorlabs │
│  DDS │ Toptica │ PI Stage │ 监控设备 (温度/磁场/真空)   │
└─────────────────────────────────────────────────────┘

各层职责

层级模块职责
GUI 层quatm.GUIQt 图形界面,实验管理、设备控制、数据可视化
通信层quatm.serversZMQ 发布/订阅消息、RPC 远程调用、分布式属性同步
实验层quatm.experiment声明式实验时序、参数扫描、设备属性管理
分析层quatm.analysis实时图像处理、曲线拟合、离子检测(Cython 加速)
物理层quatm.physics光偶极阱建模、Stark 位移、散射率、Feshbach 共振
驱动层quatm.drivers统一硬件抽象,支持 300+ 种实验室仪器
监控层quatm.monitor温度、磁场、真空等环境参数持续监测

这种架构确保:故障隔离(一个组件崩溃不影响全局)、并行处理(图像分析与实验时序同时运行)、网络透明(组件可分布在不同机器)。

文档导航

系统学习 Quatm 的最佳路径:

章节你将学到
快速开始安装 Python 环境,配置 device_db.py 接入设备,编写并运行第一个实验
实验编辑指南Experiment 基类的完整生命周期,NumberValue/BoolValue/StringCombo 参数类型,delay() 和 realtime 时序控制
设备与驱动TTLOut/DAC/genericAttr 三种属性模式,校准文件使用,自定义驱动开发
数据与分析DataClient/ImageClient 通信,HDF5 存储结构,图像分析、离子检测等内置模块
通信层ZMQ 发布/订阅通信、DataClient/ImageClient/CommandClient、分布式属性系统
GUI 组件实验浏览器、参数编辑器、序列编辑器、图像监视器的使用与定制
物理模型库原子数据库、光偶极阱建模、Stark 位移与散射率计算
监控设备温度控制器、高斯计、波长计、真空规等环境监测设备
部署指南单机、客户端—控制端分离、多控制端集群的部署架构
最佳实践单一职责、Mixin 复用、设备状态检查、异常安全关闭
应用案例MOT 装载优化、吸收成像、Rabi 振荡等完整案例
代码贡献提交 Issue、发起 Pull Request、代码审查流程

🚀 建议路径:快速开始 → 实验编辑指南 → 设备与驱动 → 应用案例。其余章节可按需查阅。

1 - 快速开始

从零开始搭建 Quatm 实验控制环境,只需几分钟即可运行第一个实验。

欢迎!下面几步就能让 Quatm 在你的机器上跑起来。

完成本指南后,你将能够:

  • ✅ 在本地安装并验证 Quatm 环境
  • ✅ 理解 device_db.py 的设备配置方式
  • ✅ 编写一个带有参数面板的完整实验脚本
  • ✅ 在模拟模式下运行和调试实验

环境要求

  • Python:3.9 及以上版本
  • 操作系统:Windows 7 以上、Linux(内核版本 5.10.261 及以上)、macOS 10.12 及以上
  • 硬件:模拟模式无需硬件;实际实验需要支持 TTL/DAC 的控制器,实时控制需要 FPGA 模块(如 ADwin、Red Pitaya、NI-FPGA 等)

安装

git clone https://github.com/quatm/quatm.git
cd quatm
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

验证

from quatm.experiment import Experiment

class HelloQuatm(Experiment):
    def build(self):
        print("Quatm 就绪!")
    def run(self):
        print("Hello, Quatm!")

HelloQuatm().run()

下一步

1.1 - 编写第一个实验

从零开始编写你的第一个 Quatm 实验脚本,学习实验类的基本结构和运行方式。

实验的基本结构

每个 Quatm 实验都是一个继承自 Experiment 的 Python 类。只需定义 build()run() 两个核心方法:

from quatm.experiment import Experiment, NumberValue
from quatm.experiment.experiment import delay

class MyFirstExperiment(Experiment):
    def build(self):
        # 声明设备
        self.setattr_device("fpga")
        # 声明参数
        self.setattr_argument(
            "target_voltage",
            NumberValue("target_voltage", ndecimals=2, step=0.01, value=4.00)
        )

    def run(self):
        # 设置 DAC 通道输出并等待后切换
        self.my_dac = 1.0
        delay(0.5)
        self.my_dac = self.target_voltage

build() — 声明阶段

build() 在实验加载时执行一次,用于声明实验中使用的设备和参数。

设备声明模式

# DAQ/控制器设备(type: local)
self.setattr_device("fpga")

# 属性设备(type: attr),直接作为实验属性使用
self.setattr_device("cooling_ttl")

# 通用属性设备(type: generic_attr)
self.setattr_device("Li_frequency")

参数类型

类型使用场景
数值NumberValue电压、频率、时间等连续量
布尔BoolValue开关、使能等二值选项
选项StringCombo模式选择、扫描类型等固定选项
self.setattr_argument("b_field", NumberValue("b_field", ndecimals=1, step=0.5, value=5.0))
self.setattr_argument("cooling", BoolValue("cooling", True))
self.setattr_argument("scan", StringCombo("scan", ["完整扫描", "快速扫描"]))

run() — 执行阶段

run() 是实验的主体逻辑,每次运行按钮点击时执行。

设备控制

def run(self):
    # 模拟量输出
    self.trap_dac = 3.5        # 设置 DAC 输出
    
    # TTL 数字输出
    self.aom_ttl = True        # 打开 AOM
    delay(0.1)
    self.aom_ttl = False       # 关闭 AOM

数据采集

def run(self):
    self.camera.expose(0.1)
    img = self.camera.last_image
    
    # 发送到数据管理器
    self._dataq.send({"atom_count": analyze(img)})

运行实验

.py 文件放入 experiments/ 目录,启动 Quatm 浏览器:

python -m quatm.GUI.browser

1.2 - 常见问题

Quatm 安装和使用中的常见问题及解决方案。

Windows 系统

pyzmq 安装失败

安装 Microsoft C++ Build Tools 后重试。

FPGA 控制器驱动

需安装厂商提供的 SDK,FPGA 需要按照实际需求定义和烧录timetable。模拟模式下无需实际硬件。

Linux 系统

Qt 图形库依赖

sudo apt install libxcb-cursor0 libxcb-xinerama0 libegl1-mesa

相机权限

Andor / BlackFly 需配置 udev 规则。

Windows Subsystem for Linux (WSL)

WSL 用户请确保在 Linux 文件系统挂载上运行,避免在 Windows 文件系统上操作导致意外错误。

1.3 - 配置仪器设备

通过 device_db.py 将实验仪器接入 Quatm 框架。

Quatm 通过 configuration/device_db.py 管理所有实验仪器。该文件定义一个名为 device_db 的字典,每个键对应一个可在实验中使用的设备名称。

设备类型

device_db 支持三种设备类型:

type说明使用场景
local驱动类实例FPGA 控制器、相机等需要完整驱动对象的设备
attr属性映射将驱动的某个通道映射为实验属性(如 DAC、TTL)
generic_attr通用属性调用驱动的任意函数,实现灵活的功能映射

配置示例

device_db = {
    # 驱动设备:加载完整的驱动实例
    "fpga": {
        "type": "local",
        "module": "quatm.drivers.fpga.client",
        "class": "fpgaClient",
        "arguments": {},
    },
    # 属性设备:TTL 通道映射
    "cooling_aom": {
        "type": "attr",
        "module": "quatm.experiment.attributes",
        "class": "TTLOut",
        "arguments": {"channel": 5, "logic": "a"},
    },
    # 属性设备:DAC 通道映射
    "trap_coil_x": {
        "type": "attr",
        "module": "quatm.experiment.attributes",
        "class": "DAC",
        "arguments": {"channel": 2},
    },
}

属性设备参数

TTLOut — 数字输出

参数说明
channelFPGA 控制器 TTL 通道编号
logic"l" 为正逻辑,"a" 为反逻辑

DAC — 模拟输出

参数说明
channelFPGA 控制器 DAC 通道编号
gaugefile校准文件路径(可选)

通用属性配置

对于需要灵活映射的驱动功能,使用 genericAttr

"Li_frequency": {
    "type": "generic_attr",
    "module": "quatm.experiment.attributes",
    "class": "genericAttr",
    "driver": "lithium_dds_0",
    "function": "set_frequency",
    "arguments": {
        "function_kwargs": {"channel": [0]},
        "minval": 40, "maxval": 90,
        "multiplier": 1E6, "display_unit": "MHz",
    },
}

校准文件

对于非线性响应的设备,可使用两列空格分隔的文本文件进行校准:

2.2  4.0
2.0  3.8
1.8  3.6
1.6  3.34

在 DAC 配置中通过 gauge 参数引用:

"rf_power": {
    "type": "attr",
    "module": "quatm.experiment.attributes",
    "class": "DAC",
    "arguments": {"channel": 3, "gauge": "configuration/gauge-rf-power.txt"},
}

自定义驱动接入

编写自定义驱动类后,在 device_db 中以 type: "local" 注册:

"my_laser": {
    "type": "local",
    "module": "my_lab.my_laser_driver",
    "class": "MyLaserDriver",
    "arguments": {"port": "/dev/ttyUSB0"},
}

然后在实验中通过 self.setattr_device("my_laser") 使用。

2 - 实验编辑指南

深入了解 Quatm 实验框架的核心 API,掌握从基础实验到高级控制的完整编写方法。

Experiment 基类

所有 Quatm 实验都继承自 Experiment 基类。该基类提供了完整的实验生命周期管理和设备控制接口。

核心方法

方法调用时机用途
build()实验加载时执行一次声明设备、定义参数
run()每次点击运行按钮实验主逻辑
start_measurement()每次测量开始前初始化操作(仅一次)
start_sequence()每次扫描序列开始前序列级初始化
end_sequence()每次扫描序列结束后序列级清理
end_measurement()测量结束后最后的清理操作

声明设备

使用 setattr_device() 将 device_db 中配置的设备引入实验:

def build(self):
    self.setattr_device("fpga")       # FPGA 控制器
    self.setattr_device("camera")      # 科学相机
    self.setattr_device("valon_5009")  # 频率合成器

设备名称必须与 configuration/device_db.py 中的键完全一致。

声明参数

使用 setattr_argument() 创建可在 GUI 中调整的实验参数:

from quatm.experiment import Experiment, NumberValue
from quatm.experiment.experiment import BoolValue, StringCombo

def build(self):
    # 数值参数
    self.setattr_argument(
        "exposure_time",
        NumberValue("exposure_time", ndecimals=2, step=0.01, value=1.0)
    )
    # 布尔开关
    self.setattr_argument("enable_cooling", BoolValue("enable_cooling", True))
    # 字符串选项
    self.setattr_argument("scan_type", StringCombo("scan_type", ["频率", "功率"]))

设备属性类型

设备接入后,根据 device_db 中的配置类型,呈现为不同的属性:

类型对应类用途
attrDAC / TTLOut直接映射到硬件通道
generic_attrgenericAttr调用驱动上的任意函数
local驱动类实例完整驱动对象

实验生命周期

每个实验按以下层次结构执行:

测量 (measurement)
  └─ 序列 (sequence / repetition)
       └─ 运行 (run)
  • run:单次实验执行,每次调用 run() 方法
  • sequence:一组使用不同参数值的 run 集合(参数扫描)
  • measurement:一个或多个 sequence 的完整测量

时序控制

delay() 函数

delay(seconds) 在非实时模式下暂停指定秒数,在实时模式下仅递增内部计时器:

def run(self):
    self.cooling_laser.on()
    delay(0.1)   # 等待 100 毫秒
    self.camera.expose(1.0)

实验控制设备

使用 realtime 上下文管理器实现精确的硬件时序:

def run(self):
    with realtime(repetitions=3):
        self.ttl_channel = True
        delay(0.001)
        self.ttl_channel = False

数据管理

发送实验数据

通过 DataClient 将数据推送到数据管理器:

def run(self):
    result = measure_atoms()
    self._dataq.send({
        "atom_count": result,
        "temperature": T
    })

数据以 HDF5 格式自动保存,支持 InfluxDB 远程推送。

前馈控制

Feed_forward 类允许根据历史数据动态调整实验参数:

from quatm.experiment.feedforward import Feed_forward

def build(self):
    self.ff = Feed_forward(self)
    self.ff.set_refresh_time(refresh_time=1)

def run(self):
    # 根据历史斜率自动调整
    self.ff.set_yslope(self.measured_slope)

模拟模式

在无实际硬件时,可通过 simulation_class_decorator 装饰器启用模拟:

from quatm.experiment.simulation_decorator import simulation_class_decorator

@simulation_class_decorator
class TestExperiment(Experiment):
    def build(self):
        self.setattr_device("fpga")

模拟模式下所有设备操作被拦截并记录,不会产生实际硬件输出。

3 - 设备与驱动

Quatm 原生支持 50+ 品牌、100+ 种实验仪器——涵盖科学相机、信号源、激光器、运动平台、DAQ 与环境监测。

Quatm 通过 configuration/device_db.py 统一管理所有仪器设备,支持三种接入模式。

设备接入模式

type行为适用场景
local实例化驱动类,作为完整对象使用FPGA 控制器、相机等需要方法调用的设备
attr将通道映射为 Python 属性DAC 输出、TTL 数字信号
generic_attr调用驱动的任意函数DDS 频率设置等灵活映射

驱动分类

Quatm 内置 50+ 品牌 的实验仪器驱动,分为以下 7 个类别:

类别品牌数典型设备
📷 科学相机15Andor EMCCD/sCMOS、FLIR Blackfly、Basler、Hamamatsu ORCA、Thorlabs TSI
📡 信号源与射频8Valon 5009、DDS AD9959、Agilent 33500、Rigol DG1020Z
🔬 激光器与光学9Cobolt、Toptica iBeam、Sirah Matisse、M² Solstis、HighFinesse 波长计
🎯 运动与定位8PI 纳米台、Attocube、Newport Picomotor、Thorlabs APT
🔌 DAQ 与电源9NI DAQ/SWITCH/Digital、Rigol DP1116A、EA PS2000B、Keithley 2110、示波器
🌡️ 环境监测9Lakeshore 218、Cryocon、Pfeiffer TPG2xx、Leybold ITR、液氦液位计
⚡ 实验控制3ADwin FPGA、NI-FPGA、Red Pitaya、Conrad 继电器板

属性设备详解

TTLOut — 数字输出

映射硬件控制器的 TTL 通道为实验属性,支持正/反逻辑:

"cooling_aom": {
    "type": "attr",
    "module": "quatm.experiment.attributes",
    "class": "TTLOut",
    "arguments": {"channel": 5, "logic": "a"},
}

实验中直接赋值:self.cooling_aom = True

DAC — 模拟输出

映射硬件控制器的 DAC 通道,支持校准曲线:

"trap_x": {
    "type": "attr",
    "module": "quatm.experiment.attributes",
    "class": "DAC",
    "arguments": {"channel": 2, "gauge": "gauge-trap-x.txt"},
}

校准文件

非线性设备使用两列文本文件校准。第一列为期望物理量,第二列为实际 DAC 值,系统自动线性插值。

自定义驱动

"my_laser": {
    "type": "local",
    "module": "my_lab.laser_driver",
    "class": "LaserController",
    "arguments": {"port": "/dev/ttyUSB0"},
}

通信协议

协议典型设备
VISA / SCPI信号发生器、万用表、示波器、电源
串口 (RS232/RS485)激光器、真空计、位移台、温控器
Modbus RTUOmron/Lumel 温控器
TCP/IP (Telnet/JSON)M² 激光器、Attocube 控制器
原生 SDK DLLAndor、Basler、Hamamatsu 等相机
NI-DAQmxNI 数据采集卡
USB HIDANC350 纳米定位器
SPIAD9959 DDS

3.1 - 科学相机

Andor、Basler、Hamamatsu、FLIR 等 15 品牌科学相机与图像采集驱动。

概述

Quatm 为全球 15 个主流科学相机品牌提供统一的 ICamera 接口封装,覆盖 EMCCD、sCMOS、高速 CMOS 和工业相机。


Andor 系列:iXon EMCCD / Zyla sCMOS / Shamrock 光谱仪

概述

Quatm 提供两套 Andor 相机驱动,通过原生 SDK 实现高性能成像控制:

驱动类SDK适用型号接口
AndorSDK2Cameraatmcd32d.dll (SDK2)iXon EMCCD, Luca, ClaraPCIe / USB
AndorSDK3Cameraatcore.dll (SDK3)Zyla, Neo, Marana (sCMOS)USB3 / CameraLink
ShamrockSpectrographShamrockCIF.dllSR-303i, SR-500i 等光谱仪USB

所有类继承自 io.camera 接口,支持 ROI、binning、曝光控制和帧缓冲管理。

Andor SDK2 (EMCCD) AndorSDK2Camera

⚙️ iXon EMCCD Andor SDK2 系列
通信DLL (atm32cd32)
读出模式EM/传统
ADC 频率1/5/10 MHz
像素深度16-bit
制冷TEC(≤ -100°C)
适用于极低光信号场景(单原子/离子荧光),通过电子倍增(EM Gain)实现单光子级灵敏度。
驱动模块:AndorSDK2Camera

初始化

from quatm.drivers.andor.AndorSDK2 import AndorSDK2Camera

# 连接第一台相机
cam = AndorSDK2Camera(cam_id=0)

# 配置采集参数
cam.setup_acquisition(
    exposure=0.1,       # 曝光时间 (s)
    em_gain=200,        # EM 增益 (0-1000)
    readout_rate="5MHz",# 读出速率
    pre_amp_gain=2,     # 前置放大增益
    hsspeed=0,          # 水平转移速率
    temperature=-70,    # 目标温度 (°C)
)

# 采集单帧
cam.start_acquisition(nframes=1)
image = cam.read_multiple_images(nframes=1)

关键参数

参数说明典型范围
exposure单帧曝光时长0.001 – 3600 s
em_gain电子倍增增益0 – 1000(线性或真实增益模式)
readout_rateADC 读出频率1MHz / 5MHz / 10MHz
temperature传感器目标温度-60 至 -100°C(取决于冷却器)
pre_amp_gain前置放大器增益1× – 4×

Andor SDK3 (sCMOS) AndorSDK3Camera

⚙️ Zyla / Neo sCMOS Andor SDK3 系列
通信DLL (atcore)
传感器sCMOS
接口USB3 / CameraLink
像素深度12/16-bit
帧率最高 100 fps(全分辨率)
适用于快速序列成像和需要大视场的场景。基于 GenAPI 属性模型配置曝光、ROI 和触发。
驱动模块:AndorSDK3Camera

初始化

from quatm.drivers.andor.AndorSDK3 import AndorSDK3Camera

cam = AndorSDK3Camera(cam_id=0)
cam.setup_acquisition(
    exposure=0.05,
    pixel_format="Mono16",
    trigger_mode="Internal",
)

Andor Shamrock 光谱仪 ShamrockSpectrograph

控制光栅选择、中心波长和狭缝宽度:

from quatm.drivers.andor.Shamrock import ShamrockSpectrograph

spec = ShamrockSpectrograph(idx=0)
spec.set_wavelength(780.24)      # 中心波长 (nm)
spec.set_grating(2)              # 选择光栅
spec.set_slit_width(50, port=1)  # 入口狭缝 (µm)

设备配置

"emccd": {
    "type": "local",
    "module": "drivers.andor.AndorSDK2",
    "class": "AndorSDK2Camera",
    "arguments": {"cam_id": 0},
}

FLIR / Teledyne / Blackfly S / Grasshopper3

概述

Quatm 通过 TeledyneSpinnakerCamera 类封装 Spinnaker SDK,支持所有兼容 GenICam/GenAPI 的 FLIR/Teledyne USB3/GigE 相机。

⚙️ Blackfly S / Grasshopper3 FLIR Spinnaker 系列
通信Spinnaker SDK
接口USB3 / GigE
像素格式Mono8/16, Bayer
触发硬件/软件
帧率取决于型号
用于实验室通用成像:MOT 监测、对准光束成像、设备状态监控。
驱动模块:TeledyneSpinnakerCamera

初始化

from quatm.drivers.teledyne.spinnaker import TeledyneSpinnakerCamera

# 列出所有可用相机
cam_list = TeledyneSpinnakerCamera.list_cameras()

# 连接指定相机(序列号或索引)
cam = TeledyneSpinnakerCamera(cam_id="serial_xxx")
# 或使用索引
cam = TeledyneSpinnakerCamera(cam_id=0)

# 配置并开始采集
cam.setup_acquisition(
    exposure=0.02,          # 20 ms 曝光
    pixel_format="Mono8",
    width=1920, height=1200,
    offset_x=0, offset_y=0,
)

关键方法

方法说明
list_cameras()枚举系统中所有 Spinnaker 相机
setup_acquisition(**kwargs)配置 ROI、曝光、像素格式等
start_acquisition(nframes)开始采集指定帧数
read_multiple_images(nframes)读取已采集图像
get_device_info()获取相机序列号、型号、固件版本

常用属性操作

通过 GenAPI 节点名称直接读写相机参数:

# 设置增益
cam.set_attribute("Gain", 10.0)
# 启用自动曝光
cam.set_attribute("ExposureAuto", "Continuous")
# 获取传感器温度
temp = cam.get_attribute("DeviceTemperature")

设备配置

"monitor_cam": {
    "type": "local",
    "module": "drivers.teledyne.spinnaker",
    "class": "TeledyneSpinnakerCamera",
    "arguments": {"cam_id": 0},
}
  • stop(): Stop capturing images.

  • quatm.drivers.blackfly.bfly.Camserver(name, serial)

    class quatm.drivers.blackfly.bfly.Camserver(object):
        def __init__(self, name, serial):
            pass
    
        def generateImageIndex(self):
            pass
    
        def run(self):
            pass
    
        def sendimage(self, im):
            pass
    
        def updateBusInfo(self):
            pass
    
    • generateImageIndex(): In the current measurement, count the images. If the next run has started (either task, repetition or run changes), reset the counter (imgindex).

    • run(): Run loop running forever. Sends images from the camera to the imagestream and initiates reconfiguration of the camera in case properties have changed.

    • sendimage(im): Send Blackfly camera image via the imagestream. The image is converted to numpy array, additional information like binning, timestamp, etc., is added to a dictionary and both are sent to the imagestream.

      • Args: im - Blackfly image object.
      • Returns: None
    • updateBusInfo(): Detect cameras on the bus and update info in properties if new camera has been found.

  • quatm.drivers.blackfly.bfly.pc2

    class quatm.drivers.blackfly.bfly.pc2(object):
        pass
    
    • Dummy class in case driver is not installed.

Function:

  • quatm.drivers.blackfly.bfly.run(name)

    def quatm.drivers.blackfly.bfly.run(name):
        pass
    
    • Initialize a Camserver and run it.

Thorlabs TSI / uc480 科学相机

TLCamera ThorlabsTLCamera

⚙️ TSI 系列 Thorlabs 科学相机
通信TLCamera SDK
接口USB3
传感器sCMOS / CCD
支持ROI, binning
适用于 SDK 级控制的高帧率科学成像。
驱动模块:ThorlabsTLCamera
from quatm.drivers.thorlabs.TLCamera import ThorlabsTLCamera
cam = ThorlabsTLCamera(serial="12345678")
cam.setup_acquisition(exposure=0.01, width=1024, height=768)

概述

Quatm 为全球 15 个主流科学相机品牌提供统一的 io.camera 接口封装,覆盖 EMCCD、sCMOS、高速 CMOS 和工业相机。所有驱动通过原生 SDK 实现高性能采集。


Andor 系列:EMCCD / sCMOS / 光谱仪

概述

Quatm 提供两套 Andor 相机驱动,通过原生 SDK 实现高性能成像控制:

驱动类SDK适用型号接口
AndorSDK2Cameraatmcd32d.dll (SDK2)iXon EMCCD, Luca, ClaraPCIe / USB
AndorSDK3Cameraatcore.dll (SDK3)Zyla, Neo, Marana (sCMOS)USB3 / CameraLink
ShamrockSpectrographShamrockCIF.dllSR-303i, SR-500i 等光谱仪USB

所有类继承自 io.camera 接口,支持 ROI、binning、曝光控制和帧缓冲管理。

Andor SDK2 (EMCCD) AndorSDK2Camera

⚙️ iXon EMCCD Andor SDK2 系列
通信DLL (atm32cd32)
读出模式EM/传统
ADC 频率1/5/10 MHz
像素深度16-bit
制冷TEC(≤ -100°C)
适用于极低光信号场景(单原子/离子荧光),通过电子倍增(EM Gain)实现单光子级灵敏度。
驱动模块:AndorSDK2Camera

初始化

from quatm.drivers.andor.AndorSDK2 import AndorSDK2Camera

# 连接第一台相机
cam = AndorSDK2Camera(cam_id=0)

# 配置采集参数
cam.setup_acquisition(
    exposure=0.1,       # 曝光时间 (s)
    em_gain=200,        # EM 增益 (0-1000)
    readout_rate="5MHz",# 读出速率
    pre_amp_gain=2,     # 前置放大增益
    hsspeed=0,          # 水平转移速率
    temperature=-70,    # 目标温度 (°C)
)

# 采集单帧
cam.start_acquisition(nframes=1)
image = cam.read_multiple_images(nframes=1)

关键参数

参数说明典型范围
exposure单帧曝光时长0.001 – 3600 s
em_gain电子倍增增益0 – 1000(线性或真实增益模式)
readout_rateADC 读出频率1MHz / 5MHz / 10MHz
temperature传感器目标温度-60 至 -100°C(取决于冷却器)
pre_amp_gain前置放大器增益1× – 4×

Andor SDK3 (sCMOS) AndorSDK3Camera

⚙️ Zyla / Neo sCMOS Andor SDK3 系列
通信DLL (atcore)
传感器sCMOS
接口USB3 / CameraLink
像素深度12/16-bit
帧率最高 100 fps(全分辨率)
适用于快速序列成像和需要大视场的场景。基于 GenAPI 属性模型配置曝光、ROI 和触发。
驱动模块:AndorSDK3Camera

初始化

from quatm.drivers.andor.AndorSDK3 import AndorSDK3Camera

cam = AndorSDK3Camera(cam_id=0)
cam.setup_acquisition(
    exposure=0.05,
    pixel_format="Mono16",
    trigger_mode="Internal",
)

Andor Shamrock 光谱仪 ShamrockSpectrograph

控制光栅选择、中心波长和狭缝宽度:

from quatm.drivers.andor.Shamrock import ShamrockSpectrograph

spec = ShamrockSpectrograph(idx=0)
spec.set_wavelength(780.24)      # 中心波长 (nm)
spec.set_grating(2)              # 选择光栅
spec.set_slit_width(50, port=1)  # 入口狭缝 (µm)

设备配置

"emccd": {
    "type": "local",
    "module": "drivers.andor.AndorSDK2",
    "class": "AndorSDK2Camera",
    "arguments": {"cam_id": 0},
}

FLIR / Teledyne Spinnaker 系列

概述

Quatm 通过 TeledyneSpinnakerCamera 类封装 Spinnaker SDK,支持所有兼容 GenICam/GenAPI 的 FLIR/Teledyne USB3/GigE 相机。

⚙️ Blackfly S / Grasshopper3 FLIR Spinnaker 系列
通信Spinnaker SDK
接口USB3 / GigE
像素格式Mono8/16, Bayer
触发硬件/软件
帧率取决于型号
用于实验室通用成像:MOT 监测、对准光束成像、设备状态监控。
驱动模块:TeledyneSpinnakerCamera

初始化

from quatm.drivers.teledyne.spinnaker import TeledyneSpinnakerCamera

# 列出所有可用相机
cam_list = TeledyneSpinnakerCamera.list_cameras()

# 连接指定相机(序列号或索引)
cam = TeledyneSpinnakerCamera(cam_id="serial_xxx")
# 或使用索引
cam = TeledyneSpinnakerCamera(cam_id=0)

# 配置并开始采集
cam.setup_acquisition(
    exposure=0.02,          # 20 ms 曝光
    pixel_format="Mono8",
    width=1920, height=1200,
    offset_x=0, offset_y=0,
)

关键方法

方法说明
list_cameras()枚举系统中所有 Spinnaker 相机
setup_acquisition(**kwargs)配置 ROI、曝光、像素格式等
start_acquisition(nframes)开始采集指定帧数
read_multiple_images(nframes)读取已采集图像
get_device_info()获取相机序列号、型号、固件版本

常用属性操作

通过 GenAPI 节点名称直接读写相机参数:

# 设置增益
cam.set_attribute("Gain", 10.0)
# 启用自动曝光
cam.set_attribute("ExposureAuto", "Continuous")
# 获取传感器温度
temp = cam.get_attribute("DeviceTemperature")

设备配置

"monitor_cam": {
    "type": "local",
    "module": "drivers.teledyne.spinnaker",
    "class": "TeledyneSpinnakerCamera",
    "arguments": {"cam_id": 0},
}
  • stop(): Stop capturing images.

  • quatm.drivers.blackfly.bfly.Camserver(name, serial)

    class quatm.drivers.blackfly.bfly.Camserver(object):
        def __init__(self, name, serial):
            pass
    
        def generateImageIndex(self):
            pass
    
        def run(self):
            pass
    
        def sendimage(self, im):
            pass
    
        def updateBusInfo(self):
            pass
    
    • generateImageIndex(): In the current measurement, count the images. If the next run has started (either task, repetition or run changes), reset the counter (imgindex).

    • run(): Run loop running forever. Sends images from the camera to the imagestream and initiates reconfiguration of the camera in case properties have changed.

    • sendimage(im): Send Blackfly camera image via the imagestream. The image is converted to numpy array, additional information like binning, timestamp, etc., is added to a dictionary and both are sent to the imagestream.

      • Args: im - Blackfly image object.
      • Returns: None
    • updateBusInfo(): Detect cameras on the bus and update info in properties if new camera has been found.

  • quatm.drivers.blackfly.bfly.pc2

    class quatm.drivers.blackfly.bfly.pc2(object):
        pass
    
    • Dummy class in case driver is not installed.

Function:

  • quatm.drivers.blackfly.bfly.run(name)

    def quatm.drivers.blackfly.bfly.run(name):
        pass
    
    • Initialize a Camserver and run it.

Thorlabs TSI / uc480

Thorlabs 科学相机

Quatm 支持多类 Thorlabs 设备,包含位移台、光学测量仪器与相机。

TLCamera 科学相机 ThorlabsTLCamera

⚙️ TSI 系列 Thorlabs 科学相机
通信TLCamera SDK
接口USB3
传感器sCMOS / CCD
支持ROI, binning
适用于需要 SDK 级别控制的高帧率科学成像。
驱动模块:ThorlabsTLCamera
from quatm.drivers.thorlabs.TLCamera import ThorlabsTLCamera
cam = ThorlabsTLCamera(serial="12345678")

---

## Basler — Pylon SDK 系列

⚙️ Basler ace / dart Pylon SDK 系列
通信 Pylon SDK (GenICam)
接口 USB3 / GigE
传感器 CMOS
像素格式 Mono8/16, Bayer
功能 ROI, Binning, 硬件触发
工业级 CMOS 相机,适合 MOT 荧光监测、对准光束成像等常规实验室成像任务。
驱动模块:BaslerPylonCamera
```python from quatm.drivers.Basler.pylon import BaslerPylonCamera # 枚举全部相机 cams = BaslerPylonCamera.list_cameras() cam = BaslerPylonCamera(cam_id=cams[0]) cam.setup_acquisition(exposure=0.02) cam.start_acquisition(nframes=1)

Hamamatsu ORCA 系列 sCMOS

⚙️ ORCA-Fusion / ORCA-Flash4.0 Hamamatsu DCAM
通信DCAM SDK (DLL)
传感器sCMOS
像素2048×2048 (Fusion)
帧率最高 100 fps
读出噪声< 1.6 e⁻
超低噪声 sCMOS,适用于单原子/单离子荧光定量成像。
驱动模块:DCAMCamera
from quatm.drivers.DCAM.DCAM import DCAMCamera

cam = DCAMCamera(idx=0)
cam.setup_acquisition(exposure=0.1, pixel_format="Mono16")

Photometrics Prime / Evolve 系列

⚙️ Prime BSI / Evolve EMCCD Photometrics PVCAM
通信PVCAM SDK (DLL)
传感器背照式 sCMOS / EMCCD
接口PCIe / USB3
像素深度16-bit
背照式 sCMOS 提供高量子效率;EMCCD 型号支持单光子灵敏度。
驱动模块:PVCAMCamera
from quatm.drivers.Photometrics.pvcam import PVCAMCamera

cam = PVCAMCamera(cam_name="Prime_BSI_95B")
cam.setup_acquisition(exposure=0.05)

Princeton Instruments PIXIS / ProEM

⚙️ PIXIS / ProEM / IsoPlane Princeton PICam
通信PICam SDK (DLL)
传感器CCD / EMCCD
制冷液氮 / TEC
接口PCIe / USB
光谱学级 CCD/EMCCD,常与 Acton/IsoPlane 光谱仪配合使用。
驱动模块:PicamCamera
from quatm.drivers.PrincetonInstruments.picam import PicamCamera

cam = PicamCamera(cam_id=0)
cam.setup_acquisition(exposure=1.0)  # 长曝光光谱采集

PCO edge / dimax 高速相机

⚙️ edge / dimax / pco.panda PCO SC2
通信SC2 SDK (DLL)
接口CameraLink HS / USB3 / GigE
帧率最高数千 fps
传感器sCMOS / 高速 CMOS
适合快速动力学过程:MOT 装载动态、离子晶体重排实时观测。
驱动模块:PCOSC2Camera
from quatm.drivers.PCO.SC2 import PCOSC2Camera

cam = PCOSC2Camera(interface="USB 3.0")
cam.setup_acquisition(exposure=0.001)  # 1 ms 高速采集

Allied Vision Alvium / Mako

⚙️ Alvium / Mako / Bonito Allied Vision Vimba X
通信VimbaX SDK (GenICam)
接口USB3 / GigE / CameraLink
传感器CMOS
紧凑型工业相机,适合空间受限的光路集成。
驱动模块:AlliedVisionVimbaXCamera
from quatm.drivers.AlliedVision.VimbaX import AlliedVisionVimbaXCamera

cam = AlliedVisionVimbaXCamera(cam_id=0)

IDS uEye+ / Ensenso

⚙️ uEye+ / Ensenso 3D IDS peak
通信IDS peak SDK
接口USB3 / GigE
传感器CMOS
通用 USB/GigE 相机,包括 Ensenso 3D 立体相机。
驱动模块:GenericIDSPeakCamera
from quatm.drivers.IDS.peak import GenericIDSPeakCamera

cam = GenericIDSPeakCamera(cam_id=0)

通用配置范式

所有相机通过 device_db.pytype: "local" 注册:

"imaging_cam": {
    "type": "local",
    "module": "drivers.Basler.pylon",
    "class": "BaslerPylonCamera",
    "arguments": {"cam_id": 0},
}

3.2 - 信号源与射频

Valon 5009、DDS AD9959、Agilent、Rigol 等频率合成器与射频仪器驱动。

概述

Quatm 支持从通用函数发生器到矢量网络分析仪的多种射频仪器,涵盖频率合成、任意波形和 S 参数测量。


Valon 5009 双通道微波频率合成器

概述

Valon 5009 是一款双通道频率合成器(23.5 MHz – 6 GHz),通过串口控制。Quatm 通过 valon 封装,支持独立设置两路输出频率和功率。

⚙️ Valon 5009 Dual RF Synthesizer
通信串口 (RS232)
频率范围23.5 MHz – 6 GHz
通道数2
输出功率-30 ~ +10 dBm
频率分辨率0.1 Hz
广泛应用于离子阱实验中驱动微波跃迁(如 Ba⁺ 9.9 GHz 超精细跃迁)或作为 AOM 驱动源。
驱动模块:valon

初始化

from quatm.drivers.valon.valon_quatm import valon

# 连接 Valon(默认 /dev/ttyUSB0)
valon = valon(port="/dev/ttyUSB0")

# 设置通道 1 频率为 500 MHz
valon.set_frequency(freq=500e6, source=1)

# 设置通道 2 频率为 9.925 GHz(需外部倍频)
valon.set_frequency(freq=9.925e9, source=2)

# 发送原始指令
valon.sendRaw("LOCK 1 ON\r\n")

关键方法

方法说明
set_frequency(freq, source)设置通道 1 或 2 输出频率 (Hz)
sendCommand(source, command, value)发送格式化 SCPI 命令
sendRaw(cmd)发送原始字符串命令

串口通信

Valon 驱动底层通过 VSerialPortserial.Serial 子类)通信,典型参数:

# 串口参数(驱动默认)
port = "/dev/ttyUSB0"
baudrate = 115200
timeout = 0.1
🔬 Ba⁺ 微波跃迁扫描 Ba⁺

使用 Valon 5009 驱动 9.925 GHz 超精细跃迁,扫描频率测量 Rabi 振荡。

关键参数
起始频率9.924 GHz
终止频率9.926 GHz
步进10 kHz
每点重复100 次
# 实验片段:频率扫描
import numpy as np
frequencies = np.arange(9.924e9, 9.926e9, 10e3)
for f in frequencies:
    valon.set_frequency(freq=f, source=2)
    # ... 执行探测序列 ...

class quatm.drivers.valon.valon_prog.Valon_Standalone(name='Valon')

Bases: object

  • Standalone driver for the Valon frequency generator. Commands can be sent via the Commandhub and are processed in parallel to the experiment, thereby the experiment is not delayed by the Valon.

    • run()
  • function quatm.drivers.valon.valon_prog.run()


DDS AD9959 四通道直接数字合成

概述

AD9959 驱动封装 AD9959 评估板,通过 SPI 总线控制 4 个独立 DDS 通道,实现精密频率、幅度和相位控制。

⚙️ AD9959 评估板 4 通道 DDS
通信SPI
通道数4
频率分辨率32-bit (0.12 Hz @ 500 MHz 时钟)
相位分辨率14-bit
幅度控制10-bit DAC
广泛应用于冷原子/离子实验中的 AOM 驱动、边带生成和相干操控。
驱动模块:AD9959

初始化

from quatm.drivers.dds import AD9959

dds = AD9959()

# 配置通道 0 — 冷却光 AOM
dds.set_frequency(0, 80e6)       # 80 MHz
dds.set_amplitude(0, 0.5)        # 50% 幅度
dds.set_phase(0, 0)              # 0° 相位

# 配置通道 1 — 再泵浦光 AOM(+0.1 MHz 差频)
dds.set_frequency(1, 80.1e6)
dds.set_amplitude(1, 0.3)

关键方法

方法说明
set_frequency(ch, freq_hz)设置通道频率 (Hz)
set_amplitude(ch, amp)设置通道幅度 (0–1 分数)
set_phase(ch, phase_deg)设置通道相位 (°)
update_all()一次性更新所有通道

设备配置

"aom_dds": {
    "type": "local",
    "module": "drivers.DDS",
    "class": "AD9959",
}

dds.set_amplitude(1, 0.5)


## 典型应用

| 应用 | 配置 |
|------|------|
| AOM 驱动 | 单通道固定频率 |
| 拉曼跃迁 | 双通道差频锁定 |
| 阱驱动 | 多通道相位控制 |
| 边带冷却 | 频率调制 |

## 替代驱动

还提供基于串口(AT 命令)接口的 AD9959 板替代驱动:

```python
from quatm.drivers.dds.alibaba import AD9959Board

Rigol DG1020Z 双通道函数发生器

DG1020Z

⚙️ DG1020Z Rigol 函数发生器
通信VISA (USB/LAN)
通道数2
频率范围1 µHz – 25 MHz
幅度1 mVpp – 10 Vpp
采样率200 MSa/s
用于生成 AOM/EOM 驱动信号、调制波形和自定义任意波形。
驱动模块:RigolDG1020Z
from quatm.drivers.AWG.specific import RigolDG1020Z
fg = RigolDG1020Z(addr="USB0::...")
fg.set_frequency(80e6)
fg.set_amplitude(1.0)       # 1.0 Vpp
fg.enable_output(channel=1, enable=True)
fg.set_function(channel=1, function="SIN")

=== Agilent 信号源扩展内容 ===

  • run()

DDS AD9959

概述

AD9959 驱动封装 AD9959 评估板,通过 SPI 总线控制 4 个独立 DDS 通道,实现精密频率、幅度和相位控制。

⚙️ AD9959 评估板 4 通道 DDS
通信SPI
通道数4
频率分辨率32-bit (0.12 Hz @ 500 MHz 时钟)
相位分辨率14-bit
幅度控制10-bit DAC
广泛应用于冷原子/离子实验中的 AOM 驱动、边带生成和相干操控。
驱动模块:AD9959

初始化


dds = AD9959()

# 配置通道 0 — 冷却光 AOM
dds.set_frequency(0, 80e6)       # 80 MHz
dds.set_amplitude(0, 0.5)        # 50% 幅度
dds.set_phase(0, 0)              # 0° 相位

# 配置通道 1 — 再泵浦光 AOM(+0.1 MHz 差频)
dds.set_frequency(1, 80.1e6)
dds.set_amplitude(1, 0.3)

关键方法

方法说明
set_frequency(ch, freq_hz)设置通道频率 (Hz)
set_amplitude(ch, amp)设置通道幅度 (0–1 分数)
set_phase(ch, phase_deg)设置通道相位 (°)
update_all()一次性更新所有通道

设备配置

"aom_dds": {
    "type": "local",
    "module": "drivers.DDS",
    "class": "AD9959",
}

dds.set_amplitude(1, 0.5)


## 典型应用

| 应用 | 配置 |
|------|------|
| AOM 驱动 | 单通道固定频率 |
| 拉曼跃迁 | 双通道差频锁定 |
| 阱驱动 | 多通道相位控制 |
| 边带冷却 | 频率调制 |

## 替代驱动

还提供基于串口(AT 命令)接口的 AD9959 板替代驱动:

```python

Rigol DG1020Z

DG1020Z 双通道函数/任意波形发生器

⚙️ DG1020Z Rigol 函数发生器
通信VISA (USB/LAN)
通道数2
频率范围1 µHz – 25 MHz
幅度1 mVpp – 10 Vpp
采样率200 MSa/s
用于生成 AOM/EOM 驱动信号、调制波形和自定义任意波形。
驱动模块:RigolDG1020Z
from quatm.drivers.awg.specific import RigolDG1020Z

fg = RigolDG1020Z(addr="USB0::0x1AB1::0x0642::DG1ZA123456789::INSTR")
fg.set_frequency(80e6)     # 80 MHz
fg.set_amplitude(1.0)      # 1.0 Vpp
fg.enable_output(channel=1, enable=True)
fg.set_function(channel=1, function="SIN")

DP1116A 可编程直流电源

⚙️ DP1116A Rigol 直流电源
通信VISA
输出16V/10A 或 32V/5A
通道数1
分辨率1 mV / 1 mA
用于线圈电流控制、激光二极管驱动和电路板供电。
驱动模块:DP1116A
from quatm.drivers.rigol.power_supply import DP1116A

ps = DP1116A(addr="USB0::0x1AB1::0x0E11::DP1A123456789::INSTR")
ps.set_voltage(12.0)       # 12V
dc.set_current(0.5)        # 500 mA 限流
ps.enable_output(True)

示波器

Rigol DS 系列示波器兼容 Tektronix SCPI 指令集,通过 ITektronixScope 驱动控制:

from quatm.drivers.tektronix.base import ITektronixScope

scope = ITektronixScope(addr="USB0::0x1AB1::0x04CE::DS123456789::INSTR", nchannels=4)
scope.set_timebase(scale=1e-6)     # 1 µs/div
scope.set_vertical(channel=1, scale=0.5)  # 0.5 V/div
waveform = scope.acquire(channel=1)

关键方法(信号发生器)


Agilent / Keysight 33500 系列任意波形发生器

⚙️ 33500B / 33220A / 33250A Agilent/Keysight
通信VISA (USB/LAN/GPIB)
通道数1–2
频率最高 120 MHz (33500B)
分辨率14-bit
采样率250 MSa/s
波形正弦/方波/锯齿/脉冲/噪声/ARB
实验室标准信号源,用于 AOM 驱动、调制信号和参考时钟生成。
驱动模块:Agilent33500 / Agilent33220A
from quatm.drivers.awg.specific import Agilent33500

awg = Agilent33500(addr="USB0::0x0957::0x2C07::MY52801234::INSTR")

# 配置 80 MHz 正弦波
awg.set_function(channel=1, function="SIN")
awg.set_frequency(80e6)
awg.set_amplitude(1.0)      # 1 Vpp
awg.enable_output(channel=1, enable=True)

# 脉冲串模式 — 生成 N 个周期后自动关闭
awg.enable_burst(channel=1, ncycles=100)

支持型号

驱动类适用型号
Agilent3350033500B、33510B、33520B、33522B
Agilent33220A33220A、33250A
RigolDG1000DG1022、DG1032
RigolDG1020ZDG1022Z、DG1032Z

Instek AFG2000 / AFG2225 双通道

⚙️ AFG-2225 / AFG-2100 Instek
通信VISA
通道数1 (AFG2000) / 2 (AFG2225)
频率最高 25 MHz
采样率200 MSa/s
性价比高的双通道任意波形发生器。
驱动模块:InstekAFG2225 / InstekAFG2000
from quatm.drivers.awg.specific import InstekAFG2225

awg = InstekAFG2225(addr="USB0::...")
awg.set_frequency(10e6)
awg.set_amplitude(2.0)
awg.enable_output(channel=1, enable=True)
awg.enable_output(channel=2, enable=True)

Tektronix AFG1000 任意波形发生器

⚙️ AFG1022 / AFG1062 Tektronix
通信VISA
通道数2
频率最高 60 MHz (AFG1062)
采样率300 MSa/s
任意波形64 MB 存储
双通道高性能 AWG,支持大容量自定义波形。
驱动模块:TektronixAFG1000
from quatm.drivers.awg.specific import TektronixAFG1000

awg = TektronixAFG1000(addr="USB0::...")
awg.set_function(channel=1, function="ARB")
# 加载自定义波形...

Tektronix DPO/MSO 系列示波器

⚙️ DPO2000 / MSO4000 系列 Tektronix 示波器
通信VISA
带宽100 MHz – 1 GHz
通道数2–4
采样率最高 5 GS/s
通过 SCPI 自动化波形采集和参数测量。常用于实验调试和脉冲序列验证。
驱动模块:ITektronixScope
from quatm.drivers.tektronix.base import ITektronixScope

scope = ITektronixScope(
    addr="USB0::0x0699::0x0401::C012345::INSTR",
    nchannels=4
)

# 配置触发
scope.set_trigger(source=1, level=0.5, slope="POS")
scope.set_timebase(scale=1e-6)          # 1 µs/div
scope.set_vertical(channel=1, scale=0.1) # 0.1 V/div

# 采集波形
waveform = scope.acquire(channel=1)

Agilent E5071C 矢量网络分析仪

⚙️ E5071C Agilent VNA
通信VISA
频率9 kHz – 20 GHz
端口2–4
功能S 参数、阻抗、史密斯圆图
用于 RF 器件特性表征——滤波器、放大器、天线和传输线的 S 参数测量。
驱动模块:AgilentE5071C
from quatm.drivers.Agilent.vna import AgilentE5071C

vna = AgilentE5071C(addr="TCPIP::192.168.1.100::INSTR")
vna.set_frequency_range(start=1e6, stop=1e9, points=1001)
vna.set_if_bandwidth(100)       # 100 Hz IFBW
vna.set_averaging(count=10)

# 读取 S21 参数
freq, s21 = vna.read_S_parameters(parameter="S21")

PicoVNA 便携式矢量网络分析仪

⚙️ PicoVNA Pico Technology
通信TCP/SCPI (端口 5025)
频率300 kHz – 8.5 GHz
端口2
动态范围

100 dB

紧凑型 USB 控制 VNA,适合实验室桌面 RF 调试。
驱动模块:PicoVNA
from quatm.drivers.PicoTech.vna_scpi import PicoVNA

vna = PicoVNA(addr="localhost")  # 或 IP 地址
vna.set_frequency_range(start=10e6, stop=500e6)
s_params = vna.read_S_parameters(parameter="S21")

通用 SCPI 设备配置

"function_gen": {
    "type": "local",
    "module": "drivers.awg.specific",
    "class": "Agilent33500",
    "arguments": {"addr": "USB0::..."},
}

3.3 - 激光器与光学

Cobolt、Toptica、Sirah Matisse、M² Solstis、HighFinesse 波长计等激光器与光学测量驱动。

概述

Quatm 支持半导体激光器、泵浦激光器、可调谐环形激光器及光学测量仪器。激光器类设备通过串口控制;SCPI 仪器继承标准接口。


概述

Quatm 支持半导体激光器、泵浦激光器、可调谐环形激光器及光学测量仪器。激光器类设备通过串口和SCPI协议通信。


Hubner Cobolt MLD / DPL 单频激光器

⚙️ Cobolt 06-01 系列 Hubner Cobolt
通信串口 (115200 baud)
波长405/445/488/515/532/561/594/633/660/780/1064 nm
功率25–300 mW
调制模拟 + 数字 TTL (高达 5 MHz)
紧凑型 DPSS/半导体激光器,适合离子/原子冷却光、再泵浦光和荧光激发。
驱动模块:Cobolt
from quatm.drivers.Hubner.Cobolt import Cobolt

laser = Cobolt(conn="/dev/ttyUSB0")

# 开启激光
laser.set_autostart(True)
laser.set_power(50e-3)         # 50 mW

# 数字调制(TTL)
laser.set_digital_modulation(True)
laser.set_modulation_power(100e-3)  # 调制时的高功率

# 读取运行参数
hours = laser.get_operating_hours()
temp = laser.get_base_temperature()

Toptica iBeam 智能半导体激光器

⚙️ iBeam 系列 Toptica
通信串口 (115200 baud)
波长375–1550 nm
带内置控制器的智能激光头,支持自动电流/功率校准和状态诊断。
驱动模块:TopticaIBeam
from quatm.drivers.Toptica.ibeam import TopticaIBeam

laser = TopticaIBeam(conn="/dev/ttyUSB0")
laser.set_power(channel=0, power=10e-3)
laser.enable(channel=0, enable=True)

Laser Quantum Finesse 泵浦激光器

⚙️ Finesse Laser Quantum
通信串口 (19200 baud)
功率4–16 W (532 nm)
噪声< 0.1% RMS
应用钛宝石/染料激光器泵浦
超低噪声连续波 DPSS 激光器,用于泵浦 Sirah Matisse 等可调谐环形激光器。
驱动模块:Finesse
from quatm.drivers.LaserQuantum.base import Finesse

pump = Finesse(conn="/dev/ttyUSB0")
pump.set_power(10.0)           # 10 W
pump.enable(True)
actual_power = pump.get_power()

Lighthouse Photonics Sprout G

⚙️ Sprout G Lighthouse Photonics
通信串口 (19200 baud)
波长532 nm
功率6–18 W
噪声< 0.2% RMS
高功率 532 nm 固态泵浦激光器,适用于钛宝石激光器和光偶极阱。
驱动模块:SproutG
from quatm.drivers.LighthousePhotonics.base import SproutG

sprout = SproutG(conn="/dev/ttyUSB0")
sprout.set_power(15.0)
sprout.enable(True)

Sirah Matisse 可调谐环形激光器

⚙️ Matisse Sirah Lasertechnik
通信VISA 或 TCP/IP
波长范围可见光–近红外 (取决于染料/钛宝石)
线宽< 50 kHz (锁定)
调谐元件双折射滤波器 + 薄/厚标准具 + 压电
精密可调谐环形激光器系统。MatisseTuner 协调激光器与 HighFinesse 波长计,实现自动波长调谐和扫描拼接。
驱动模块:SirahMatisse / MatisseTuner
from quatm.drivers.Sirah.Matisse import SirahMatisse

matisse = SirahMatisse(addr="TCPIP::192.168.1.10::INSTR")

# 设置波长
matisse.set_birefringent_filter(wavelength=780.24)  # nm
matisse.set_thin_etalon(wavelength=780.24)
matisse.set_thick_etalon(wavelength=780.24)

# 压电扫描
matisse.set_piezo_voltage(50.0)   # 0–100 V
# 自动调谐(需配合波长计)
from quatm.drivers.Sirah.tuner import MatisseTuner

tuner = MatisseTuner(laser=matisse, wavemeter=wlm)
tuner.tune_to(wavelength=780.24)  # 自动搜索并锁定
tuner.scan(start=780.20, stop=780.30, speed=0.01)  # nm/s

M² Solstis 窄线宽可调谐激光器

⚙️ Solstis M² Lasers
通信TCP/IP JSON + WebSocket
波长范围700–1000 nm (钛宝石)
线宽< 50 kHz
功能标准具锁定、腔参考锁定、波长计反馈
全数字可调谐激光系统,通过 TCP/IP JSON 接口完全远程控制。支持 WebSocket 实时状态流。
驱动模块:Solstis (ICE Bloc)
from quatm.drivers.M2.solstis import Solstis

solstis = Solstis(addr="192.168.1.20", port=8080)

# 波长调谐
solstis.set_wavelength(780.24)
# 标准具锁定
solstis.lock_etalon()
# 太赫兹扫描(与 EMM 模块配合)
solstis.set_terahertz_scan(start_freq=0, stop_freq=100e9)

光功率计 & 波长计

Thorlabs PM100/PM400 光功率计

Thorlabs 光功率计详情见本页下方。

Ophir Vega 激光功率/能量计

⚙️ Vega Ophir
通信串口
探头热电堆/光电二极管/热释电
功率µW – kW
能量µJ – J
多功能激光测量仪,支持连续波功率和脉冲能量测量。
驱动模块:VegaPowerMeter
from quatm.drivers.Ophir.base import VegaPowerMeter

pm = VegaPowerMeter(conn="/dev/ttyUSB0")
power = pm.get_power()

HighFinesse WS6/WS7 精密波长计

⚙️ WS6 / WS7 HighFinesse
通信原生 wlmData.dll
精度2–200 MHz (取决于型号)
通道数1–8
测量速率最高 500 Hz
波长范围350–1120 nm
用于精密激光频率测量和反馈控制的 Fizeau 干涉仪波长计。多通道型号可同时监测多台激光器频率。
驱动模块:WLM
from quatm.drivers.HighFinesse.wlm import WLM

wlm = WLM(version=7, dll_path="C:\\wlm\\wlmData.dll")

# 读取通道 1 当前频率
freq = wlm.get_frequency(channel=1)    # THz
wavelength = wlm.get_wavelength(channel=1)  # nm

# 曝光控制(自动适应光强)
wlm.set_exposure(channel=1, mode="auto")

Thorlabs 光功率计

光功率计 GenericPM

⚙️ PM100 / PM400 系列 Thorlabs 功率计
通信VISA (USB)
支持探头光电二极管/热电堆/热释电
波长范围取决于探头
功率范围nW – W 级
通过 SCPI 命令与 Thorlabs 功率计表头通信,支持多种探头类型。
驱动模块:GenericPM
from quatm.drivers.thorlabs.misc import GenericPM

pm = GenericPM(addr="USB0::0x1313::0x8078::P1234567::INSTR")

# 设置工作波长(用于探头校准)
pm.set_wavelength(780.0)    # 780 nm

# 读取功率
power = pm.get_power()      # 返回当前功率 (W)

TLCamera 科学相机 ThorlabsTLCamera


Thorlabs 光功率计 PM100 / PM400

⚙️ PM100 / PM400 系列 Thorlabs 功率计
通信VISA (USB)
支持探头光电二极管/热电堆/热释电
波长范围取决于探头
功率范围nW – W 级
通过 SCPI 命令与 Thorlabs 功率计表头通信,支持多种探头类型。
驱动模块:GenericPM
from quatm.drivers.Thorlabs.misc import GenericPM
pm = GenericPM(addr="USB0::0x1313::0x8078::P1234567::INSTR")
pm.set_wavelength(780.0)    # 780 nm 校准
power = pm.get_power()      # 当前功率 (W)

3.4 - 运动与定位

PI 纳米定位台、Attocube、Newport Picomotor、Thorlabs APT 等精密运动与定位驱动。

概述

Quatm 支持从压电纳米定位到步进电机长行程的多种运动平台,统一 IMultiaxisStage 接口。


Physik Instrumente (PI) 压电纳米定位

概述

GenericPIController 封装 PI 通用控制器串口通信,通过 ASCII 命令集控制多种 PI 压电定位平台。

⚙️ PI 压电控制器 E-xxx 系列
通信串口 (RS232)
协议PI ASCII 命令集
轴数取决于控制器型号
精度亚纳米级
典型应用包括高 NA 物镜精密对焦、光纤耦合自动对准、干涉仪光路调节和光偶极阱束腰位置控制。
驱动模块:GenericPIController

初始化

from quatm.drivers.PhysikInstrumente.base import GenericPIController

# 串口连接
stage = GenericPIController(conn="/dev/ttyUSB0")

# 归零
stage.home(axis=0)

# 绝对定位(µm)
stage.move_to(axis=0, position=50.0)

# 相对移动
stage.move_by(axis=1, delta=10.0)

# 查询当前位置
pos = stage.get_position(axis=0)

关键方法

方法说明
home(axis)指定轴归零
move_to(axis, position)绝对定位 (µm)
move_by(axis, delta)相对移动 (µm)
get_position(axis)查询当前位置
stop(axis)紧急停止

设备配置

"objective_z": {
    "type": "local",
    "module": "drivers.PhysikInstrumente.base",
    "class": "GenericPIController",
    "arguments": {"conn": "/dev/ttyUSB0"},
}

## 使用示例

```python
# 在 Experiment 类中
self.pi_stage = self.get_device("pi_stage")

# 移动到指定位置 (μm)
self.pi_stage.move_absolute(x=50.0, y=25.0, z=10.0)

# 相对移动
self.pi_stage.move_relative(dx=1.0, dy=0.0, dz=0.0)

注意:压电平移台有行程限制,超出范围会触发硬件保护。使用前请查阅设备手册确认最大行程。


Thorlabs APT/Kinesis 位移台

KDC101 / K10CR1 系列

⚙️ KDC101 / K10CR1 / 滤光轮 Thorlabs APT/Kinesis
通信串口 (FTDI)
协议APT (二进制)
适用设备直流伺服电机、步进电机、滤光轮、快门
统一封装 Thorlabs APT 协议设备。
驱动模块:BasicKinesisDevice
from quatm.drivers.Thorlabs.kinesis import BasicKinesisDevice
stage = BasicKinesisDevice(conn="27200001")
stage.home()
stage.move_to(position=25.0)    # mm

Elliptec 压电谐振电机

⚙️ ELLx 系列 Thorlabs Elliptec
通信串口 (9600 baud)
行程取决于滑块
精度µm 级
紧凑型压电谐振电机,适合空间受限的光学调整架。
驱动模块:ElliptecMotor
from quatm.drivers.Thorlabs.elliptec import ElliptecMotor
motor = ElliptecMotor(conn="/dev/ttyUSB0", addrs=[0])
motor.move_to(axis=0, position=10.0)

电动滤光轮 FW102/FW212

from quatm.drivers.Thorlabs.serial import FW
fw = FW(conn="/dev/ttyUSB0")
fw.set_position(position=2)    # 切换到第 2 个滤光片位置

Physik Instrumente (PI)

概述

GenericPIController 封装 PI 通用控制器串口通信,通过 ASCII 命令集控制多种 PI 压电定位平台。

⚙️ PI 压电控制器 E-xxx 系列
通信串口 (RS232)
协议PI ASCII 命令集
轴数取决于控制器型号
精度亚纳米级
典型应用包括高 NA 物镜精密对焦、光纤耦合自动对准、干涉仪光路调节和光偶极阱束腰位置控制。
驱动模块:GenericPIController

初始化

from quatm.drivers.PhysikInstrumente.base import GenericPIController

# 串口连接
stage = GenericPIController(conn="/dev/ttyUSB0")

# 归零
stage.home(axis=0)

# 绝对定位(µm)
stage.move_to(axis=0, position=50.0)

# 相对移动
stage.move_by(axis=1, delta=10.0)

# 查询当前位置
pos = stage.get_position(axis=0)

关键方法

方法说明
home(axis)指定轴归零
move_to(axis, position)绝对定位 (µm)
move_by(axis, delta)相对移动 (µm)
get_position(axis)查询当前位置
stop(axis)紧急停止

设备配置

"objective_z": {
    "type": "local",
    "module": "drivers.PhysikInstrumente.base",
    "class": "GenericPIController",
    "arguments": {"conn": "/dev/ttyUSB0"},
}

## 使用示例

```python
# 在 Experiment 类中
self.pi_stage = self.get_device("pi_stage")

# 移动到指定位置 (μm)
self.pi_stage.move_absolute(x=50.0, y=25.0, z=10.0)

# 相对移动
self.pi_stage.move_relative(dx=1.0, dy=0.0, dz=0.0)

注意:压电平移台有行程限制,超出范围会触发硬件保护。使用前请查阅设备手册确认最大行程。


Thorlabs 位移台与电机

Quatm 支持多类 Thorlabs 设备,包含位移台、光学测量仪器与相机。

APT/Kinesis 位移台 BasicKinesisDevice

⚙️ KDC101 / K10CR1 / 滤光轮 Thorlabs APT/Kinesis
通信串口 (FTDI)
协议APT (二进制)
适用设备直流伺服电机、步进电机、滤光轮、快门
统一封装 Thorlabs APT 协议设备,通过串口(FTDI 芯片)通信。
驱动模块:BasicKinesisDevice
from quatm.drivers.thorlabs.kinesis import BasicKinesisDevice

# 连接指定序列号的设备
stage = BasicKinesisDevice(conn="27200001")  # 序列号

# 归零
stage.home()

# 绝对定位(mm)
stage.move_to(position=25.0)

# 读取当前位置
pos = stage.get_position()

Elliptec 压电谐振电机 ElliptecMotor

⚙️ ELLx 系列 Thorlabs Elliptec
通信串口 (9600 baud)
行程取决于滑块长度
精度µm 级
真空兼容可选
紧凑型压电谐振电机,适合空间受限的光学调整架。
驱动模块:ElliptecMotor
from quatm.drivers.thorlabs.elliptec import ElliptecMotor

motor = ElliptecMotor(conn="/dev/ttyUSB0", addrs=[0])
motor.move_to(axis=0, position=10.0)   # mm

电动滤光轮

from quatm.drivers.thorlabs.serial import FW

fw = FW(conn="/dev/ttyUSB0")          # FW102 / FW212
fw.set_position(position=2)            # 切换到第 2 个滤光片位置

KDC101 电机平移台

通过 .NET SDK 控制 Thorlabs KDC101/T-Cube 系列电机平移台。

from quatm.drivers.thorlabs.kdc101 import KDC101

stage = KDC101("26001234")   # 序列号
stage.home()                  # 回零
stage.move_absolute(10.0)     # 移动到 10.0 mm
pos = stage.get_position()    # 读取当前位置
功能说明
回零自动寻找限位开关
绝对移动移动到指定位置 (mm)
相对移动相对当前位置移动
位置读取实时读取当前位置

##概述

Quatm 支持从压电纳米定位到步进电机长行程的多种运动平台。所有平台继承 io.stage 接口,提供统一的 move_to / get_position / home API。


Attocube ANC300 / ANC350 纳米定位

⚙️ ANC300 Attocube
通信TCP/IP (端口 7230)
轴数最多 7 轴
行程mm 级
精度nm 级
适用低温 / 真空
模块化纳米定位控制器,通过 TCP/IP 远程控制。广泛用于低温恒温器内物镜和样品的精确定位。
驱动模块:ANC300
from quatm.drivers.Attocube.anc300 import ANC300

anc = ANC300(conn=("192.168.1.30", 7230))

# 归零
anc.home(axis=0)

# 纳米级步进
anc.move_by(axis=0, delta=0.1)  # 100 nm

# 连续扫描模式
anc.set_continuous_mode(axis=1, enable=True)
anc.set_continuous_speed(axis=1, speed=100.0)  # nm/s
⚙️ ANC350 Attocube (USB)
通信USB HID (PyUSB)
轴数最多 3 轴
控制USB 直接连接
USB 版本,适合桌面应用。
驱动模块:ANC350
from quatm.drivers.Attocube.anc350 import ANC350

anc = ANC350(conn=0)  # 第一台 USB 设备
anc.move_to(axis=0, position=50.0)

Newport Picomotor 8742 4 轴控制器

⚙️ Picomotor 8742 Newport
通信USB (PyUSB) 或 TCP/IP Telnet (端口 23)
轴数4
步长< 30 nm
真空兼容可选
压电惯性电机控制器,支持 USB 直连或网络控制。真空兼容型号可直接用于真空腔内的光学元件调整。
驱动模块:Picomotor8742
from quatm.drivers.Newport.picomotor import Picomotor8742

# USB 连接
pico = Picomotor8742(conn=0)

# 或 TCP/IP
pico = Picomotor8742(conn="192.168.1.40", multiaddr=(0, 1))

pico.move_to(axis=0, position=5.0)  # mm
pico.home(axis=0)

SmarAct MCS2 / SCU3D 高精度定位

⚙️ MCS2 SmarAct
通信原生 MCS2 SDK
轴数最多 18 轴
精度nm 级
速度最高 20 mm/s
真空/低温可选模块
模块化高精度定位系统,支持多轴协调运动和复杂轨迹。
驱动模块:MCS2
from quatm.drivers.SmarAct.MCS2 import MCS2

mcs = MCS2(locator="usb:sn:12345678")
mcs.move_to(axis=0, position=10.0)  # mm
mcs.get_position(axis=0)
⚙️ SCU3D SmarAct 3 轴
通信SCU3DControl SDK
轴数3
一体化 3 轴控制器,适合紧凑空间。
驱动模块:SCU3D
from quatm.drivers.SmarAct.scu3d import SCU3D

scu = SCU3D(idx=0)
scu.move_to(axis=1, position=25.0)

Standa 8SMC 步进电机控制器

⚙️ 8SMC4 / 8SMC5 Standa
通信串口 (115200 baud)
轴数1–4
步进分辨率取决于电机/丝杠
应用长行程位移台、旋转台
经济型步进电机控制器,适合光学平台上的长行程粗定位。
驱动模块:Standa8SMC
from quatm.drivers.standa.base import Standa8SMC

stage = Standa8SMC(conn="/dev/ttyUSB0")
stage.move_to(position=50.0)  # mm
stage.home()

Arcus Performax 多轴步进控制

⚙️ Performax Arcus Technology
通信USB (DLL) 或 RS485 串口
轴数最多 4 轴
功能加减速曲线、限位检测
高性能步进电机控制器,提供平滑的 S 曲线加减速。
驱动模块:GenericPerformaxStage
from quatm.drivers.arcus.performax import GenericPerformaxStage

stage = GenericPerformaxStage(idx=0, conn="USB")
stage.move_to(axis=0, position=100.0)
stage.set_acceleration(axis=0, accel=50.0)   # mm/s²

Trinamic TMCM-1110 一体化步进电机

⚙️ TMCM-1110 Trinamic
通信串口 (9600 baud, TMCL 协议)
功能StallGuard 失速检测、CoolStep 节能
一体化步进电机模块,内置控制器和驱动器。适合简单旋转/平移任务和光路快门。
驱动模块:TMCM1110
from quatm.drivers.trinamic.base import TMCM1110

motor = TMCM1110(conn="/dev/ttyUSB0")
motor.move_to(position=180.0)  # 旋转 (°)
motor.set_velocity(500.0)      # °/s

Thorlabs Elliptec 压电谐振电机

Thorlabs 位移台详情见本页下方。


通用运动平台配置

"objective_z": {
    "type": "local",
    "module": "drivers.Attocube.anc300",
    "class": "ANC300",
    "arguments": {"conn": ("192.168.1.30", 7230)},
}

3.5 - DAQ 与电源

NI DAQ、Rigol/EA 电源、Keithley/Voltcraft 万用表、示波器等数据采集与电学测量驱动。

概述

数据采集和电源设备是实验自动化的基础设施。Quatm 提供统一的 NI-DAQmx 封装和 SCPI/Modbus 仪器驱动。


Rigol DP1116A 可编程直流电源

⚙️ DP1116A Rigol 直流电源
通信VISA
输出16V/10A 或 32V/5A
通道数1
分辨率1 mV / 1 mA
用于线圈电流控制、激光二极管驱动和电路板供电。
驱动模块:DP1116A
from quatm.drivers.rigol.power_supply import DP1116A

ps = DP1116A(addr="USB0::0x1AB1::0x0E11::DP1A123456789::INSTR")
ps.set_voltage(12.0)       # 12V
dc.set_current(0.5)        # 500 mA 限流
ps.enable_output(True)

Rigol DP932 可编程直流电源

用于为各种实验室设备提供可编程直流电源。

from quatm.drivers.rigol.dp932 import RigolDP932

psu = RigolDP932("USB0::...")
psu.set_voltage(1, 5.0)     # 通道 1: 5.0 V
psu.set_current(1, 1.0)     # 通道 1: 1.0 A 限流
psu.output_on(1)

NI-SWITCH 矩阵/多路复用开关

⚙️ PXI-25xx / SCXI-11xx 系列 NI-SWITCH
通信NI-SWITCH API
拓扑矩阵/多路复用/通用
通道取决于模块
切换速度ms 级
最大电压300 V (取决于模块)
NI 开关模块通过 niswitch Python API 控制。适用于实验中的信号路由切换、校准多路复用和线圈极性翻转。
驱动模块:ni_switch
from quatm.drivers.NI.ni_switch import NISwitch

sw = NISwitch(resource_name="PXI1Slot2")
sw.connect(channel1="ch0", channel2="com0")
sw.disconnect(channel1="ch0", channel2="com0")
all_relays = sw.get_relay_count()

NI-Digital 数字波形发生器/分析仪

⚙️ PXIe-657x / PXIe-655x 系列 NI-Digital
通信NI-Digital Pattern API
通道32–128
速率最高 200 MHz
电压1.2–5.5 V (可编程)
功能Pattern 生成/采集、PMU 参数测量
NI 数字波形仪器通过 nidigital Python API 控制。生成和采集高速数字波形,适用于自定义 TTL 时序协议和芯片级数字测试。
驱动模块:ni_digital
from quatm.drivers.NI.ni_digital import NIDigital

dig = NIDigital(resource_name="PXI1Slot3")
dig.configure_voltage_levels(voltage=3.3)
pattern = [0b10101010] * 100  # 100 周期数字波形
dig.burst_pattern(pattern, frequency=10e6)

NI-DAQmx 多功能数据采集卡

⚙️ PCIe-63xx / USB-63xx / PXI 系列 NI DAQ
通信NI-DAQmx
模拟输入16-bit, 最高 2 MS/s
模拟输出16-bit
数字 I/OTTL, 最高 10 MHz
计数器2–4 通道
通用多功能数据采集卡,用于模拟信号记录、时序数字 I/O 和光子计数。
驱动模块:NIDAQ
from quatm.drivers.NI.daq import NIDAQ

daq = NIDAQ(
    dev_name="Dev1",
    rate=100_000,         # 100 kS/s
    buffer_size=10_000,
)

# 模拟输入(连续采集)
daq.configure_ai(channels=["ai0", "ai1"], voltage_range=(-10, 10))
daq.start_ai()
data = daq.read_ai(samples=1000)

# 模拟输出
daq.configure_ao(channels=["ao0"], voltage_range=(0, 5))
daq.write_ao(channel="ao0", voltage=3.3)

# 数字 I/O
daq.configure_di(lines=["port0/line0"])
daq.configure_do(lines=["port0/line1"])
daq.write_do(line="port0/line1", value=True)

# 计数器(光子计数 / 频率测量)
daq.configure_counter(
    counter="ctr0",
    mode="edge_count",
    source="PFI0",
)
counts = daq.read_counter("ctr0")

Conrad 继电器板控制器

⚙️ Relay Board Conrad
通信串口 (19200 baud, 二进制协议)
通道每板 8 继电器,支持菊花链
触点AC/DC 切换
经济型多通道继电器控制器,适合粗粒度开关控制:磁阱线圈极性切换、设备供电开关、激光快门控制。
驱动模块:RelayBoard
from quatm.drivers.Conrad.base import RelayBoard

# 单板
rb = RelayBoard(conn="/dev/ttyUSB0", start_addr=0)
rb.set_relay(relay=0, state=True)   # 闭合第 1 个继电器
rb.set_relay(relay=3, state=False)  # 断开第 4 个继电器

# 字节写入(同时控制 8 路)
rb.write_byte(0b10101010)

Elektro Automatik PS2000B 高功率电源

⚙️ PS2000B 系列 Elektro Automatik
通信串口 (115200 baud)
功率640 W – 15 kW (取决于型号)
电压最高 1500 V
电流最高 510 A
功能恒压/恒流/恒功率模式
高功率可编程直流电源,用于磁阱线圈大电流驱动和 Feshbach 共振磁场线圈供电。
驱动模块:PS2000B
from quatm.drivers.ElektroAutomatik.base import PS2000B

ps = PS2000B(conn="/dev/ttyUSB0", remote_mode=True)

# 恒流模式 — 磁场线圈
ps.set_current(50.0)      # 50 A
ps.set_voltage_limit(20.0) # 20 V 限压
ps.enable_output(True)

# 读取实际值
actual_v = ps.get_voltage()
actual_i = ps.get_current()

Keithley 2110 台式数字万用表

⚙️ 2110 Keithley
通信VISA (USB/LAN)
功能DCV/ACV/DCI/ACI/电阻/电容/频率/温度
精度5½ 位
采样率最高 50 kS/s
精密台式万用表,用于电学特性表征和传感器校准。
驱动模块:Keithley2110
from quatm.drivers.Keithley.multimeter import Keithley2110

dmm = Keithley2110(addr="USB0::0x05E6::0x2110::1234567::INSTR")

# DC 电压测量
voltage = dmm.measure_voltage(range="10V")

# 4 线电阻测量
resistance = dmm.measure_resistance_4wire(range="100Ω")

# 温度(热电偶)
temp = dmm.measure_temperature(tc_type="K")

Voltcraft VC7055 双通道台式万用表

⚙️ VC7055 Voltcraft
通信串口 (115200 baud, SCPI)
通道数2
功能DCV/ACV/DCI/ACI/电阻/频率/电容
蓝牙可选 (VC7055BT)
双通道台式万用表,内置蓝牙的 BT 型号支持无线数据采集。
驱动模块:VC7055
from quatm.drivers.Voltcraft.multimeter import VC7055

dmm = VC7055(addr="/dev/ttyUSB0")

# 双通道同时测量
v1 = dmm.measure_voltage(channel=1)
v2 = dmm.measure_voltage(channel=2)

设备配置

"daq": {
    "type": "local",
    "module": "drivers.NI.daq",
    "class": "NIDAQ",
    "arguments": {"dev_name": "Dev1", "rate": 100_000},
},
"coil_ps": {
    "type": "local",
    "module": "drivers.ElektroAutomatik.base",
    "class": "PS2000B",
    "arguments": {"conn": "/dev/ttyUSB0", "remote_mode": True},
},
"dmm": {
    "type": "local",
    "module": "drivers.Keithley.multimeter",
    "class": "Keithley2110",
    "arguments": {"addr": "USB0::..."},
},

3.6 - 环境监测

Lakeshore、Cryocon、Pfeiffer、Leybold 等温度、真空、低温监测驱动。

概述

实验室环境监测是量子实验稳定性的基础。Quatm 内置温度、真空和低温液位监测驱动,支持实时数据记录和异常告警。


Lakeshore 218 温度监测器

⚙️ 218 Lakeshore
通信串口 (9600 baud, 7E1)
通道数8
传感器二极管 (Si/GaAs)、铂电阻 (Pt100/1000)、Cernox、RuO₂
温度1.4 K – 1500 K (取决于传感器)
低温物理实验标准温度监测器。8 通道独立配置,支持二极管、电阻温度计和 Cernox 薄膜电阻。
驱动模块:Lakeshore218
from quatm.drivers.Lakeshore.base import Lakeshore218

ls = Lakeshore218(conn="/dev/ttyUSB0")

# 配置通道 1 为硅二极管
ls.set_sensor_type(channel=1, sensor_type="DT-670")

# 读取温度
temp = ls.get_temperature(channel=1)   # Kelvin
all_temps = ls.get_all_temperatures()  # 全部 8 通道

# 读取传感器原始值(电压/电阻)
raw = ls.get_reading(channel=1)

Cryocon 12C / 14C / 18C 温度控制器

⚙️ 12C / 14C / 18C Cryocon
通信串口 (9600 baud)
通道数2–4 (取决于型号)
支持传感器二极管/Pt/Cernox
带 PID 加热输出的低温温度控制器,用于精密温度稳定。
驱动模块:Cryocon1x
from quatm.drivers.Cryocon.base import Cryocon1x

cryo = Cryocon1x(conn="/dev/ttyUSB0", nchannels=4)

# 读取通道 1 温度
temp = cryo.get_temperature(channel=1)

# PID 设定点
cryo.set_setpoint(channel=1, temperature=4.2)  # 4.2 K
cryo.set_heater_range(channel=1, range="low")
cryo.enable_heater(channel=1, enable=True)

Lumel RE72 · Omron E5_C 温控器

⚙️ RE72 / E5_C Lumel / Omron
通信RS485 Modbus RTU
功能PID 自整定、斜坡/保持程序
应用光学平台温度稳定、激光晶体温控
工业级 PID 温度控制器,通过 Modbus RTU 协议通信。常用于激光器晶体温度控制和光学平台环境温控。
驱动模块:LumelRE72Controller / OmronE5xCController
from quatm.drivers.Lumel.base import LumelRE72Controller
from quatm.drivers.Omron.base import OmronE5xCController

# Lumel RE72
lumel = LumelRE72Controller(conn="/dev/ttyUSB1", daddr=1)
temp = lumel.get_temperature()
lumel.set_setpoint(25.0)

# Omron E5_C
omron = OmronE5xCController(conn="/dev/ttyUSB1", daddr=2)
omron.set_setpoint(30.0)
omron.enable_heater(True)

Pfeiffer TPG2xx 高真空计

⚙️ TPG2xx 系列 Pfeiffer Vacuum
通信串口 (9600 baud)
通道数2
支持规管Pirani / Cold Cathode / 复合规
量程大气压 – 10⁻¹⁰ mbar
紧凑型双通道真空计控制器,同时支持粗真空(Pirani)和超高真空(冷阴极)规管。
驱动模块:TPG2xx
from quatm.drivers.Pfeiffer.base import TPG2xx

tpg = TPG2xx(conn="/dev/ttyUSB0")

# 读取两路压力
p1 = tpg.get_pressure(channel=1)  # mbar
p2 = tpg.get_pressure(channel=2)

# 规管类型识别
gauge_type = tpg.get_gauge_type(channel=1)

Leybold ITR 宽量程真空计

⚙️ ITR 系列 Leybold
通信串口 (9600 baud, 二进制协议)
量程大气压 – 5×10⁻¹⁰ mbar
输出持续压力数据流
宽量程皮拉尼/冷阴极复合真空计,主动推送压力数据。
驱动模块:GenericITR
from quatm.drivers.Leybold.base import GenericITR

itr = GenericITR(conn="/dev/ttyUSB0")
pressure = itr.get_pressure()  # mbar

Agilent XGS-600 多通道真空控制器

⚙️ XGS-600 Agilent
通信串口 (RS485)
通道数最多 6 路规管
规管类型Hot Filament / Cold Cathode / Pirani / Convection
大型真空系统的多规管控制器,通过 RS485 串联地址访问。
驱动模块:XGS600
from quatm.drivers.Agilent.pressure import XGS600

xgs = XGS600(conn="/dev/ttyUSB0", addr=1)

# 读取所有通道压力
pressures = xgs.get_all_pressures()
p1 = xgs.get_pressure(channel=1)

低温液位监测

Cryomagnetics LM500 液氦/液氮液位计

⚙️ LM500 / LM510 Cryomagnetics
通信串口 (9600 baud)
功能He/N₂ 液位、温度、样品室温度
通道1–2 液位 + 4 温度
超导磁体杜瓦液位监测标准设备。同时监测液氦/液氮液位和样品室温度。
驱动模块:LM500
from quatm.drivers.Cryomagnetics.base import LM500

lm = LM500(conn="/dev/ttyUSB0")

helium_level = lm.get_helium_level()    # %
nitrogen_level = lm.get_nitrogen_level() # %
sample_temp = lm.get_temperature()

American Magnetics 1700 液位监测器

⚙️ 1700 American Magnetics
通信串口或 TCP/IP (端口 7180)
功能He / N₂ 液位、继电器控制
支持串口和网络双接口的液位监测器。
驱动模块:AM1700
from quatm.drivers.AmericanMagnetics.base import AM1700

am = AM1700(conn="192.168.1.50")  # TCP/IP
# 或串口: am = AM1700(conn="/dev/ttyUSB0")
level = am.get_helium_level()

通用环境监测配置

"chamber_pressure": {
    "type": "local",
    "module": "drivers.Pfeiffer.base",
    "class": "TPG2xx",
    "arguments": {"conn": "/dev/ttyUSB0"},
},
"cryo_temp": {
    "type": "local",
    "module": "drivers.Lakeshore.base",
    "class": "Lakeshore218",
    "arguments": {"conn": "/dev/ttyUSB1"},
},

3.7 - 实验控制与其他

ADwin、NI-FPGA、Red Pitaya 等 FPGA 控制器与辅助设备驱动,覆盖从纳秒级实时时序到通用开关逻辑的全谱实验控制需求。

概述

FPGA 控制器和辅助设备是实验自动化的重要组成——从纳秒级实时时序到继电器开关,Quatm 提供统一的控制接口。目前已支持 ADwin、NI-FPGA、Red Pitaya 等多个品牌。


ADwin

概述

ADwin 是 Jaeger Computergesteuerte Messtechnik 公司的实时控制器系列,基于 FPGA/DSP 架构,独立于 PC 操作系统执行实时任务。

⚙️ ADwin Gold II / Pro II
通信PCI / USB
处理器DSP + FPGA
时序精度纳秒级
模拟输入16-bit
数字 I/OTTL (5V)
内存32 MB DRAM
运行 ADbasic 编译的实时进程,与 Quatm 通过共享内存或寄存器读写通信。典型应用包括激光冷却时序、MOT 磁场开关和光子计数采集。
驱动模块:ADwin

工作原理

PC (Quatm)                    ADwin (实时)
┌──────────┐    PCI/USB    ┌──────────────┐
│ experiment│ ←──────────→ │ ADbasic 进程   │
│   .py     │  Par/Data    │ 纳秒时序 + 采集 │
└──────────┘               └──────────────┘

Quatm 实验脚本通过 ADwin 驱动读写参数和数据数组,与 ADwin 上运行的 ADbasic 进程交互。时序关键部分在 ADwin 硬件上执行,Python 侧负责参数设置和结果读取。

初始化

from quatm.drivers.adwin import ADwin

# 连接 ADwin(PCI 总线)
adw = ADwin(device_number=1)

# 加载并启动 ADbasic 进程
adw.load_process("experiment_sequence.TB1")
adw.start_process()

# 设置实验参数
adw.set_par(1, 100_000)     # Par_1 = 100 µs 冷却时间
adw.set_par(2, 50)          # Par_2 = 50 次循环
adw.set_par(3, 10_000)      # Par_3 = 10 ms 探测时间

# 启动一次实验序列(ADbasic 中通过事件触发)
adw.trigger()

# 读取采集数据
photons = adw.get_data(1, data_length=1000)  # 从 Data_1 读取光子计数

关键方法

方法说明
load_process(binary_path)加载 ADbasic 编译的二进制进程
start_process()启动已加载的进程
stop_process()停止运行中的进程
set_par(index, value)写入整型参数(1–80)
set_fpar(index, value)写入浮点参数(1–80)
get_par(index)读取整型参数
get_data(index, data_length)读取数据数组(1–200)
set_data(index, values)写入数据数组
trigger()发送软件触发事件

典型 ADbasic 进程结构

' ADbasic 代码片段 — 实验时序
Init:
  Par_1 = 100000   ' 冷却时间 (µs)
  Par_2 = 50       ' 循环次数
Event:
  For i = 1 To Par_2
    P2_DAC(1, 5000)   ' 设置 AOM 功率
    P2_DAC(2, 800)    ' 设置磁场
    ' ... 等待、采集、切换 ...
  Next i

设备配置

"adwin": {
    "type": "local",
    "module": "quatm.drivers.adwin",
    "class": "ADwin",
    "arguments": {"device_number": 1},
}

Exception:

  • quatm.drivers.adwin.adwin.AdWinDriverError(message)

    class quatm.drivers.adwin.adwin.AdWinDriverError(Exception):
        pass
    

quatm.drivers.adwin.client module

Class:

  • quatm.drivers.adwin.client.AdWinClient(experiment, simulating=None)

    class quatm.drivers.adwin.client.AdWinClient(object):
        def filter_cmdlist(self, combinetime=1e-08):
            pass
    
        def push(self, time, command, value, combinetime=1e-09):
            pass
    
        def start_realtime(self, processortime=0, repetitions=1):
            pass
    
        def stop(self):
            pass
    

quatm.drivers.adwin.units module


NI-FPGA LabVIEW FPGA 模块化仪器

⚙️ PXIe-78xxR / PCIe-78xxR 系列 NI-FPGA
通信NI-FPGA Interface Python API
FPGAXilinx Kintex/Virtex
数字 I/O最高 1 Gb/s
模拟 I/O最高 3.2 GS/s
编程LabVIEW FPGA + Python 运行时控制
通过 nifpga Python API 在运行时控制 LabVIEW FPGA 位流。适合需要极高吞吐量和确定性时序的自定义数字信号处理。
驱动模块:ni_fpga
from quatm.drivers.NI.ni_fpga import NIFPGA

fpga = NIFPGA(resource_name="RIO0", bitfile="custom_logic.lvbitx")
fpga.run()
fpga.write_control("pulse_width", 100)        # ns
fpga.write_control("trigger_delay", 50)
fpga.read_indicator("photon_count")

Conrad 继电器板

⚙️ Relay Board Conrad
通信串口 (19200 baud)
通道8 继电器/板
支持菊花链扩展
经济型多通道继电器控制器,适合磁阱线圈极性切换、设备供电开关和激光快门控制。
驱动模块:RelayBoard
from quatm.drivers.Conrad.base import RelayBoard

rb = RelayBoard(conn="/dev/ttyUSB0", start_addr=0)
rb.set_relay(relay=0, state=True)
rb.set_relay(relay=3, state=False)
rb.write_byte(0b10101010)

4 - 数据与分析

Quatm 数据管理架构、实时监控、图像处理与分析工具的完整文档。

quatm.analysis package

Submodules

quatm.analysis.bright_spots 模块

检测图像中的亮斑(如离子)。使用 skimage.features.blob_dog 进行亮斑检测。

输入:

  • 图像流

输出:

  • 图像流:
    • np.array:包含亮斑位置掩码
    • dict:检测到的亮斑数量 N_bright
  • Datastream:
    • bloblist: the locations of the bright spots
    • dict: N_bright the number of bright spots detected

Properties:

  • imagestreams ([str]): Input streams
  • max_sigma (float): Parameter from blob_dog
  • threshold (float): Parameter from blob_dog

Hint: 将输出流用作图像监视器中的掩码。

class quatm.analysis.bright_spots.BrightSpots(name)

Bases: object

run()

quatm.analysis.bright_spots.main_run(name)

quatm.analysis.crashit module

模拟分析程序崩溃场景以测试容错。

quatm.analysis.gaussfit module

对数据集执行一维高斯拟合。

Fit function: [ f(x) = \frac{A_0}{\sqrt{2\pi}\sigma} e^{\frac{-(x-\mu)^2}{2\sigma^2}} + C ]

Output: 输出为包含拟合结果字典和拟合曲线二维数组的数据流。

Fit parameter nomenclature:

  • A0: ( A_0 )
  • sigma: ( \sigma )
  • pos: ( \mu )
  • offset: ( C )
  • height: ( \frac{A_0}{\sqrt{2\pi}\sigma} )

In older versions some of the parameters were named differently:

  • area: ( A_0 )
  • height: ( A_0 )

Format of the input datastream: The fit can handle two types of data:

  • 1D numpy.array (data.ndim == 1): the y-values are taken from the data, and the x values are a linear spaced index from 0 to ny.
  • 2D numpy.array:
    • x = data[0]
    • y = data[1]

Properties controlling the program:

  • datastreams: list of input datastreams

class quatm.analysis.gaussfit.Gaussfit(name)

Bases: object

run()

quatm.analysis.gaussfit.main_run(name)

quatm.analysis.imagedivider module

Handle absorption imaging data. According to Beer’s Law, light travelling through an atomic cloud is attenuated by:

[ I = I_0 e^{-n(x,y)\sigma} ]

where ( I_0 ) is the intensity before the cloud (Imaging beam without atoms) and ( I ) is the attenuated intensity (Image with atoms), ( \sigma ) is the absorption cross section, and ( n(x,y) ) is the column density of the atoms. Transforming this equation allows us to determine the column density of the atoms from the import two images.

[ n(x,y) = \frac{ln(I_0/I)}{\sigma} ]

where ( \sigma ) is given by:

[ N_{atoms} = \frac{ln(I_0/I)}{\frac{\sigma_0}{1+(2\Delta/\Gamma)^2}} ]

where effscale rescales the value from atoms per ( m^2 ) to atoms per pixel.

[ \sigma_0 = \frac{\hbar\omega\Gamma}{2 I_{sat}/C_2} ]

where ( \omega ) is the angular frequency of the laser, ( \Gamma ) is the linewidth of the transition in angular frequencies, ( I_{sat} ) is the saturation intensity in SI units, and ( C_2 ) is the Clebsh-Gordon coefficient for the dipole transition.

Properties:

  • imagestreams: input datastreams
  • imageWithAtoms: index of the image containing the image data with atoms (0 being the first image in each run)
  • imageWithoutAtoms: the image containing the image without atoms
  • absorptionCrossection: defaults to ( \sigma_0 )
  • detuning_rad: detuning of the imaging laser from resonance
  • linewidth_rad: linewidth of the transition

class quatm.analysis.imagedivider.ImageSlice(name)

Bases: object

  • C_2 = 0.6666666666666666
  • gamma = 36897377.3978814
  • h_bar = 1.0545716346179718e-34
  • isat = 25.4
  • omega = 2807325165778985.0
run()
  • sig0 = 1.4335384024006802e-13

quatm.analysis.imagedivider.main_run(name)

quatm.analysis.imageselector module

使用 imgindex 从流中每次选取单张图像。

Input:

  • One image stream

Output:

  • Imagestream: the selected image

Properties:

  • imagestreams: ([str]) input image streams
  • SelectedImage: (int) the number of the image to be selected counting from 0.

class quatm.analysis.imageselector.ImageSlice(name)

Bases: object

run()

quatm.analysis.imageselector.main_run(name)

quatm.analysis.imageslice module

从图像流中创建线性轨迹和子区域。

![Imageslice]

Input:

  • Imagestream

Output:

  • colsum_ (datastream): summation in the direction of columns (use only row that lie within the region of interest. (gray area))
  • rowsum_ (datastream): summation along rows
  • colsumcut_, rowsumcut_: use only data within the region of interest
  • colint, rowint, colintcut, rowintcut: Perform numeric integration (which means the sum is multiplied by the metric pixel size)
  • (imagestream): send the image within the ROI

Properties:

  • cutimg: (bool) send the image inside the ROI
  • colsum: send the column sum
  • rowsum: send the sum over the rows
  • colsumcut, rowsumcut: (bool) send the corresponding data restricted to the region of interest
  • colint, rowint, colintcut, rowintcut: similar to the sum version but taking into account the scale. Therefore these versions can be treated as integrals

class quatm.analysis.imageslice.ImageSlice(name)

Bases: object

run()

quatm.analysis.imageslice.main_run(name)

4.1 - 2D 高斯拟合

astropy 实时二维高斯拟合——检测 ROI,输出参数和轮廓线。

概述

TwoDGaussFit 对图像流执行实时二维高斯拟合(Gaussian2D + Const2D),输出中心坐标、宽度和振幅。

from quatm.analysis.TwoDGaussFit import TwoDGaussFit

fitter = TwoDGaussFit(props=props, image_stream="andor")
fitter.run()
# 输出: x0, y0, sigma_x, sigma_y, amplitude, offset

4.2 - 1D 高斯拟合

Cython 加速一维高斯拟合——输出位置、宽度、幅度和 3D 峰值密度。

概述

Gaussfit 对一维数据流执行 Cython 优化高斯拟合。输出 A0、sigma、pos、offset、waist 和三维峰值密度。

from quatm.analysis.gaussfit import Gaussfit

gf = Gaussfit(props=props, data_stream="pmt")
gf.run()
# 输出: pos, sigma, A0, offset, waist, peak_density_3D

4.3 - 表格组件

table_parameterItemtable_parameter 类扩展了 pyqtgraph 参数树的功能,使其能够以表格形式显示和编辑 NumPy 记录数组。通过注册自定义参数类型,这些类可以轻松地集成到现有的 pyqtgraph 应用程序中,提供灵活且强大的数据编辑功能。

概述

这个代码定义了一个用于编辑 NumPy 记录数组的自定义参数类型 table_parameter,并在 PyQt 环境中实现了一个表格小部件,用于显示和编辑记录数组的数据。

table_parameterItem

table_parameterItem 继承自 pTypes.WidgetParameterItem,是一个用于编辑 NumPy 记录数组的表格小部件。

主要方法

  • __init__(self, param, depth)

    • 初始化参数项,并隐藏小部件。
  • makeWidget(self)

    • 创建一个表格小部件 (QTableWidget)。
    • 获取初始值,并根据值的结构设置表格的行列数和标题。
    • 连接信号和槽,以便在表格内容更改时触发相应的操作。
  • value(self)

    • 获取表格当前的值,并返回一个 NumPy 记录数组。
    • 尝试从表格中读取数据并填充到 NumPy 数组中,如果失败则返回初始值。
  • setValue(self, arr)

    • 设置表格的值。
    • 根据提供的 NumPy 数组填充表格的每个单元格。
  • valueChanged(self, param, val, force=False)

    • 当参数值更改时调用,更新表格的显示内容。
    • 断开信号连接,更新表格值后重新连接信号,确保信号处理不会重复触发。

table_parameter

table_parameter 继承自 Parameter,用于管理和存储表格参数项的值。

主要方法

  • __init__(self, **opts)

    • 初始化参数项,传递其他参数选项。
  • setValue(self, value, blockSignal=None)

    • 设置参数项的值,并返回实际设置的值。
    • 在设置值之前断开信号连接,避免信号重复触发,设置完毕后重新连接信号。
  • valueIsDefault(self)

    • 判断当前值是否等于默认值。
    • 返回一个布尔值,表示当前值是否等于默认值。

registerParameterType 函数

使用 registerParameterType 函数将自定义参数类型 table_parameter 注册到参数树中,使其可以在参数树中使用。

使用场景

  • 该代码主要用于需要在图形用户界面中编辑和显示 NumPy 记录数组的场景。
  • 适用于科学计算、数据分析等需要处理大量数据的应用程序。
  • 提供了一种灵活的方式在 Qt 应用程序中集成和使用表格参数项。

4.4 - 数据管理分析模块

这段代码实现了一个复杂的图形用户界面应用,用于科学实验数据的管理、分析和可视化。

主要功能和组件介绍

1. 数据存储管理 (H5StorageDataMgr)

  • 数据存储:通过HDF5文件格式保存和加载实验数据。
  • 数据订阅:管理数据流和图像流的订阅,确保在实验过程中捕获和存储所有相关数据。
  • 定时保存:定期自动保存数据,以防数据丢失。
  • 数据清理:在需要时清理当前加载的数据。

2. 图形用户界面 (H5StorageGui)

  • 标签页管理:包含选择数据、绘制数据和事件数据三个主要标签页,每个标签页对应不同的功能模块。
  • 数据选择和加载:允许用户选择数据文件和加载特定实验数据进行分析。
  • 保存和加载按钮:提供保存当前数据和从文件加载数据的功能。

3. 数据绘图 (H5DataPlotter)

  • 数据可视化:使用pyqtgraph和matplotlib库将实验数据绘制成图表,支持多种图形格式(如折线图、散点图等)。
  • 坐标轴选择:允许用户选择和配置x轴和y轴的数据源和显示方式。
  • 定期更新:定期检查并更新绘图数据,以确保图表反映最新的实验数据。
  • 数据导出:将绘制的图表导出为PDF或PNG格式文件。

4. 事件数据处理 (EventPlotter)

  • 事件分析:处理和绘制事件数据,例如离子存活率或损失率的概率或频率。
  • 自定义事件函数:用户可以选择和配置不同的事件函数来分析数据。
  • 保存事件数据:将事件分析结果保存为CSV或pickle文件,方便后续数据处理和分析。

交互功能和用户体验

  • 交互式控件:使用Qt提供交互式控件,如按钮、复选框、组合框和文本输入框,使用户能够方便地进行数据选择、配置和操作。
  • 动态更新:用户界面和绘图能够实时更新,确保用户始终看到最新的实验数据。
  • 多样化导出选项:支持将图表导出为不同格式,便于用户在报告和演示中使用。

辅助功能

  • 错误和信息处理:通过日志和弹窗显示错误信息和操作反馈,帮助用户及时了解系统状态和操作结果。
  • 数据过滤和处理:支持数据过滤和自定义处理函数,提供灵活的数据分析手段。

这个应用程序特别适合用于需要频繁收集、分析和可视化实验数据的科研环境。通过集成多种数据处理和绘图功能,它能够显著提高实验数据管理和分析的效率。

导入模块

代码导入了必要的模块和库,用于数据处理、图形绘制、图形用户界面(GUI)开发等。主要模块包括:

  • NumPySciPy:用于科学计算和数据处理。
  • matplotlibpyqtgraph:用于图形绘制。
  • Qt:用于构建图形用户界面。
  • pandas:用于数据处理和分析。

全局变量和常量定义

定义了一些物理常数,例如m_Li(锂原子质量)、m_Ba(钡原子质量)和kB(玻尔兹曼常数),这些常量用于后续的计算和拟合。

H5StorageGui 类

这是主界面类,继承自 BWidget。它包含了三个主要组件:

  1. H5StorageDataMgr:用于数据管理和存储。
  2. H5DataPlotter:用于数据的绘制和展示。
  3. EventPlotter:用于处理和绘制事件数据。

__init__ 方法

  • 初始化三个主要组件并将它们添加到标签页中。
  • 设置保存、加载和清除按钮,并配置定时器以定期保存数据。

H5StorageDataMgr 类

该类用于管理HDF5数据存储和加载。主要功能包括:

  • 选择数据存储目录。
  • 管理数据订阅。
  • 存储和加载数据文件。
  • 定期保存和更新数据。

__init__ 方法

  • 初始化数据管理器,设置数据存储路径和文件名。
  • 添加数据订阅编辑器,用于管理数据流和图像流。
  • 配置定时器以定期更新数据。

数据存储和加载

  • savetoFile 方法:将当前数据保存到HDF5文件中。
  • loadFromFile 方法:从HDF5文件中加载数据。
  • clear 方法:清除当前数据。

H5DataPlotter 类

用于绘制和展示数据。主要功能包括:

  • 设置坐标轴选择器。
  • 管理不同数据源。
  • 定期检查和更新数据。
  • 导出图形到PDF或PNG格式。

__init__ 方法

  • 初始化绘图窗口和数据选择器。
  • 设置坐标轴选择器和导出按钮。
  • 配置定时器以定期检查数据更新。

数据更新和绘制

  • checkForNewData 方法:定期检查是否有新数据,并更新绘图。
  • updateDatasources 方法:更新数据源列表。
  • update 方法:更新坐标轴选择器和绘图数据。
  • gen_export_plot 方法:生成用于导出的图形。
  • exportpngexportpdf 方法:导出图形到PNG和PDF格式。

EventPlotter 类

继承自 H5DataPlotter,用于处理和绘制事件数据。主要功能包括:

  • 设置和管理事件数据的坐标轴选择器。
  • 处理事件数据的计算和拟合。
  • 导出事件数据的图形。

__init__ 方法

  • 初始化事件绘图窗口和数据选择器。
  • 配置定时器以定期检查事件数据更新。

数据更新和绘制

  • updateData 方法:更新事件数据。
  • get_event_data 方法:获取和处理事件数据。
  • addFittingaddBinning 方法:添加数据拟合和分箱处理。
  • save_events 方法:保存事件数据。

EventYAxisWidget 类

继承自 YAxisWidget,用于事件数据的Y轴管理。主要功能包括:

  • 管理和更新Y轴数据。
  • 处理事件函数和参数。

updateData 方法

  • 更新Y轴数据和事件函数参数。
  • 处理和应用数据过滤器。

EventFuncWidget 类

用于设置事件函数和参数。主要功能包括:

  • 管理和选择事件函数。
  • 配置事件函数参数。

主要功能总结

  1. 数据管理:通过 H5StorageDataMgr 类实现,支持数据的存储、加载和定期保存。
  2. 数据绘制:通过 H5DataPlotter 类和 EventPlotter 类实现,支持数据和事件数据的绘制、更新和导出。
  3. 图形用户界面:通过 Qt 构建,支持用户交互、数据选择和配置。

4.5 - 数据流订阅管理

这段代码实现了能够动态订阅、显示和更新数据流的数据可视化界面。

PlotDataEditor

PlotDataEditor 类是一个管理数据或图像流订阅的小部件。它包含以下关键部分:

  • 初始化方法:接收属性对象和数据字典,设置布局,创建一个下拉菜单用于选择数据流。
  • 更新数据流列表:清空并重新填充下拉菜单中的数据流。
  • 更新数据通道:根据用户选择更新数据通道。

ScrollPlot

ScrollPlot 类继承自 pg.PlotItem,用于显示滚动数据图表。它的主要功能包括:

  • 初始化方法:设置图表属性,初始化数据缓冲区,创建数据流客户端和属性对象。
  • 初始化数据缓冲区:创建一个用于存储数据的数组。
  • 数据馈送方法:将新数据块添加到数据数组中。
  • 更新图表:根据数据数组更新图表显示。
  • 设置新数据:从数据流接收新数据,并调用数据馈送和图表更新方法。
  • 数据选择对话框:弹出一个对话框供用户选择数据流。
  • 订阅窗口:管理数据流订阅的对话框。
  • 配置窗口:弹出一个对话框供用户配置图表属性。

ScrollWindow

ScrollWindow 类继承自 BMainWindow,是应用程序的主窗口。它包含以下关键部分:

  • 初始化方法:创建主窗口和图形窗口,初始化多个 ScrollPlot 实例,并添加到窗口中。
  • 初始化图表:循环创建并添加 ScrollPlot 实例。
  • 数据馈送方法:将新数据块添加到数据数组中。
  • 更新图表:根据数据数组更新所有图表的显示。
  • 更新方法:定期调用数据馈送和图表更新方法。

main 函数

main 函数是程序的入口点,执行以下步骤:

  1. 创建一个 QApplication 实例。
  2. 创建并显示 ScrollWindow 实例。
  3. 启动应用程序事件循环。

主要功能和工作流程

  1. 数据订阅和显示PlotDataEditor 管理数据流订阅,ScrollPlot 显示订阅的数据,并定期更新图表。
  2. 用户交互:用户可以通过图形界面选择和配置数据流,更新图表显示。
  3. 定期更新:通过定时器定期检查和更新数据,实现滚动显示效果。

4.6 - 数据流订阅管理

SubscriptionEditor 类提供了一个直观的界面,用户可以方便地管理数据和图像流的订阅。通过灵活的属性管理和用户交互,确保用户能够轻松地添加、删除和更新订阅,从而适应不断变化的需求和数据源。

概述

这个代码定义了一个订阅编辑器 SubscriptionEditor 类,主要用于管理程序对数据流或图像流的订阅。在 PyQt 环境中,通过一个简单的图形用户界面,用户可以查看和修改当前的订阅列表。

SubscriptionEditor

SubscriptionEditor 类继承自 QWidget,用于管理数据或图像流的订阅。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:props(属性对象)、category(类别,例如 ‘Image’ 或 ‘Data’)、parent(父组件)、propprefix(属性前缀)、streamkey(流键)、fullList(全列表)。
    • 设置类的各种属性,并初始化图形界面组件,包括 QVBoxLayoutQListWidgetQComboBox
    • 调用 loadSubscriptions 方法加载当前的订阅,并调用 update_streamlist 方法更新可用的流列表。
    • 添加“添加”和“删除”按钮,并连接到相应的槽函数。
  • loadSubscriptions 方法

    • 从属性中加载当前的订阅列表,并将其显示在 QListWidget 中。
  • handle_property_changes 方法

    • 检查属性是否发生变化,如果发生变化则更新订阅列表,并发出 propertiesChanged 信号。
  • update_streamlist 方法

    • 更新 QComboBox 中可用的流列表。
    • 如果类别是 ‘List’,则使用全列表更新。
    • 否则,从属性中获取活动流,并计算每个流的时间差,并将其添加到 QComboBox 中。
  • add 方法

    • QComboBox 中选择的流添加到订阅列表中。
    • 检查流是否已经在订阅列表中,如果没有,则添加到 QListWidget 和属性中,并发出 subscriptionsChanged 信号。
  • deletemarked 方法

    • 删除 QListWidget 中选中的流。
    • 从属性中删除对应的流,并更新 QListWidget,最后发出 subscriptionsChanged 信号。

使用场景

  • 该代码主要用于需要管理数据或图像流订阅的应用程序。
  • 适用于需要动态调整订阅数据源的场景,例如科学计算、数据采集和监控等应用。
  • 提供了一种用户友好的方式,通过图形界面查看和修改订阅列表。

4.7 - 图表动态显示器

这个脚本可以用于需要实时监控和展示数据流的应用程序,例如科学实验、工业监控和实时数据分析等。用户可以通过 GUI 配置数据流的订阅和绘图属性,实时查看和分析数据变化。

概述

这个脚本使用 Qt 和 pyqtgraph 库创建了一个实时更新的绘图工具。工具订阅数据流并动态更新图表显示。核心组件包括 UpdatingPlot 类和 LivePlot 类。

主要组件

UpdatingPlot

UpdatingPlot 类继承自 pg.PlotItem,用于创建能够订阅数据流并实时更新的图表。

主要方法和属性
  • 初始化方法 __init__

    • 初始化数据客户端和属性客户端。
    • 设置绘图区域的上下文菜单,添加订阅和配置选项。
    • 启动定时器,每隔 10 毫秒调用 setnewData 方法更新数据。
  • setnewData 方法

    • 检查数据流中是否有新数据。
    • 处理新数据并更新曲线显示。
  • subscribe_window 方法

    • 创建并显示一个对话框,允许用户配置数据流订阅。
    • 更新订阅配置。
  • updateConfiguration 方法

    • 更新数据流订阅。
    • 清除旧的绘图,并为每个数据流创建新的曲线。
  • configureWindow 方法

    • 创建并显示一个对话框,允许用户配置绘图属性。
    • 更新绘图配置。

LivePlot

LivePlot 类继承自 QtWidgets.QWidget,用于创建包含 UpdatingPlot 图表的窗口。

主要方法和属性
  • 初始化方法 __init__

    • 初始化窗口布局,添加 UpdatingPlot 图表。
    • 设置窗口大小提示和显示配置。
  • sizeHint 方法

    • 返回窗口的大小提示。
  • setSizeHint 方法

    • 设置窗口的宽度和高度提示。

使用场景

这个脚本可以用于需要实时监控和展示数据流的应用程序,例如科学实验、工业监控和实时数据分析等。用户可以通过 GUI 配置数据流的订阅和绘图属性,实时查看和分析数据变化。

示例

下面是一个示例,展示如何使用 UpdatingPlotLivePlot 类:

def main(name):
    app = QtGui.QApplication([])
    camWin = LivePlot(name)
    camWin.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main('dummyname')

在这个示例中,main 函数创建一个 LivePlot 窗口并启动应用程序事件循环。运行此代码将显示一个包含实时更新图表的窗口。

关键功能

  • 实时数据更新:使用定时器定期检查数据流中的新数据并更新图表显示。
  • 动态配置:通过 GUI 配置数据流订阅和绘图属性,支持用户自定义设置。
  • 可扩展性:基于 Qt 和 pyqtgraph 构建,易于扩展和集成其他功能。

4.8 - 图形ROI管理器

这个类适用于需要在图形界面中显示和管理多个兴趣区域的应用程序,特别是那些需要通过中心属性类来通信和管理属性的场景。例如,科学实验中的图像处理和分析,实时监控中的区域选择和管理等。

概述

这个脚本定义了一个名为 zmq_ROI 的类,它继承自 pyqtgraph.ROI,并通过 Quatm 的中心属性类 Properties 来通信其属性。该类主要用于在图形界面中显示和管理一个兴趣区域(ROI),并实时更新其属性。

主要组件

zmq_ROI

zmq_ROI 类继承自 pg.ROI,用于创建一个可以通过属性类 Properties 来管理和通信其属性的兴趣区域。

属性和方法
  • 静态属性

    • roilist:存储所有 ROI 名称的列表。
    • p_pos:存储 ROI 的位置。
    • p_size:存储 ROI 的大小。
    • color:存储 ROI 的颜色。
  • 初始化方法 __init__

    • 初始化 ROI 的名称和属性。
    • 将 ROI 名称添加到 roilist 中(如果不存在)。
    • 设置 ROI 的位置和大小,并启动一个定时器,每隔 1000 毫秒调用 _publish_values 方法。
  • update_from_properties 方法

    • 从属性中更新 ROI 的颜色、位置和大小。
  • _publish_values 方法

    • 检查 ROI 的位置和大小是否发生变化。如果发生变化,则更新属性中的位置和大小。
    • 如果属性中有变化,则从属性中更新 ROI 的信息。

使用场景

这个类适用于需要在图形界面中显示和管理多个兴趣区域的应用程序,特别是那些需要通过中心属性类来通信和管理属性的场景。例如,科学实验中的图像处理和分析,实时监控中的区域选择和管理等。

示例

下面是一个使用 zmq_ROI 类的示例:

import pyqtgraph as pg
from PyQt6.QtWidgets import QApplication
import sys

def main():
    app = QApplication(sys.argv)
    win = pg.GraphicsLayoutWidget(show=True)
    view = win.addViewBox()
    view.setAspectLocked(True)
    img = pg.ImageItem()
    view.addItem(img)
    
    # 创建并添加 zmq_ROI 实例
    roi = zmq_ROI('exampleROI', pos=[50, 50], size=[100, 100])
    view.addItem(roi)
    
    # 显示窗口
    win.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

在这个示例中,main 函数创建一个包含图像和兴趣区域(ROI)的窗口。运行此代码将显示一个窗口,其中包含一个可拖动和调整大小的 ROI。

关键功能

  • 属性通信:通过 Properties 类管理和通信 ROI 的属性,使得多个 ROI 可以共享和实时更新其属性。
  • 定时更新:通过定时器定期检查和更新 ROI 的位置和大小。
  • 图形界面集成:集成到 pyqtgraph 中,提供强大的图形界面支持。

4.9 - 偏斜高斯拟合

Cython 偏态正态拟合——额外输出偏度和众数。

概述

GaussfitSkewed 使用偏态正态分布对一维数据进行 Cython 优化拟合,输出偏度参数 a 和众数 mode

from quatm.analysis.gaussfit_skewed import GaussfitSkewed

gs = GaussfitSkewed(props=props, data_stream="tof")
gs.run()
# 输出: pos, sigma, A0, offset, a (偏度), mode (众数)

4.10 - 属性编辑器

这个代码实现了一个属性编辑器 GUI,用于管理和编辑属性树。

ScalableGroup 类

ScalableGroup 类是一个自定义的参数组,用于自动生成两个子参数,这两个子参数始终互为倒数。

初始化方法
  • __init__ 方法
    • 初始化参数组,并设置组类型、添加文本和添加列表。
    • 调用基类 GroupParameter 的初始化方法。
添加新参数方法
  • addNew 方法
    • 根据参数类型(字符串、浮点数或整数)添加新的子参数。
    • 设置新子参数的初始值和属性。

TreeEdit 类

TreeEdit 类用于从 Properties 类中提取信息并根据树视图进行格式化。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置父类和子树路径。
    • 从属性对象中提取条目,并创建参数组。
    • 连接参数组的状态变化信号到 change 方法。
解析字典方法
  • _parsedict 方法
    • 将字典格式化为可以在树视图中查看的格式。
    • 根据不同的数据类型(整数、布尔、字符串、浮点数、列表、字典)创建相应的参数条目。
更改参数方法
  • change 方法
    • 处理树视图中的任何更改。
    • 根据参数类型和变化的数据更新属性对象。
更新方法
  • _update_update_whole_tree 方法
    • 更新树视图中选定条目或整个树视图。
    • 根据属性对象中的数据重新生成参数条目。

PropEdit 类

PropEdit 类是属性编辑器的主要 GUI 窗口,用于管理属性树。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置子树路径。
    • 创建布局和参数树视图。
    • 添加更新、删除、保存和加载按钮,并连接相应的槽函数。
更新、保存、加载和删除方法
  • update 方法
    • 更新参数树视图。
  • save 方法
    • 将当前属性保存到文件。
  • load 方法
    • 从文件加载属性并更新参数树视图。
  • delete 方法
    • 删除当前选定的参数条目。

PropSelector 类

PropSelector 类是属性选择器 GUI,用于从属性树中选择和管理键列表。

初始化方法
  • __init__ 方法
    • 初始化类实例,设置子树路径。
    • 创建布局和参数树视图。
    • 添加选择和删除按钮,并连接相应的槽函数。
选择和删除方法
  • select 方法
    • 从参数树视图中选择当前条目并更新键列表。
  • updateKeys 方法
    • 更新键列表视图。
  • delete_marked 方法
    • 删除当前选定的键条目。

主函数

  • main 方法
    • 创建应用程序实例,设置窗口图标,创建并显示主窗口。
    • 进入应用程序事件循环。

代码逻辑

  1. 导入所需模块:导入标准库、第三方库和项目特定模块。
  2. 定义 ScalableGroup 类:自定义参数组,用于自动生成子参数。
  3. 定义 TreeEdit 类:从 Properties 类中提取信息并根据树视图进行格式化。
  4. 定义 PropEdit 类:属性编辑器的主要 GUI 窗口。
  5. 定义 PropSelector 类:属性选择器 GUI,用于选择和管理键列表。
  6. 定义主函数:创建并启动应用程序。
  7. 运行主程序:检查是否在交互模式下运行,如果不是,则运行主程序。

运行流程概述

  1. 启动应用程序:创建 QApplication 实例,并设置窗口图标。
  2. 创建 PropEdit 实例:初始化属性编辑器,并显示主窗口。
  3. 管理属性树:通过参数树视图和按钮与属性对象交互,更新、保存、加载和删除属性条目。
  4. 进入事件循环:应用程序进入事件循环,等待用户交互。

4.11 - 属性更新管理器

该代码实现了一个用于检查属性更新的 GUI 应用程序。通过 PropertiesChecker 类,用户可以定期检查属性是否更新,并在属性未更新时发出警报,使用了 Qt 的多种控件和信号槽机制来实现用户交互和数据更新。

PropertiesChecker 类

PropertiesChecker 类用于检查属性是否定期更新,并在属性未更新时发出警报。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 创建两个 Properties 对象,用于检查属性的更新。
    • 初始化一个 QSoundEffect 对象,用于播放警报声音。
    • 调用 run 方法开始检查属性更新。
警报窗口方法
  • open_alert_window 方法
    • 创建并显示一个警报对话框,当属性未更新时调用。
    • 播放警报声音。
属性检查方法
  • run 方法
    • 使用一个无限循环定期检查属性是否更新。
    • 每隔一段时间设置和检查属性值。
    • 如果属性值未更新,则打印错误信息并显示警报窗口;否则,打印属性仍在更新的信息。

主函数

  • main 方法
    • 创建应用程序实例,设置窗口图标,创建并显示主窗口。
    • 进入应用程序事件循环。

代码逻辑

  1. 导入所需模块:导入标准库、第三方库和项目特定模块。
  2. 定义 PropertiesChecker 类:包含初始化方法、警报窗口方法和属性检查方法。
  3. 定义主函数:创建并启动应用程序。
  4. 运行主程序:检查是否在交互模式下运行,如果不是,则运行主程序。

运行流程概述

  1. 启动应用程序:创建 QApplication 实例,并设置窗口图标。
  2. 创建 PropertiesChecker 实例:初始化属性检查器,并开始检查属性更新。
  3. 检查属性更新:在 run 方法中,定期设置和检查属性值,并在属性未更新时发出警报。
  4. 显示警报窗口:当属性未更新时,显示警报对话框并播放警报声音。
  5. 进入事件循环:应用程序进入事件循环,等待用户交互。

4.12 - 数据流图片流监视器

该代码使用 Qt 库构建了一个 GUI 应用,用于显示和编辑数据流、图像数据和相机属性。代码主要定义了一些自定义窗口小部件(widgets),包括参数显示框、图像数据框和相机属性框,并实现了上下文菜单、订阅管理和数据选择对话框等功能。

概要

该应用用于显示和编辑数据流、图像及相机属性,包含参数显示框、图像数据框和相机属性框等组件。

主要类和功能

ParameterBox

该类继承自 BFrame,用于显示单个参数。它包括以下功能:

  • 初始化:设置框架样式、获取属性和数据流名称,并初始化显示标签。
  • 数据更新:使用定时器定期从数据流中获取新数据,并更新显示值。
  • 上下文菜单:右键单击时显示上下文菜单,包括订阅管理和数据选择功能。
  • 订阅管理:打开订阅管理窗口以编辑订阅。
  • 数据选择:打开数据选择对话框以选择要显示的数据。

ImageDataBox

该类继承自 BFrame,用于显示图像数据。它包括以下功能:

  • 初始化:设置框架样式、获取属性,并初始化显示框。
  • 上下文菜单:右键单击时显示上下文菜单,包括订阅管理功能。
  • 订阅管理:打开订阅管理窗口以编辑订阅。
  • 数据更新:通过设置新数据的方法更新显示框内容。

CamPropsBox

该类继承自 ImageDataBox,用于显示相机属性。它包括以下功能:

  • 初始化:获取相机名称和属性子树,并设置定时器定期更新数据。
  • 上下文菜单:右键单击时显示上下文菜单,包括属性和相机选择功能。
  • 属性窗口:打开属性选择窗口以编辑相机属性。
  • 相机选择窗口:打开相机选择窗口以选择要显示的相机。
  • 数据更新:根据当前相机和配置获取并显示相机属性。

DataBox

这是一个简单的用于显示标签和值的框,继承自 QWidget。它主要包括:

  • 初始化:设置布局,添加标签和值的显示。
  • 大小提示:返回组件的建议大小。

详细描述

ParameterBox

  • __init__ 方法

    • 初始化框架样式和宽度。
    • 获取参数属性和数据流名称。
    • 初始化显示标签和值标签,并设置布局。
    • 设置上下文菜单策略和定时器。
  • setNewData 方法

    • 检查数据流中是否有新数据。
    • 更新显示值。
  • openMenu 方法

    • 打开上下文菜单,包含订阅管理和数据选择选项。
  • dataSelectDialog 方法

    • 打开数据选择对话框,允许用户选择要显示的数据。
  • subscribe_window 方法

    • 打开订阅管理窗口,允许用户编辑订阅。
  • updateSubscription 方法

    • 更新数据流订阅。
  • updateDataLists 方法

    • 更新数据列表和显示标签。

ImageDataBox

  • __init__ 方法

    • 初始化框架样式和宽度。
    • 获取属性并初始化显示框。
    • 设置上下文菜单策略。
  • openMenu 方法

    • 打开上下文菜单,包含订阅管理选项。
  • subscribe_window 方法

    • 打开订阅管理窗口,允许用户编辑订阅。
  • dataSelectDialog 方法

    • 打开数据选择对话框,允许用户选择要显示的数据。
  • setNewData 方法

    • 更新显示框内容。

CamPropsBox

  • __init__ 方法

    • 获取相机名称和属性子树。
    • 设置定时器定期更新数据。
  • openMenu 方法

    • 打开上下文菜单,包含属性和相机选择选项。
  • props_window 方法

    • 打开属性选择窗口,允许用户编辑相机属性。
  • cams_window 方法

    • 打开相机选择窗口,允许用户选择相机。
  • setNewData 方法

    • 更新相机属性显示。

DataBox

  • __init__ 方法

    • 设置布局,添加标签和值显示。
  • sizeHint 方法

    • 返回组件的建议大小。

运行流程

  1. 创建 ParameterBoxImageDataBoxCamPropsBox 的实例。
  2. 定时器触发,调用 setNewData 方法从数据流中获取新数据并更新显示。
  3. 用户右键单击组件,显示上下文菜单。
  4. 用户选择订阅管理或数据选择选项,打开相应的对话框。
  5. 用户在对话框中编辑订阅或选择数据,更新组件显示。

4.13 - 数据流图片流监视器

该代码实现了一个基于 Qt 的应用程序,用于订阅和显示数据流或图像流。应用程序提供了一个可滚动的绘图窗口,用户可以通过多种交互方式来管理数据源和配置绘图属性。

功能介绍

该代码实现了一个基于 Qt 的应用程序,用于订阅和显示数据流或图像流。应用程序提供了一个可滚动的绘图窗口,用户可以通过多种交互方式来管理数据源和配置绘图属性。

代码结构

  1. 导入必要的模块和库
  2. 定义 PlotDataEditor
  3. 定义 ScrollPlot
  4. 定义 ScrollWindow
  5. 定义脚本入口

类:PlotDataEditor

功能介绍

PlotDataEditor 类是一个小部件,用于管理程序对数据流或图像流的订阅。

方法

  • __init__:初始化 PlotDataEditor 对象,设置布局和控件,更新可用流的列表。
    • 参数:props (属性对象)、data (初始数据字典)、category (流的类别)、parent (父对象)、preselect (预选择的流名称)。
  • update_streamlist:更新流选择框中的可用流列表。
  • updateDatachannel:更新选定的数据通道,并在父对象中设置相关属性。

类:ScrollPlot

功能介绍

ScrollPlot 类是一个绘图部件,用于订阅数据流并实时更新显示。

方法

  • __init__:初始化 ScrollPlot 对象,设置属性,订阅数据流,并配置绘图选项。
    • 参数:name (绘图的名称)、parent (父对象)。
  • initDataBuffer:初始化数据缓冲区,用于存储接收的数据。
  • feedData:将新数据块添加到数据缓冲区,并计算运行平均值(如果启用)。
  • clearPlot:清除绘图中的数据。
  • updatePlot:更新绘图,显示新的数据点和运行平均值。
  • updatePlotContent:更新绘图内容,删除当前内容以便显示新的数据。
  • updateTitle:更新绘图的标题。
  • updateSubscription:更新数据流的订阅,切换到新的数据流。
  • updateDataLists:更新数据列表和相关属性。
  • setnewData:接收新数据并更新绘图。
  • setScatterplot:设置散点图的绘图选项。
  • deletePlot:删除绘图并从属性中移除相关配置。
  • dataSelectDialog:打开数据选择对话框,用于选择新的数据源。
  • subscribe_window:打开订阅窗口,用于管理数据流的订阅。
  • configureWindow:打开配置窗口,用于修改绘图属性。
  • running_mean:静态方法,计算运行平均值。

类:ScrollWindow

功能介绍

ScrollWindow 类是主窗口类,包含多个滚动绘图,用于显示和管理数据流。

方法

  • __init__:初始化 ScrollWindow 对象,设置窗口和工具栏,并恢复之前保存的绘图。
    • 参数:name (窗口的名称)、parent (父对象)、n_plots (初始绘图数量)。
  • init_toolbar:初始化工具栏,添加操作按钮。
  • updateAllSubscriptions:更新所有绘图的订阅。
  • restorePlots:恢复之前保存的绘图。
  • addPlot:添加新绘图到窗口中。

脚本入口

功能介绍

脚本入口用于创建应用程序实例,显示主窗口并启动应用事件循环。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ScrollWindow 实例。
  3. 显示主窗口。
  4. 启动应用事件循环。

总结

该代码实现了一个完整的应用程序,用于管理和显示数据流。通过定义多个类和方法,用户可以方便地订阅数据流、配置绘图属性以及实时更新绘图。

4.14 - 数据实时监视器

该模块是一个用于在科学实验中实时绘制和分析数据的控件。该控件集成了 pyqtgraph 库,用于高效地绘制和更新图表。

类:DataPlotterWidget

方法:__init__

功能:初始化 DataPlotterWidget 对象,设置属性和布局,启动定时器用于实时数据更新。

参数

  • axis_name:轴名称
  • prop_root:属性根路径
  • datastream_names:数据流名称列表
  • n_yaxis:Y轴数量
  • parent:父对象

主要步骤

  1. 初始化属性和数据管理器 (DataSummary)。
  2. 创建并设置网格布局 (QGridLayout)。
  3. 调用 buildPlotWidget 方法创建绘图小部件。
  4. 调用 buildDataSelector 方法创建数据选择器。
  5. 启动定时器,每20毫秒调用 checkForNewData 方法检查新数据。
方法:buildPlotWidget

功能:创建并设置绘图窗口和右键菜单。

主要步骤

  1. 创建 pyqtgraph 图形布局窗口 (GraphicsLayoutWidget)。
  2. 在窗口中添加绘图项 (PlotItem)。
  3. 添加右键菜单选项,通过 QAction 类实现。
方法:buildDataSelector

功能:创建并设置数据选择器界面。

主要步骤

  1. 创建数据选择器 (DataSelectorItem)。
  2. 创建 X轴选择器 (XAxisWidget) 和多个 Y轴选择器 (YAxisWidgetHelper)。
  3. 设置网格布局 (QGridLayout) 来管理数据选择器控件的排列和显示。
  4. 隐藏配置界面,默认不显示。
方法:toggleConfig

功能:切换配置界面的显示和隐藏状态。

主要步骤

  1. 根据 configVisible 变量的值显示或隐藏配置界面。
  2. 更新 configVisible 变量的值。
方法:setDataSource

功能:设置或更改数据源。

参数text - 数据源名称。

方法:checkForNewData

功能:检查是否有新数据,并更新图表。

主要步骤

  1. 调用 recvData 方法从数据源接收数据。
  2. 如果有新数据,更新 lastUpdate 时间戳。
  3. 调用 updateDatasourcesupdate 方法更新数据源和图表。
方法:updateDatasources

功能:检查并更新数据源列表。

主要步骤

  1. 创建一个新的数据源列表 sourcelist
  2. 如果数据源列表有变化,更新数据选择器中的数据源列表。
方法:update

功能:更新数据选择器中的可选数据字段,并更新图表。

主要步骤

  1. 从当前数据集中选择所有代表浮点数或整数的键。
  2. 更新数据选择器中的可选键列表。
  3. 调用 _updatePlotData 方法更新图表。
方法:_updatePlotData

功能:更新图表数据。

主要步骤

  1. 获取当前选中的 X轴字段。
  2. 调用每个 Y轴选择器的 updateData 方法更新数据。
方法:exportpdf

功能:导出图表为 PDF 文件。

主要步骤

  1. 创建一个 matplotlib 图表对象。
  2. 调用每个 Y轴选择器的 plotmpl 方法将数据绘制到图表上。
  3. 保存图表为 PDF 文件并使用查看器打开。
方法:clear

功能:清除数据。

主要步骤

  1. 调用数据管理器的 clear 方法清除数据。
  2. 移除所有图表项。
方法:plotData

功能:在图表中绘制数据。

参数

  • x:X轴数据
  • y:Y轴数据

主要步骤

  1. 创建一个 pg.PlotDataItem 对象并设置绘图样式。
  2. 将数据添加到图表项中并绘制。

类:YAxisWidgetHelper

方法:__init__

功能:初始化 YAxisWidgetHelper 对象,设置属性和布局。

参数

  • label:标签
  • plotter:数据绘图器对象
  • props:属性对象
  • plotitem:绘图项对象
  • parent:父对象

主要步骤

  1. 初始化 Y轴选择器,创建并设置布局和过滤器组合框。
  2. 创建并配置绘图项。
方法:updateYscale

功能:更新 Y轴缩放比例。

参数text - 缩放比例文本。

方法:createContextMenu

功能:创建上下文菜单。

参数position - 菜单位置。

主要步骤

  1. 创建菜单项用于添加过滤、分箱和拟合。
  2. 显示菜单并处理用户选择。
方法:_initPlot

功能:初始化绘图项。

主要步骤

  1. 创建并配置 pg.PlotDataItem 对象。
  2. 添加到绘图项中。
方法:configurePlot

功能:配置绘图样式。

主要步骤

  1. 设置绘图项的绘图样式。
  2. 如果有后续数据处理步骤,递归调用其配置方法。
方法:addBinning

功能:添加分箱处理步骤。

主要步骤

  1. 如果当前没有后续处理步骤,创建 BinningWidget 并添加到布局中。
  2. 更新数据。
方法:addFitting

功能:添加拟合处理步骤。

主要步骤

  1. 如果当前没有后续处理步骤,创建 FittingWidget 并添加到布局中。
  2. 更新数据。
方法:reevaluateData

功能:重新评估数据。

主要步骤

  1. 获取当前 X轴字段。
  2. 调用 updateData 方法更新数据。
方法:updateData

功能:更新数据。

参数xtext - X轴字段。

主要步骤

  1. 获取当前 Y轴字段。
  2. 从数据源获取数据并应用过滤器。
  3. 更新图表中的数据。
方法:plotmpl

功能:在 matplotlib 图表中绘制数据。

参数

  • axmatplotlib 图表轴对象。

主要步骤

  1. 将数据绘制到 matplotlib 图表轴中。
  2. 如果有后续数据处理步骤,递归调用其绘图方法。

4.15 - 图像查看器

该代码实现了一个基于 Qt 的图像查看器应用,名为 ImageWindow。这个应用包含一个中心图像显示区域和两个用于显示线图的侧边栏。用户可以通过该应用实时查看和分析图像数据,并调整图像的显示参数。

功能介绍

该代码实现了一个基于 Qt 的图像查看器应用,名为 ImageWindow。这个应用包含一个中心图像显示区域和两个用于显示线图的侧边栏。用户可以通过该应用实时查看和分析图像数据,并调整图像的显示参数。

代码结构

  • 导入必要的模块和库
  • 定义 ImageWindow
  • 定义主函数 main
  • 定义脚本入口

类:ImageWindow

简短功能介绍

ImageWindow 类是一个主窗口,包含一个图像显示区域和两个用于显示线图的侧边栏。此外,它还提供了一些工具栏和面板,用于调整图像显示参数和查看图像信息。

方法:__init__

功能:初始化 ImageWindow 对象,并设置窗口名称和父对象。

参数

  • name:窗口名称。
  • parent:父对象(可选)。

主要步骤

  1. 调用父类 BMainWindow 的构造函数。
  2. 初始化属性字段。
  3. 调用 initUI 方法初始化用户界面。

方法:initUI

功能:初始化用户界面,包括状态栏、图像显示区域和停靠窗口。

主要步骤

  1. 显示状态栏信息。
  2. 创建图像显示区域并设置为中心部件。
  3. 创建停靠窗口(Dock Widgets)。

方法:createDockWidgets

功能:创建用于显示线图、直方图和图像信息的停靠窗口。

主要步骤

  1. 创建顶部的线图停靠窗口并添加到主窗口。
  2. 创建右侧的线图停靠窗口并添加到主窗口。
  3. 创建左侧的直方图停靠窗口并添加到主窗口。
  4. 创建顶部的图像信息停靠窗口并添加到主窗口。

方法:update_min_max

功能:更新图像显示的最小和最大亮度值。

主要步骤

  1. 获取直方图的最小和最大亮度值。
  2. 更新属性中的最小和最大亮度值。

方法:get_tick_position

功能:获取直方图梯度的刻度位置。

主要步骤

  1. 获取直方图梯度的所有刻度位置。
  2. 计算并返回归一化的刻度位置。

方法:closeEvent

功能:在窗口关闭事件中保存当前图像的显示范围和刻度位置。

主要步骤

  1. 获取图像显示的 x 和 y 范围。
  2. 保存显示范围和刻度位置到属性中。
  3. 调用父类的关闭事件处理方法。

主函数:main

功能:创建并显示 ImageWindow 实例。

参数

  • name:窗口名称。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ImageWindow 实例并设置窗口图标。
  3. 显示窗口。
  4. 启动应用事件循环。

脚本入口

功能:解析命令行参数并调用 main 函数。

主要步骤

  1. 检查是否以交互模式运行。
  2. 解析命令行参数获取程序实例名称。
  3. 调用 main 函数。

4.16 - 图像监视器

该代码实现了一个基于 Qt 的图像监控器应用,名为 ImageDisplay。这个应用能够接收并实时显示图像数据,并提供多种工具来调整和保存图像。用户可以通过该应用监控图像流,应用滤波器,调整显示参数,并保存当前图像。

功能介绍

该代码实现了一个名为ImageDisplay的图像监控器应用,。这个应用能够接收并实时显示图像数据,并提供多种工具来调整和保存图像。用户可以通过该应用监控图像流,应用滤波器,调整显示参数,并保存当前图像。

代码结构

  • 导入必要的模块和库
  • 定义 ImageDisplay
  • 定义主函数 main
  • 定义脚本入口

类:ImageDisplay

简短功能介绍

ImageDisplay 类是一个自更新的图像显示窗口,能够实时接收和显示图像数据,并提供多种工具和设置来调整图像显示效果。

方法:__init__

功能:初始化 ImageDisplay 对象,并设置窗口名称和父对象。

参数

  • name:窗口名称。
  • parent:父对象(可选)。

主要步骤

  1. 初始化属性字段。
  2. 创建并设置图像显示区域。
  3. 订阅图像流和掩码流。
  4. 设置图像显示和掩码显示的初始数据。
  5. 创建图像显示窗口和控件布局。
  6. 启动定时器以定期更新图像。

方法:sizeHint

功能:返回窗口的推荐大小。

返回值QtCore.QSize(800, 700)

方法:noise_filter

功能:应用噪声滤波器处理图像。

参数

  • img:待处理的图像数据。

主要步骤

  1. 将图像数据转换为绝对值。
  2. 应用双边滤波器和中值滤波器进行去噪处理。
  3. 返回处理后的图像。

方法:spot_detector

功能:检测图像中的亮点。

参数

  • img:待处理的图像数据。

主要步骤

  1. 将图像二值化,阈值为 _spot_level

方法:update_image

功能:定期更新图像显示。

主要步骤

  1. 检查是否有新图像数据。
  2. 接收并处理新图像数据。
  3. 更新图像显示。
  4. 更新图像掩码。

方法:update_mask

功能:更新图像掩码。

主要步骤

  1. 检查是否有新掩码数据。
  2. 接收并处理新掩码数据。
  3. 更新掩码显示。

方法:saveCurrentImage

功能:保存当前显示的图像为 PNG 文件。

主要步骤

  1. 构建文件路径,包含当前时间戳。
  2. 保存图像数据到文件。

方法:subscribe_window

功能:打开订阅窗口,用于选择图像流。

主要步骤

  1. 打开订阅窗口。
  2. 更新图像流订阅。

方法:subscribe_mask

功能:打开订阅窗口,用于选择掩码流。

主要步骤

  1. 打开订阅窗口。
  2. 更新掩码流订阅。

方法:_subscribe_win

功能:创建并显示订阅窗口。

参数

  • key:订阅的键。

主要步骤

  1. 创建对话框。
  2. 添加订阅编辑器到对话框。
  3. 显示对话框。

方法:configureWindow

功能:打开配置窗口,用于调整图像显示参数。

主要步骤

  1. 创建对话框。
  2. 添加属性编辑器到对话框。
  3. 显示对话框。

主函数:main

功能:创建并显示 ImageDisplay 实例。

参数

  • name:窗口名称。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 ImageDisplay 实例并设置窗口图标。
  3. 显示窗口。
  4. 启动应用事件循环。

脚本入口

功能:解析命令行参数并调用 main 函数。

主要步骤

  1. 检查是否以交互模式运行。
  2. 解析命令行参数获取程序实例名称。
  3. 调用 main 函数。

4.17 - 吸收成像 (imagedivider)

Beer-Lambert 柱密度计算——有原子/无原子/背景三帧成像。

概述

ImageDivider 根据 Beer-Lambert 定律处理吸收成像数据,利用有原子图像(with-atoms)、无原子图像(without-atoms)和背景图像(background)计算二维原子柱密度。

from quatm.analysis.imagedivider import ImageDivider

div = ImageDivider(props=props, image_stream="absorption")
div.run()
# 输出: 柱密度图像 (atoms/m²)

4.18 - 离子检测系列

BrightSpots / IonState / SingleIonPresent——离子存在性与量子态判别。

模块概览

方法用途
BrightSpots (ion_blob)cv2.connectedComponents阈值+连通分量分析
BrightSpots (bright_spots)skimage.blob_dogDoG 斑点检测
SingleIonPresent多标准综合计数+位置+宽度+偏度
IonState四图序列离子态分类(存活/热/搁置/丢失)

IonState 判别流程

图像 1 (无离子) → 图像 2 (有离子) → 图像 3 (存活?) → 图像 4 (搁置?)
                                              ↓
                               存活 / 热离子 / 搁置 / 丢失 / 无离子
from quatm.analysis.ion_state import IonState

detector = IonState(props=props)
detector.run()
# 输出: state = "survived" | "hot" | "shelved" | "lost" | "no_ion"

4.19 - 图像处理工具

热像素过滤/检测、图像旋转、切片、选择器和背景减法。

模块列表

模块功能
hot_pixel_filterHotFilter邻域比较→热像素均值替换
hot_pixel_finderHotFilter检测异常像素坐标
rotate_imageImageRotateimutils 旋转+坐标补偿
imagesliceImageSliceROI 行/列求和与积分
imageselectorImageSlice多图中按 index 选择
substract_imageImageSubstract背景图像减法
from quatm.analysis.hot_pixel_filter import HotFilter

filter = HotFilter(props=props, image_stream="andor")
filter.run()

5 - GUI 组件

Quatm 基于 Qt 的图形界面——12 个核心组件,覆盖实验浏览、参数编辑、任务调度、数据可视化和设备监控。

Quatm 提供了完整的可视化图形界面。以下是所有 GUI 组件的详细文档。

组件索引

组件文档简介
🔍 实验浏览器主窗口——多文档界面、文件树、队列和代码编辑
⚙️ 实验管理器核心执行引擎——测量→序列→单次运行的生命周期管理
📋 实验队列任务队列表格——优先级排序、状态跟踪、暂停/终止/重启
📝 准备台参数暂存、复制、循环构建后推入队列
🔁 循环器条件循环——根据测量结果自动切换实验组
🪟 实验窗口单实验控制——动态参数界面 + 代码编辑
🎛️ 参数系统FloatBox/BoolBox/ComboBox——参数 GUI 控件体系
🌲 属性编辑器基于 pyqtgraph ParameterTree 的键值浏览
📈 实时绘图实时一维数据流——多曲线、缩放、订阅管理
💡 LED指示灯红/绿 LED 状态灯——径向渐变动画
🧱 GUI基础类BWidget/BMainWindow/BFrame,窗口持久化
📷 图像监视器实时科学图像显示——ROI、滤波、子类定制
📊 分析管理器分析进程的启动/停止/状态监控
📡 数据流监视器多类型数据流——曲线/图像/消息三合一监视
✏️ 序列编辑器QScintilla 代码编辑 + 时序图可视化
进程管理器五类后台进程(Server/Driver/GUI/Viewer/Monitor)
🔌 设备管理器PyVISA 设备发现与驱动绑定
💾 数据存储HDF5 存储/加载 + 定时自动保存
⏱️ 自动保存定时保存时间表编辑器
📈 实时滚动图实时滚动折线/散点图——运行平均 + 多曲线
📐 数据模型DictSyncModel——字典/列表到 Qt 表格映射
🔧 实验辅助ODT 对准 + 电场补偿 + 压电镜 + Verdi 对准
🎚️ 参数框紧凑型标签-数值实时参数显示
🗂️ 可折叠组件手风琴式可折叠面板对话框
🧩 实验参数面板实验参数控制面板
🔌 DAC 控制器FPGA DAC 手动设置工具
🧵 后台工作线程QRunnable 后台工作线程——信号驱动
⏱️ 时序浏览器实验时序可视化(DAC+TTL 图表)
📊 滚动波形窗口多通道实时滚动波形显示
📡 订阅编辑器数据/图像流订阅管理
📋 表格参数实验参数树表格编辑节点
🎯 远程 ROI可远程同步的 ROI 组件
🖼️ 图像查看器科学图像查看器(线剖面+LUT)
🔔 属性检查器属性健康轮询+异常告警
📐 辅助绘图工具通用测量数据绘图(多Y轴+滤波+拟合)

架构总览

┌─────────────────────────────────────────────────────────┐
│                     Browser (主窗口)                     │
├──────────────┬──────────────────┬───────────────────────┤
│ FileSelector │  ExperimentWindow│     CodeEditor         │
│ (实验目录树)  │  (参数界面+提交)  │    (代码编辑)          │
├──────────────┴──────────────────┴───────────────────────┤
│ ExperimentQ ← PrepStation ← Looper                      │
│  (任务队列)    (准备台)      (条件循环)                   │
├─────────────────────────────────────────────────────────┤
│          ExperimentManager (执行引擎)                    │
└─────────────────────────────────────────────────────────┘

启动 GUI

python -m quatm.GUI.browser

参数编辑器

quatm.GUI.parameterboxquatm.GUI.property_editor — 可视化调整实验参数:

  • 自动根据 NumberValue / BoolValue / StringCombo 生成对应控件
  • 支持参数分组(group 参数)
  • 扫描标签页支持设置参数扫描范围

序列编辑器

quatm.GUI.editor_sequencer — 可视化编排实验时序:

  • 拖拽式 TTL 脉冲和模拟输出编辑
  • 支持并行和串行任务
  • 微秒级定时精度

图像监视器

quatm.GUI.image_monitor.ImageMonitor — 实时显示科学图像:

  • 支持 ROI 区域选择和分析
  • 可子类化定制显示逻辑

数据流监视器

quatm.GUI.streammonitor — 实时数据流可视化:

  • 动态绘图 (updating_plot)
  • 表格参数显示 (table_parameter)
  • 数据订阅管理 (subscription_editor)

辅助工具

工具文件功能
实验助手experiment_helper.py多功能实验助手面板
ODT 对准odt_alignment_helper.py光偶极阱对准辅助
电场补偿comp_helper.py杂散场补偿辅助
自动保存auto_save_editor.py实验数据自动保存配置
H5 存储h5storage.pyHDF5 文件浏览与管理

启动 GUI

python -m quatm.GUI.browser

5.1 - 实验浏览器 (Browser)

Quatm 主窗口——实验浏览、文件选择、队列管理和多窗口工作区。

概述

Browser 是 Quatm 的主应用程序窗口,基于 QMainWindow + QMdiArea 多文档界面架构。它将文件浏览、实验队列、任务管理和代码编辑整合在统一工作区中。

架构

┌─────────────┬──────────────────────────────────┐
│ FileSelector │       QMdiArea (子窗口区)          │
│ (实验目录树)  │   ┌──────────┬─────────────────┐ │
│             │   │Experiment │  CodeEditor     │ │
├─────────────┤   │Window     │  (实验代码编辑)    │ │
│ ExperimentQ │   └──────────┴─────────────────┘ │
│ (任务队列)    │                                  │
├─────────────┤                                   │
│ PrepStation │                                   │
│ (准备台)     │                                   │
├─────────────┤                                   │
│ Looper      │                                   │
│ (循环器)     │                                   │
└─────────────┴──────────────────────────────────┘

核心组件

组件描述
实验目录FileSelectorexperiments/ 目录树,双击打开实验文件
任务队列ExperimentQ表格化任务列表,支持暂停/终止/删除
任务执行ExperimentManager从队列取出任务并调度执行
准备台PrepStation编辑和预览实验参数后推入队列
循环器Looper根据测量结果条件循环运行
代码编辑CodeEditor基于 QScintilla 的 Python 代码编辑器

启动

from quatm.GUI.browser import Browser

browser = Browser()
browser.show()

或从命令行:

python -m quatm.GUI.browser

窗口持久化

Browser 继承 QMainWindow,通过 QSettings 自动保存和恢复:

  • 主窗口几何位置和大小
  • 已打开的 ExperimentWindow 子窗口及其文件路径

5.2 - 实验管理器 (ExperimentManager)

核心实验执行引擎——管理测量→序列→单次运行的生命周期。

概述

ExperimentManager 是 Quatm 的核心执行引擎,负责从 ExperimentQ 队列中取出任务并按测量 → 序列 → 单次运行的层级结构调度执行。

执行流程

queue_fn (持续轮询)
  └─→ start_measurement
       └─→ _sequence_run (循环扫描/序列)
            └─→ _runloop (单次实验运行)
                 └─→ end_measurement

关键方法

方法说明
queue_fn()持续轮询 ExperimentQ,取出就绪任务
start_measurement(task)初始化测量上下文
_sequence_run(task)处理扫描参数循环
_runloop(task)执行单次实验运行
end_measurement(task)结束测量,保存数据

线程模型

from quatm.GUI.experiment_manager import ExperimentManager

manager = ExperimentManager(browser)
# 内部使用 browser_workers.Worker 线程池
# 任务在独立线程中执行,不阻塞 GUI

5.3 - 实验队列 (ExperimentQ)

任务队列表格——维护实验任务的优先级排序、状态跟踪和生命周期管理。

概述

ExperimentQQGroupBox 内嵌的表格部件,通过 ScheduleModel 管理实验任务的优先级排序和状态显示。

任务状态

状态含义
queued等待执行
running正在执行
paused已暂停
finished执行完成
error执行出错

操作

按钮功能
⏸ Pause暂停队列自动执行
⏹ Stop终止当前任务
🔄 Restart重新运行已完成/出错的任务
🗑 Delete从队列中移除任务

数据模型

# expDict 结构
expDict = {
    task_id: {
        "name": "Rabi 扫描",
        "status": "queued",
        "priority": 1,
        "repeat": 10,
        ...
    }
}

任务按 priority(越小越优先)→ task_id(FIFO)排序。

5.4 - 准备台 (PrepStation)

实验参数暂存与编辑区——在推入队列前预览、复制和微调任务。

概述

PrepStationQGroupBox 内的表格部件,通过 PrepModel 暂存实验任务。在推入 ExperimentQ 之前,可以在此处预览参数、复制任务和构建实验循环。

功能

操作说明
📋 暂存ExperimentWindow 提交任务到此待编辑
📝 复制复制任务生成变体(如改变扫描参数)
🔁 构建循环将多个任务组合为 Looper 循环组
💾 保存/加载将参数集保存为 JSON 文件
➡️ 推入队列确认后推入 ExperimentQ 排队执行

数据模型

PrepModel 继承 DictSyncModel,自动同步表格编辑到内部字典。表格列包括任务名、参数、重复次数和状态。

5.5 - 循环器 (Looper)

条件循环执行器——根据测量结果自动决定是否重复或切换实验。

概述

LooperQGroupBox 内的条件循环控制面板。它管理实验任务组,根据每次运行的测量结果自动判断是否继续循环或切换下一组任务。

核心逻辑

开始循环
  └─→ 运行当前组任务
       └─→ 读取测量结果
            ├─ 满足条件 → 继续循环当前组
            └─ 不满足 → 切换到下一组

组件

组件说明
groupDict循环组字典,每组合多个任务
DataManager管理测量结果数据
LoopManager控制循环逻辑和条件判断
AutoSaveEditor自动 HDF5 保存计划配置
LedIndicator循环运行状态指示灯

用法

# 在 PrepStation 中构建循环组后推入 Looper
looper.add_group("优化组", tasks=[task1, task2])
looper.add_group("测量组", tasks=[task3])
looper.set_condition("优化组.信号 > 阈值 → 切换到测量组")
looper.start()

5.6 - 实验窗口 (ExperimentWindow)

单实验控制窗口——动态构建参数界面并管理提交、扫描和参数持久化。

概述

ExperimentWindow 是每个实验文件的控制面板。它通过 importlib 动态加载实验模块,自动解析 NumberValue / BoolValue / StringCombo 参数并生成对应的控件界面。

功能

功能说明
🔍 动态加载importlib 导入实验模块,反射获取参数定义
🎛️ 参数界面自动生成 FloatBox / BoolBox / ComboBox 控件
📤 提交队列将当前参数集提交到 ExperimentQ
🔁 扫描参数设置参数扫描范围和步进
💾 保存/加载JSON 格式的参数集读写
✏️ 代码编辑内嵌 CodeEditor 查看和修改实验代码

参数解析

class MyExperiment(Experiment):
    cooling_time = NumberValue(100, unit='µs', minval=1, maxval=10000)
    readout_mode = BoolValue(False)
    qubit_select = StringCombo(['q0', 'q1', 'q2'])

这些定义自动生成带标签、单位和范围的控件。

5.7 - 参数系统

FloatBox/BoolBox/ComboBox——实验中参数参数的 GUI 控件体系。

概述

Quatm 提供了一套完整的参数 GUI 控件,将实验参数定义自动映射为可视化控件。所有控件继承 BasicManager 基类,通过 Properties 与实验运行时双向同步。

控件类体系

BasicManager (QFrame)
├── FloatManager → FloatBox  (QDoubleSpinBox)
├── BoolManager  → BoolBox   (QCheckBox)
└── ComboManager → ComboBox  (QComboBox)

FloatBox — 数值参数

from quatm.GUI.arg_boxes import FloatBox

box = FloatBox(
    props=props,
    value=NumberValue(100, unit='µs', minval=1, maxval=10000),
    parent=parent,
    display_multiplier=1,
    step=10,
    ndecimals=1,
)
参数说明
valueNumberValue 实例,含默认值、单位、范围
display_multiplier显示倍率(如 µs→ms 转换)
step步进值
ndecimals小数位数

BoolBox — 布尔开关

from quatm.GUI.arg_boxes import BoolBox

box = BoolBox(props=props, value=BoolValue(False), parent=parent)

ComboBox — 下拉选择

from quatm.GUI.arg_boxes import ComboBox

box = ComboBox(
    props=props,
    value=StringCombo(['q0', 'q1', 'q2']),
    parent=parent,
)

数据流

用户调整控件 → Properties 更新 → 实验脚本读取 self.param
实验脚本写入 self.param → Properties 通知 → GUI 控件刷新

5.8 - 属性编辑器 (PropertyEditor)

基于 pyqtgraph ParameterTree 的属性查看与编辑工具。

概述

PropEdit 是基于 pyqtgraph.parametertree.ParameterTree 的属性编辑器。它将 Properties 中的键值数据可视化为可展开的树状视图,支持动态类型识别和搜索过滤。

组件

组件说明
属性编辑器PropEditBWidget + ParameterTree,支持搜索和刷新
属性选择器PropSelectorQComboBox,下拉列出属性键
树生成器TreeEditProperties 字典转换为 Parameter 节点
可扩展组ScalableGrouppyqtgraph GroupParameter 子类,支持动态添加子参数

用法

from quatm.GUI.property_editor import PropEdit

editor = PropEdit(name="设备状态", parent=parent, props=props)
# 自动生成树状视图,双击节点编辑值

特性

  • 动态类型:自动识别 int/float/str/bool 并匹配对应控件
  • 搜索过滤:内置搜索框快速定位参数
  • 实时同步:修改自动写回 Properties

5.9 - 实时绘图 (UpdatingPlot)

基于 pyqtgraph 的实时一维数据流可视化。

概述

UpdatingPlot 继承 pyqtgraph.PlotItem,通过 DataClient 订阅数据流实现实时绘图。每 10ms 检查新数据,自动添加/移除曲线。

数据流

数据源 → ZeroMQ PUB → DataClient 订阅
                            ↓
                      UpdatingPlot (10ms 轮询)
                            ↓
                        pyqtgraph 渲染

用法

from quatm.GUI.updating_plot import UpdatingPlot

plot = UpdatingPlot(name="PMT 信号")
# 右键菜单 → 订阅编辑器 → 选择数据流

交互功能

功能说明
📊 多曲线自动管理多条数据曲线
🔍 缩放平移pyqtgraph 内置交互
📡 订阅管理SubscriptionEditor 选择数据源
⚙️ 属性配置PropEdit 调整显示参数

5.10 - LED 指示灯 (LedIndicator)

红/绿双色 LED 状态指示灯——带径向渐变和颜色切换动画。

概述

LedIndicator 继承 QAbstractButton,渲染一个带径向渐变效果的圆形 LED 灯。支持绿色/红色切换,常用于显示设备连接状态、实验运行状态等。

颜色模式

方法颜色说明
set_green()🟢通常表示正常/就绪
set_red()🔴通常表示错误/警告

视觉效果

  • 径向渐变:中心高亮 → 边缘暗色,模拟真实 LED 发光
  • 开关状态:On 时亮色,Off 时暗色(模拟熄灭状态)

用法

from quatm.GUI.qled import LedIndicator

led = LedIndicator(parent=parent)
led.set_green()   # 设备就绪
led.set_red()     # 设备异常

5.11 - GUI 基础类 (quatmQt)

BWidget、BMainWindow、BFrame——带几何持久化和属性通信的 Qt 基类。

概述

quatmQt.py 定义了所有 Quatm GUI 组件的基类,提供窗口几何持久化和 Properties 通信总线。

类层次

QWidget  → BWidget
QFrame   → BFrame
QMainWindow → BMainWindow

BWidget — 基础 Widget

from quatm.GUI.quatmQt import BWidget

widget = BWidget(name="my_widget", parent=None)
特性说明
几何持久化通过 QSettings 自动保存/恢复位置和大小
属性通信每个实例自动关联 Properties 实例
命名空间name 参数用于 QSettings 键和日志标识

BMainWindow — 主窗口基类

from quatm.GUI.quatmQt import BMainWindow

window = BMainWindow(name="MainWindow", parent=None)
window.setWindowTitle("Quatm")

BWidget 的全部特性外,还管理窗口标题和菜单栏。

CustomCompleter

from quatm.GUI.quatmQt import CustomCompleter

completer = CustomCompleter(items, parent)
completer.setFilterMode("contains")  # 或 "begins"

contains / begins 匹配模式的下拉自动补全组件,用于搜索框和命令输入。

5.12 - 图像监视器 (ImageMonitor)

实时科学图像显示与分析——支持 ROI、滤波和子类定制。

概述

ImageMonitor 用于实时显示科学相机采集的图像数据。支持 ROI 区域选择、图像滤波和自定义显示逻辑。

功能

功能说明
📷 实时显示高速刷新科学图像
🔲 ROI 选择矩形/自由形状感兴趣区域
🎚️ 滤波高斯、中值等图像预处理
🧬 可扩展子类化 ImageMonitor 定制显示逻辑

子类化示例

class FluorescenceMonitor(ImageMonitor):
    def process_image(self, image):
        # 自定义处理逻辑
        return image - background

参见 数据与分析 中的图像查看器和监视器文档。

5.13 - 分析管理器 (AnalysisManager)

树形视图面板——管理分析进程的启动、停止与状态监控。

概述

TreeViewWidget 是管理分析进程的树形视图面板。它显示所有注册的分析模块,支持启动/停止单个进程、批量终止游离进程,以及实时状态监控。

功能

操作说明
▶️ 启动选中分析模块并启动对应进程
⏹ 停止终止运行中的分析进程
🔄 状态刷新实时更新各进程运行状态
🧹 清理终止所有失去响应的游离进程

用法

from quatm.GUI.analysismanager import TreeViewWidget

mgr = TreeViewWidget(parent=parent)
mgr.addItem("ROI 分析", "roi_analysis")
mgr.startProcess("roi_analysis")

5.14 - 数据流监视器 (StreamMonitor)

多类型实时数据流监视——支持曲线、图像和文本消息三合一。

概述

StreamMonitor 通过 DataClient 订阅 ZeroMQ 数据流,实时显示三种类型的数据:一维数值曲线、二维科学图像和文本日志消息。

功能模式

模式说明
📈 曲线实时滚动的数值曲线(如 PMT 信号、温度)
🖼️ 图像二维科学图像流(如相机快照)
📝 消息文本日志或状态消息流

用法

from quatm.GUI.streammonitor import StreamMonitor

monitor = StreamMonitor(props=props, parent=parent)
# 右键 → 订阅编辑器 → 选择数据流

5.15 - 序列编辑器 (EditorSequencer)

代码编辑器 + 时序可视化——QScintilla 编辑 + 多通道状态图渲染。

概述

ExperimentSequencer 将 Python 实验代码与可视化时序图关联。CodeEditor 基于 QScintilla 提供语法高亮和自动补全;ExperimentSequencer.plotSequence() 将代码解析为 TTL/模拟通道的时序状态图。

组件

组件说明
CodeEditorQScintilla Python 编辑器,语法高亮
ExperimentParser解析实验代码提取时序指令
ExperimentSequencer渲染多通道状态图

用法

from quatm.GUI.editor_sequencer import ExperimentSequencer

seq = ExperimentSequencer(parent=parent)
seq.setCode(code_str)
seq.plotSequence()  # 渲染时序图

5.16 - 进程管理器 (ProcessManager)

分布式进程面板——管理 Server/Driver/GUI/Viewer/Monitor 五类后台进程。

概述

ProcessManager 管理 Quatm 分布式架构中的所有后台进程。进程分为五类:Server(通信)、Driver(设备驱动)、GUI(图形界面)、Viewer(数据查看)和 Monitor(环境监控)。

进程类别

类别说明典型进程
ServerZeroMQ 通信服务CommandHub, DataHub
Driver设备驱动进程Andor, ADwin, Valon
GUI图形界面进程Browser, PrepStation
Viewer数据查看进程UpdatingPlot, StreamMonitor
Monitor环境监控进程温度、真空监测

用法

from quatm.GUI.processmanager import ProcessManager

pm = ProcessManager(parent=parent)
pm.startProcess("Andor", "Driver")
pm.stopProcess("Andor")

5.17 - 设备管理器 (DeviceManager)

PyVISA 设备发现与驱动绑定——扫描、查询、选择 VISA 仪器。

概述

VISADeviceLister 通过 PyVISA 扫描系统中所有 VISA 仪器,支持设备识别查询和驱动文件绑定。它生成 DeviceInfo 对象,供 device_db.py 配置使用。

工作流

1. refresh_devices() → 扫描 VISA 总线
2. query_device_info() → 获取 *IDN? 标识
3. select_driver_file() → 绑定驱动类
4. add_device_to_selected() → 添加到 device_db

用法

from quatm.GUI.device_manager import VISADeviceLister

dl = VISADeviceLister(parent=parent)
dl.refresh_devices()
# 列表中显示所有 USB/GPIB/LAN VISA 设备

5.18 - 数据存储 (H5Storage)

HDF5 数据存储/加载/定时保存——含数据选择与绘图一体化面板。

概述

H5StorageGui 提供 HDF5 文件的读写、定时自动保存和数据可视化。支持多标签页数据浏览、binning 处理和 inline 绘图。

功能

功能说明
💾 保存实验数据写入 HDF5 文件
📂 加载从 HDF5 文件恢复实验数据
⏱️ 定时保存按时间表自动执行保存
📊 绘图内嵌 BinningWidget 数据可视化
🧹 清空清除已保存数据

用法

from quatm.GUI.h5storage import H5StorageGui

storage = H5StorageGui(props=props, parent=parent)
storage.savetoFile("data.h5")
storage.loadFromFile("data.h5")

5.19 - 实时滚动图 (LivePlot)

实时滚动折线/散点图——数据流订阅、运行平均与多曲线。

概述

ScrollPlot 提供基于 pyqtgraph 的实时滚动图表。支持折线图和散点图模式、运行平均滤波和多曲线叠加。

功能

功能说明
📈 滚动显示最新数据自动滚动到视野内
📊 散点图setScatterplot() 切换模式
🔢 运行平均running_mean 参数平滑数据
📡 订阅通过 DataClient 订阅数据流
🎨 多曲线同时显示多条数据曲线

用法

from quatm.GUI.live_plot import ScrollPlot

plot = ScrollPlot(name="实时信号", parent=parent)
plot.subscribe_window()  # 选择数据源
plot.feedData(new_data)

5.20 - 自动保存编辑器 (AutoSaveEditor)

定时保存时间表编辑器——配置 HDF5 自动保存的频率和触发条件。

概述

AutoSaveEditor 是一个弹窗编辑器,用于配置实验数据的定时自动保存计划。设置保存间隔、触发条件和目标路径。

配置项

参数说明
保存间隔定时保存的时间间隔
触发条件按时间或事件触发
目标路径HDF5 文件存储位置

用法

from quatm.GUI.auto_save_editor import AutoSaveEditor

editor = AutoSaveEditor(props=props, parent=parent)
editor.load_AutoSaveEditor_props()
editor.update_ticked([dt1, dt2, dt3])

5.21 - 实验辅助工具

ODT 对准、电场补偿、Verdi 对准——实验自动化校准与优化工具集。

概述

Quatm 将日常实验校准任务封装为 GUI 辅助工具,实现一键运行和自动优化。


ODT 对准辅助 — OdtAlignmentHelper

通过 AC 斯塔克位移信号自动优化光偶极阱的激光对准。

from quatm.GUI.odt_alignment_helper import OdtAlignmentHelper

helper = OdtAlignmentHelper(props=props, parent=parent)
helper.run_all()  # 执行完整对准流程

杂散场补偿 — CompensationHelper

通过迭代测量各轴补偿电压,自动最小化杂散电场/磁场。

组件说明
PlotWidget三轴补偿信号的实时绘图
ControlWidget补偿参数的手动微调面板
from quatm.GUI.comp_helper import CompensationHelper

comp = CompensationHelper(props=props, parent=parent)

Verdi 对准辅助 — VerdiAlignmentHelper

通过压电镜控制与 AC 斯塔克信号优化 Verdi 泵浦激光对准。

from quatm.GUI.verdi_alignment_helper import VerdiAlignmentHelper

verdi = VerdiAlignmentHelper(props=props, parent=parent)

压电镜控制 — PiezoMirrorControl

简单四方向面板,通过按钮或键盘(WASD)控制压电反射镜。

from quatm.GUI.piezo_mirror_controler import PiezoMirrorControl

mirror = PiezoMirrorControl(props=props, parent=parent)
# WASD 或点击方向键控制

多功能助手 — LittleHelper

聚合以上所有辅助工具的标签页主窗口。

python -m quatm.GUI.little_helper

5.22 - 数据模型 (Models)

DictSyncModel/ListSyncModel——将 Python 字典/列表自动映射为 Qt 表格。

概述

models.py 提供将 Python 数据结构映射为 Qt 表格模型的基类。ExperimentQPrepStationLooper 的表格界面均基于此构建。

核心类

说明
_SyncSubstruct字典操作辅助,支持 append/insert/pop 回调
DictSyncModel字典→表格映射基类,支持排序、编辑、删除
ListSyncModel列表→表格映射基类
ScheduleModelExperimentQ 的排序模型(优先级+任务号)

用法

from quatm.GUI.models import DictSyncModel

model = DictSyncModel(
    headers=["名称", "值", "单位"],
    dataNames=["name", "value", "unit"],
    init={"name": "param1", "value": 100, "unit": "µs"}
)

5.23 - 可折叠组件 (Expandables)

CollapsibleDialog——可折叠/展开的手风琴式树形对话框。

概述

CollapsibleDialog 提供手风琴式可折叠面板对话框。每个面板包含一个展开/折叠按钮和自定义内容区域,适合配置界面和高级参数设置。

核心类

说明
SectionExpandButton三角形箭头按钮,点击展开/折叠
CollapsibleDialog树形对话框容器,add_section() 添加面板

用法

from quatm.GUI.theexpandables import CollapsibleDialog

dialog = CollapsibleDialog(title="高级设置", parent=parent)
dialog.add_section("相机设置", QLabel("曝光时间"))
dialog.add_section("触发设置", QLabel("触发源"))

5.24 - 参数框 (ParameterBox)

紧凑型实时参数显示——标签-数值对面板,订阅数据流自动刷新。

概述

ParameterBox 以紧凑的标签-数值对形式显示实时数据流中的单个参数。自动订阅数据流并更新显示,适合仪表盘式监控面板。

用法

from quatm.GUI.parameterbox import ParameterBox

box = ParameterBox(prop_key="pmt_signal", parent=parent)
box.subscribe_window()  # 选择数据源
# 实时显示 PMT 信号值

5.25 - 实验参数面板 (SimpleDefaults)

DefaultExp + 参数管理器基类——从设备数据库自动构建实验属性 UI。

概述

simple_defaults.py 是 Quatm 参数 UI 的底层框架。DefaultExpdevice_db.py 加载所有设备属性并按 group 键自动分组,BasicManager 系列类提供 Float/Int/Bool/String/Frequency 等多种参数输入控件。

类体系

DefaultExp (Experiment)
└── 自动加载 device_db 属性 → 分组

BasicManager (QFrame)
├── IntManager     → QSpinBox
│   ├── FloatManager    → QDoubleSpinBox
│   └── FrequencyManager → 频率输入
├── BoolManager    → QCheckBox
└── ComboManager   → QComboBox

DefaultExp

from quatm.GUI.simple_defaults import DefaultExp

exp = DefaultExp(props=props)
# 自动生成 group 分组:{"激光器": [param1, param2], "探测": [param3]}

BasicManager

所有参数控件的基类,自动从 Properties 同步值:

from quatm.GUI.simple_defaults import FloatManager

mgr = FloatManager(
    props=props, parent=parent,
    name="cooling_time",
    unit="µs", minval=1, maxval=10000,
    step=10, ndecimals=1, default_value=100,
)
参数说明
name参数名,对应 Properties 键
unit显示单位(后缀)
minval/maxval值范围
display_multiplier显示倍率
ndecimals小数位数

5.26 - ADwin DAC 控制 (SimpleAdwin)

ADwin 16 路 DAC 通道手动电压设置工具。

概述

DACvaluesDACsingle 提供 ADwin 系统 16 个 DAC 通道的手动电压设置界面,用于调试和校准时的独立通道控制。

组件

组件说明
DACvalues16 通道批量电压设置面板
DACsingle单通道精细调节控件

用法

from quatm.GUI.simple_Adwin import DACvalues

dac = DACvalues(adwin_device=adw, parent=parent)
dac.set_channel(0, 5.0)  # 通道 0 输出 5V

5.27 - 后台工作线程 (Workers)

Worker/WorkerSignals——通用 QRunnable 后台线程封装。

概述

browser_workers.pyhelper_workers.py 提供基于 QRunnable 的通用后台工作线程封装,通过信号机制传递 finished/error/result/progress 状态。

信号

信号说明
finished任务完成
error(tuple)异常信息
result(object)返回结果
progress(int)进度百分比
terminate请求终止(helper_workers 扩展)
publish数据发布(helper_workers 扩展)

用法

from quatm.GUI.browser_workers import Worker

worker = Worker(fn=my_long_task)
worker.signals.finished.connect(on_done)
worker.signals.error.connect(on_error)
QThreadPool.globalInstance().start(worker)

5.28 - 实验时间线 (Timeline)

ADwin 实验时序可视化——DAC 和 TTL 通道随时间变化的图表查看器。

概述

Timeline 加载 ADwin 记录的实验数据,将多通道 DAC 电压和 TTL 状态渲染为时间序列图表,方便调试和验证实验时序逻辑。

用法

from quatm.GUI.experiment_timeline import Timeline

tl = Timeline(data_file="experiment_trace.h5")
tl.show()
# 查看 DAC 通道 1-4 和 TTL 通道 1-8 的时序

5.29 - 滚动波形窗口 (ScrollWindow)

多通道实时滚动波形显示窗口,支持数据流订阅与动态更新。

概述

ScrollWindowBMainWindow 子类的多通道实时波形显示器。内嵌 ScrollPlot 绘图组件和 PlotDataEditor 数据配置面板。

组件

组件说明
ScrollWindow主窗口,管理多通道布局
ScrollPlotpyqtgraph 实时滚动波形图
PlotDataEditor数据源选择和显示参数配置

用法

from quatm.GUI.scrollwindow import ScrollWindow

win = ScrollWindow(name="PMT 监测", parent=parent)
win.subscribe_channels(["ch1", "ch2"])

5.30 - 订阅编辑器 (SubscriptionEditor)

管理数据/图像流的订阅列表——添加、删除和浏览已订阅的数据源。

概述

SubscriptionEditor 提供一个对话框界面,列出所有可用的数据流和图像流,支持添加/删除订阅,是 UpdatingPlotLivePlotStreamMonitor 的数据源选择组件。

用法

from quatm.GUI.subscription_editor import SubscriptionEditor

editor = SubscriptionEditor(props=props, parent=parent)
editor.add_subscription("pmt_signal")

5.31 - 表格参数 (TableParameter)

基于 QTableWidget 的 numpy 结构化数组编辑器——用于 pyqtgraph 参数树。

概述

table_parameter 提供 pyqtgraph ParameterTree 的表格编辑节点。允许在参数树中直接编辑 numpy 结构化数组(如校准表、扫描序列)。

用法

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

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

5.32 - 远程 ROI (zmq_ROI)

通过 Properties 发布位置/大小的可远程同步 ROI 组件。

概述

zmq_ROI 继承 pyqtgraph.ROI,将其位置和大小属性通过 ZeroMQ Properties 发布到网络,允许远程客户端同步查看和调整 ROI 区域。

用法

from quatm.GUI.zmq_ROI import zmq_ROI

roi = zmq_ROI(name="分析区域", props=props, parent=view)
# 拖动 ROI → Properties 自动更新 → 远程同步

5.33 - 图像查看器 (ImageWindow)

带侧边线剖面和直方图 LUT 的科学图像查看器主窗口。

概述

ImageWindowBMainWindow 子类的科学图像查看器。支持多 dock 布局:侧边线剖面(x/y 方向强度分布)、直方图 LUT 调节和 ROI 分析。

功能

功能说明
🖼️ 图像显示高动态范围科学图像渲染
📏 线剖面水平和垂直方向的强度剖面
🎨 LUT直方图调节伪彩色映射
🧩 多 dock灵活的子窗口布局

用法

from quatm.GUI.image_group import ImageWindow

win = ImageWindow(name="吸收成像", parent=parent)
win.set_image(absorption_image)

5.34 - 属性检查器 (PropertiesChecker)

轮询检测 Properties 系统状态——异常时弹窗+声音告警。

概述

PropertiesChecker 定时轮询 Quatm 的 Properties 通信总线,检测关键属性的健康状态。当检测到异常(如设备断连、数据超时)时弹出告警窗口并播放声音提示。

用法

from quatm.GUI.properties_checker import PropertiesChecker

checker = PropertiesChecker(props=props, interval_ms=5000)
checker.start_monitoring()

5.35 - 辅助绘图 (HelperPlotter)

通用测量数据绘图组件——多 Y 轴、滤波、拟合。

概述

DataPlotterWidgetDataSummary 获取测量数据并自动渲染图表。支持多 Y 轴叠加、数据滤波和曲线拟合。

功能

功能说明
📊 自动绘图从 DataSummary 提取测量数据
📈 多 Y 轴不同量纲的数据叠加显示
🔢 滤波运行平均、中值滤波
📐 拟合线性/指数/高斯曲线拟合

用法

from quatm.GUI.helper_plotter import DataPlotterWidget

plotter = DataPlotterWidget(data_summary=summary, parent=parent)
plotter.plot_all()

6 - 通信层

Quatm 分布式通信与数据管理系统 — 基于 ZeroMQ 的进程间通信框架

概述

通信层是 Quatm 框架的通信骨干。所有进程间通信(设备驱动、分析脚本、GUI 面板之间的数据交互)都通过 ZeroMQ 的 发布/订阅(PUB/SUB) 模式进行,命令与控制则通过 RPC 实现。这确保了:

  • 故障隔离:某个相机驱动崩溃不会导致整个实验中断
  • 并行处理:图像处理与实验时序可同时运行
  • 网络透明:各组件可以运行在不同的机器上
实验脚本
     │
     ▼
[with realtime():]  ──→  FPGA  ──→  DAC/TTL 输出
     │
     ▼
分析脚本  ◄──  图像/数据流 (ZMQ PUB/SUB)
     │
     ▼
结果发布  ──→  DataManager  ──→  HDF5 存储

客户端类型

quatm.servers 提供了四种标准客户端,用于处理不同类型的进程间通信:

客户端用途适用场景
CommandClient控制驱动和进程向设备发送指令、启停驱动
DataClient传输小数据1D 曲线、标量值、元数据
ImageClient传输大数据块相机图像(2D 数组)
MessageClient日志消息传递错误、警告、信息、调试消息

基础客户端 — GenericClient

所有客户端的基类,封装了 ZMQ 连接和数据收发逻辑。

from quatm.servers.clients import GenericClient

client = GenericClient("my_channel")
client.subscribe("data_stream_name")
# 发送数据
client.send({"temperature": 25.0, "timestamp": 12345})
# 接收数据
if client.has_new_data():
    data = client.recv()
方法说明
subscribe(name)订阅指定的数据流
unsubscribe(name)取消订阅
send(data)发送数据
recv()接收数据
has_new_data()检查是否有新数据到达

数据客户端 — DataClient

专为小数据集设计的客户端,数据以 JSON 格式序列化,支持 NumPy 数组附件。

from quatm.servers.clients import DataClient

data_client = DataClient("analysis_result")
data_client.send({
    "fit_params": {"A0": 1.5, "sigma": 0.3, "pos": 10.2},
    "fit_curve": numpy_array
})

图像客户端 — ImageClient

优化用于传输相机图像等大型 2D 数据块。

from quatm.servers.clients import ImageClient

img_client = ImageClient("camera_output")
img_client.send(image_array)  # 发送 NumPy 图像数组

命令客户端 — CommandClient

用于向驱动程序发送控制命令,使用独立通道以确保命令不被数据流阻塞。

消息客户端 — MessageClient

标准化的消息传递接口,所有消息带有时间戳和来源信息。

from quatm.servers import send_error, send_warning, send_info, send_debug

send_info("实验开始执行")
send_warning("激光功率偏低,请检查")
send_error("相机连接失败")

分布式属性系统

Quatm 通过分布式属性树管理所有运行时配置参数,支持跨进程实时同步。

配置层级

层级说明示例
Configuration深层、基础系统属性运行哪些硬件、可用驱动列表
Properties对象特定参数ROI 位置、校准值、拟合参数
Preferences不影响数据的次要选择鼠标指针形状、窗口位置

PropertyAttribute

将分布式属性映射为 Python 属性,读写操作自动同步到属性树。

from quatm.servers.properties import PropertyAttribute, Properties

class MyComponent:
    # 声明分布式属性,默认值为 42.0
    _my_param = PropertyAttribute('/MyComponent/param', 42.0)

    def __init__(self):
        self._props = Properties('MyComponent')

    def do_something(self):
        # 读取属性值
        x = self._my_param.value
        # 写入属性值,自动同步到分布式树
        self._my_param.value = 99.0

Properties

管理组件内部属性的同步副本,通过后台守护线程使用 ZMQ PUB/SUB 连接到中央属性中心。

from quatm.servers.properties import Properties

props = Properties('MyProcess')
props.set('/path/to/property', value)
current_value = props.get('/path/to/property')

配置读取器

读取静态配置文件 configuration/configfile.json,提供系统级别的运行时配置。

from quatm.servers.configreader import ConfigReader

reader = ConfigReader()
config = reader.getConfiguration()

常用路径常量

quatm.servers 导出以下路径常量,方便定位工作目录:

常量说明
workpath工作根目录
driverpath驱动文件目录
iconpath图标资源目录
datapath数据存储目录
experiment_path实验脚本目录
configpath配置文件目录

6.1 - ZMQ 客户端 (clients)

DataClient/ImageClient/CommandClient——ZeroMQ 发布/订阅通信。

概述

clients.py 提供 Quatm 的核心 ZMQ 通信基础设施。各级客户端通过 PUB/SUB 模式收发数据、图像和命令。

客户端类

数据类型用途
GenericClient基类,socket 管理 + JSON 序列化
DataClientdict + numpy array一维数据流发送/接收
ImageClientnumpy image二维图像流传输
CommandClientstring设备驱动命令发送

用法

from quatm.servers.clients import DataClient

dc = DataClient(props=props)
dc.send({"pmt": 1234}, arr=numpy_array)
data = dc.recv(timeout=1000)  # ms

6.2 - 属性树 (Properties)

分布式分层属性树——类 Unix 路径语法,ZMQ 实时同步。

概述

Properties 是 Quatm 的核心状态管理系统。它是一个分层键值树,通过 ZMQ REP/XPUB 在进程间实时同步变更。

说明
Properties线程化属性树服务,ZMQ 发布/订阅同步
PropertyAttribute描述符式树节点访问器

用法

from quatm.servers.properties import Properties

props = Properties()
props["laser/power"] = 50e-3      # 设置
power = props["laser/power"]       # 读取
props.subscribe("laser/*")         # 监听子树

# 远程访问(另一进程)
value = props["camera/exposure"]   # 自动 ZMQ 同步

6.3 - 数据管理 (DataSummary)

多流数据聚合——按实验运行对齐,超时补齐后 HDF5 存储。

概述

DataSummary 聚合多个 ZMQ 数据流,按实验运行自动对齐时间轴,补齐缺失数据,并以 HDF5 格式保存结构化数据集。

from quatm.servers.datamgr import DataSummary

summary = DataSummary(props=props, streams=["pmt", "temperature"])
summary.start()
# 每次实验结束后自动保存: experiment_001.h5

6.4 - 消息系统 (MessageClient)

标准化日志消息——info/warning/error/debug 四级,时间戳+源标识。

概述

MessageClient 提供跨进程的标准化日志消息系统,支持四级日志级别。

全局函数

函数级别
send_info(msg)ℹ️ 信息
send_warning(msg)⚠️ 警告
send_error(msg)❌ 错误
send_debug(msg)🐛 调试
from quatm.servers.messageclient import send_error, send_info

send_info("实验启动完成")
send_error("相机连接超时")

6.5 - 配置与属性持久化

configreader + propertylogger——JSON 配置文件读取与属性树磁盘持久化。

模块

模块功能
configreader.ConfigReader读取 configfile.json 配置
configreader.Properties()读取 properties.json 启动属性
propertylogger.run_propertylogger()定期将属性树写入磁盘 JSON
datalogger.DataStreamLogger监控活跃数据流并记录时间戳
imagelogger.ImageStreamLogger监控活跃图像流并记录时间戳
from quatm.servers.configreader import ConfigReader

cfg = ConfigReader()
work_path = cfg.get("workpath")
device_db = cfg.get("device_db")

6.6 - 外围服务模块

CameraHub、InfluxDB、Mattermost、Bokeh、ZMQ 代理等外围服务。

服务列表

模块功能
camerahub.CameraHubFLIR Spinnaker 相机发现/启动/配置
influxdb.influxdbInfluxDB 时间序列数据写入与查询
mattermost.post_to_mattermost()Mattermost 频道消息/文件发送
image_network_serverBokeh Web 实时图像浏览器
xsub_xpub.run_server()ZMQ XSUB/XPUB 代理服务
experiment_status实验状态监控→Mattermost 通知
from quatm.servers.influxdb import influxdb

db = influxdb(host="localhost", database="quatm")
db.write("temperature", {"lab_temp": 22.5})

7 - 部署指南

在实际实验环境中部署和运行 Quatm 框架的指南。

部署架构

Quatm 的通信基于 ZeroMQ,支持灵活的网络拓扑:

┌──────────────────┐        ZeroMQ        ┌──────────────────┐
│  控制端 (实验室)   │ ◄──────────────────► │  客户端 (办公)    │
│  • 设备驱动        │                      │  • GUI 浏览器     │
│  • 实验引擎        │                      │  • 参数编辑器     │
│  • 数据采集        │                      │  • 数据监视器     │
└──────────────────┘                      └──────────────────┘

核心服务

服务模块功能
数据管理datamgr.DataSummary接收、存储实验数据为 HDF5
数据记录datalogger实时数据流记录
图像记录imagelogger图像数据存储
属性管理properties.Properties分布式属性同步
配置读取configreader路径和配置管理
消息转发xsub_xpubZeroMQ 消息代理

单机部署

所有组件在同一台计算机上运行:

git clone https://github.com/quatm/quatm.git
cd quatm
pip install -r requirements.txt
# 编辑 configuration/device_db.py
python -m quatm.GUI.browser

分离部署

控制端运行实验引擎,客户端远程连接:

# 控制端(实验室计算机)
python -m quatm.servers.experiment_server --port 7777

# 客户端(办公计算机)
python -m quatm.GUI.browser --connect 192.168.1.100:7777

系统服务(Linux)

[Unit]
Description=Quatm Experiment Server
After=network.target

[Service]
Type=simple
User=labuser
WorkingDirectory=/home/labuser/quatm
ExecStart=/home/labuser/.venv/bin/python -m quatm.servers.experiment_server
Restart=always

[Install]
WantedBy=multi-user.target

数据存储

  • 本地:HDF5 格式,保存在 Data/年-月-日/ 目录
  • 远程:支持 InfluxDB 推送(配置 properties.json

8 - 实验框架

Quatm 实验调度、任务管理、序列编辑与运行监控的核心组件文档。

quatm.experiment 包

该包提供对实验的完整控制。用户可以编写简单或高级的实验脚本并执行。

教程

快速开始

要定义一个实验,需要创建一个继承自 Experiment 的类,并至少定义 buildrun 两个方法。在 build 阶段,会创建一个实验窗口用于进一步配置。run 阶段在点击窗口中的"运行"按钮时执行,可多次执行以实现重复测量或参数扫描。

简单示例:

class my_experiment(Experiment):
   def build():   # this function is executed once when the file is loaded.
      # you want to use the dac MyDAC you configured in device.db
      self.setattr_device("Mydac")   # -0.1600
      # define additional variables
      self.setattr_argument("targetvoltage", NumberValue(ndecimals=2, step=0.01, value=4.00))

   def run():  # this function is executed for each run of the experiment
      self.Mydac = 1      # set the dac to 1V
      delay(1)          # delay 1 second
      self.Mydac = self.targetvoltage # set the DAC to a user-defined target voltage

在此示例中,声明需要使用 Mydac DAC。Mydac 必须是 device_db 中的有效条目。所有 setattr_... 函数应放在 build 阶段。

额外定义的变量是 targetvoltagesetattr_argument 用于在实验窗口中创建可通过 GUI 设置或扫描的字段,默认值为 4,步长为 0.01。

run() 阶段,输出设为 1V,等待一秒后设为用户定义的值。build 阶段定义的属性可通过 self 前缀在 run 阶段访问。

基本配置

配置文件 device_db.py 位于 configuration 目录中,定义了一个名为 device_db 的字典。每个键对应一个可在实验中使用的设备。以下示例配置了一个 TTL 通道和一个 DAC 通道。

示例:

device_db = {
   "controller": {
      "type": "local",
      "module": "quatm.drivers.fpga.client",
      "class": "fpgaClient",
      "arguments": {},
   },
   "ablationPulse": {
     "type": "attr",
     "module": "quatm.experiment.ttl",
     "class": "TTLOut",
     "arguments": {"channel": 0},
   },
   "trapX2": {
     "type": "attr",
     "module": "quatm.experiment.dac",
     "class": "DAC",
     "arguments": {"channel": 2},
   }
}

配置文件中定义了两类设备。第一类是 FPGA 控制器的 local 驱动。module 指向驱动类所在的 Python 模块,class 指定要实例化的类,arguments 为传递给构造函数的参数。

第二类将一个 TTL 通道映射为实验属性。使用 TTL 或 DAC 属性设备前,必须先定义对应的控制器驱动。

第三类定义了一个 DAC 通道。DAC 通道可指定额外的参数(如校准文件)。

接入自定义驱动

假设你编写了 evalcontrol 驱动模块,包含 AD9959 类。该类接受 bus_numberport_numbers 参数,提供 set_frequency 方法设置 DDS 频率。DDS 多通道需指定目标通道。

我们希望通过 Li_frequency 属性访问 DDS 的通道 0,并将软件限制在 40-90 MHz 以保护硬件。对应的 device_db 配置如下:

自定义驱动配置示例:

device_db = {
   ...

   "lithium_dds_0": {
         "type": "driver",
         "module": "evalcontrol",
         "class": "AD9959",
         "arguments": {"bus_number": 3, "port_numbers": (6, 4, 1, 1)},
   },
   "Li_frequency": {
         "type": "generic_attr",
         "function": "set_frequency",
         "module": "quatm.experiment.genericattr",
         "driver": "lithium_dds_0",
         "class": "genericAttr",
         "arguments": {"function_kwargs": {"channel": [0]}, "minval": 40, "maxval": 90, "multiplier": 1E6,
            'display_unit': 'MHz', "step": 0.1},
   },

   ...
}

第一条配置生成驱动类的实例。之后可通过 generic_attr 定义多个参数,每个参数调用驱动类中的不同函数。function 指定要调用的函数名,function_kwargs 传递额外参数。minval/maxval 提供软件限制,multiplier 控制显示单位。编写实验脚本时应使用 SI 单位,GUI 通过 display_unitmultiplier 显示。step 控制 GUI 步长。

配置完成后,在实验中这样使用:

class my_experiment(Experiment):
   def build():
      self.setattr_device("Li_frequency")
      self.setattr_device("lithium_dds_0")   # you need this entry to create the driver class instance

   def run():
      self.Li_frequency = 66E6                 # set the DDS to 66MHz
      delay(1)                               # delay 1 second
      self.Li_frequency = 50E6                 # set DDS to 50MHz

使用校准文件

Quatm DAC 通道支持校准文件。例如,当电压控制衰减器的响应为非线性时,可使用校准文件将期望的 RF 功率映射为实际 DAC 值。校准文件为两列空格分隔的文本文件(可用 numpy.loadtxt 读取)。

一个典型的校准文件内容如下:

2.2 4
2   3.8
1.8 3.6
1.6 3.34
1.4 3.12
1.2 2.90
1.0 2.68
0.8 2.48
0.6 2.26

第一列为 DAC 值,第二列为 RF 功率。两列关系应严格单调。建议使用 SI 基本单位(如 1.12E-7 W 而非 11.2 µW)。

使用时在 DAC 配置中通过 gauge 参数指定校准文件路径(相对于项目根目录)。

一般情况下 device_db.py 的内容结构如下:

device_db = {
   ...

   "rf": {
      "type": "attr",
      "module": "quatm.experiment.dac",
      "class": "DAC",
      "arguments": {"channel": 9, "minval": 0.1, "maxval": 

8.1 - 数据类控件

该代码实现了三个自定义的GUI控件类,用于处理实验中的浮点数、布尔值和组合框参数。代码使用了quatm.GUI.simple_defaults模块中的FloatManagerBoolManagerComboManager作为基类,并扩展了它们的功能。主要类包括:FloatBoxBoolBoxComboBox

类和方法

FloatBox

FloatBox 继承自 FloatManager,用于处理实验中的浮点数参数。

方法:

  • __init__(self, props, value, parent=None, **kwargs):初始化浮点数控件。

    • props:属性对象,用于存储和管理配置数据。
    • value:初始值。
    • parent:父窗口。
    • **kwargs:其他关键字参数,包括参数名称等。
    • 调用父类的初始化方法,并传递参数名称。
  • updateValue(self, value):更新实验中的对应参数。

    • value:新的浮点数值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。

BoolBox

BoolBox 继承自 BoolManager,用于处理实验中的布尔值参数。

方法:

  • updateValue(self, value):更新实验中的对应参数。

    • value:新的布尔值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。
  • updateCheckbox(self):更新复选框状态。

    • 如果属性中的值与当前复选框的状态不一致,则更新复选框的状态。

ComboBox

ComboBox 继承自 ComboManager,用于处理实验中的组合框参数。

方法:

  • updateValue(self, value):更新实验中的对应参数。
    • value:新的组合框值。
    • 将值转换为字符串列表中的对应值。
    • 更新控件的值,并在属性对象中设置对应的参数值和最后设置的参数信息。

类的详细说明

FloatBox

FloatBox类用于处理实验中的浮点数参数。它继承自FloatManager,并扩展了其功能,以便在属性对象中设置参数值。

class FloatBox(FloatManager):
    ''' Box for handling the attribute argument

    Args:
        argument:(NumberValue)
            points to the argument in the experiment

        unit:(str)
            unit string

        display_multiplier:(float)
            multiplication factor for the unit

    '''
    def __init__(self, props, value, parent=None, **kwargs):
        super().__init__(props, parent, parName=kwargs['name'], **kwargs)

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        self.value = value*self.display_multiplier
        if self._props:
            self._props.set(self.parName, value*self.display_multiplier)
            self._props.set('last_set', self.parName+': '+str(value))

BoolBox

BoolBox类用于处理实验中的布尔值参数。它继承自BoolManager,并扩展了其功能,以便在属性对象中设置参数值。

class BoolBox(BoolManager):
    ''' GUI for boolean values

    KWArgs:
        parName:(str)
            name of the parameter
        value:(BoolValue)
            reference to the argument class

    '''

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        self.value = bool(value)
        if self._props:
            self._props.set(self.parName, bool(value))
            self._props.set('last_set', self.parName+': '+str(value))

    def updateCheckbox(self):
        ''' updates the spin box if properties have changed '''
        val=self.value     #the values in properties are in SI units. Non SI only on disp
        if val != self.isChecked():
            self.setChecked(val)

ComboBox

ComboBox类用于处理实验中的组合框参数。它继承自ComboManager,并扩展了其功能,以便在属性对象中设置参数值。

class ComboBox(ComboManager):
    ''' GUI for boolean values

    KWArgs:
        parName:(str)
            name of the parameter
        argument:(BoolValue)
            reference to the argument class
    '''

    def updateValue(self, value):
        '''Update the corresponding argument in Experiment

        Args:
            value:(type needs to correspont the to the argument type it represents
        '''
        value = self.stringlist[value]

        self.value = value
        if self._props:
            self._props.set(self.parName, value)
            self._props.set('last_set', self.parName+': '+str(value))

总结

该代码实现了三个自定义的GUI控件类:FloatBoxBoolBoxComboBox,用于处理实验中的不同类型的参数。这些类继承自相应的管理类,并扩展了它们的功能,以便在属性对象中设置和更新参数值。

8.2 - 实验窗口控件类

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承Qt的基本控件类,并添加了一些自定义的功能来实现。

类和方法

BWidget

BWidget 继承自 QWidget,实现了一个基础窗口小部件类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化窗口小部件。

    • name:窗口小部件名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复窗口几何设置。
  • closeEvent(self, event):处理窗口关闭事件。

    • event:关闭事件。
    • 保存窗口几何设置并调用父类的关闭事件处理方法。

BFrame

BFrame 继承自 QFrame,实现了一个基础框架类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化框架。

    • name:框架名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复框架几何设置。
  • closeEvent(self, event):处理框架关闭事件。

    • event:关闭事件。
    • 保存框架几何设置并调用父类的关闭事件处理方法。

BMainWindow

BMainWindow 继承自 QMainWindow,实现了一个基础主窗口类,包含移动和调整大小事件的日志记录功能。

方法:

  • __init__(self, name='Noname', parent=None):初始化主窗口。

    • name:主窗口名称,默认为’Noname’。
    • parent:父窗口。
    • 初始化属性对象并恢复主窗口几何设置。
  • closeEvent(self, event):处理主窗口关闭事件。

    • event:关闭事件。
    • 保存主窗口几何设置并调用父类的关闭事件处理方法。

CustomCompleter

CustomCompleter 继承自 QCompleter,实现了一个自定义的自动完成器。

方法:

  • __init__(self, items, parent=None, match_flag='contains'):初始化自动完成器。

    • items:自动完成项。
    • parent:父窗口。
    • match_flag:匹配标志,默认为’contains’。
    • 设置完成模式为弹出完成。
  • pathFromIndex(self, index):根据索引返回路径。

    • index:索引。
    • 根据匹配标志返回路径。

SearchComboBox

SearchComboBox 继承自 QComboBox,实现了一个带有自动完成功能的组合框。

方法:

  • __init__(self, parent=None, match_flag='contains'):初始化组合框。

    • parent:父窗口。
    • match_flag:匹配标志,默认为’contains’。
    • 设置可编辑性和自动完成器。
  • add_if_new(self, text):如果文本不存在,则添加并返回索引。

    • text:文本。
    • 如果文本不存在于组合框中,则添加并返回其索引。
  • find_or_add(self, text):如果文本存在则设置当前项,如果不存在则添加并设置当前项。

    • text:文本。
    • 查找或添加文本,并设置为当前项。

SearchLineEdit

SearchLineEdit 继承自 QLineEdit,实现了一个自定义的文本编辑控件,用于SearchComboBox

方法:

  • __init__(self, parent=None):初始化文本编辑控件。

    • parent:父窗口。
  • keyPressEvent(self, event):处理按键事件。

    • event:按键事件。
    • 根据按键类型执行相应操作。
  • focusInEvent(self, event):处理获得焦点事件。

    • event:获得焦点事件。
    • 选择所有文本。
  • focusOutEvent(self, event):处理失去焦点事件。

    • event:失去焦点事件。
    • 存储当前文本。

类的详细说明

BWidget

BWidget类是一个基础窗口小部件类,包含移动和调整大小事件的日志记录功能。

class BWidget(QWidget):
    """ base class of quatm Widgets
        includes logging of move and resize events"""

    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("quatm", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')

    def closeEvent(self,event):
        settings=QtCore.QSettings("quatm", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

BFrame

BFrame类是一个基础框架类,包含移动和调整大小事件的日志记录功能。

class BFrame(QFrame):
    """ base class of quatm Widgets
        includes logging of move and resize events"""

    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("quatm", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')

    def closeEvent(self,event):
        settings=QtCore.QSettings("quatm", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

BMainWindow

BMainWindow类是一个基础主窗口类,包含移动和调整大小事件的日志记录功能。

class BMainWindow(QMainWindow):
    def __init__(self,name='Noname',parent=None):
        super().__init__(parent)
        self._props=Properties(name)
        self._name = name
        settings=QtCore.QSettings("quatm", self._name)
        try:
            self.restoreGeometry(settings.value("geometry"))
        except:
            print('geometry not found')
        self.setWindowTitle(name)

    def closeEvent(self,event):
        settings=QtCore.QSettings("quatm", self._name)
        settings.setValue("geometry", self.saveGeometry())
        super().closeEvent(event)

CustomCompleter

CustomCompleter类是一个自定义的自动完成器,用于实现不同的匹配方式。

class CustomCompleter(QCompleter):
    def __init__(self, items, parent=None, match_flag='contains'):
        super(CustomCompleter, self).__init__(items, parent)
        self.setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
        self.match_flag = match_flag

    def pathFromIndex(self, index):
        path = index.data()
        if self.match_flag == 'contains' and self.completionPrefix() in path:
            return path
        elif self.match_flag == 'begins' and path.startswith(self.completionPrefix()):
            return path
        return ''

SearchComboBox

SearchComboBox类是一个带有自动完成功能的组合框,允许用户搜索和选择项。

class SearchComboBox(QComboBox):
    """
    QComboBox with the autocompleter QCompleter enabled.
    This adds an editable QLineEdit which allows the contents of the combobox to be searched.
    Filtered list appears as a popup below the search box.
    The full list can be accessed by click the drop-down arrow.
    match_flag: can be either 'contains' or 'begins to get the matchFlag to MatchContains or MatchStartsWith.
    Has a custom QLineEdit called SearchLineEdit.
    """
    def __init__(self, parent=None, match_flag='contains'):
        super().__init__(parent)
        self.setLineEdit(SearchLineEdit(self))
        self.setEditable(True)
        self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
        self.completer = CustomCompleter(self.model(), self, match_flag)
        self.setCompleter(self.completer)
        self.setDuplicatesEnabled(False)

    def add_if_new(self, text):
        """if it's in the box, add it. return the index of the item"""
        idx = self.findText(text)
        if

 idx < 0:  # findText returns -1 if the item isn't in the combobox
            self.addItem(text)
            idx = self.findText(text)
        return idx

    def find_or_add(self, text):
        """if it's in the box, set it, if not, add and set it"""
        idx = self.add_if_new(text)
        self.setCurrentIndex(idx)

SearchLineEdit

SearchLineEdit类是SearchComboBox的自定义文本编辑控件,处理特殊的按键事件和焦点事件。

class SearchLineEdit(QLineEdit):
    """
    Custom QLineEdit for the SearchComboBox class.
    On focus in (e.g. when clicked on for the first time) the full text is selected.
    On focus out or pressing enter, the current text is stored. When pressing escape, the stored text is applied.
    On escape, reverts the
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.parent = parent

    def keyPressEvent(self, event: QKeyEvent):
        if event.key() == Qt.Key.Key_Escape:
            self.setText(self.lastText)
        elif event.key() == Qt.Key.Key_Enter:
            self.lastText = self.text()
        else:
            super().keyPressEvent(event)

    def focusInEvent(self, event):
        super().focusInEvent(event)
        QTimer.singleShot(0, self.selectAll)  # ensures other events are processed first. Prevents UI locking up.

    def focusOutEvent(self, event):
        super().focusInEvent(event)
        self.lastText = self.text()

总结

该代码实现了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承Qt的基本控件类,并添加了一些自定义的功能来实现。

8.3 - 实验序列编辑器

该代码实现了一个图形用户界面(GUI)应用程序,用于编辑和可视化实验序列。应用程序使用了Qt库来创建界面,Qsci库提供代码编辑器,pyqtgraph库用于绘图。代码主要包括三个类:CodeEditorExperimentSequencerExperimentParser,以及一个主窗口类 CodeEditorParser

类和方法

CodeEditor

CodeEditor 继承自 QsciScintilla,实现了一个简单的代码编辑器,具有语法高亮和自动补全功能。

方法:

  • __init__(self, parent=None, filename=None):初始化编辑器,设置字体、缩进、自动补全和行号。

    • parent:父窗口
    • filename:要加载的文件名
    • 设置最小尺寸为800x600
    • 设置编辑器字体为Courier New,字号12,固定间距
    • 设置缩进宽度为4,不使用制表符缩进,启用自动缩进
    • 启用自动补全,触发阈值为3个字符
    • 设置边距宽度以显示行号
    • 如果提供了文件名,则加载文件内容到编辑器中
  • saveFile(self):保存当前文本到文件。

    • 如果提供了文件名,则将编辑器中的文本写入文件
    • 如果保存成功,打印"file saved successfully"
    • 如果保存失败,打印错误信息
    • 如果文件名无效,打印"filename is invalid, failed to save file"

ExperimentSequencer

ExperimentSequencer 继承自 QtWidgets.QWidget,用于可视化实验序列。

方法:

  • __init__(self, parent=None, filename=None):初始化窗口,订阅属性并创建绘图窗口。

    • parent:父窗口
    • filename:文件名(未使用)
    • 订阅PropertiesSequencer属性
    • 创建GraphicsLayoutWidget并设置背景为白色
    • 将绘图窗口添加到网格布局中
  • plotSequence(self, sequence):绘制实验序列,输入格式由 ExperimentParser 定义。

    • sequence:包含实验序列的字典,键为通道名,值为包含时间和状态的子字典
    • 重置绘图窗口
    • 矢量化布尔值到整数的转换
    • 找到全局最小和最大时间
    • 处理开始和结束时未定义的值
    • 准备颜色
    • 为每个通道创建线图,根据通道名选择颜色
    • 将所有图的X轴链接到第一个图

ExperimentParser

ExperimentParser 用于解析实验代码,模拟实验运行并输出包含通道、时间和通道状态的表。

方法:

  • __init__(self, filename=None):初始化解析器,构建实验。

    • filename:文件名
    • 调用buildExperiment方法构建实验
  • buildExperiment(self):构建实验,使其在 self.filename 中可访问。

    • 动态导入模块并获取实验类
    • 模拟实验命令堆栈
  • simulateExperiment(self):模拟实验运行,返回指令堆栈,并按通道组织为字典。

    • 运行实验,获取模拟的命令堆栈
    • 将命令堆栈转移到字典中,键为通道名,值为包含时间和状态的子字典

CodeEditorParser

CodeEditorParser 继承自 QtWidgets.QMainWindow,将代码编辑器、解析器和实验代码的可视化结合在一起。

方法:

  • __init__(self, parent=None, filename=None):初始化主窗口,创建停靠窗口和按钮。

    • parent:父窗口
    • filename:文件名
    • 设置窗口标题为“Experiment Editor”
    • 设置窗口几何尺寸为1280x800
    • 创建停靠窗口和按钮
    • 初始化时模拟实验序列并绘制
  • addButtons(self):添加保存和模拟按钮。

    • 创建保存和模拟按钮
    • 将按钮添加到布局中
    • 连接按钮点击事件到相应的方法
  • createDocks(self):创建停靠区,包含左侧的 CodeEditor 和右侧的 ExperimentSequencer

    • 创建CodeEditor实例并添加到左侧停靠区
    • 创建ExperimentSequencer实例并添加到右侧停靠区
  • simulateExperiment(self):模拟当前版本的实验,将指令堆栈传递给 ExperimentSequencer 进行可视化。

    • 保存文件,重建实验并模拟运行
    • 将模拟的指令堆栈传递给ExperimentSequencer进行绘制

main() 函数

  • 创建 QApplication 实例。
  • 创建 CodeEditorParser 实例并显示。
  • 启动应用程序的主循环。
def main():
    app = QtWidgets.QApplication(sys.argv)
    Win = CodeEditorParser(filename=sys.argv[1])
    Win.show()
    sys.exit(app.exec())

代码执行

代码通过命令行执行,接收一个文件名作为参数:

python script.py your_experiment_file.py

总结

该代码实现了一个集成代码编辑、实验序列解析和可视化的GUI工具。通过Qt提供的窗口和控件,用户可以方便地编辑实验代码,并实时查看实验序列的变化。

8.4 - 多线程任务管理器

该代码实现了一个实验管理器 (ExperimentManager) 类,用于管理和运行实验队列中的任务。该管理器在一个工作线程中不断检查队列中的实验任务,并根据任务的优先级和状态来决定执行哪些实验。实验任务由测量、序列(或扫描)和运行组成,在执行实验时会调用相关的开始和结束函数来控制实验的流程。

以下是该代码的详细中文文档说明:

代码概述

该代码实现了一个实验管理器 (ExperimentManager) 类,用于管理和运行实验队列中的任务。该管理器在一个工作线程中不断检查队列中的实验任务,并根据任务的优先级和状态来决定执行哪些实验。实验任务由测量、序列(或扫描)和运行组成,在执行实验时会调用相关的开始和结束函数来控制实验的流程。

依赖库

  • numpy:用于数值计算和数组操作。
  • time:用于时间操作和延时。
  • Qt.QtCore:用于信号槽机制和日期时间操作。
  • quatm.GUI.browser_workers:包含 Worker 类,用于多线程处理。
  • quatm.servers:包含发送信息和错误的函数。

ExperimentManager

该类包含了管理实验任务队列的功能,包括运行实验、暂停实验、终止实验等。

初始化方法 __init__(self, browser=None)

初始化实验管理器,设置浏览器、属性、队列、线程池等,并启动实验队列。

参数:

  • browser:浏览器对象,用于获取属性和队列。

运行实验方法 run(self, taskNr, progress_callback=None)

处理实验任务的运行逻辑。

参数:

  • taskNr:任务编号。
  • progress_callback:进度回调函数。

内部方法 _sequence_run(self)

初始化运行循环并开始实验。

内部方法 _runloop(self)

运行实验(或实验扫描),在每次运行前检查实验是否暂停或终止。

暂停方法 pause(self)

暂停或继续实验。

启动队列方法 start_queue(self)

在实验线程中启动实验队列工作器。

队列函数 queue_fn(self, progress_callback=None)

实验队列持续检查实验字典中的新任务,如果字典为空或有实验在运行,则不做任何操作。

检查到期方法 due_check(taskDict)

检查任务是否到期。

参数:

  • taskDict:任务字典。

返回:

  • TrueFalse,表示任务是否到期。

更新表格方法 update_table(self)

通知 GUI 更新表格显示。

终止实验方法 terminate_experiment(self)

优雅地终止实验,允许当前运行完成。

开始测量方法 start_measurement(self)

设置参数并调用实验的 start_measurement 函数。

开始序列方法 start_sequence(self)

调用实验的 start_sequence 函数。

结束序列方法 end_sequence(self)

调用实验的 end_sequence 函数。

结束测量方法 end_measurement(self)

运行 end_measurement 函数,并清理表格。

设置字典方法 set_dict(self, name, value)

设置实验参数。

参数:

  • name:参数名。
  • value:参数值。

设置运行编号方法 set_run_nr(self, value)

设置实验运行编号并更新表格。

参数:

  • value:运行编号。

设置重复编号方法 set_rep_nr(self, value)

设置实验重复编号并更新表格。

参数:

  • value:重复编号。

代码详细说明

初始化 ExperimentManager

在初始化方法中,实验管理器会从浏览器对象中获取属性和队列,并启动实验队列工作器。实验队列工作器会在一个单独的线程中运行,不断检查实验队列中的任务。

运行实验 run

在运行实验方法中,实验管理器会检查任务是否存在,并获取任务的详细信息,包括实验名、参数、扫描参数、扫描值等。然后调用相关的开始和结束方法来控制实验的流程。

队列函数 queue_fn

队列函数会持续检查实验字典中的新任务,并根据任务的优先级和状态来决定执行哪些实验。如果任务到期,则运行任务,否则继续检查下一个任务。

暂停和终止实验

实验管理器提供了暂停和终止实验的方法。暂停方法会切换实验的暂停状态,并更新队列显示。终止方法会优雅地终止实验,允许当前运行完成。

其他辅助方法

实验管理器还提供了一些辅助方法,用于设置实验参数、更新表格显示等。

代码示例

以下是一个简单的使用示例:

from PyQt6.QtWidgets import QApplication
import sys
from quatm.servers import Properties
from quatm.GUI.browser import Browser
from quatm.GUI.experiment_manager import ExperimentManager

app = QApplication(sys.argv)
browser = Browser()
experiment_manager = ExperimentManager(browser)

# 添加实验任务到队列
experiment_manager.queue.add_task(task_dict)

# 开始运行实验
experiment_manager.run(taskNr)

sys.exit(app.exec())

8.5 - 实验序列编辑器

该代码实现了一个实验浏览器(Browser)应用程序,提供了图形用户界面来管理和运行各种实验。通过使用Qt库构建界面,代码实现了实验文件选择、实验队列管理、参数设置和实验执行等功能。

代码概述

该代码实现了一个实验浏览器(Browser)应用程序,提供了图形用户界面来管理和运行各种实验。通过使用Qt库构建界面,代码实现了实验文件选择、实验队列管理、参数设置和实验执行等功能。

依赖库

  • osimportlib.utilinspecttracebacknumpyjsondatetime:标准库,用于文件操作、模块加载、错误处理、数值计算和日期时间处理。
  • Qt.QtCoreQt.QtWidgets:用于构建GUI应用程序。
  • quatm.serversquatm.GUI:自定义库,用于属性管理和GUI组件。

类和方法

Browser

Browser 继承自 QMainWindow,实现了实验浏览器的主界面。

信号:

  • experimentOpened:实验打开信号。

方法:

  • __init__(self):初始化浏览器,设置属性、任务队列和其他组件,并恢复窗口几何设置。
  • closeEvent(self, event):处理窗口关闭事件,调用父类的关闭事件处理方法。
  • init_ui(self):初始化用户界面,设置状态栏和中央窗口区域,并创建停靠窗口。
  • create_dock_widgets(self):创建停靠窗口,包含文件选择器、实验队列、准备站和循环器。
  • open_experiment(self, filepath, startup=False):打开一个新的实验窗口,如果实验已经打开,则不执行任何操作。
  • update_exp_window_task(self):更新所有实验窗口中的任务号。

ExperimentSubWindow

ExperimentSubWindow 继承自 QMdiSubWindow,实现了实验窗口的容器。

方法:

  • __init__(self, name, props, parent=None):初始化子窗口,设置窗口标题和属性。
  • store_geometry(self):存储窗口几何设置。

ExperimentWindow

ExperimentWindow 继承自 QWidget,实现了单个实验的控制,包括参数设置和任务提交。

方法:

  • __init__(self, filepath, props, parent=None, browser=None):初始化实验窗口,加载实验文件并构建用户界面。
  • init_ui(self):初始化用户界面,创建控件和布局。
  • save_params(self, backup=False):保存实验参数到JSON文件。
  • load_params(self):从JSON文件加载实验参数。
  • get_files(self):打开文件选择对话框,获取文件路径。
  • update_task_qsb(self):更新任务号选择框。
  • submit_to_queue(self):提交实验到实验队列。
  • submit_next(self):提交实验到实验队列,并设置最高优先级。
  • submit_to_prepper(self):提交实验到准备站。
  • setup_scan(self):设置扫描序列。
  • setup_task_dict(self):创建任务字典,存储实验参数。
  • build_argument_dict(self):创建实验参数字典。
  • edit_sequence(self):打开序列编辑器窗口。
  • closeEvent(self, event):处理窗口关闭事件,移除打开的窗口。
  • gui_columns(self):返回GUI列数。
  • arguments(self):返回实验参数。
  • argument_names(self):返回实验参数名称列表。
  • argument_dicts(self):返回实验参数字典列表。
  • store_geometry(self):存储窗口几何设置。

SequenceEditor

SequenceEditor 继承自 QDialog,实现了序列编辑器窗口。

方法:

  • __init__(self, experimentWindow, parent=None):初始化序列编辑器窗口,设置窗口标题和图标,并创建控件和布局。
  • update_parameter(self, parname, n):根据参数名称更新参数的范围和步长。
  • update_list_generator(self):更新列表生成器。
  • update_values(self):更新序列编辑器中的值。

QDock

QDock 继承自 QDockWidget,实现了包含实验队列、准备站和循环器的停靠窗口。

方法:

  • __init__(self, parent=None):初始化停靠窗口,设置布局和子控件。

FileSelector

FileSelector 继承自 QWidget,实现了实验文件选择器。

方法:

  • __init__(self, browser, parent=None):初始化文件选择器,设置属性和布局,并创建文件树视图。
  • file_model(self, directory):创建文件模型,用于显示目录中的文件和文件夹。
  • set_column_widths(self):设置文件树视图的列宽。
  • go_up(self):导航到上一级目录。
  • create_context_menu(self, position):创建上下文菜单,提供编辑和组合编辑选项。
  • open_editor(self, filename):打开代码编辑器。
  • open_file(self):打开文件或目录。

辅助函数

filepath_split(filepath)

拆分文件路径,返回路径、扩展名、名称和文件名。

def filepath_split(filepath):
    """
    takes /dir/name.ext
    returns path, ext, name, filename
    = /dir/name, ext, name, name.ext
    """
    path, ext = os.path.splitext(filepath)  # /dir/name, ext
    name = os.path.basename(path)  # name
    filename = os.path.basename(filepath)  # name.ext
    return path, ext, name, filename

主函数

初始化应用程序并启动主窗口。

def main():
    qApp = QApplication(sys.argv)
    Win = Browser()
    qApp.setWindowIcon(QIcon(iconpath + '/browser.png'))
    Win.show()
    sys._excepthook = sys.excepthook

    sys.excepthook = exception_hook
    sys.exit(qApp.exec())


def exception_hook(exctype, value, traceback):
    send_error('[Browser] ' + str([exctype, value, traceback]))
    sys._excepthook(exctype, value, traceback)
    sys.exit(1)


# Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    send_info('[Browser] Quatm Browser starts')
    if (sys.flags.interactive != 1) or not hasattr(Qt, 'PYQT_VERSION'):
        main()

总结

该代码实现了一个实验浏览器应用程序,通过图形用户界面管理和运行各种实验。它提供了实验文件选择、实验队列管理、参数设置和实验执行等功能,并使用Qt库构建用户界面。

8.6 - 实验队列管理器

该代码实现了一个实验队列管理器,通过图形用户界面(GUI)来显示和控制实验任务队列。使用Qt库来构建界面,其中包含按钮和表格,用于管理实验任务。代码主要包括一个类:ExperimentQ

类和方法

ExperimentQ

ExperimentQ 继承自 QGroupBox,实现了一个实验队列管理器,显示和控制实验任务队列。

方法:

  • __init__(self, browser, parent=None, title="Experiment Queue"):初始化实验队列管理器。

    • browser:浏览器对象,用于访问属性和实验管理器
    • parent:父窗口
    • title:组框标题,默认为"Experiment Queue"
    • 创建按钮和表格,并设置布局
    • 初始化属性
    • 设置锁定标志为False
  • create_buttons(self):创建并配置控制按钮。

    • 创建暂停按钮、终止按钮、终止所有按钮和重启按钮
    • 设置按钮图标、提示信息和点击事件处理函数
  • init_table_actions(self):初始化表格操作。

    • 创建删除、终止、终止所有、休眠和暂停操作
    • 设置操作的快捷键和上下文
    • 将操作添加到表格
  • init_table(self):初始化表格。

    • 创建 QTableView 并设置选择行为、选择模式和上下文菜单策略
    • 隐藏垂直表头并设置其调整模式为内容适应
    • 初始化 expDict 为一个空字典
    • 创建 ScheduleModel 并将其设置为表格模型
    • 设置水平表头的调整模式
  • set_model(self, model):设置表格的新模型。

    • model:新的模型对象
    • 将模型设置为表格模型
  • delete_clicked(self):从队列中删除任务,或者如果任务正在运行则优雅地终止。

    • 获取选中的行,并获取对应的任务编号
    • 如果任务状态为“Running”或“Scanning”,则标记任务为终止
    • 否则,从模型中删除任务
    • 设置当前索引为选中的行
  • terminate_clicked(self):优雅地终止选中的任务(允许完成运行)。

    • 获取选中的行,并获取对应的任务编号
    • 标记任务为终止,状态设置为“Termination Pending”
    • 如果没有选中任务,且模型中有任务,则终止第一个任务
  • terminate_all(self):终止所有任务。

    • 遍历所有任务,标记为终止,状态设置为“Termination Pending”
  • set_sleeping(self):将选中的任务设置为“Sleeping”状态,或者取消“Sleeping”状态。

    • 获取选中的行,并获取对应的任务编号
    • 如果任务状态为“Sleeping”,则设置为“Queued”,否则设置为“Sleeping”
  • pause(self):暂停当前运行的实验。

    • 调用浏览器的实验管理器的暂停方法
    • 根据实验管理器的暂停状态,切换暂停按钮的图标
  • update_item(self, k, v):更新表格中的项目。

    • k:键(任务编号)
    • v:值(任务信息)
    • 将任务信息更新到模型中,并解锁
  • delete_item(self, k):删除表格中的项目。

    • k:键(任务编号)
    • 从模型中删除任务,并解锁
  • restart(self):用于测试按钮的功能。

    • 设置属性值并进行各种操作,打印结果

代码执行

该代码通过创建 ExperimentQ 对象,并将其嵌入到主窗口中来执行。主窗口中会包含实验队列的表格和控制按钮,用户可以通过这些按钮来控制实验任务的状态。

# 示例代码,展示如何创建并显示 ExperimentQ 对象
if __name__ == "__main__":
    import sys
    from PyQt6.QtWidgets import QApplication, QMainWindow

    app = QApplication(sys.argv)
    mainWindow = QMainWindow()
    browser = ...  # 创建或获取浏览器对象
    experimentQueue = ExperimentQ(browser)
    mainWindow.setCentralWidget(experimentQueue)
    mainWindow.show()
    sys.exit(app.exec())

8.7 - 多线程任务管理器

该代码实现了一个多线程工作者类(Worker)和信号类(WorkerSignals),用于在应用程序中处理多线程任务。Worker类继承自QRunnableWorkerSignals类继承自QObject,定义了一组可用的信号,以便在工作线程中传递信息。

代码概述

该代码实现了一个多线程工作者类(Worker)和信号类(WorkerSignals),用于在应用程序中处理多线程任务。Worker类继承自QRunnableWorkerSignals类继承自QObject,定义了一组可用的信号,以便在工作线程中传递信息。

依赖库

  • sys:用于获取异常信息。
  • traceback:用于格式化异常跟踪信息。
  • Qt.QtCore:提供Qt核心功能,包括信号和槽机制、可运行对象等。

类和方法

WorkerSignals

WorkerSignals 继承自 QObject,定义了一组可用的信号,以便在工作线程中传递信息。

信号:

  • finished:没有数据,表示任务完成。
  • error:传递一个包含异常类型、异常值和格式化异常跟踪信息的元组。
  • result:传递处理函数返回的结果数据。
  • progress:传递一个整数,表示进度百分比。
  • update_ui:用于更新用户界面。
  • tableUpdate:用于更新表格。
  • addItem:传递一个整数和一个QVariant,用于添加项目。
  • deleteItem:传递一个整数,用于删除项目。
  • taskStart:表示任务开始。
  • taskDone:表示任务完成。
class WorkerSignals(QObject):
    '''
    Defines the signals available from a running worker thread.
    Supported signals are:

    finished
        No data

    error
        `tuple` (exctype, value, traceback.format_exc() )

    result
        `object` data returned from processing, anything

    progress
        `int` indicating % progress

    '''
    finished = pyqtSignal()
    error = pyqtSignal(tuple)
    result = pyqtSignal(object)
    progress = pyqtSignal(int)
    update_ui = pyqtSignal()
    tableUpdate = pyqtSignal()
    addItem = pyqtSignal(int, QtCore.QVariant)
    deleteItem = pyqtSignal(int)
    taskStart = pyqtSignal()
    taskDone = pyqtSignal()

Worker

Worker 继承自 QRunnable,实现了一个工作线程,用于处理耗时的任务。

方法:

  • __init__(self, fn, *args, **kwargs):初始化工作线程。

    • fn:要在线程中运行的函数。
    • args:传递给函数的参数。
    • kwargs:传递给函数的关键字参数。
    • 初始化时存储函数和参数,并创建一个WorkerSignals实例。
  • run(self):运行工作线程。

    • 尝试运行传入的函数,并传递参数和关键字参数。
    • 如果出现异常,捕获并发出error信号。
    • 最后,无论是否有异常,都会发出finished信号,表示任务完成。
class Worker(QRunnable):
    '''
    Worker thread
    Inherits from QRunnable to handle worker thread setup, signals and wrap-up.

    :param callback: The function callback to run on this worker thread. Supplied args and
                     kwargs will be passed through to the runner.
    :type callback: function
    :param args: Arguments to pass to the callback function
    :param kwargs: Keywords to pass to the callback function

    '''

    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()

        # Store constructor arguments (re-used for processing)
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
        self.signals = WorkerSignals()

        # Add the callback to our kwargs
        self.kwargs['progress_callback'] = self.signals.progress

    @pyqtSlot()
    def run(self):
        """
        Initialise the runner function with passed args, kwargs.
        """

        # Retrieve args/kwargs here; and fire processing using them
        try:
            result = self.fn(*self.args, **self.kwargs)
        except:
            traceback.print_exc()
            exctype, value = sys.exc_info()[:2]
            self.signals.error.emit((exctype, value, traceback.format_exc()))
        finally:
            self.signals.finished.emit()  # Done

总结

该代码定义了一个用于多线程任务处理的工作者类(Worker)和信号类(WorkerSignals)。Worker类继承自QRunnable,可以在工作线程中运行传入的函数,并通过信号机制传递任务的进度、结果或错误信息。WorkerSignals类定义了一组信号,以便在工作线程和主线程之间进行通信。

8.8 - 自动保存编辑器

该代码实现了一个自动保存编辑器,通过图形用户界面(GUI)来管理和设置定期自动保存的时间。使用Qt库来构建界面,包括日期时间编辑控件和复选框。主要类包括:AutoSaveEditorDateTimeWidget

类和方法

AutoSaveEditor

AutoSaveEditor 继承自 BWidget,实现了一个自动保存时间的编辑器。

信号:

  • subscriptionsChanged:订阅改变信号。
  • propertiesChanged:属性改变信号。

方法:

  • __init__(self, props, max_items, name='regular_auto_save_times', parent=None):初始化自动保存编辑器。

    • props:属性对象,用于存储和管理配置数据。
    • max_items:最大项目数量。
    • name:属性名称,默认为’regular_auto_save_times’。
    • parent:父窗口。
    • 设置布局,并加载和初始化日期时间控件。
  • load_AutoSaveEditor_props(props, prop_name, max_items):加载自动保存编辑器属性。

    • props:属性对象。
    • prop_name:属性名称。
    • max_items:最大项目数量。
    • 返回日期时间和勾选状态。
  • update_props(props, prop_name, datetimes, ticked):更新属性。

    • props:属性对象。
    • prop_name:属性名称。
    • datetimes:日期时间数组。
    • ticked:勾选状态数组。
  • update_datetime(self, idx, datetime_save):更新日期时间。

    • idx:索引。
    • datetime_save:新的日期时间。
  • update_ticked(self, idx, ticked):更新勾选状态。

    • idx:索引。
    • ticked:新的勾选状态。
  • accept(self):接受并保存更改。

    • 更新属性并通知父组件,然后关闭窗口。

DateTimeWidget

DateTimeWidget 继承自 QFrame,实现了一个日期时间选择控件。

方法:

  • __init__(self, idx, parent, datetime_save=datetime.datetime.now(), ticked=False):初始化日期时间控件。

    • idx:索引。
    • parent:父组件。
    • datetime_save:初始日期时间,默认为当前时间。
    • ticked:初始勾选状态,默认为False。
    • 设置布局,创建并初始化日期时间编辑控件和复选框。
  • datetime_changed(self):日期时间改变事件处理。

    • 更新日期时间,并通知父组件。
  • ticked_changed(self):勾选状态改变事件处理。

    • 更新勾选状态,并通知父组件。

主函数

代码通过创建 QApplication 实例和 AutoSaveEditor 窗口来执行,并启动应用程序的主循环。

if __name__ == '__main__':
    import sys

    props = Properties('Tests/AutoSaveEditor')
    pp = AutoSaveEditor(props, max_items=20)
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QApplication.instance().exec_()

代码执行

该代码通过命令行执行,创建一个AutoSaveEditor对象,并显示自动保存编辑器窗口。

类的详细说明

AutoSaveEditor

AutoSaveEditor类用于管理和设置定期自动保存的时间。它提供了一个图形用户界面,允许用户添加、编辑和删除自动保存的时间点。

方法:

  • __init__(self, props, max_items, name='regular_auto_save_times', parent=None)

    • 初始化方法,设置布局并加载和初始化日期时间控件。
  • load_AutoSaveEditor_props(props, prop_name, max_items)

    • 静态方法,用于从属性对象中加载日期时间和勾选状态,并返回它们。
  • update_props(props, prop_name, datetimes, ticked)

    • 静态方法,用于更新属性对象中的日期时间和勾选状态。
  • update_datetime(self, idx, datetime_save)

    • 更新指定索引的日期时间。
  • update_ticked(self, idx, ticked)

    • 更新指定索引的勾选状态。
  • accept(self)

    • 接受并保存更改,更新属性并通知父组件,然后关闭窗口。

DateTimeWidget

DateTimeWidget类用于显示和编辑单个日期时间和勾选状态。

方法:

  • __init__(self, idx, parent, datetime_save=datetime.datetime.now(), ticked=False)

    • 初始化方法,设置布局,创建并初始化日期时间编辑控件和复选框。
  • datetime_changed(self)

    • 日期时间改变事件处理,更新日期时间并通知父组件。
  • ticked_changed(self)

    • 勾选状态改变事件处理,更新勾选状态并通知父组件。

8.9 - 实验时间线查看器

该代码实现了一个实验时间线查看器,通过图形用户界面(GUI)来显示和控制实验时间序列。使用Qt库来构建界面,其中包含按钮、文本框和绘图区域。代码主要包括三个类:TimelineTimelinePlotterSelectorWidget

类和方法

Timeline

Timeline 继承自 QMainWindow,实现了一个实验时间线查看器。

方法:

  • __init__(self, *args, **kwargs):初始化时间线查看器。

    • 设置窗口标题为"Timeline Viewer"。
    • 加载JSON文件中的实验序列。
    • 创建主窗口组件,包括文件加载区、绘图区和选择区。
    • 设置中央窗口部件。
  • plot_experimental_sequence(self, time_dict, init_vals=None):绘制实验时间序列。

    • 重置绘图区域。
    • 深拷贝时间序列字典。
    • 找到最大时间tmax
    • 为每个时间序列添加一个点,确保每个序列都在tmax结束。
    • 准备颜色。
    • 为每个选中的输出绘制折线图,并根据条件选择不同的颜色和填充方式。
  • load_file(self, filename):加载实验序列文件。

    • 读取JSON文件并解析实验序列。
    • 获取输出名称集合。
    • 构建时间序列字典。
    • 逆向设备数据库转换时间序列字典。
    • 更新选择器组件中的名称。
  • decode_ttl_bitmask(self, bitmask, command):解码TTL位掩码。

    • 将位掩码转换为二进制字符串。
    • 找到二进制字符串中的所有1的位置。
    • 根据命令生成TTL字典。
  • get_set_of_used_outputs(self, sequence):获取使用的输出集合。

    • 遍历实验序列,提取所有使用的输出名称。
  • construct_time_sequences(self, sequence, set_of_output_names):构建时间序列字典。

    • 创建时间序列字典结构。
    • 填充时间序列字典。
  • reverse_device_db_transformation(self, time_sequence_dict, device_db_path=workpath+'/configuration/'):逆向设备数据库转换时间序列字典。

    • 加载设备数据库。
    • 构建逆向映射字典。
    • 根据逆向映射字典转换时间序列字典中的名称和值。

TimelinePlotter

TimelinePlotter 继承自 GraphicsLayoutWidget,用于可视化实验序列。

方法:

  • __init__(self, sequence):初始化绘图组件。
    • 订阅属性。
    • 设置背景为白色。
    • 初始化绘图字典。

SelectorWidget

SelectorWidget 继承自 QFrame,用于选择要显示的实验序列。

方法:

  • __init__(self, parent=None, clear_name_dict=None):初始化选择器组件。

    • 创建主布局和按钮。
    • 创建滚动区域用于显示复选框。
  • get_names(self, clear_name_dict):获取并显示名称。

    • 获取清晰名称字典的键并排序。
    • 如果名称未变化,则直接返回。
    • 否则,更新滚动区域中的复选框。
  • select_all(self):全选复选框。

    • 将所有复选框设为选中状态。
  • deselect_all(self):取消全选复选框。

    • 将所有复选框设为未选中状态。

主函数

代码通过创建 QApplication 实例和 Timeline 窗口来执行,并启动应用程序的主循环。

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Timeline()
    window.setWindowIcon(QtGui.QIcon(workpath + '/quatm/icons/time_line.png'))
    window.setWindowTitle('Timeline Viewer')
    window.show()
    sys.exit(app.exec())

代码执行

该代码通过命令行执行,创建一个Timeline对象,并显示实验时间线查看器窗口。

8.10 - 多线程处理框架

该代码实现了一个基于 Qt 的多线程处理框架。主要包含两个类:WorkerSignals 和 Worker。WorkerSignals 类定义了线程工作时使用的各种信号,而 Worker 类继承自 QRunnable,用于处理多线程任务的设置、执行和信号传递。

功能介绍

该代码实现了一个基于 Qt 的多线程处理框架。主要包含两个类:WorkerSignalsWorkerWorkerSignals 类定义了线程工作时使用的各种信号,而 Worker 类继承自 QRunnable,用于处理多线程任务的设置、执行和信号传递。

代码结构

  • 导入必要的模块和库
  • 定义类 WorkerSignals
  • 定义类 Worker

类:WorkerSignals

简短功能介绍

WorkerSignals 类定义了可从正在运行的工作线程发出的信号。这些信号用于指示线程的各种状态和进度,包括完成、错误、结果和进度更新。

属性

  • finished:无数据的信号,指示线程已完成。
  • error:包含异常类型、值和追溯信息的元组信号。
  • result:处理结果数据的信号。
  • progress:指示进度的整数信号。
  • terminate:终止信号。
  • start:启动信号。
  • publish:发布信号。
  • runDone:运行完成信号。
  • logging:日志信号,包含日志信息字符串。
  • clear:清除信号。

类:Worker

简短功能介绍

Worker 类继承自 QRunnable,用于处理工作线程的设置、信号和结束。它允许在独立线程中运行指定的函数,并通过信号机制与主线程通信。

方法:__init__

功能:初始化 Worker 对象,存储传递的函数及其参数,并设置信号。

参数

  • fn:要在工作线程中运行的函数。
  • args:传递给函数的参数。
  • kwargs:传递给函数的关键字参数。

主要步骤

  1. 调用父类 QRunnable 的构造函数。
  2. 存储传递的函数及其参数。
  3. 初始化 WorkerSignals 对象。
  4. 将进度回调添加到关键字参数中。

方法:run

功能:初始化传递的函数并执行它,处理可能的异常,并通过信号机制传递结果。

主要步骤

  1. 尝试运行传递的函数,并捕获其结果。
  2. 如果发生异常,捕获异常信息并发出 error 信号。
  3. 如果函数运行成功,发出 result 信号传递结果。
  4. 最后,无论是否发生异常,发出 finished 信号指示完成。

8.11 - 实验任务循环管理器

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承Qt的基本控件类,并添加了一些自定义的功能来实现。

代码结构

  1. 导入必要的模块和库
  2. 定义主要的 Looper
  3. 定义 LoopItem 类及其子类(TaskItem, ListItem, ConditionalItem 等)
  4. 定义辅助类(DataManager, LoopManager, LoopGroup 等)
  5. 实现 GUI 部件和功能

类:Looper

简短功能介绍

Looper 类是整个循环控制的核心。它负责管理任务组、定时器、按钮和循环的启动与终止。

方法

  • __init__:初始化 Looper 对象,设置属性和布局,创建按钮和标签页。
  • add_tab:添加新的任务组标签页。
  • delete_tab:删除指定的任务组标签页。
  • create_buttons:创建控制按钮。
  • save_loop:保存当前循环配置。
  • load_loop:加载之前保存的循环配置。
  • terminate_by_time:根据时间自动终止循环。

类:LoopItem

简短功能介绍

LoopItem 类是所有循环项的基类,提供了基本的属性和方法。它被 TaskItem, ListItem, ConditionalItem 等类继承,并扩展其功能。

子类:TaskItem

  • 功能:表示单个任务项,执行特定的任务并跟踪运行次数。
  • 方法
    • __init__:初始化任务项,设置任务信息和UI组件。
    • run:执行任务,并将任务添加到任务队列。
    • end_run:更新任务状态和运行次数。
    • task_start:任务开始时的操作。
    • task_end:任务结束时的操作。
    • update_task:更新任务信息。
    • max_check:检查是否达到最大运行次数。

子类:ListItem

  • 功能:表示一个任务列表,按顺序执行列表中的任务。
  • 方法
    • __init__:初始化任务列表项,设置任务列表信息和UI组件。
    • run:执行当前任务,并更新任务索引。
    • end_run:更新任务列表状态和运行次数。
    • edit_list:编辑任务列表。
    • update_task_labels:更新任务标签。

子类:ConditionalItem

  • 功能:表示条件项,根据条件的结果执行不同的任务。
  • 方法
    • __init__:初始化条件项,设置条件信息和UI组件。
    • run:评估条件并选择下一步操作。
    • update_boxes:更新条件的UI组件。

类:DataManager

简短功能介绍

DataManager 类管理数据订阅和更新,处理数据的接收和存储。

方法

  • __init__:初始化数据管理器,设置属性和数据客户端。
  • set_new_data:处理新的数据,更新数据字典。
  • edit_subscriptions:编辑数据订阅。

类:LoopManager

简短功能介绍

LoopManager 类负责管理循环的执行,处理循环任务的启动、终止和控制。

方法

  • __init__:初始化循环管理器,设置属性和线程池。
  • loop_fn:循环执行函数,处理循环任务。
  • run_loop:启动循环任务。
  • terminate:终止循环任务。
  • task_start:任务开始时的操作。
  • task_end:任务结束时的操作。

类:LoopGroup

简短功能介绍

LoopGroup 类表示一个任务组,包含多个任务项和一个组项。

方法

  • __init__:初始化任务组,设置属性和布局。
  • create_buttons:创建任务组的控制按钮。
  • delete_group:删除任务组。
  • update_loop_group_file:更新任务组配置文件。

类:Baustelle

简短功能介绍

Baustelle 类是任务组的编辑器,提供添加、删除和编辑任务项的功能。

方法

  • __init__:初始化编辑器,设置属性和布局。
  • add_task_item:添加新的任务项。
  • add_list_item:添加新的任务列表项。
  • add_conditional:添加新的条件项。
  • add_group_item:添加新的组项。
  • update_idx:更新任务项的索引。

类:LoopSubMgr

简短功能介绍

LoopSubMgr 类是一个GUI,用于编辑数据流的订阅。

方法

  • __init__:初始化订阅管理器,设置属性和布局。
  • update_subscriptions:更新数据流的订阅。

类:ListEdit

简短功能介绍

ListEdit 类是一个对话框,用于编辑 ListItem 的任务列表。

方法

  • __init__:初始化对话框,设置属性和布局。
  • closeEvent:在对话框关闭时更新任务列表。

类:PrepBox 和 ListBox

简短功能介绍

PrepBoxListBox 类分别用于显示和管理预备任务列表和当前任务列表。

方法

  • init_ui:初始化UI组件。
  • set_model:设置数据模型。
  • push_selection:将选中的任务添加到任务列表。
  • unpack_selection:解包选中的任务并添加到任务列表。
  • move_up:在任务列表中上移任务。
  • move_down:在任务列表中下移任务。
  • delete_clicked:删除选中的任务。

类:VLine

简短功能介绍

VLine 类用于在UI中创建分隔线。

类:LoopTabWidget 和 EditableTabBar

简短功能介绍

LoopTabWidgetEditableTabBar 类自定义了标签页控件,允许编辑标签页名称和管理标签页。

方法

  • addTab:添加新的标签页。
  • setIconOn:设置标签页的图标为启用状态。
  • setIconOff:设置标签页的图标为禁用状态。
  • setTabText:设置标签页的文本。
  • editTab:编辑标签页名称。

辅助函数

功能

  • get_experiment:获取实验对象。
  • edit_key_in_place:编辑字典中的键。
  • find_or_add:在组合框中查找或添加项目。
  • parse_text:解析文本,转换为特定格式。

8.12 - 实验任务预备队列管理器

该代码定义了几个自定义的GUI控件类,包括基础窗口小部件、框架、主窗口以及带有自动完成功能的组合框和自定义的文本编辑控件。这些控件通过继承Qt的基本控件类,并添加了一些自定义的功能来实现。

概要

该代码定义了用于管理和展示队列(Queue)和准备站(PrepStation)表格的模型。模型指定了表格数据的形式(如字典或列表),以及如何展示和操作这些数据,包括如何获取、设置和删除数据,以及如何排序数据。模型可以直接从数据集中读取数据,并在数据集发生更改时自动更新表格。

主要类和功能

_SyncSubstruct

此类定义了用于操作表格数据字典的方法。方法包括添加、插入、弹出、设置、删除和获取字典项。这个类主要是为了便于在模型中更新数据字典,并在数据更新时调用回调函数来通知模型。

DictSyncModel

这是一个基类,用于将字典(backing_store)转换为表格。模型可以读取和编辑字典中的数据,并根据需要更新表格显示。其主要功能包括:

  • 初始化模型,设置表头、数据名称和初始数据。
  • 获取行数和列数。
  • 获取和设置单元格数据。
  • 获取表头数据。
  • 插入和删除字典项。
  • 排序和转换数据。
关键方法
  • rowCount: 返回字典中的条目数。
  • columnCount: 返回列的数量,即表头的数量。
  • data: 根据索引和角色获取数据。
  • setData: 设置单元格数据,并根据需要进行类型转换。
  • headerData: 获取表头数据。
  • __setitem__: 插入或更新字典项,并更新表格显示。
  • __delitem__: 删除字典项,并更新表格显示。
  • __getitem__: 获取字典项。
  • sort_key: 定义排序键(由子类实现)。
  • convert: 将字典键转换为列数据(由子类实现)。
  • flags: 定义单元格的属性(由子类实现)。

ScheduleModel

这是用于管理实验队列的表格模型。数据结构是一个字典,每个字典代表一个实验任务。任务按优先级和任务编号排序。

关键方法
  • sort_key: 返回用于排序的键,首先按优先级排序,然后按任务编号排序。
  • convert: 将字典键转换为列数据,特别是将日期时间字符串转换为 QDateTime 对象。
  • flags: 定义可编辑和不可编辑的列。

ListSyncModel

类似于 DictSyncModel,但处理的是列表而不是字典。主要用于管理需要按顺序排列的数据集合。

关键方法
  • rowCount: 返回列表的长度。
  • columnCount: 返回列的数量。
  • data: 根据索引和角色获取数据。
  • setData: 设置单元格数据,并根据需要进行类型转换。
  • headerData: 获取表头数据。
  • __delitem__: 删除列表项,并更新表格显示。
  • __getitem__: 获取列表项。
  • sort_key: 定义排序键(由子类实现)。
  • convert: 将列表项转换为列数据(由子类实现)。
  • flags: 定义单元格的属性(由子类实现)。

PrepModel

这是用于准备站的表格模型,使用列表来管理任务,因为准备站中的任务不需要唯一的 ID,可以自由更改顺序。

关键方法
  • convert: 将列表项转换为列数据,特别是将日期时间字符串转换为 QDateTime 对象。
  • flags: 定义可编辑和不可编辑的列。

功能特点

  • 数据同步:模型可以同步更新数据字典或列表,并通知表格更新显示。
  • 数据排序:模型可以根据指定的键对数据进行排序。
  • 数据转换:模型可以根据列索引转换数据类型,如将日期时间字符串转换为 QDateTime 对象。
  • 数据编辑:模型支持在表格中编辑数据,并将更改反映到原始数据集合中。
  • 表格属性:模型可以定义哪些列是可编辑的,哪些是只读的。

运行流程

  1. 创建模型实例,传入初始数据。
  2. 模型通过 rowCountcolumnCount 方法告知表格数据的大小。
  3. 表格通过 data 方法获取单元格数据并显示。
  4. 当用户编辑表格时,模型通过 setData 方法更新数据集合。
  5. 模型通过发射信号通知表格数据已更改,表格自动更新显示。

8.13 - 实验运行调度管理器

Prepper 类是 Quatm 实验调度与运行系统的核心组件,负责管理实验队列、线程调度和状态跟踪。

概述

Prepper 类(位于 quatm.gui.prepper 模块)是实验调度和运行系统的核心,提供以下核心能力:

  • 任务队列管理:维护待执行的实验任务列表
  • 线程调度:基于线程池的单线程调度策略,避免并发冲突
  • 状态跟踪:通过 expDict 追踪每个实验的配置和运行状态
  • 定时轮询:周期性检查任务状态并更新 UI

核心架构

graph TD
    A[实验任务入队] --> B[queue 任务队列]
    B --> C[threadpool 线程池]
    C --> D[执行实验]
    D --> E[expDict 状态更新]
    E --> F[timer 定时刷新 UI]
    F --> G[browser 界面展示]

API 参考

构造函数

from quatm.gui.prepper import Prepper

prepper = Prepper(browser=None)
参数类型必填说明
browserobject浏览器/UI 对象,用于界面交互和状态展示

成员变量

变量类型说明
browserobject关联的 UI 浏览器对象
queueQueue实验任务队列(FIFO)
expDictdict实验配置与状态字典
threadpoolThreadPoolExecutor线程池(max_workers=1)
timerQTimerUI 定时刷新器

使用示例

基础用法

from quatm.gui.prepper import Prepper
from quatm.experiments import RabiExperiment

# 1. 初始化调度器
prepper = Prepper(browser=my_browser)

# 2. 创建实验并加入队列
exp = RabiExperiment(
    qubit="q0",
    durations=[10, 20, 50, 100],  # ns
    amplitudes=[0.1, 0.2, 0.3, 0.4]
)
prepper.queue.put(exp)

# 3. 启动调度(从队列中取出并执行)
prepper.start()

批量实验调度

# 批量提交多个实验
experiments = [
    RabiExperiment(qubit="q0", durations=range(10, 100, 10)),
    RamseyExperiment(qubit="q0", delays=range(0, 1000, 50)),
    T1Experiment(qubit="q0", wait_times=range(1, 100, 5)),
]

for exp in experiments:
    prepper.queue.put(exp)

# 调度器会按 FIFO 顺序逐个执行
prepper.start()

线程模型

Prepper 使用 max_workers=1 的线程池设计,原因如下:

  1. 硬件安全:避免多个实验同时操作同一 FPGA 控制器,防止寄存器冲突
  2. 状态一致性:确保 expDict 在单线程下读写安全,无需加锁
  3. 可预测性:实验按入队顺序严格串行执行,结果可复现
from concurrent.futures import ThreadPoolExecutor

# Prepper 内部等价于:
self.threadpool = ThreadPoolExecutor(max_workers=1)

错误处理

调度器内置了异常捕获机制,通过 traceback 模块记录详细的堆栈信息:

import traceback

def _run_experiment(self, exp):
    try:
        result = exp.run()
        self.expDict[exp.id] = {"status": "done", "result": result}
    except Exception as e:
        self.expDict[exp.id] = {
            "status": "error",
            "error": str(e),
            "traceback": traceback.format_exc()
        }

实验失败不会中断调度器——错误被记录在 expDict 中,后续任务继续执行。

扩展指南

添加调度策略

如需支持优先级调度或依赖调度,可以扩展 Prepper 类:

class PriorityPrepper(Prepper):
    """支持优先级调度的实验管理器"""

    def __init__(self, browser=None):
        super().__init__(browser)
        from queue import PriorityQueue
        self.queue = PriorityQueue()

    def submit(self, exp, priority=0):
        """提交实验并指定优先级(数值越小优先级越高)"""
        self.queue.put((priority, exp))

添加实验类型

通过实现统一的实验接口,Prepper 可以支持任意实验类型:

class BaseExperiment:
    """所有实验的基类"""

    def run(self):
        raise NotImplementedError

    @property
    def id(self):
        return id(self)

# Prepper 通过鸭子类型支持任何实现了 run() 方法的对象

常见问题

Q: 为什么线程池大小固定为 1? A: 量子物理实验中,多个实验同时操作同一硬件可能导致不可预料的结果。单线程模型保证了时序确定性。

Q: 如何查看当前队列中的任务? A: 通过 prepper.queue.qsize() 获取待执行任务数,通过 prepper.expDict 查看各实验状态。

Q: 实验执行中可以暂停吗? A: 任何进程或者子进程都可以在实验执行过程中随时暂停、编辑、删除和添加。

8.14 - 实验预处理

该代码展示了一个名为 PrepStation 的类,用于实验的预处理和队列管理。

详细代码分析:PrepStation 类及其相关组件

该代码展示了一个名为 PrepStation 的类,用于实验的预处理和队列管理。以下是对代码的详细分析,涵盖导入的模块、类的定义及其成员、注释和错误处理等方面。

PrepStation 类

PrepStation 类是该代码的核心部分,用于管理实验任务的预处理和队列操作。以下是对该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 接受 browserparenttitle 作为参数。
    • 初始化各类成员变量,如 parentbrowserqueueexpDictqWidgetlayoutbuttonLayoutprops_taskparamDirtableprepList
    • 调用 init_uiinit_table_actions 方法来设置界面和表格操作。
初始化界面
  • init_ui 方法
    • 配置表格的垂直头,使其根据内容调整大小并隐藏。
    • 创建各种按钮并设置其图标、工具提示和点击事件。
    • 将按钮添加到布局中,并设置布局对齐方式。
初始化表格操作
  • init_table_actions 方法
    • 创建各种操作(如删除、休眠、推送、循环、编辑、查看和保存)并设置其快捷键和触发事件。
    • 将这些操作添加到表格中。
设置模型
  • set_model 方法
    • 创建 PrepModel 实例并设置为表格模型。
    • 调整表格列的宽度。
加载之前的任务
  • load_previous 方法
    • prepfile.json 文件中加载之前的任务列表,并打开相关的实验窗口。
    • 更新 prepList
任务操作方法
  • push 方法

    • 将选中的任务推送到队列中,如果没有选中任务,则推送第一个任务。
  • push_row 方法

    • 推送指定行的任务到队列中,并更新任务状态。
  • push_first 方法

    • 推送第一个任务到队列中。
  • delete_clicked 方法

    • 删除选中的任务,并更新任务文件。
  • set_sleeping 方法

    • 设置选中的任务为休眠状态。
  • push_to_looper 方法

    • 将选中的任务推送到循环器中。
  • move_up 方法

    • 上移选中的任务。
  • move_down 方法

    • 下移选中的任务。
  • update_prep_file 方法

    • 更新任务文件,将当前任务列表保存到 prepfile.json
编辑和查看参数
  • open_editor 方法

    • 打开任务编辑器窗口以修改任务参数。
  • open_viewer 方法

    • 打开参数查看器窗口以查看任务参数。
  • save_params 方法

    • 将实验参数保存到 JSON 文件中。

其他类和辅助函数

  • ExpEditWindow

    • 用于编辑实验参数的窗口。
    • 初始化方法 __init__init_ui
    • 提交修改的方法 submit
  • ParViewWindow

    • 用于查看实验参数的窗口。
    • 初始化方法 __init__init_ui
  • CheckLayout

    • 包含复选框和参数输入框的布局。
    • 初始化方法 __init__
  • DisplayBox

    • 显示参数名称、值和单位的布局。
    • 初始化方法 __init__init_ui
  • get_experiment 函数

    • 获取实验实例,如果实验窗口未打开则打开窗口。

8.15 - 实验集合管理器

该代码定义了一个用于管理和监控多个进程的图形用户界面(GUI)应用程序。

环境变量设置

代码通过检查操作系统平台设置了 QT_SCALE_FACTOR 环境变量,以调整 MacOS 上的缩放比例。

SingleProcess 类

SingleProcess 类用于表示单个可管理的进程。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 接受 scriptnameactivecategoryparent 作为参数。
    • 根据操作系统平台设置 Python 解释器路径。
    • 创建和配置按钮、布局和样式表。
    • 配置定时器以定期更新进程状态。
进程管理方法
  • startProcess 方法

    • 停止现有进程(如果有)。
    • 使用 subprocess.Popen 启动新的进程。
    • 更新按钮状态。
  • stopProcess 方法

    • 停止现有进程,根据需要选择终止或强制杀死进程。
    • 更新按钮状态。
  • updateStatus 方法

    • 定期检查进程状态并更新按钮颜色以指示进程是否运行。
析构方法
  • __del__ 方法
    • 确保在对象销毁时停止进程。

ProcessManager 类

ProcessManager 类用于管理多个 SingleProcess 实例。以下是该类的详细分析:

初始化方法
  • __init__ 方法
    • 初始化类实例,并设置初始状态或配置。
    • 读取配置文件,创建 SingleProcess 实例,并将其添加到布局中。
    • 设置窗口样式和布局。
事件处理方法
  • closeEvent 方法
    • 在关闭窗口时,停止所有正在运行的进程。
析构方法
  • __del__ 方法
    • 在对象销毁时输出调试信息。

主函数

  • main 方法
    • 设置高 DPI 缩放策略。
    • 创建应用程序实例,设置窗口图标,创建和显示主窗口。
    • 进入应用程序事件循环。

结论

该代码实现了一个进程管理和监控的 GUI 应用程序。通过 SingleProcess 类,用户可以启动、停止和监控单个进程;通过 ProcessManager 类,用户可以批量管理多个进程。代码结构清晰,使用了 Qt 的多种控件和信号槽机制来实现用户交互和数据更新。

8.16 - 实验参数管理器

该代码定义了一个用于管理和监控多个进程的图形用户界面(GUI)应用程序。

DefaultExp 类概述

DefaultExp 是一个实验类,包含所有设备的属性,并组织这些属性以便于管理和访问。

方法详解

build(self)
  • 功能
    • 设置实验的初始参数,如计数器。
    • 遍历设备数据库,加载设备并根据设备类型进行分组。
    • 处理属性的加载错误,并将设备分为显示和隐藏两类。
run(self)
  • 功能
    • 运行实验的主要逻辑(此处为空实现,作为模板)。

BasicManager 类概述

BasicManager 是一个基础管理类,用于创建和管理各种类型的参数小部件。

构造方法

  • 参数说明

    • props:属性对象,用于与属性数据库交互。
    • parent:父级小部件。
    • kwargs:其他参数,用于初始化属性。
  • 功能

    • 初始化基础属性,如单位、最大最小值、步长等。
    • 设置样式并调用 _initGUI 方法。

方法详解

_initGUI(self)
  • 功能
    • 初始化图形界面,创建布局和标签。
    • 如果存在工具提示,则设置工具提示。
    • 创建定时器,用于定期更新参数值。
updateSpin(self)
  • 功能
    • 占位方法,用于在子类中实现具体的更新逻辑。

IntManager 类概述

IntManager 继承自 BasicManager,用于管理整数类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个整数选择框 (QSpinBox)。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。
updateValue(self, v)
  • 参数

    • v:新值。
  • 功能

    • 更新实验和属性对象中的参数值。
updateSpin(self)
  • 功能
    • 检查属性对象中的值是否有变化,如果有变化,则更新选择框中的值。

BoolManager 类概述

BoolManager 继承自 QCheckBox,用于管理布尔类型的参数。

方法详解

updateValue(self, val)
  • 参数

    • val:新值。
  • 功能

    • 更新实验和属性对象中的布尔值。
updateCheckbox(self)
  • 功能
    • 检查属性对象中的布尔值是否有变化,如果有变化,则更新复选框的状态。

FloatManager 类概述

FloatManager 继承自 IntManager,用于管理浮点数类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个浮点数选择框 (QDoubleSpinBox)。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。

ComboManager 类概述

ComboManager 继承自 BasicManager,用于管理下拉列表类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个下拉列表 (QComboBox)。
    • 根据提供的字符串列表初始化下拉列表的选项。
    • 连接下拉列表的选项变化信号到 updateValue 方法。
updateValue(self, v)
  • 参数

    • v:新值。
  • 功能

    • 更新实验和属性对象中的选项值。

FrequencyManager 类概述

FrequencyManager 继承自 IntManager,用于管理频率类型的参数。

方法详解

initSpin(self)
  • 功能
    • 创建一个浮点数选择框 (QDoubleSpinBox),用于选择频率值。
    • 从属性对象中获取初始值并设置到选择框中。
    • 连接选择框的值变化信号到 updateValue 方法。

SimpleDefaults 类概述

SimpleDefaults 继承自 QFrame,用于显示和管理实验的默认参数。

构造方法

  • 功能
    • 初始化属性对象和实验对象。
    • 调用实验对象的 build 方法构建实验。
    • 创建和设置主布局。
    • 根据实验的分组创建相应的参数管理小部件,并添加到布局中。

主函数

main()

  • 功能
    • 创建应用程序实例。
    • 创建 SimpleDefaults 窗口并显示。
    • 启动应用程序的事件循环。

使用场景

  • 该代码主要用于科学实验和数据采集系统中,帮助管理和显示实验的各种参数。
  • 适用于需要频繁调整参数和查看参数变化的场景,如实验室研究和工业控制系统。

8.17 - 实验运行监视器

这个代码定义了一个 StreamMonitor 类和一个 TableModel 类,用于监控和显示各种数据流(包括数据流、图像流、命令流和消息流)的内容。它还提供了一个主函数 main,用于初始化和运行一个包含多个标签页的 PyQt 应用程序,每个标签页显示不同类型的数据流。

概述

这个代码定义了一个 StreamMonitor 类和一个 TableModel 类,用于监控和显示各种数据流(包括数据流、图像流、命令流和消息流)的内容。它还提供了一个主函数 main,用于初始化和运行一个包含多个标签页的 PyQt 应用程序,每个标签页显示不同类型的数据流。

StreamMonitor

StreamMonitor 类继承自 QWidget,用于监控和显示不同类型的数据流。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:name(数据流名称)、streamtype(数据流类型,如 ‘Data’、‘Image’ 等)、parent(父组件)。
    • 根据 streamtype 初始化不同类型的客户端对象(如 DataClientImageClient 等)。
    • 初始化用户界面,包括标签、复选框、组合框、按钮、文本编辑器和表格视图等。
    • 设置一个定时器,用于定期更新数据流的内容。
  • _update_message 方法

    • 定期从消息流中获取新消息,并将其添加到消息列表中。
    • 如果启用了保存选项,则将新消息写入文件。
  • update_text 方法

    • 根据用户选择的过滤条件更新显示的消息内容。
    • 使用 QTableView 显示过滤后的消息列表。
  • _update_selected_message 方法

    • 从文件中读取历史消息,并更新显示内容。
  • _update_list 方法

    • 定期从数据流中获取新数据,并将其添加到消息列表中。
  • load_selected_message 方法

    • 打开文件对话框,允许用户选择一个消息文件,并加载文件内容。
  • update_table_selected 方法

    • 根据用户选择的过滤条件更新显示的历史消息内容。
  • on_checkbox_changed 方法

    • 处理复选框状态变化事件。

TableModel

TableModel 类继承自 QAbstractTableModel,用于管理和显示表格数据。

主要方法和属性

  • 初始化方法 __init__

    • 接受参数:data(表格数据),并初始化模型。
  • data 方法

    • 根据指定的索引和角色返回相应的数据内容和样式。
  • rowCount 方法

    • 返回表格的行数。
  • columnCount 方法

    • 返回表格的列数。
  • headerData 方法

    • 返回表头的标签内容。

使用场景

  • 该代码主要用于需要监控和显示实时数据流的应用程序。
  • 适用于数据分析、系统监控和日志管理等场景。
  • 提供了一种用户友好的方式,通过图形界面查看和管理不同类型的数据流和消息内容。

主函数 main

  • 创建一个包含多个标签页的 QTabWidget,每个标签页显示不同类型的数据流。
  • 初始化和运行 PyQt 应用程序。

通过这种方式,用户可以方便地在一个界面中监控和管理多种类型的数据流和消息内容。

8.18 - 实验任务折叠管理

这段代码定义了一个可折叠的对话框组件,允许用户在应用程序中添加和管理可折叠的部分。主要组件包括 SectionExpandButton 类和 CollapsibleDialog 类,它们协同工作以实现可折叠部分的创建和管理。

概述

这段代码定义了一个可折叠的对话框组件,允许用户在应用程序中添加和管理可折叠的部分。主要组件包括 SectionExpandButton 类和 CollapsibleDialog 类,它们协同工作以实现可折叠部分的创建和管理。

主要组件

SectionExpandButton

SectionExpandButton 类继承自 QPushButton,用于创建一个可以展开或折叠其关联部分的按钮。

主要方法和属性
  • 初始化方法 __init__

    • 接受参数:item(关联的部分项)、text(按钮文本)、parent(父组件)。
    • 设置按钮的初始文本,并连接点击事件到 on_clicked 方法。
  • on_clicked 方法

    • 处理按钮的点击事件,切换关联部分的展开或折叠状态。
    • 如果部分是展开的,则将其折叠;如果是折叠的,则将其展开。

CollapsibleDialog

CollapsibleDialog 类继承自 QDialog,用于创建一个包含可折叠部分的对话框。

主要方法和属性
  • 初始化方法 __init__

    • 创建并配置一个 QTreeWidget 以隐藏标题,并将其添加到对话框的布局中。
    • 设置树的缩进为 0。
  • add_section 方法

    • 接受参数:title(部分的标题)、widget(部分的内容部件)。
    • 调用 add_button 方法创建一个按钮,并调用 add_widget 方法将内容部件添加为按钮的子项。
  • define_sections 方法

    • 定义并添加对话框中的所有部分。
    • 示例实现中,创建了一个包含两个标签的 QFrame 部件,并将其添加到部分中。
  • add_button 方法

    • 接受参数:title(部分的标题)。
    • 创建一个 QTreeWidgetItem 项,并将其添加为树的顶级项。
    • 创建一个 SectionExpandButton 按钮,将其设置为项的部件,并返回该项。
  • add_widget 方法

    • 接受参数:button(按钮项)、widget(部分的内容部件)。
    • 创建一个 QTreeWidgetItem 项,将其设置为按钮项的子项,并将内容部件设置为子项的部件。

使用场景

这个组件可以用于需要包含多个可折叠部分的对话框的应用程序,例如设置对话框、信息面板等。通过扩展 CollapsibleDialog 类并重写 define_sections 方法,可以轻松定义和管理对话框中的各个部分。

示例

下面是一个示例,展示如何使用 CollapsibleDialogSectionExpandButton 类:

import sys
from PyQt6.QtWidgets import QApplication

class MyCollapsibleDialog(CollapsibleDialog):
    def define_sections(self):
        widget1 = QFrame(self.tree)
        layout1 = QHBoxLayout(widget1)
        layout1.addWidget(QLabel("Content 1"))
        self.add_section("Section 1", widget1)
        
        widget2 = QFrame(self.tree)
        layout2 = QHBoxLayout(widget2)
        layout2.addWidget(QLabel("Content 2"))
        self.add_section("Section 2", widget2)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    dialog = MyCollapsibleDialog()
    dialog.define_sections()
    dialog.show()
    sys.exit(app.exec())

在这个示例中,MyCollapsibleDialog 类继承自 CollapsibleDialog 并重写了 define_sections 方法,定义了两个可折叠部分。运行此代码将显示一个包含两个可折叠部分的对话框。

9 - 应用案例

通过真实实验案例了解 Quatm 框架在量子物理研究中的广泛应用。

Quatm 已在世界一流量子实验室中稳定运行,支撑从基础原子物理到精密量子操控的全链条实验。

超冷原子实验

案例说明
MOT 装载优化多维参数扫描自动优化磁光阱装载效率
吸收成像相机触发、三帧成像与高斯拟合的自动化
光偶极阱ODT 功率频率扫描、寿命测量与 Feshbach 共振标定
偶极阱优化辅助工具交互式 ODT 对准与杂散场补偿

离子阱实验

案例说明
离子装载与冷却多阶段时序:烧蚀→冷却→俘获→荧光探测
量子态操控与检测光学泵浦、微波操控与量子跳跃统计
电场偏移补偿辅助工具自动杂散场补偿与电压扫描

原子/离子相互作用

案例说明
原子—离子碰撞双系统协同控制的冷原子—单离子碰撞实验

系统校准

案例说明
系统校准相机暗噪声、快门响应、频率合成器验证、触发延迟标定等自动化校准任务

9.1 - MOT 装载优化

利用 Quatm 的参数扫描和多维时序控制,自动优化磁光阱装载效率。

功能介绍

该实验通过继承 Experiment 基类,实现对磁光阱(MOT)磁场线圈、冷却光和回泵光的协同控制。实验支持自动扫描磁场梯度和冷却光失谐两个维度,每次运行后通过吸收成像测量原子数,最终找到最优的 MOT 装载参数组合。

代码结构

  • 导入 Experiment 基类和参数类型
  • 定义 MOTLoadExperiment
  • build() 中声明设备和扫描参数
  • run() 中编排装载—压缩—探测时序

类:MOTLoadExperiment

简短功能介绍

继承自 Experiment 的实验类,负责 MOT 装载的完整自动控制流程。

方法:build()

功能:声明实验中使用的设备和可调参数。

参数声明

  • b_gradient:磁场梯度(NumberValue,单位 G/cm)
  • cooling_detuning:冷却光失谐(NumberValue,单位 MHz)
  • loading_time:装载时间(NumberValue,单位 s)
  • tof_time:自由飞行时间(NumberValue,单位 ms)

设备声明

  • trap_coil_xtrap_coil_ytrap_coil_z:DAC 控制的磁场线圈
  • cooling_aomrepump_aom:TTL 控制的激光开关
  • camera_trigger:相机触发 TTL

方法:run()

功能:单次 MOT 装载—探测的执行逻辑。

主要步骤

  1. 设置磁场线圈电流,建立梯度磁场
  2. 开启冷却光和回泵光,开始装载原子
  3. delay(loading_time) 等待装载完成
  4. 关闭磁场和冷却光,开始自由飞行
  5. delay(tof_time) 等待原子云膨胀
  6. 触发探测光脉冲和相机曝光
  7. 分析吸收图像,通过 DataClient 推送原子数

参数扫描

在 GUI 中为 b_gradientcooling_detuning 设置扫描范围,Quatm 自动遍历所有组合,每次运行记录对应原子数。扫描完成后可绘制二维装载效率图谱。

涉及的设备

Trap 线圈(DAC×3)、冷却光 AOM(TTL+DAC)、回泵光(TTL)、探测光(TTL)、相机触发(TTL)、吸收成像相机

9.2 - 电场偏移补偿辅助工具

该代码实现了一个用于补偿电场漂移的辅助工具(CompensationHelper)。该工具通过使用 Qt 库构建图形界面,帮助进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

代码概述

该代码实现了一个用于补偿电场漂移的辅助工具(CompensationHelper)。该工具通过使用 Qt 库构建图形界面,帮助进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

依赖库

  • sys, time, numpy:标准库,用于系统操作、时间管理和数值计算。
  • Qt:用于构建 GUI 应用程序。
  • pyqtgraph:用于绘制图形。
  • quatm.serversquatm.GUI:自定义库,用于属性管理和 GUI 组件。

类和方法

CompensationHelper

CompensationHelper 继承自 BWidget,实现了电场补偿的主界面。

方法:

  • __init__(self, parent):初始化补偿助手,设置布局并添加绘图和控制小部件。

PlotWidget

PlotWidget 继承自 QFrame,实现了绘图窗口。

方法:

  • __init__(self, parent):初始化绘图窗口,创建每个陷阱轴的标签页和数据流名称。
  • constructScanRange(self):构建扫描范围,根据中心和跨度生成线性扫描范围。

TabWidget

TabWidget 继承自 QFrame,实现了每个陷阱轴的标签页。

方法:

  • __init__(self, name, _prop_root, datastream_names, n_yaxis=2, parent=None):初始化标签页,设置布局和按钮。
  • toggleDataTaking(self):切换数据管理器的状态(启动/暂停)。
  • setPlotDefaults(self):设置绘图的默认参数。
  • avModeSwitch(self):切换平均模式的状态。

ControlWidget

ControlWidget 继承自 QFrame,实现了控制窗口。

方法:

  • __init__(self, parent):初始化控制窗口,创建按钮和参数框。
  • run_all_fn(self, progress_callback=None):运行所有轴的扫描函数。
  • run_all(self):启动所有轴的扫描。
  • print_output(self):打印输出。
  • task_done(self):任务完成时调用。
  • progress_fn(self, n):更新进度。
  • init_data_taking(self):初始化数据采集。

SingleAxisWidget

SingleAxisWidget 继承自 QFrame,实现了单个轴的扫描控制。

方法:

  • __init__(self, name, parent):初始化单个轴的扫描控制窗口,设置布局和按钮。
  • switch_tabs(self):切换标签页。
  • findIntersection(self):找到两个线性拟合结果的交点。
  • getFromDefaults(self):从默认值中获取补偿电压。
  • pushToDefaults(self):将补偿电压推送到默认值。
  • run_all_fn(self, progress_callback=None):运行所有扫描函数。
  • init_data_manager(self):初始化数据管理器。
  • start_scan(self):开始扫描。
  • progress_fn(self, n):更新进度。
  • run_done(self):扫描完成时调用。
  • handle_error(self, err_msg):处理错误。
  • clear(self):清除绘图。

CompVoltageScan

CompVoltageScan 继承自 QFrame,实现了电压扫描功能。

方法:

  • __init__(self, parent, axis_name):初始化电压扫描窗口,设置布局和按钮。
  • initGUI(self):初始化用户界面,创建控件和布局。
  • switchTabs(self):切换标签页。
  • constructScanRange(self):构建扫描范围。
  • initExperiment(self):初始化实验参数。
  • updateScan(self):更新扫描参数。
  • runExperimentSequence(self, progress_callback):运行实验序列。
  • stop(self):停止扫描。
  • run(self):启动扫描。
  • progress_fn(self, n):更新进度。
  • print_output(self, s):打印输出。
  • thread_complete(self):线程完成时调用。
  • terminate(self):终止扫描。

辅助函数

find_or_add(box, text)

在组合框中查找或添加项目。

def find_or_add(box, text):
    """if it's in the box, set it, if not, add and set it"""
    idx = box.findText(text)
    if idx < 0:
        box.addItem(text)
        idx = box.findText(text)
    box.setCurrentIndex(idx)

总结

该代码实现了一个用于补偿电场漂移的辅助工具。通过图形用户界面,用户可以进行电压扫描、数据管理和图形绘制。代码包含多个类,每个类负责特定的功能模块,例如图形绘制、控制参数设置和实验序列管理。

9.3 - 离子装载与冷却

利用 Quatm 的多阶段时序控制,实现从激光烧蚀到荧光探测的完整离子装载流程。

功能介绍

该实验通过四个精确定时阶段:烧蚀、冷却、俘获和荧光探测,实现钡离子(Ba⁺)的自动装载。各阶段参数可在 GUI 中独立调节,支持确定性装载(失败自动重试)。

代码结构

  • 导入 ExperimentNumberValueBoolValue
  • 定义 IonLoading
  • build() 中声明各阶段参数和设备
  • run() 中串联四阶段时序

类:IonLoading

简短功能介绍

继承自 Experiment,管理离子装载的完整多阶段流程。

方法:build()

功能:声明离子装载所需的设备和可调参数。

参数声明

  • ablation_power:烧蚀激光功率(NumberValue
  • cooling_493_power:493 nm 冷却光功率(NumberValue
  • cooling_650_power:650 nm 回泵光功率(NumberValue
  • cooling_time:Doppler 冷却时长(NumberValue
  • detection_time:荧光探测积分时间(NumberValue
  • enable_auto_retry:是否启用自动重试(BoolValue

设备声明

  • ablation_laser:烧蚀激光 TTL
  • cooling_493:493 nm 冷却光(TTL + DAC)
  • cooling_650:650 nm 回泵光(TTL + DAC)
  • rf_trap:射频囚禁场(DDS)
  • emccd:EMCCD 相机

方法:run()

功能:执行一次完整的离子装载序列。

主要步骤

  1. 触发烧蚀激光脉冲,从靶材产生离子
  2. 开启 493 nm 冷却光和 650 nm 回泵光
  3. delay(cooling_time) Doppler 冷却离子
  4. 开启 EMCCD 曝光,采集荧光图像
  5. delay(detection_time) 荧光积分
  6. 调用 bright_spots.detect() 检测离子存在
  7. 若未检测到且 enable_auto_retry 为真,自动重试

涉及的设备

烧蚀激光(TTL)、冷却激光 493 nm(TTL+DAC)、回泵光 650 nm(TTL+DAC)、射频源(DDS)、EMCCD 相机

9.4 - 偶极阱优化辅助工具

该代码实现了一个名为 LittleHelper 的 Qt 桌面应用程序,它包含多个标签页,每个标签页提供不同的帮助功能。目前实现了两个帮助功能:xODT AlignmentStray Field Compensation

功能介绍

该代码实现了一个名为 LittleHelper 的 Qt 应用程序,它包含多个标签页,每个标签页提供不同的帮助功能。目前实现了两个帮助功能:xODT AlignmentStray Field Compensation

代码结构

  • 导入必要的模块和库
  • 定义 LittleHelper
  • 定义 TabWidget
  • 定义脚本入口

类:LittleHelper

简短功能介绍

LittleHelper 类是一个主窗口类,用于创建和显示包含多个标签页的主窗口。

方法:__init__

功能:初始化 LittleHelper 对象,设置窗口标题并创建标签页部件。

参数

  • *args**kwargs:可变参数和关键字参数,用于初始化基类。

主要步骤

  1. 调用父类的 __init__ 方法。
  2. 设置窗口标题为 “Little Helper”。
  3. 创建并设置 TabWidget 作为中央部件。

类:TabWidget

简短功能介绍

TabWidget 类是一个包含多个标签页的部件,每个标签页提供不同的帮助功能。

方法:__init__

功能:初始化 TabWidget 对象,创建并添加标签页。

参数

  • parent:父对象。

主要步骤

  1. 调用父类的 __init__ 方法。
  2. 创建主布局并设置为垂直布局。
  3. 初始化标签页组件 QTabWidget
  4. 创建并添加标签页:
    • tab1OdtAlignmentHelper 标签页,用于 xODT 对准。
    • tab2CompensationHelper 标签页,用于杂散场补偿。
  5. 将标签页添加到 QTabWidget 中。
  6. QTabWidget 添加到主布局中并设置布局。

脚本入口

简短功能介绍

脚本入口用于创建应用程序实例,显示主窗口并启动应用事件循环。

主要步骤

  1. 创建 QApplication 实例。
  2. 创建 LittleHelper 实例。
  3. 显示主窗口。
  4. 启动应用事件循环。

主要类和方法

  • LittleHelper:主窗口类,包含多个标签页。

    • __init__:初始化窗口标题和标签页部件。
  • TabWidget:包含多个标签页的部件。

    • __init__:初始化标签页并添加不同的帮助功能标签页。

脚本入口

  • 创建 QApplication 实例。
  • 创建 LittleHelper 实例并显示主窗口。
  • 启动应用事件循环。

9.5 - 系统校准

Quatm 在日常实验系统校准与维护中的自动化应用。

功能介绍

除物理实验外,Quatm 将日常校准任务也编为标准实验脚本,实现一键运行和自动记录。覆盖相机暗噪声、快门响应、频率合成器验证和触发延迟标定等常见校准需求。

代码结构

所有校准实验均遵循相同的结构模式:

  • 继承 Experiment
  • build() 中声明被测设备和校准参数
  • run() 中执行校准流程并自动记录结果

典型校准任务

相机暗噪声表征

功能:在无光条件下连续采集图像帧,统计暗电流噪声分布。

主要步骤

  1. 关闭所有光源,设置相机曝光时间
  2. 循环采集 N 帧暗图像
  3. 计算每像素的均值和标准差
  4. 保存噪声图谱至 HDF5

涉及设备:相机

快门响应时间测量

功能:测量机械快门从 TTL 触发到完全开启/关闭的延迟时间。

主要步骤

  1. 光电探测器对准快门后的光束
  2. TTL 触发快门开启,同步启动高速采集
  3. 记录探测器信号上升/下降沿时间
  4. 重复测量取平均

涉及设备:快门(TTL)、光电探测器

频率合成器验证

功能:验证 Valon 5009 或 DDS 频率合成器的实际输出频率和功率。

主要步骤

  1. 设置频率合成器到目标频率
  2. 频谱仪测量实际输出
  3. 扫描频率范围,记录偏差
  4. 生成校准曲线

涉及设备:Valon 5009/DDS(串口)、频谱仪

相机触发延迟标定

功能:测量 TTL 触发到相机实际曝光窗口之间的延迟。

主要步骤

  1. 脉冲光源与相机触发共享同一 TTL 信号
  2. 扫描触发延迟参数
  3. 检测每帧中光脉冲出现位置
  4. 标定最佳延迟值

涉及设备:相机、脉冲光源(TTL)

9.6 - 原子—离子碰撞实验

利用 Quatm 的多系统协同控制,研究冷原子与单离子之间的碰撞动力学。

功能介绍

该实验同时控制冷原子(Rb)和单离子(Ba⁺)两套独立系统。通过精确的空间和时间重叠,研究低温下原子—离子碰撞的动力学过程。Quatm 将两套系统的设备统一管理,确保时序同步。

代码结构

  • 导入 ExperimentNumberValueBoolValue
  • 定义 AtomIonInteraction
  • build() 中声明两套系统的设备和参数
  • run() 中协调原子和离子的并行时序

类:AtomIonInteraction

简短功能介绍

继承自 Experiment,管理原子和离子两套控制系统的协同运行。

方法:build()

功能:声明原子和离子两侧的全部设备和参数。

原子侧参数声明

  • mot_loading_time:MOT 装载时间(NumberValue
  • mot_b_gradient:磁场梯度(NumberValue

离子侧参数声明

  • ion_position_xion_position_y:离子在阱中位置(NumberValue
  • interaction_time:相互作用等待时间(NumberValue

设备声明

  • 原子侧:trap_coil_*(DAC×3)、cooling_aom(TTL)、repump_aom(TTL)、camera(吸收成像)
  • 离子侧:paul_electrode_*(DAC×4)、ablation_laser(TTL)、cooling_493(TTL+DAC)、emccd

方法:run()

功能:执行一次原子—离子碰撞实验。

主要步骤

  1. 并行启动原子 MOT 装载和离子装载
  2. 移动离子到预定位置(ion_position_xion_position_y
  3. 等待 MOT 装载完成,压缩原子云
  4. 原子云与离子在空间和时间上重合
  5. delay(interaction_time) 等待碰撞发生
  6. 分别检测:吸收成像测原子损失,荧光探测测离子态变化
  7. 两路数据通过 DataClient 分别推送

涉及的设备

原子侧:MOT 线圈(DAC×3)、冷却/回泵光(TTL×2)、吸收成像相机 离子侧:Paul 阱电极(DAC×4)、烧蚀激光(TTL)、冷却光(TTL+DAC)、EMCCD

9.7 - 量子态操控与检测

利用 Quatm 的精确时序和统计分析,实现离子量子态的光学泵浦与状态相关荧光检测。

功能介绍

该实验实现 D 态 shelving 量子态检测协议:通过光学泵浦将离子制备到暗态,施加微波操控后,利用状态相关荧光区分 S 态和 D 态。自动重复数百次测量,统计量子跃迁概率。

代码结构

  • 导入 ExperimentNumberValueStringCombo
  • 定义 QuantumStateDetection
  • build() 中声明操控和检测参数
  • run() 中编排泵浦—操控—检测序列

类:QuantumStateDetection

简短功能介绍

继承自 Experiment,封装量子态操控与荧光检测的完整协议。

方法:build()

功能:声明量子态检测所需的设备和参数。

参数声明

  • mw_frequency:微波频率(NumberValue
  • mw_duration:微波脉冲宽度(NumberValue
  • pump_duration:光学泵浦时间(NumberValue
  • repetitions:重复测量次数(NumberValue
  • scan_mode:扫描模式(StringCombo:频率扫描/功率扫描/时间扫描)

设备声明

  • valon_5009:微波频率合成器
  • cooling_493:冷却/探测光(TTL + DAC)
  • cooling_650:回泵/泵浦光(TTL + DAC)
  • emccd:EMCCD 相机
  • pmt_counter:PMT 光子计数器

方法:run()

功能:执行一次量子态检测序列。

主要步骤

  1. Doppler 冷却离子
  2. 光学泵浦到暗态(D₅/₂)
  3. 施加微波脉冲驱动量子跃迁
  4. 开启探测光,PMT 记录荧光光子数
  5. 根据光子数阈值判断离子终态(亮/暗)
  6. 重复 N 次,统计跃迁概率
  7. 切换微波频率/功率,进入下一次扫描点

涉及的设备

微波源(Valon 5009)、冷却光(TTL+DAC)、回泵光(TTL+DAC)、EMCCD、PMT 光子计数器

9.8 - 吸收成像

利用 Quatm 的相机控制和图像分析,实现原子云吸收成像的自动化采集与分析。

功能介绍

该实验通过集成相机触发、图像采集和高斯拟合,实现冷原子吸收成像的全自动流程。支持三帧成像法(原子像、背景像、探测光像),自动计算光学深度分布,并通过 gaussfit 模块拟合提取原子数和温度。

代码结构

  • 导入 ExperimentNumberValuegaussfit 分析模块
  • 定义 AbsorptionImaging
  • build() 中声明相机和探测光参数
  • run() 中编排成像时序并调用分析

类:AbsorptionImaging

简短功能介绍

继承自 Experiment,封装吸收成像的完整采集与分析流程。

方法:build()

功能:声明实验设备和成像参数。

参数声明

  • exposure_time:相机曝光时间(NumberValue
  • probe_pulse_duration:探测光脉冲宽度(NumberValue
  • tof_time:自由飞行膨胀时间(NumberValue

设备声明

  • camera:Andor 或 BlackFly 相机
  • probe_aom:探测光 TTL 控制
  • trap_coil_z:Z 方向磁场线圈

方法:run()

功能:执行一次完整的吸收成像探测。

主要步骤

  1. 关闭磁场线圈,释放原子云
  2. delay(tof_time) 等待自由飞行
  3. 触发探测光脉冲(probe_aom = True
  4. 同步触发相机曝光
  5. 读取图像数据
  6. 调用 gaussfit.fit_2d() 拟合光学深度
  7. 通过 DataClient 发送原子数和温度结果

涉及的设备

探测光 AOM(TTL)、相机(Andor/BlackFly)、磁场线圈(DAC)

9.9 - 光偶极阱实验

利用 Quatm 的双参数扫描和寿命测量功能,研究 ODT 中冷原子的俘获与损耗特性。

功能介绍

该实验实现对光偶极阱(ODT)的功率控制、频率扫描和原子寿命自动测量。支持 ODT 功率和射频频率的双参数扫描,用于精确标定 Feshbach 共振位置。

代码结构

  • 导入 ExperimentNumberValueBoolValue
  • 定义 ODTExperiment
  • build() 中声明 ODT 设备和扫描参数
  • run() 中编排装载、俘获和探测时序

类:ODTExperiment

简短功能介绍

继承自 Experiment,管理 ODT 的功率控制、频率扫描和寿命测量。

方法:build()

功能:声明 ODT 实验所需的设备和参数。

参数声明

  • odt_power:ODT 激光功率(NumberValue
  • rf_frequency:射频频率(NumberValue,用于 Feshbach 扫描)
  • hold_time:原子在 ODT 中的停留时间(NumberValue
  • enable_rf:是否启用射频(BoolValue

设备声明

  • odt_aom:ODT 光路 AOM(DAC + TTL)
  • valon_5009:射频频率合成器
  • camera:吸收成像相机

方法:run()

功能:执行一次 ODT 俘获—探测循环。

主要步骤

  1. MOT 装载原子云
  2. 开启 ODT 激光,关闭磁场线圈
  3. delay(hold_time) 保持原子在 ODT 中
  4. 关闭 ODT,释放原子
  5. 吸收成像探测剩余原子数
  6. 记录 ODT 功率和原子数至 HDF5

涉及的设备

ODT 激光 AOM(DAC+TTL)、射频源(Valon 5009)、磁场线圈(DAC)、吸收成像相机

10 - 实验最佳实践

编写可靠、高效的 Quatm 实验脚本的建议与技巧。

实验结构设计

单一职责原则

每个实验脚本聚焦一个明确的物理目标,避免混合多个不相关的逻辑:

experiments/
├── absorption_imaging.py    # 吸收成像
├── fluorescence_detect.py   # 荧光探测
├── rabi_scan.py             # Rabi 振荡
└── sideband_cooling.py      # 边带冷却

复用公共逻辑

将重复步骤提取为 Mixin 类:

class CoolingMixin:
    def doppler_cooling(self, duration=5):
        self.cooling_laser = True
        self.repump_laser = True
        from quatm.experiment.experiment import delay
        delay(duration)
        self.cooling_laser = False

class SidebandExperiment(CoolingMixin, Experiment):
    def run(self):
        self.doppler_cooling()
        # ... 后续步骤

设备管理

在 build 中声明,在 run 中使用

def build(self):
    self.setattr_device("camera")    # 声明
    self.setattr_device("fpga")

def run(self):
    self.camera.expose(0.1)         # 使用

设备状态检查

在实验开始前检查设备连接和状态:

def run(self):
    if not self.controller.is_ready():
        raise RuntimeError("控制器未就绪")
    self.camera.set_temperature(-70)

错误处理与恢复

异常安全关闭

务必在 finally 或上下文管理器中确保关键设备安全关闭:

def run(self):
    try:
        self.mot_coils = True
        with realtime():
            self.cooling_laser = True
            delay(5000)
    finally:
        self.cooling_laser = False
        self.mot_coils = False

使用模拟模式测试

在连接真实硬件前,先通过模拟模式验证实验逻辑:

# 在 device_db.py 中设置模拟模式
"/Devices/simulating": True

性能优化

合理使用 realtime 上下文

realtime() 上下文内的代码直接转换为 FPGA 时序指令,避免在其中放入复杂计算:

# ❌ 不推荐
with realtime():
    result = complex_computation()  # 计算耗时不明确
    self.dac_output = result

# ✅ 推荐
result = complex_computation()  # 在 realtime 外完成计算
with realtime():
    self.dac_output = result

大数据流优化

对于图像等大数据,使用 ImageClient 而非 DataClient,确保数据通道不被阻塞。

测试策略

单元测试

每个自定义驱动和 Mixin 应编写对应的单元测试:

# tests/test_cooling_mixin.py
def test_doppler_cooling():
    exp = MockExperiment()
    exp.doppler_cooling(duration=1)
    assert exp.cooling_laser == False  # 冷却结束后应关闭

集成测试

在模拟模式下运行完整实验流程,验证各组件协作正常。

常见问题

问题说明解决方案
delay() 单位混淆delay(100) 是 100ms,不是 100s使用 delay(5*1000) 明确表示秒
忘记关闭激光/磁场实验异常退出时设备保持开启使用 try/finally 确保关闭
属性缓存未刷新PropertyAttribute 值未及时同步始终使用 .value 读写属性
相机未冷却就采集暗电流噪声过大采集前检查温度:assert camera.temperature <= -60

## 数据管理

通过 `DataClient` 发送结构化的实验数据:

```python
def run(self):
    self._dataq.send({
        "atom_count": N,
        "temperature": T,
        "b_field": self.b_field,
    })

数据以 HDF5 格式保存,自动包含时间戳和扫描参数。

性能优化

  • 减少 GUI 更新频率:仅在关键步骤更新显示
  • 使用 simulation_class_decorator 在模拟模式下快速迭代
  • 高频循环中避免 print(),使用 send_debug() 代替

错误处理

def run(self):
    try:
        self.controller.start_process(1)
        delay(10)
    finally:
        self.controller.reset()
        self.shutter = False

11 - 物理模型库

量子物理实验的物理建模与计算工具

概述

Quatm 物理模型库(physics)提供冷原子/离子混合实验所需的物理建模和计算工具。它包含原子属性数据库、光与物质相互作用计算、光偶极阱(ODT)势建模、Feshbach 共振分析等功能。

原子数据库 — quatm.physics.odt.atomlib

提供常用实验原子/离子的物理属性数据,包含基态到激发态的跃迁频率、线宽、Clebsch-Gordan 耦合系数等。

预定义原子

原子/离子字典名典型用途
Ba⁺BariumDict离子阱量子计算
⁶LiLithiumDict超冷费米气体
Mg⁺MagnesiumDict离子阱量子计算
⁸⁷RbRubidiumDict玻色-爱因斯坦凝聚
Ca⁺CalciumDict离子阱精密测量

属性字段

每个原子字典包含以下物理常数:

字段说明
name元素/同位素名称
charge电荷量 (C)
mass原子质量 (kg)
SP_frequencies强跃迁 (S→P) 角频率
SP_decays强跃迁线宽 (角频率)
SP_linpolcouplingClebsch-Gordan 平方耦合系数
DP_frequencies弱跃迁 (D 态) 频率
DP_decays弱跃迁线宽
DP_linpolcoupling弱跃迁耦合系数

使用示例

from quatm.physics.odt.atomlib import Atom, BariumDict

# 创建钡离子实例
ba_ion = Atom(BariumDict)
print(f"质量: {ba_ion.mass:.2e} kg")
print(f"电荷: {ba_ion.charge:.2e} C")

预实例化的原子可直接导入:Ba, Li, Mg, Rb, Ca

光与物质相互作用 — quatm.physics.odt.lightmatterint

计算给定原子和激光配置下的光-物质相互作用量,基于 Metcalf 和 van der Straten 的形式理论。

LMinteraction

from quatm.physics.odt.lightmatterint import LMinteraction
from quatm.physics.odt.atomlib import Ba
from quatm.physics.odt.lasers import Laser

# 创建激光对象和相互作用计算器
laser = Laser(wavelength=532e-9, power=10.0, waist=50e-6)
lm = LMinteraction(ion=Ba, laser=laser)

关键方法

方法功能公式
SPStarkShift(transition)单跃迁 AC Stark 位移\(\delta_n = -\frac{3\pi c^2}{2\omega_0^3} \left(\frac{\Gamma}{\omega_0-\omega_L} + \frac{\Gamma}{\omega_0+\omega_L}\right) I\)
S12shift()S→P 总 Stark 位移各跃迁加权求和
ScattRate(transition)单跃迁散射率非共振光子散射速率
TotalScattRate()总散射率所有强跃迁散射率之和

光偶极阱建模 — quatm.physics.odt.opticaltraputils

Trap

建模完整的光偶极阱势,综合计算以下贡献:

  • 一个或多个高斯激光束的光学势
  • 直流电场(杂散场和四极曲率)
  • 与附加囚禁离子的库仑相互作用
from quatm.physics.odt.opticaltraputils import Trap

trap = Trap(
    laser=laser,
    ion=ba_ion,
    efields=efield_config,
    laseroffset=(0.0, 0.0)  # 激光束偏离阱中心的位置
)

关键方法

方法说明
AnalTrapDepth()无线性杂散场时的解析阱深 (mK)
FullPotential2D(x, y)计算 (x, y) 处的 2D 完整势
FullPotential3D(x, y, z)计算 (x, y, z) 处的 3D 完整势
FullPotential(point, ion_pos)计算空间某点的完整势 (K),可含其他离子位置

物理学公式参考

AC Stark 位移

光偶极阱中原子经历的 AC Stark 位移:

$$U_{\text{dip}} = -\frac{3\pi c^2}{2\omega_0^3} \left(\frac{\Gamma}{\omega_0 - \omega_L} + \frac{\Gamma}{\omega_0 + \omega_L}\right) I$$

其中 $\omega_0$ 为原子共振频率,$\omega_L$ 为激光频率,$\Gamma$ 为跃迁线宽,$I$ 为激光强度。

光子散射率

非共振光子散射导致的加热速率为:

$$\Gamma_{\text{sc}} = \frac{3\pi c^2}{2\hbar\omega_0^3} \left(\frac{\omega_L}{\omega_0}\right)^3 \left(\frac{\Gamma}{\omega_0 - \omega_L} + \frac{\Gamma}{\omega_0 + \omega_L}\right)^2 I$$

11.1 - 原子数据库 (atomlib)

Ba、Rb、Li、Mg、Ca 原子属性——质量、跃迁频率、Clebsch-Gordan 系数。

概述

atomlib 提供常用冷原子和离子实验原子种类的预计算物理数据。

预定义原子

字典种类典型用途
BariumDictBa⁺离子阱量子计算
RubidiumDict⁸⁷Rb玻色-爱因斯坦凝聚
LithiumDict⁶Li超冷费米气体
MagnesiumDictMg⁺离子阱精密测量
CalciumDictCa⁺离子阱光钟

属性字段

属性说明
mass原子质量 (kg)
ground_state基态能级标识
excited_state激发态能级标识
transition_frequency跃迁频率 (Hz)
decay_rate自发辐射衰减率 (s⁻¹)
clebsch_gordanClebsch-Gordan 耦合系数

11.2 - 电场计算 (efields)

离子阱电场势能——杂散场、曲率和一维离子位置计算。

概述

efields 计算 Paul 阱中离子的电场势能分布,支持杂散场和曲率参数,基于 James 方法求解一维离子平衡位置。

说明
efields电场势能计算,含杂散场和曲率
DCTrap管理平均/随机杂散场配置
from quatm.physics.odt.efields import efields

field = efields(stray_field=(1e-3, 0, 0), curvature=0.01)
potential = field.compute_potential(x_grid)

11.3 - 激光模型 (lasers)

高斯光束激光——光束尺寸、强度、波前曲率和缩放电场。

概述

Laser 类建模高斯光束激光器,管理波长/频率/波数的自动同步转换,计算沿传播方向的光束尺寸、R 曲率半径和缩放电场。

from quatm.physics.odt.lasers import Laser

laser = Laser(wavelength=1064e-9, power=10.0, waist=50e-6)
intensity = laser.intensity(z=0.0)
w = laser.beam_radius(z=0.01)

11.4 - 光物质作用 (lightmatterint)

AC Stark 频移和散射率——S→P 和 D→P 跃迁的 Clebsch-Gordan 加权计算。

概述

LMinteraction 计算激光场与原子的相互作用:包括基态到激发态(S→P)和亚稳态到激发态(D→P)的 AC Stark 频移及离共振光子散射率。

from quatm.physics.odt.lightmatterint import LMinteraction

lm = LMinteraction(atom=Ba, laser=laser)
shift = lm.stark_shift(intensity=1e6)  # Hz
rate = lm.scattering_rate(intensity=1e6)  # s⁻¹

11.5 - 光阱模型 (opticaltraputils)

复合阱——偶极光束+电场的全 1D/2D/3D 势阱计算。

概述

Trap 将高斯光束光偶极阱与静电场组合为复合势阱模型,计算阱深(势能转折点)和三维势能分布。

from quatm.physics.odt.opticaltraputils import Trap

trap = Trap(laser=odt_laser, efield=dc_field)
depth = trap.trap_depth()  # µK
potential_2d = trap.potential_2d(x, y, z=0)

11.6 - 统计工具 (statistics)

二项式 Wilson 评分区间——离子态判别置信区间。

概述

statistics 提供基于 Wilson 评分区间的二项式比例置信区间工具,用于离子态判别的统计误差估计。

函数说明
wilson_score(p, n)计算比例 p 的 Wilson 评分
wilson_err(p, n)Wilson 置信区间半宽
getrandbincont(p, n, N)从二项式结果采样 N 次实验概率

Wigner 符号 (utils)

utils 模块提供 Wigner3jWigner6j 符号的完整 Racah 公式实现,用于角动量耦合计算。

12 - 代码贡献指南

如何对Quatm项目贡献您的智慧

Quatm是一个开源项目,我们热爱并欢迎大家提交补丁和贡献,以使Quatm及其文档变得更好。

贡献Quatm

Quatm主要托管在 https://github.com/quatm/quatm,并在项目私有Git服务器进行镜像备份。

贡献者许可协议

在您参与对本项目的贡献时,除非在有书面协议的例外情况下,您(或您的雇主)保留对您的贡献的版权,并自动给予我们使用和重新分发您的贡献作为项目一部分的权限。具体细节请参考本项目的贡献者许可协议

代码审核

所有提交都需要经过审核。我们使用 GitHub 的Pull Request(Merge Request)进行代码审核。

社区准则

在交流讨论中,请遵循 Quatm社区准则

创建问题

如果您想在Quatm中看到某些功能(或者发现某些功能没有按预期工作),但您不确定如何自己修复,请创建一个 issue。您也可以通过社交媒体直接与我们联系。

报告 Bug

  • 使用 GitHub Issue 的 Bug 报告模板创建新 Issue
  • 详细描述问题:你期望看到什么?实际看到了什么?
  • 附上截图和 GIF 动画,展示操作步骤和问题现象
  • 提供复现步骤,使维护者能快速定位问题

功能建议

  • 使用 GitHub Issue 的功能建议模板
  • 清晰简洁地描述建议的功能
  • 尽可能包含使用场景和预期效果

Pull Request 流程

  1. Fork 项目仓库
  2. 创建功能分支:git checkout -b feature/my-feature
  3. 编写代码并添加测试
  4. 确保所有状态检查通过
  5. 提交 PR 并填写 PR 模板

代码风格

Python 代码风格

所有 Python 代码必须遵循 PEP 8 规范:

  • 使用 4 空格缩进
  • 类名使用 CamelCase,函数和变量使用 snake_case
  • 导入顺序:标准库 → 第三方库 → 本地模块
  • 为公开 API 编写 docstring

Git 提交信息规范

  • 使用现在时态(“Add feature”,不是 “Added feature”)
  • 使用祈使语气(“Move cursor to…",不是 “Moves cursor to…")
  • 第一行限制在 72 字符以内
  • 在第一行之后引用相关 Issue 编号

示例:

Add temperature monitor driver for LFI3751

Implement RS-232 communication and PID auto-tuning
for the Wavelength Electronics LFI3751 controller.

Closes #42

社区联系方式

13 - 监控设备

实验室环境监测设备驱动 — 温度控制器、高斯计、示波器、激光控制器、真空规

概述

quatm.monitor 包提供实验室硬件和环境条件的监控驱动。每个监控器作为独立进程运行,通过 RPC 框架暴露功能,持续轮询硬件设备并将读数发布到分布式属性系统,供 GUI、日志和实验反馈使用。

注意:每个监控模块都是可独立运行的脚本。RPC 绑定地址通过命令行参数配置。


温度控制器 — LFI3751

Wavelength Electronics LFI-3751 温度控制器驱动,通过 RS-232 串口通信。

主要功能

  • NTC 热敏电阻校准(Steinhart-Hart 系数)
  • 温度和电流限制配置
  • PID 自动优化 (auto_PID)
  • 传感器类型选择(热敏电阻、RTD、AD590、LM335)

使用示例

from quatm.monitor.LFI3751 import LFI3751

tc = LFI3751("/dev/ttyUSB0")
# 配置 NTC 热敏电阻参数
tc.set_sensor_properties(a=1.125e-3, b=2.347e-4, c=8.563e-8)
# 设置温度限制
tc.set_temperature_limits(lo=15.0, hi=35.0)
# 设定目标温度并启动
tc.set_temperature(25.0)
tc.turn_on()
# 读取当前温度
current_temp = tc.get_temperature()
参数说明
port串口设备路径,如 /dev/ttyUSB0

高斯计 — PCE-MFM_3000

PCE-MFM 3000 高斯计驱动,通过串口返回磁场读数(Gauss)。

使用示例

from quatm.monitor.PCE_MFM_3000 import PCE_MFM_3000

gm = PCE_MFM_3000("/dev/ttyUSB1")
b_field = gm.get_b()  # 返回磁场值 (Gauss)

⚠️ 注意:霍尔探头的磁场校准会随时间漂移,Feshbach 共振实验建议定期对照已知原子跃迁(如 RF 谱)重新校准。


示波器 — ds1054z

Rigol DS1054Z 数字示波器驱动,通过 PyVISA SCPI 命令进行波形捕获、电压测量和频率分析。

参数说明
resourceVISA 资源字符串

激光控制器 — dlc_pro

Toptica DLC pro 激光控制器接口,监控激光二极管电流、温度设定值、压电扫描参数和锁频状态。

使用示例

from quatm.monitor.dlc_pro import toptica

laser = toptica("192.168.1.50", 1998)
locked = laser.get_lock_status()    # 检查锁频状态
error = laser.get_error_signal()     # 读取锁频误差信号

真空规 — mvc3

真空规驱动,用于监测实验腔体的真空度。在冷原子实验中,超高真空(UHV)环境对原子寿命至关重要。

13.1 - LFI3751 温控器

Wavelength Electronics LFI3751 温控器驱动——PyVISA 通信。

概述

LFI3751 驱动 Wavelength Electronics 的高精度半导体激光器温控器,通过 PyVISA 通信。

from quatm.monitor.LFI3751 import LFI3751

tc = LFI3751(addr="USB0::...")
temp = tc.get_temperature()
tc.set_setpoint(25.0)

13.2 - 高斯计 (PCE-MFM 3000)

PCE-MFM 3000 高斯计驱动——串口通信,实时磁场测量。

概述

PCE_MFM_3000 驱动 PCE Instruments 的磁场强度测量仪,通过串口实时读取磁感应强度。

from quatm.monitor.PCE_MFM_3000 import PCE_MFM_3000

gauss = PCE_MFM_3000(port="/dev/ttyUSB0")
field = gauss.get_field()  # 返回 mT 值

13.3 - 腔体环境传感器

Arduino 温湿度气压传感器——腔体环境实时监测。

概述

arduino 驱动通过 Arduino Nano 读取腔体内的温度、湿度和气压传感器数据。

from quatm.monitor.cavity_arduino import arduino

env = arduino(port="/dev/ttyACM0")
temp, hum, press = env.read_all()

13.4 - PC 健康监控

CPU/内存/磁盘/网络实时监控——基于 psutil。

概述

PC_health 通过 psutil 监控实验控制计算机的 CPU 使用率、内存占用、磁盘空间和网络流量,防止因资源耗尽导致实验中断。

from quatm.monitor.pc_health import PC_health

health = PC_health()
cpu = health.get_cpu_percent()
mem = health.get_memory_usage()
disk = health.get_disk_free()

13.5 - 示波器 (DS1054Z)

Rigol DS1054Z 示波器驱动——PyVISA 波形采集与电压测量。

概述

ds1054z 驱动 Rigol DS1054Z 四通道数字示波器,通过 PyVISA 进行波形采集和自动测量。

from quatm.monitor.ds1054z import ds1054z

scope = ds1054z(addr="USB0::...")
waveform = scope.get_waveform(channel=1)
vpp = scope.measure_vpp(channel=1)

14 - 工具函数

Quatm 通用工具函数 — 变密度采样等辅助功能

概述

quatm.utils 包提供 Quatm 框架中跨模块使用的通用工具函数。


变密度采样 — quatm.utils.vds

变密度采样(Variable Density Sampling, VDS)允许在参数空间中高效探索,将采样点集中在感兴趣的区域(如量子系统中的共振或相变附近)。

核心思想

在物理实验中,某些参数区域比其他区域更有意义。例如:

  • Feshbach 共振附近的磁场扫描
  • 光谱线中心附近的频率扫描
  • 相变临界点附近的参数探索

VDS 通过在感兴趣区域自动加密采样点,在平坦区域稀疏采样,实现以最少的数据点获取最多信息。

gauss_prime_norm — 归一化高斯导数

高斯函数的导数,归一化到最大值为 1:

$$f(x) = \sqrt{e} \cdot \frac{x - \mu}{\sigma} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)$$

from quatm.utils.vds import gauss_prime_norm

# 计算 x=5.0 处的高斯导数值
val = gauss_prime_norm(5.0, mu=5.0, sigma=1.0)
参数说明
x输入值,可以是标量或 numpy.ndarray
mu高斯中心
sigma高斯标准差

gauss_prime_norm_abs — 绝对值归一化高斯导数

高斯导数绝对值的归一化形式,适合用作对称峰检测的兴趣函数。

create_support_points_stochastic — 随机支持点生成

从精细等距网格开始,随机移除低兴趣区域的点,保留高兴趣区域的点。

from quatm.utils.vds import (
    create_support_points_stochastic,
    gauss_prime_norm_abs
)

# 定义兴趣函数:在 x=5.0 附近集中采样
def interest(x, center, width):
    return gauss_prime_norm_abs(x, center, width)

points = create_support_points_stochastic(
    start=0.0,      # 扫描起点
    stop=10.0,      # 扫描终点
    steps=50,       # 最终支持点数量
    interest_fn=interest,
    max_stepsize=0.5,   # 最大允许步长
    enhancement=0.8,    # 0-1,1 表示强增强
    center=5.0,         # 传递给 interest_fn
    width=1.0           # 传递给 interest_fn
)
参数说明
start扫描起点,始终包含在最终支持点中
stop扫描终点,始终包含在最终支持点中
steps最终支持点数量
interest_fn兴趣函数 f(x, **kwargs),返回 0(低兴趣)到 1(高兴趣)
max_stepsize相邻支持点最大间距
enhancement0-1,1 表示强增强感兴趣区域,0 表示均匀随机采样
**kwargs传递给 interest_fn 的额外参数

应用场景

变密度采样特别适用于:

  • Feshbach 共振谱扫描:在共振峰附近加密采样
  • 光谱线扫描:在线心附近提高分辨率
  • 相变参数扫描:在临界区域精细探索
  • 阱频率测量:在预期共振频率附近集中采样

14.1 - 变密度采样 (VDS)

变密度采样——在感兴趣区域密集采样,边缘稀疏采样的实验参数生成器。

概述

quatm.utils.vds 提供变密度采样(Variable Density Sampling)工具,用于生成实验扫描参数。在参数空间的感兴趣区域密集采样,而在边缘区域稀疏采样,优化有限的实验时间。

函数

函数说明
create_support_points_stochastic(limits, n, roi)随机变密度采样点生成
gauss_prime_norm(x, mu, sigma)高斯归一化导数
gauss_prime_norm_abs(x, mu, sigma)高斯归一化导数的绝对值

用法

from quatm.utils.vds import create_support_points_stochastic

points = create_support_points_stochastic(
    limits=[(0, 100), (0, 50)],  # 参数范围
    n=200,                         # 采样点数
    roi=[(30, 70), (20, 30)],     # 感兴趣区域(密集采样)
)