Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resonator depletion measurement #822

Merged
merged 13 commits into from
May 20, 2024
2 changes: 2 additions & 0 deletions src/qibocal/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .allxy.allxy import allxy
from .allxy.allxy_drag_pulse_tuning import allxy_drag_pulse_tuning
from .allxy.allxy_resonator_depletion_tuning import allxy_resonator_depletion_tuning
from .classification import single_shot_classification
from .coherence.spin_echo import spin_echo
from .coherence.spin_echo_signal import spin_echo_signal
Expand Down Expand Up @@ -97,6 +98,7 @@ class Operation(Enum):
allxy = allxy
allxy_drag_pulse_tuning = allxy_drag_pulse_tuning
drag_tuning = drag_tuning
allxy_resonator_depletion_tuning = allxy_resonator_depletion_tuning
flipping = flipping
dispersive_shift = dispersive_shift
chevron = chevron
Expand Down
17 changes: 11 additions & 6 deletions src/qibocal/protocols/allxy/allxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def _acquisition(
all_ro_pulses.append({})
for qubit in targets:
sequences[-1], all_ro_pulses[-1][qubit] = add_gate_pair_pulses_to_sequence(
platform, gates, qubit, sequences[-1], params.beta_param
platform, gates, qubit, sequences[-1], beta_param=params.beta_param
)

# execute the pulse sequence
Expand Down Expand Up @@ -134,13 +134,15 @@ def add_gate_pair_pulses_to_sequence(
gates,
qubit,
sequence,
sequence_delay=0,
readout_delay=0,
beta_param=None,
):
pulse_duration = platform.create_RX_pulse(qubit, start=0).duration
# All gates have equal pulse duration

sequenceDuration = 0
pulse_start = 0
sequence_duration = sequence.get_qubit_pulses(qubit).duration + sequence_delay
pulse_start = sequence.get_qubit_pulses(qubit).duration + sequence_delay

for gate in gates:
if gate == "I":
Expand Down Expand Up @@ -206,11 +208,14 @@ def add_gate_pair_pulses_to_sequence(
)
sequence.add(RY90_pulse)

sequenceDuration = sequenceDuration + pulse_duration
pulse_start = pulse_duration
sequence_duration += pulse_duration
pulse_start = sequence_duration

# RO pulse starting just after pair of gates
ro_pulse = platform.create_qubit_readout_pulse(qubit, start=sequenceDuration + 4)
ro_pulse = platform.create_qubit_readout_pulse(
qubit, start=sequence_duration + readout_delay
)

sequence.add(ro_pulse)
return sequence, ro_pulse

Expand Down
172 changes: 172 additions & 0 deletions src/qibocal/protocols/allxy/allxy_resonator_depletion_tuning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
from dataclasses import dataclass, field
from typing import Optional

import numpy as np
import numpy.typing as npt
import plotly.graph_objects as go
from qibolab import AveragingMode, ExecutionParameters
from qibolab.platform import Platform
from qibolab.pulses import PulseSequence
from qibolab.qubits import QubitId

from qibocal.auto.operation import Data, Parameters, Results, Routine

from . import allxy


@dataclass
class AllXYResonatorParameters(Parameters):
"""AllXYDrag runcard inputs."""

delay_start: float
"""Initial delay parameter for resonator depletion."""
delay_end: float
"""Final delay parameter for resonator depletion."""
delay_step: float
"""Step delay parameter for resonator depletion."""


@dataclass
class AllXYResonatorResults(Results):
"""AllXYDrag outputs."""


@dataclass
class AllXYResonatorData(Data):
"""AllXY acquisition outputs."""

delay_param: Optional[float] = None
"""Delay parameter for resonator depletion."""
data: dict[tuple[QubitId, float], npt.NDArray[allxy.AllXYType]] = field(
default_factory=dict
)
"""Raw data acquired."""

@property
def delay_params(self):
"""Access qubits from data structure."""
return np.unique([b[1] for b in self.data])


def _acquisition(
params: AllXYResonatorParameters,
platform: Platform,
targets: list[QubitId],
) -> AllXYResonatorData:
r"""
Data acquisition for allXY experiment varying delay after a measurement pulse to characterise resonator depletion time: https://arxiv.org/pdf/1604.00916.
Passive resonator depletion time: Time it takes the process by which photons inside a resonator dissipate over time without any external intervention.
After a measurement is performed, photons remain in the resonator and qubits errors induced if trying to drive the qubit by leftover photons due to the coupling
resonator-qubit inducing a shift in the qubit frequency. This experiment is used to characterise the resonator depletion time by waiting an increased delay time
until the allXY pattern looks right.
"""

data = AllXYResonatorData()

delays = np.arange(params.delay_start, params.delay_end, params.delay_step)
# sweep the parameters
for delay_param in delays:
for gates in allxy.gatelist:
# create a sequence of pulses
ro_pulses = {}
sequence = PulseSequence()
for qubit in targets:
ro_pulse = platform.create_qubit_readout_pulse(qubit, start=0)
sequence.add(ro_pulse)
sequence, ro_pulses[qubit] = allxy.add_gate_pair_pulses_to_sequence(
platform,
gates,
qubit,
sequence,
sequence_delay=int(
delay_param
), # We need conversion to int due to devices for now
readout_delay=1000,
)

# execute the pulse sequence
results = platform.execute_pulse_sequence(
sequence,
ExecutionParameters(
nshots=params.nshots,
relaxation_time=params.relaxation_time,
averaging_mode=AveragingMode.CYCLIC,
),
)

# retrieve the results for every qubit
for qubit in targets:
z_proj = 2 * results[ro_pulses[qubit].serial].probability(0) - 1
# store the results
gate = "-".join(gates)
data.register_qubit(
allxy.AllXYType,
(qubit, float(delay_param)),
dict(prob=np.array([z_proj]), gate=np.array([gate])),
)
return data


def _fit(_data: AllXYResonatorData) -> AllXYResonatorResults:
"""Post-processing for allXYDrag."""
return AllXYResonatorResults()


def _plot(data: AllXYResonatorData, target: QubitId, fit: AllXYResonatorResults = None):
"""Plotting function for allXYDrag."""

figures = []
fitting_report = ""

fig = go.Figure()
delay_params = data.delay_params

for j, delay_param in enumerate(delay_params):
delay_param_data = data[target, delay_param]
fig.add_trace(
go.Scatter(
x=delay_param_data.gate,
y=delay_param_data.prob,
mode="markers+lines",
opacity=0.5,
name=f"Delay {delay_param}",
showlegend=True,
legendgroup=f"group{j}",
text=allxy.gatelist,
textposition="bottom center",
),
)

fig.add_hline(
y=0,
line_width=2,
line_dash="dash",
line_color="grey",
)
fig.add_hline(
y=1,
line_width=2,
line_dash="dash",
line_color="grey",
)

fig.add_hline(
y=-1,
line_width=2,
line_dash="dash",
line_color="grey",
)

fig.update_layout(
showlegend=True,
xaxis_title="Gate sequence number",
yaxis_title="Expectation value of Z",
)

figures.append(fig)

return figures, fitting_report


allxy_resonator_depletion_tuning = Routine(_acquisition, _fit, _plot)
"""AllXYDrag Routine object."""
9 changes: 9 additions & 0 deletions tests/runcards/protocols.yml
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,15 @@ actions:
unrolling: True
nshots: 10

- id: resonator_depletion_tuning
operation: allxy_resonator_depletion_tuning
parameters:
delay_start: 1000.0
delay_end: 3000.0
delay_step: 1000.0
Jacfomg marked this conversation as resolved.
Show resolved Hide resolved
nshots: 10


- id: allXY drag
operation: allxy_drag_pulse_tuning
parameters:
Expand Down