{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Ramsey detuning drift over a shift\n", "\n", "Track how the detuning (qubit frequency - drive frequency) drifts across a series\n", "of Ramsey experiments run over several hours — the signature of a TLS hop, a thermal\n", "excursion, or flux-line crosstalk that the VLM is good at flagging.\n", "\n", "Typical workflow: your control stack dumps one `.npz` per Ramsey run into a\n", "watched directory; this notebook walks that directory, auto-fits each trace, and\n", "plots the extracted detuning vs wall-clock time." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "rng = np.random.default_rng(1)\n", "tau = np.linspace(0, 10e-6, 201) # 10 µs delay sweep\n", "wall_times = np.arange(8) * 30 * 60 # every 30 min, 4 hours total\n", "\n", "# Simulate detuning drifting from 120 kHz → 180 kHz with a TLS-like jump halfway.\n", "detunings = np.array([120e3, 125e3, 132e3, 140e3, 170e3, 172e3, 175e3, 180e3])\n", "\n", "for i, det in enumerate(detunings):\n", " phase = rng.uniform(0, 2*np.pi)\n", " y = 0.5 * np.exp(-tau/4e-6) * np.cos(2*np.pi*det*tau + phase) + 0.5\n", " y += rng.normal(0, 0.01, tau.shape) # readout noise\n", " np.savez(f'ramsey_{i:02d}.npz', x=tau, y=y, wall_time=wall_times[i])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "from qcal.data import from_npz\n", "\n", "records = []\n", "for path in sorted(Path('.').glob('ramsey_*.npz')):\n", " p = from_npz(path, experiment_type='ramsey', x_unit='s')\n", " if p.fit and p.fit.ok:\n", " det = next(v for k, v in p.fit.params.items() if k.startswith('detuning_per_'))\n", " t2s = next(v for k, v in p.fit.params.items() if k.startswith('t2star_'))\n", " records.append({'file': path.name, 'detuning_hz': det, 't2star_s': t2s,\n", " 'fit_quality': p.fit.fit_quality})\n", "\n", "import pandas as pd\n", "df = pd.DataFrame(records)\n", "df" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(6.5, 3.8))\n", "ax.plot(wall_times/3600, df['detuning_hz']/1e3, marker='o')\n", "ax.set_xlabel('Wall time (hours)')\n", "ax.set_ylabel('Fitted detuning (kHz)')\n", "ax.set_title('Qubit detuning drift')\n", "ax.grid(True, alpha=0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hand the **most recent** Ramsey trace to the VLM. It sees both the plot and the\n", "fitted numbers in the prompt, so `notes` / `drift_prediction` usually flag the\n", "step change in detuning." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qcal.analyzer import analyze_payload\n", "\n", "latest = from_npz('ramsey_07.npz', experiment_type='ramsey', x_unit='s')\n", "analyze_payload(latest, backend='auto')" ] } ], "metadata": { "kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"name": "python", "version": "3.11"} }, "nbformat": 4, "nbformat_minor": 5 }