Install
openclaw skills install @yaqiangsun/qubitclient-controlReal-time quantum measurement control based on MCP (Model Context Protocol) for executing experimental tasks including: (1) S21 spectroscopy scans, (2) Rabi oscillation measurements, (3) Ramsey fringe experiments, (4) T1 relaxation time characterization, (5) T2 coherence time measurements, (6) DRAG pulse calibration, (7) Optimal π-pulse finding, (8) Power shift analysis, (9) Single-shot readout optimization, and (10) 2D spectrum acquisition. Provides unified control interface through langchain-mcp-adapters with support for parameter sweeps, data acquisition, and real-time feedback
openclaw skills install @yaqiangsun/qubitclient-control# Using CtrlTaskName
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
client = QubitCtrlClient()
# Using MCPClient directly
from qubitclient.ctrl import MCPClient
mcp = MCPClient(mcpServers=None)
S21 - S21 cavity frequency measurementDRAG - DRAG anti-crossing point measurementDELTA - Frequency offset calibrationOPTPIPULSE - Optimal π-pulse measurementPOWERSHIFT - Power shift curve measurementRABI - Rabi oscillation measurementRAMSEY - Ramsey interference measurementS21VSFLUX - S21 vs Flux measurementSINGLESHOT - Single-shot measurementSPECTRUM - Frequency spectrum analysisSPECTRUM_2D - 2D spectrum measurementT1 - T1 relaxation time measurementfrom qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
client = QubitCtrlClient()
result = client.run(
task_type=CtrlTaskName.S21,
qubits=["Q0", "Q1"],
frequency_start=-40e6, # -40 MHz
frequency_end=40e6, # +40 MHz
frequency_sample_num=101,
state=[0] # qubit state
)
# Result format:
# {
# "data": {
# "Q0": {
# "frequency": [...],
# "s21_real": [...],
# "s21_imag": [...]
# }
# },
# "parameters": {...}
# }
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
result = client.run(
task_type=CtrlTaskName.DRAG,
qubits=["Q0"],
lamb=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
stage=1,
N_repeat=1,
pulsePair=[0, 1],
signal="population" # or "iq_avg"
)
# Result format:
# {
# "data": {
# "Q0": {
# "lamb": [...],
# "population": [...],
# "optimal_lamb": 0.5
# }
# }
# }
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
result = client.run(
task_type=CtrlTaskName.RABI,
qubits=["Q0"],
drive_amp=np.linspace(0.1, 1.0, 50).tolist(), # amplitude sweep
width=30e-9, # pulse width 30ns
signal="iq_avg" # or "population"
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
result = client.run(
task_type=CtrlTaskName.RAMSEY,
qubits=["Q0"],
delta=20e6, # detuning 20 MHz
delay=10e-6, # max delay 10 us
stage=1,
scale=15,
signal="population"
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.T1,
qubits=["Q0"],
delay=np.linspace(0, 20e-6, 51).tolist(), # 0-20us delay sweep
signal="population" # or "iq_avg"
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.OPTPIPULSE,
qubits=["Q0"],
stage=1,
N_list=[1, 3, 5], # pulse numbers
amp_list=np.linspace(0.5, 1.5, 51).tolist(), # amplitude sweep
delay=20e-9, # pulse spacing
signal="population"
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.DELTA,
qubits=["Q0"],
N_list=[1, 5, 13], # pulse sequence lengths
delta_list=(np.linspace(-20, 20, 101) * 1e6).tolist(), # freq offset sweep
stage=1,
delay=20e-9
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
result = client.run(
task_type=CtrlTaskName.POWERSHIFT,
qubits=["Q0"],
power=[0.01, 0.02, 0.05, 0.1, 0.2, 0.5], # power levels
freq=[5.0e9, 5.1e9, 5.2e9] # frequency points
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.S21VSFLUX,
qubits_scan=["Q0"], # qubit to flux tune
read_bias=np.linspace(-0.5, 0.5, 51).tolist(), # bias sweep
freq=np.linspace(4e9, 6e9, 101).tolist(), # frequency sweep
qubits_read=["Q0"] # qubit to read
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
result = client.run(
task_type=CtrlTaskName.SINGLESHOT,
qubits=["Q0"],
stage=1
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.SPECTRUM,
qubits=["Q0"],
freq=np.linspace(4e9, 6e9, 201).tolist(), # frequency sweep
drive_amp=0.04, # drive amplitude
duration=40e-6, # pulse duration
from_idle=True, # start from idle state
absolute=True, # absolute frequency
signal="iq_avg" # or "population"
)
from qubitclient.ctrl import QubitCtrlClient, CtrlTaskName
import numpy as np
result = client.run(
task_type=CtrlTaskName.SPECTRUM_2D,
qubits=["Q0"],
drive_amp=0.05,
duration=40e-6,
freq=np.linspace(4e9, 6e9, 101).tolist(),
bias=np.linspace(-0.5, 0.5, 51).tolist(),
from_idle=False,
absolute=True
)
from qubitclient.ctrl import MCPClient
mcp = MCPClient(mcpServers=None)
# Call tasks directly by name
result = mcp.call("s21", {
"qubits": ["Q0", "Q1"],
"frequency_start": -40e6,
"frequency_end": 40e6,
"frequency_sample_num": 101
})
result = mcp.call("rabi", {
"qubits": ["Q0"],
"drive_amp": [0.1, 0.2, 0.3, 0.4, 0.5],
"width": 30e-9,
"signal": "iq_avg"
})
| Parameter | Type | Description |
|---|---|---|
qubits | list[str] | List of qubit identifiers, e.g., ["Q0", "Q1"] |
task_type | CtrlTaskName | Task type enumeration |
stage | int | Measurement stage (default: 1) |
signal | str | Output signal type: "population" or "iq_avg" |