Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/cqedtoolbox/fitfuncs/resonators.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ def guess(coordinates, data) -> Dict[str, Any]:
transmission_slope = guess_transmission_slope,
)


# return dict(
# A = 1,
# f_0 = 1,
Expand Down
20 changes: 15 additions & 5 deletions src/cqedtoolbox/protocols/operations/single_qubit/pi_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from labcore.measurement.storage import run_and_save_sweep
from labcore.measurement.sweep import sweep_parameter
from labcore.measurement.record import record_as
from labcore.data.datagen import Gaussian as GaussianDataGen
from labcore.data.datadict_storage import datadict_from_hdf5

from labcore.protocols.base import (ProtocolOperation, OperationStatus, serialize_fit_params,
Expand Down Expand Up @@ -43,6 +44,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.pi_spec.snr(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class PiSpecMaxFitParamError(CorrectionParameter):
Expand All @@ -55,6 +59,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.pi_spec.max_fit_param_error(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class PiSpecAveragingFactor(CorrectionParameter):
Expand All @@ -67,6 +74,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.pi_spec.averaging_factor(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class PiSpecMaxAveragingIncreases(CorrectionParameter):
Expand All @@ -79,6 +89,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.pi_spec.max_averaging_increases(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


class IncreaseAveragingCorrection(Correction):
name = "increase_averaging"
Expand Down Expand Up @@ -162,11 +175,8 @@ def _measure_dummy(self) -> Path:
frequencies = np.linspace(self.start_freq(), self.end_freq(), int(self.steps()))
center = (self.start_freq() + self.end_freq()) / 2 + self._SIM_CENTER

def generate(frequencies):
return (self._SIM_AMP * np.exp(-0.5 * ((frequencies - center) / self._SIM_SIGMA) ** 2)
+ self._SIM_NOISE_AMP * (np.random.randn() + 1j * np.random.randn()))

sweep = sweep_parameter("frequencies", frequencies, record_as(generate, "signal"))
generator = GaussianDataGen(x0=center, sigma=self._SIM_SIGMA, A=self._SIM_AMP, of=0, noise_std=self._SIM_NOISE_AMP, imaginary=True)
sweep = sweep_parameter("frequencies", frequencies, record_as(lambda frequencies: np.atleast_1d(generator.generate(np.atleast_1d(frequencies)))[0], "signal"))
loc, _ = run_and_save_sweep(sweep, "data", self.name)
logger.info("Dummy measurement complete")
return loc
Expand Down
44 changes: 23 additions & 21 deletions src/cqedtoolbox/protocols/operations/single_qubit/power_rabi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from labcore.analysis.fitfuncs.generic import Cosine
from labcore.measurement.storage import run_and_save_sweep
from labcore.measurement import sweep_parameter, record_as
from labcore.data.datagen import Sine
from labcore.data.datadict_storage import datadict_from_hdf5

from labcore.protocols.base import (
Expand Down Expand Up @@ -42,6 +43,8 @@ class SNRThreshold(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.snr()
def _qick_setter(self, v): self.params.corrections.power_rabi.snr(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -51,6 +54,8 @@ class MaxFitParamError(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.max_fit_param_error()
def _qick_setter(self, v): self.params.corrections.power_rabi.max_fit_param_error(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -60,6 +65,8 @@ class AveragingIncreaseFactor(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.averaging_factor()
def _qick_setter(self, v): self.params.corrections.power_rabi.averaging_factor(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -69,6 +76,8 @@ class MaxAveragingIncreases(CorrectionParameter):

def _qick_getter(self): return int(self.params.corrections.power_rabi.max_averaging_increases())
def _qick_setter(self, v): self.params.corrections.power_rabi.max_averaging_increases(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -78,6 +87,8 @@ class SamplingIncreaseFactor(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.sampling_factor()
def _qick_setter(self, v): self.params.corrections.power_rabi.sampling_factor(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -87,6 +98,8 @@ class MaxSamplingIncreases(CorrectionParameter):

def _qick_getter(self): return int(self.params.corrections.power_rabi.max_sampling_increases())
def _qick_setter(self, v): self.params.corrections.power_rabi.max_sampling_increases(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -96,6 +109,8 @@ class DelayIncreaseFactor(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.delay_factor()
def _qick_setter(self, v): self.params.corrections.power_rabi.delay_factor(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -105,6 +120,8 @@ class MaxDelayIncreases(CorrectionParameter):

def _qick_getter(self): return int(self.params.corrections.power_rabi.max_delay_increases())
def _qick_setter(self, v): self.params.corrections.power_rabi.max_delay_increases(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -114,6 +131,8 @@ class GainRangeShrinkFactor(CorrectionParameter):

def _qick_getter(self): return self.params.corrections.power_rabi.gain_shrink_factor()
def _qick_setter(self, v): self.params.corrections.power_rabi.gain_shrink_factor(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
Expand All @@ -123,6 +142,8 @@ class MaxGainRangeShrinks(CorrectionParameter):

def _qick_getter(self): return int(self.params.corrections.power_rabi.max_gain_shrinks())
def _qick_setter(self, v): self.params.corrections.power_rabi.max_gain_shrinks(v)
_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -258,20 +279,6 @@ def report_output(self) -> str:
return f"gain range: [{self._last_new_start:.3f}, {self._last_new_end:.3f}]"


# ---------------------------------------------------------------------------
# Synthetic data helper
# ---------------------------------------------------------------------------

@dataclass
class SyntheticPowerRabiData:
pi_amp: float
noise_amp: float

def generate(self, gains: float) -> np.complex128:
signal = (np.cos(2 * np.pi * gains / (2 * self.pi_amp)) + 2) - 1j * (np.cos(2 * np.pi * gains / (2 * self.pi_amp)) + 2)
noise = self.noise_amp * (np.random.randn() + 1j * np.random.randn())
return signal + noise


# ---------------------------------------------------------------------------
# Operation
Expand Down Expand Up @@ -371,14 +378,9 @@ def _measure_qick(self) -> Path:
def _measure_dummy(self):
logger.info("Starting dummy power rabi measurement")
gains = np.linspace(self.start_gain(), self.end_gain(), int(self.steps_gain()))
generator = SyntheticPowerRabiData(
pi_amp = self._SIM_PI_AMP,
noise_amp = self._SIM_NOISE_AMP
)

sweep = sweep_parameter("gains", gains, record_as(generator.generate, "signal"))
generator = Sine(f= 1 / (2 * self._SIM_PI_AMP), phi = np.pi / 2, noise_std=self._SIM_NOISE_AMP)
sweep = sweep_parameter("gains", gains, record_as(lambda gains: np.atleast_1d(generator.generate(np.atleast_1d(gains)) - 1j * generator.generate(np.atleast_1d(gains)))[0], "signal"))
loc, _ = run_and_save_sweep(sweep, "data", self.name)

logger.info("Dummy measurement complete")
return loc

Expand Down
84 changes: 55 additions & 29 deletions src/cqedtoolbox/protocols/operations/single_qubit/res_spec.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import logging
from pathlib import Path
from dataclasses import dataclass, field
from typing import Any

import numpy as np
from numpy.typing import ArrayLike
from numpy.typing import ArrayLike, NDArray
import matplotlib.pyplot as plt

from labcore.analysis import DatasetAnalysis, FitResult
from labcore.measurement.storage import run_and_save_sweep
from labcore.data.datadict_storage import datadict_from_hdf5
from labcore.measurement import sweep_parameter, record_as
from labcore.data.datagen import DataGen

from labcore.protocols.base import (ProtocolOperation, OperationStatus, serialize_fit_params,
ParamImprovement, CorrectionParameter, CheckResult, Correction)
Expand All @@ -36,20 +38,6 @@ class UnwindAndFitRet:
fig: plt.Figure
ax: plt.Axes

@dataclass
class SyntheticHangerResonatorData:
f0: float
Qc: float
Qi: float
A: float
phi: float
noise_amp: float

def generate(self, frequencies: ArrayLike) -> ArrayLike:
Q_l = 1./(1./self.Qc + 1./self.Qi)
Q_e_complex = self.Qc * np.exp(-1j * self.phi)
response = self.A * (1 - (Q_l / Q_e_complex) / (1 + 2j * Q_l * (frequencies - self.f0) / self.f0))
return response + self.noise_amp * (np.random.randn() + 1j * np.random.randn())


@dataclass
Expand All @@ -63,6 +51,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.snr(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class MaxWindowShifts(CorrectionParameter):
Expand All @@ -75,6 +66,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.max_window_shifts(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class SamplingIncreaseFactor(CorrectionParameter):
Expand All @@ -87,6 +81,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.sampling_factor(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class MaxSamplingIncreases(CorrectionParameter):
Expand All @@ -99,6 +96,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.max_sampling_increases(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class AveragingIncreaseFactor(CorrectionParameter):
Expand All @@ -111,6 +111,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.averaging_factor(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class MaxAveragingIncreases(CorrectionParameter):
Expand All @@ -123,6 +126,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.max_averaging_increases(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


@dataclass
class MaxFitParamError(CorrectionParameter):
Expand All @@ -135,6 +141,9 @@ def _qick_getter(self):
def _qick_setter(self, value):
self.params.corrections.res_spec.max_fit_param_error(value)

_dummy_getter = _qick_getter
_dummy_setter = _qick_setter


class WindowShiftCorrection(Correction):
name = "window_shift"
Expand Down Expand Up @@ -252,11 +261,36 @@ def report_output(self) -> str:
return self._last_change


# ---------------------------------------------------------------------------
# HangerResonator DataGen
# ---------------------------------------------------------------------------

@dataclass
class HangerResonator(DataGen):
A: float = 1
Qc: float = 1000
Qi: float = 1000
f0: float = 1e9
phi: float = 0
imaginary: bool = True

@staticmethod
def model(
coordinates: NDArray[Any], A: float, Qc: float, Qi: float, f0: float, phi: float
) -> NDArray[Any]:
Q_l = 1.0 / (1.0 / Qc + 1.0 / Qi)
Q_e_complex = Qc * np.exp(-1j * phi)
return A * (1 - (Q_l / Q_e_complex) / (1 + 2j * Q_l * (coordinates - f0) / f0))


# ---------------------------------------------------------------------------
# Operation
# ---------------------------------------------------------------------------

class ResonatorSpectroscopy(ProtocolOperation):

_SIM_F0 = 7e9
_SIM_QI = 20e3
_SIM_QC = 20e3
_SIM_QI = 500
_SIM_QC = 500
_SIM_A = 4.0
_SIM_PHI = 0.0
_SIM_NOISE_AMP = 0.05
Expand Down Expand Up @@ -352,18 +386,10 @@ def _measure_qick(self) -> Path:
def _measure_dummy(self):
logger.info("Starting dummy resonator spectroscopy measurement")
frequencies = np.linspace(self.start_frequency(), self.end_frequency(), int(self.steps()))
generator = SyntheticHangerResonatorData(
f0 = self._SIM_F0,
Qi = self._SIM_QI,
Qc = self._SIM_QC,
A = self._SIM_A,
phi = self._SIM_PHI,
noise_amp = self._SIM_NOISE_AMP
)

sweep = sweep_parameter("frequencies", frequencies + self.readout_lo(), record_as(generator.generate, "signal"))
f0 = (self.start_frequency() + self.end_frequency()) / 2
generator = HangerResonator(f0=f0, Qc=self._SIM_QC, Qi=self._SIM_QI, A=self._SIM_A, phi=self._SIM_PHI, noise_std=self._SIM_NOISE_AMP)
sweep = sweep_parameter("frequencies", frequencies, record_as(lambda frequencies: np.atleast_1d(generator.generate(np.atleast_1d(frequencies)))[0], "signal"))
loc, _ = run_and_save_sweep(sweep, "data", self.name)

logger.info("Dummy measurement complete")
return loc

Expand Down
Loading