> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.conductorquantum.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.conductorquantum.com/_mcp/server.

# Using the Electron Unload Models

> Learn how to detect electron unloading events and texture patterns

## Installation

We recommend using pip, poetry, or uv to install the package.

**`pip`**

```bash title="pip"
pip install conductorquantum
```

**`poetry`**

```bash title="poetry"
poetry add conductorquantum
```

**`uv`**

```bash title="uv"
uv add conductorquantum
```

## Authentication

The SDK requires an API key for authentication. [Sign in and create a new API key](/control/getting-started/api-keys). Remember, your API key is your access secret - keep it safe
with environment variables.

Using environment variables:

**`Python`**

```python title="Python"
from dotenv import load_dotenv
import os
from conductorquantum import ConductorQuantum

# Load API key from .env file
load_dotenv()
TOKEN = os.getenv("CONDUCTOR_API_KEY")

# Initialize client
client = ConductorQuantum(token=TOKEN)
```

Or provide the API key directly:

**`Python`**

```python title="Python"
from conductorquantum import ConductorQuantum

# Initialize client with API key
client = ConductorQuantum(token="YOUR_API_KEY")
```

## Input Format

Both detectors expect a **visualization-ready** 2D array shaped `(n_bias, n_voltage)`:

| Axis    | Dimension   | Description                                 |
| ------- | ----------- | ------------------------------------------- |
| Rows    | `n_bias`    | Resonator bias points (y-axis when plotted) |
| Columns | `n_voltage` | Unload voltage sweep (x-axis when plotted)  |

This is the same layout you'd pass to `imshow()` or `pcolormesh()` - resonator bias on the vertical axis, unload voltage on the horizontal axis.

> **Tip**
>
> **Coming from acquisition-format data?** If your data is stored as `(n_voltage, n_bias)` - one bias trace per voltage point - transpose before calling the API. This matches the typical visualization convention with unload voltage on the x-axis and resonator bias on the y-axis:
>
> ```python
> # If data.shape == (n_voltage, n_bias):
> api_input = data.T  # → (n_bias, n_voltage)
> ```

## Detecting Electron Unload Events

The Electron Unload Detector identifies the column indices in a two-dimensional resonator scan where electron unloading events occur.

### Output Format

| Key              | Type        | Description                                      |
| ---------------- | ----------- | ------------------------------------------------ |
| `unload_indices` | `list[int]` | Column indices where unload events were detected |

### Usage Example

Supply your own measurement data to follow along.

**`Python`**

```python title="Python"
import os
from dotenv import load_dotenv
import numpy as np
import matplotlib.pyplot as plt
from conductorquantum import ConductorQuantum

# Load API key from .env file
load_dotenv()
TOKEN = os.getenv("CONDUCTOR_API_KEY")
client = ConductorQuantum(token=TOKEN)

# Load your resonator measurement (shape: [n_bias, n_voltage])
data = np.load("path/to/your/data.npy")

# Run inference with the Electron Unload Detector
results = client.control.models.run(
    model="electron-unload-detector-v0",
    data=data,
)

# Access peak locations (column indices)
unload_indices = results.output["unload_indices"]
print(f"Detected electron unloading at: {unload_indices}")

# Visualize the measurement and overlay detections
plt.imshow(data, aspect="auto")
for unload_index in unload_indices:
    plt.axvline(x=unload_index, color="red", linewidth=3, alpha=0.8)

plt.title("Electron Unload Detector v0")
plt.xlabel("Unload voltage (a.u.)")
plt.ylabel("Resonator bias (a.u.)")
plt.colorbar(label="Frequency (a.u.)")
plt.tight_layout()
plt.show()
```

**`Sample output`**

```python title="Sample output"
Detected electron unloading at: [10, 23, 32, 36, 39, 44, 49]
```

### Using Physical Units

To plot with real voltage and frequency values, convert indices to coordinates:

**`Python`**

```python title="Python"
# Your physical axes
unload_voltages = np.linspace(-0.5, 0.5, data.shape[1])  # (n_voltage,)
resonator_bias = np.linspace(0, 1, data.shape[0])        # (n_bias,)

fig, ax = plt.subplots(figsize=(6, 4))
im = ax.pcolormesh(
    unload_voltages,
    resonator_bias,
    data / 1e9,
    cmap="RdYlBu_r",
    shading="auto",
)

# Convert indices to physical coordinates
for unload_index in unload_indices:
    if unload_index < len(unload_voltages):
        voltage = unload_voltages[unload_index]
        ax.axvline(x=voltage, color="black", linewidth=4, alpha=0.8)

ax.set_xlabel("Unload Voltage (V)")
ax.set_ylabel("Resonator Bias (V)")
plt.colorbar(im, label="$f_0$ (GHz)")
plt.title("Electron Unload Detector v0")
plt.tight_layout()
plt.show()
```

## Detecting Texture Clusters

The Electron Unload Texture Detector locates contiguous resonator patterns that frequently co-occur with unloading transitions. Each cluster contains the row/column indices of its member pixels so you can overlay the detections directly on your measurement.

### Output Format

| Key                              | Type              | Description                                                                                     |
| -------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| `texture_clusters`               | `list[dict]`      | List of detected texture regions                                                                |
| `texture_clusters[i]["indices"]` | `list[list[int]]` | Pixel coordinates as `[row, col]` pairs, matching `[bias_idx, voltage_idx]` in your input array |

### Usage Example

**`Python`**

```python title="Python"
import os
from dotenv import load_dotenv
import numpy as np
import matplotlib.pyplot as plt
from conductorquantum import ConductorQuantum

# Load API key from .env file
load_dotenv()
TOKEN = os.getenv("CONDUCTOR_API_KEY")
client = ConductorQuantum(token=TOKEN)

# Load your resonator measurement (shape: [n_bias, n_voltage])
data = np.load("path/to/your/data.npy")

results = client.control.models.run(
    model="electron-unload-texture-detector-v0",
    data=data,
)

print("Raw results:", results)
texture_clusters = results.output["texture_clusters"]

plt.imshow(data, aspect="auto")

for cluster in texture_clusters:
    indices = np.array(cluster["indices"])
    x_coords = indices[:, 1]  # column = voltage index (x-axis)
    y_coords = indices[:, 0]  # row = bias index (y-axis)
    plt.scatter(x_coords, y_coords, s=50, alpha=0.8)

plt.title("Electron Unload Texture Detector v0")
plt.xlabel("Unload voltage (a.u.)")
plt.ylabel("Resonator bias (a.u.)")
plt.colorbar(label="Frequency (a.u.)")
plt.tight_layout()
plt.savefig("electron-unload-texture-detector-v0.png")
plt.show()
```

**`Sample output`**

```python title="Sample output"
# 10 texture clusters detected
texture_clusters = [
    {"indices": [[2, 1], [3, 3], [4, 4], [7, 4]]},
    {"indices": [[57, 6], [57, 7], [57, 8], [57, 9], [59, 10], [57, 11]]},
    {"indices": [[23, 7], [23, 8], [23, 9]]},
    ...
]
```

### Using Physical Units

To plot with real voltage and frequency values:

**`Python`**

```python title="Python"
# Your physical axes
unload_voltages = np.linspace(-0.5, 0.5, data.shape[1])  # (n_voltage,)
resonator_bias = np.linspace(0, 1, data.shape[0])        # (n_bias,)

fig, ax = plt.subplots(figsize=(6, 4))
im = ax.pcolormesh(
    unload_voltages,
    resonator_bias,
    data / 1e9,
    cmap="magma",
    shading="auto",
)

# Convert indices to physical coordinates
for cluster in texture_clusters:
    indices = np.array(cluster["indices"])
    # indices[:, 0] = row = bias index (y-axis)
    # indices[:, 1] = col = voltage index (x-axis)
    voltage_coords = unload_voltages[indices[:, 1].astype(int)]
    bias_coords = resonator_bias[indices[:, 0].astype(int)]
    ax.scatter(voltage_coords, bias_coords, s=50, alpha=0.8)

ax.set_xlabel("Unload Voltage (V)")
ax.set_ylabel("Resonator Bias (V)")
plt.colorbar(im, label="$f_0$ (GHz)")
plt.title("Electron Unload Texture Detector v0")
plt.tight_layout()
plt.show()
```