Skip to navigation

Using the Anticrossing Detector

Input Format

The detector expects a visualization-ready tensor shaped (2, n_freqs, n_sweeps):

AxisIndexDimensionDescription
Channeldata[0]-Magnitude (dB)
Channeldata[1]-Phase (degrees)
Rowsdata[c, :, :]n_freqsFrequency bins (y-axis when plotted)
Columnsdata[c, :, :]n_sweepsSweep voltages (x-axis when plotted)

This is the same layout you’d pass to imshow() or pcolormesh() - frequency on the vertical axis, sweep voltage on the horizontal axis.

Coming from acquisition-format data? If your data is stored as (n_sweeps, n_freqs) - one frequency trace per sweep point - transpose before calling the API. This matches the typical visualization convention with sweep voltage on the x-axis and frequency on the y-axis:

# If mags.shape == (n_sweeps, n_freqs):
api_input = np.stack([mags.T, phases.T], axis=0) # → (2, n_freqs, n_sweeps)

Output Format

All indices are returned as [freq_idx, sweep_idx] pairs - matching [row, col] in your input array:

KeyTypeDescription
frequency_fit_indiceslist[list[int]]Fitted resonance position at each sweep: [[freq_idx, sweep_idx], ...]
anticrossing_indiceslist[list[int]]Detected anticrossing centers
peak_indiceslist[list[int]]Local frequency maxima near anticrossings
valley_indiceslist[list[int]]Local frequency minima near anticrossings
scorefloatQuality score (0–1, higher = stronger anticrossing signal)

Usage Example

Python
import os
import numpy as np
from dotenv import load_dotenv
from conductorquantum import ConductorQuantum
load_dotenv()
client = ConductorQuantum(token=os.getenv("CONDUCTOR_API_KEY"))
# Load your measurement data: shape (2, n_freqs, n_sweeps)
data = np.load("path/to/your/data.npy")
magnitudes = data[0] # shape: (n_freqs, n_sweeps)
phases = data[1]
results = client.control.models.run(
model="anticrossing-detector-v0",
data=data,
)
print(f"Results output: {results.output}")
output = results.output
frequency_fit_indices = np.asarray(output["frequency_fit_indices"])
anticrossing_indices = np.asarray(output["anticrossing_indices"])
peak_indices = np.asarray(output["peak_indices"])
valley_indices = np.asarray(output["valley_indices"])
Sample output
Results output: {'frequency_fit_indices': [[392, 0], [392, 1], [393, 2], [391, 3], [394, 4], [390, 5], [391, 6], [391, 7], [393, 8], [392, 9], [391, 10], [393, 11], [392, 12], [390, 13], [392, 14], [390, 15], [391, 16], [389, 17], [390, 18], [387, 19], [389, 20], [390, 21], [389, 22], [389, 23], [385, 24], [385, 25], [385, 26], [383, 27], [381, 28], [379, 29], [375, 30], [364, 31], [359, 32], [326, 33], [489, 34], [425, 35], [420, 36], [412, 37], [415, 38], [412, 39], [408, 40], [408, 41], [409, 42], [409, 43], [409, 44], [410, 45], [411, 46], [409, 47], [411, 48], [409, 49], [416, 50], [414, 51], [414, 52], [415, 53], [416, 54], [415, 55], [417, 56], [418, 57], [417, 58], [417, 59], [422, 60], [419, 61], [420, 62], [421, 63], [424, 64], [423, 65], [427, 66], [430, 67], [432, 68], [430, 69], [435, 70], [442, 71], [444, 72], [450, 73], [459, 74], [465, 75], [471, 76], [481, 77], [493, 78], [525, 79], [572, 80], [647, 81], [767, 82], [800, 83], [176, 84], [231, 85], [267, 86], [298, 87], [306, 88], [322, 89], [332, 90], [340, 91], [344, 92], [349, 93], [354, 94], [361, 95], [364, 96], [365, 97], [368, 98], [369, 99], [370, 100], [374, 101], [374, 102], [373, 103], [376, 104], [376, 105], [377, 106], [380, 107], [379, 108], [380, 109], [380, 110], [382, 111], [382, 112], [381, 113], [383, 114], [384, 115], [384, 116], [386, 117], [384, 118], [385, 119], [386, 120], [385, 121], [386, 122], [388, 123], [388, 124], [387, 125], [388, 126]], 'anticrossing_indices': [[489, 34], [800, 83]], 'peak_indices': [[489, 34], [800, 83]], 'valley_indices': [[326, 33], [176, 84]], 'score': 0.6434958298396819}

Visualize the detections

With the arrays from the previous step, overlay the detector outputs on the magnitude channel:

Python
import matplotlib.pyplot as plt
freq_axis = np.arange(magnitudes.shape[0])
sweep_axis = np.arange(magnitudes.shape[1])
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(
magnitudes,
origin="lower",
aspect="auto",
extent=[sweep_axis.min(), sweep_axis.max(), freq_axis.min(), freq_axis.max()],
cmap="viridis",
)
fig.colorbar(im, ax=ax, label="Magnitude (a.u.)")
def scatter_indices(indices_array, color, label, marker="o"):
if indices_array.size == 0:
return
rows = indices_array[:, 0]
cols = indices_array[:, 1]
ax.scatter(
cols,
rows,
s=80,
c=color,
marker=marker,
edgecolor="white",
linewidth=2,
label=label,
)
scatter_indices(frequency_fit_indices, color="red", label="Frequency fit", marker=".")
scatter_indices(peak_indices, color="cyan", label="Peak", marker="^")
scatter_indices(valley_indices, color="magenta", label="Valley", marker="v")
if anticrossing_indices.size:
unique_columns = np.unique(anticrossing_indices[:, 1])
for idx, column in enumerate(unique_columns):
ax.axvline(
x=sweep_axis[column],
color="black",
linestyle="--",
linewidth=2,
alpha=0.9,
label="Anticrossing" if idx == 0 else "_nolegend_",
)
ax.set_xlabel("Sweep voltage (a.u.)")
ax.set_ylabel("Frequency (a.u.)")
ax.set_title(f"Anticrossing Detector v0\nScore = {output['score']:.3f}")
ax.legend(loc="upper right", frameon=False)
plt.tight_layout()
plt.show()

Scatter overlays highlight each feature family while dashed vertical lines mark anticrossings, making it easy to validate frequency fits alongside neighboring peak and valley structures directly on the measurement.

Using physical units

To plot with real voltage and frequency values, use extent and convert indices:

Python
# Your physical axes
sweep_voltages = np.linspace(-3.5, -3.3, magnitudes.shape[1]) # (n_sweeps,)
frequencies_ghz = np.linspace(7.1, 7.2, magnitudes.shape[0]) # (n_freqs,)
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(
magnitudes,
origin="lower",
aspect="auto",
extent=[sweep_voltages.min(), sweep_voltages.max(),
frequencies_ghz.min(), frequencies_ghz.max()],
cmap="viridis",
)
# Convert indices to physical coordinates
if peak_indices.size:
peak_freqs = frequencies_ghz[peak_indices[:, 0]]
peak_volts = sweep_voltages[peak_indices[:, 1]]
ax.scatter(peak_volts, peak_freqs, c="cyan", marker="^", s=150,
edgecolor="black", label="Peak")
ax.set_xlabel("Sweep Voltage (V)")
ax.set_ylabel("Frequency (GHz)")