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

rb_correction_qua #960

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5c8cb53
feat: first commit of rb using qua
stavros11 May 23, 2024
b074fef
Merge branch 'main' into qua
stavros11 Jul 23, 2024
4d35d13
acquisition working
stavros11 Jul 23, 2024
804e644
remove specialized data save and load
stavros11 Jul 24, 2024
d075542
fix fitting
stavros11 Jul 24, 2024
e8feb26
fix data propagation
stavros11 Jul 24, 2024
26e172f
feat: Add context manager to start execution
alecandido Jul 28, 2024
e9d6852
feat: Expose update toggle for scripts
alecandido Jul 30, 2024
69a3dea
fix: Make use of update parameter, leave it unaltered by default
alecandido Jul 30, 2024
7f969f8
test: Make single shot script example close to minimal
alecandido Jul 30, 2024
fa232cd
docs: Document minimal script example
alecandido Jul 30, 2024
312ec56
test: Make platform explicit, make use of routine result
alecandido Jul 30, 2024
fc0aac8
test: Replace magic imports with explicitly executor-scoped routines
alecandido Jul 30, 2024
972a65f
feat: Expose missing action attributes to scripts
alecandido Jul 30, 2024
09064f3
test: Replace repeated updates with global option
alecandido Jul 30, 2024
226a600
feat: Make the executor itself a context manager, to possibly reuse it
alecandido Jul 31, 2024
d068b49
fix: use platfrom values for sweetspots and device connections
stavros11 Aug 1, 2024
8ff1ec1
Merge branch 'main' into qua
stavros11 Aug 1, 2024
80f67c6
feat: rb_correction_qua
Jacfomg Aug 1, 2024
1fde0c8
Merge remote-tracking branch 'origin/qua' into script_rb
Jacfomg Aug 1, 2024
b3faacc
fix: remove Results
Jacfomg Aug 1, 2024
8fd71c2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 1, 2024
86ee7c6
fix: comments
Jacfomg Aug 2, 2024
fc84818
Merge branch 'script_rb' of https://github.com/qiboteam/qibocal into …
Jacfomg Aug 2, 2024
e592a93
fix: parameters and add discrimate
Jacfomg Aug 7, 2024
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
202 changes: 202 additions & 0 deletions runcards/rb_correction_qua.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
from argparse import ArgumentParser
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional

import numpy as np
import numpy.typing as npt
import plotly.graph_objects as go
from qibolab import create_platform
from qibolab.qubits import QubitId

from qibocal.auto.execute import Executor
from qibocal.auto.operation import Data
from qibocal.cli.report import report
from qibocal.protocols.randomized_benchmarking import utils

RBCorrectionType = np.dtype(
[
("biases", np.float64),
("qubit_frequency", np.float64),
("pulse_fidelity_uncorrected", np.float64),
("pulse_fidelity_corrected", np.float64),
]
)
"""Custom dtype for RBCorrection routines."""


biases = np.arange(-0.02, 0.02, 0.01)
"bias points to sweep"

# Flipping
nflips_max = 200
"""Maximum number of flips ([RX(pi) - RX(pi)] sequences). """
nflips_step = 10
"""Flip step."""

# Ramsey signal
detuning = 3_000_000
"""Frequency detuning [Hz]."""
delay_between_pulses_start = 16
"""Initial delay between RX(pi/2) pulses in ns."""
delay_between_pulses_end = 5_000
"""Final delay between RX(pi/2) pulses in ns."""
delay_between_pulses_step = 200
"""Step delay between RX(pi/2) pulses in ns."""

# Std Rb Ondevice Parameters
num_of_sequences: int = 100
max_circuit_depth: int = 250
"Maximum circuit depth"
delta_clifford: int = 50
"Play each sequence with a depth step equals to delta_clifford"
seed: Optional[int] = 1234
"Pseudo-random number generator seed"
n_avg: int = 128
"Number of averaging loops for each random sequence"
save_sequences: bool = True
apply_inverse: bool = True
state_discrimination: bool = True
"Flag to enable state discrimination if the readout has been calibrated (rotated blobs and threshold)"


@dataclass
class RBCorrectionSignalData(Data):
"""Coherence acquisition outputs."""

data: dict[QubitId, npt.NDArray] = field(default_factory=dict)
"""Raw data acquired."""

@property
def average(self):
if len(next(iter(self.data.values())).shape) > 1:
return utils.average_single_shots(self.__class__, self.data)
return self


parser = ArgumentParser()
parser.add_argument("--target", default="D2", help="Target qubit index")
parser.add_argument("--platform", type=str, default="qw11q", help="Platform name")
parser.add_argument(
"--path", type=str, default="TESTRBCorrection", help="Path for the output"
)
args = parser.parse_args()

target = args.target
path = args.path

data = RBCorrectionSignalData()

platform = create_platform(args.platform)
for target in [args.target]:

# NOTE: Center around the sweetspot [Optional]
centered_biases = biases + platform.qubits[target].sweetspot

for i, bias in enumerate(centered_biases):
with Executor.open(
f"myexec_{i}",
path=path / Path(f"flux_{i}"),
platform=platform,
targets=[target],
update=True,
force=True,
) as e:

discrimination_output = e.single_shot_classification(nshots=5000)

rb_output_uncorrected = e.rb_ondevice(
num_of_sequences=num_of_sequences,
max_circuit_depth=max_circuit_depth,
delta_clifford=delta_clifford,
seed=seed,
n_avg=n_avg,
save_sequences=save_sequences,
apply_inverse=apply_inverse,
state_discrimination=state_discrimination,
)

ramsey_output = e.ramsey_signal(
delay_between_pulses_start=delay_between_pulses_start,
delay_between_pulses_end=delay_between_pulses_end,
delay_between_pulses_step=delay_between_pulses_step,
detuning=detuning,
)

flipping_output = e.flipping_signal(
nflips_max=nflips_max,
nflips_step=nflips_step,
)

discrimination_output = e.single_shot_classification(nshots=5000)

rb_output_corrected = e.rb_ondevice(
num_of_sequences=num_of_sequences,
max_circuit_depth=max_circuit_depth,
delta_clifford=delta_clifford,
seed=seed,
n_avg=n_avg,
save_sequences=save_sequences,
apply_inverse=apply_inverse,
state_discrimination=state_discrimination,
)

data.register_qubit(
RBCorrectionType,
(target),
dict(
biases=[bias],
qubit_frequency=[platform.qubits[target].native_gates.RX.frequency],
pulse_fidelity_uncorrected=[
rb_output_uncorrected.results.pars[target][
2
] # Get error covs[2]
],
pulse_fidelity_corrected=[
rb_output_corrected.results.pars[target][2]
],
),
)

report(e.path, e.history)


def plot(data: RBCorrectionSignalData, target: QubitId, path):
"""Plotting function for Coherence experiment."""

figure = go.Figure()

figure.add_trace(
go.Scatter(
x=data[target].qubit_frequency,
y=data[target].pulse_fidelity_uncorrected,
opacity=1,
name="Pulse Fidelity Uncorrected",
showlegend=True,
legendgroup="Pulse Fidelity Uncorrected",
)
)

figure.add_trace(
go.Scatter(
x=data[target].qubit_frequency,
y=data[target].pulse_fidelity_corrected,
opacity=1,
name="Pulse Fidelity Corrected",
showlegend=True,
legendgroup="Pulse Fidelity Corrected",
)
)

# last part
figure.update_layout(
showlegend=True,
xaxis_title="Frequency [GHZ]",
yaxis_title="Pulse Fidelity",
)

if path is not None:
figure.write_html(path / Path("plot.html"))


plot(data, target, path=path)
124 changes: 61 additions & 63 deletions runcards/rx_calibration.py
Original file line number Diff line number Diff line change
@@ -1,77 +1,75 @@
from qibocal.auto.execute import Executor
from qibocal.cli.report import report

executor = Executor.create(name="myexec", platform="dummy")

from myexec import close, drag_tuning, init, rabi_amplitude, ramsey

target = 0
platform = executor.platform
platform.settings.nshots = 2048
init("test_rx_calibration", force=True, targets=[target])
with Executor.open(
"myexec",
path="test_rx_calibration",
platform="dummy",
targets=[target],
update=True,
force=True,
) as e:
e.platform.settings.nshots = 2000

rabi_output = rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=platform.qubits[target].native_gates.RX.duration,
)
# update only if chi2 is satisfied
if rabi_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output.results.chi2[target][0]} greater than 2. Stopping."
rabi_output = e.rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=e.platform.qubits[target].native_gates.RX.duration,
)
rabi_output.update_platform(platform)
# update only if chi2 is satisfied
if rabi_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output.results.chi2[target][0]} greater than 2. Stopping."
)

ramsey_output = ramsey(
delay_between_pulses_start=10,
delay_between_pulses_end=5000,
delay_between_pulses_step=100,
detuning=1_000_000,
)
if ramsey_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Ramsey fit has chi2 {ramsey_output.results.chi2[target][0]} greater than 2. Stopping."
ramsey_output = e.ramsey(
delay_between_pulses_start=10,
delay_between_pulses_end=5000,
delay_between_pulses_step=100,
detuning=1_000_000,
update=False,
)
if ramsey_output.results.delta_phys[target][0] < 1e4:
print(
f"Ramsey frequency not updated, correction too small { ramsey_output.results.delta_phys[target][0]}"
)
else:
ramsey_output.update_platform(platform)
if ramsey_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Ramsey fit has chi2 {ramsey_output.results.chi2[target][0]} greater than 2. Stopping."
)
if ramsey_output.results.delta_phys[target][0] < 1e4:
print(
f"Ramsey frequency not updated, correction too small { ramsey_output.results.delta_phys[target][0]}"
)
else:
ramsey_output.update_platform(e.platform)

rabi_output_2 = rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=platform.qubits[target].native_gates.RX.duration,
)
# update only if chi2 is satisfied
if rabi_output_2.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output_2.results.chi2[target][0]} greater than 2. Stopping."
rabi_output_2 = e.rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=e.platform.qubits[target].native_gates.RX.duration,
)
rabi_output_2.update_platform(platform)
# update only if chi2 is satisfied
if rabi_output_2.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output_2.results.chi2[target][0]} greater than 2. Stopping."
)

drag_output = drag_tuning(beta_start=-4, beta_end=4, beta_step=0.5)
if drag_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Drag fit has chi2 {drag_output.results.chi2[target][0]} greater than 2. Stopping."
)
drag_output.update_platform(platform)
drag_output = e.drag_tuning(beta_start=-4, beta_end=4, beta_step=0.5)
if drag_output.results.chi2[target][0] > 2:
raise RuntimeError(
f"Drag fit has chi2 {drag_output.results.chi2[target][0]} greater than 2. Stopping."
)

rabi_output_3 = rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=platform.qubits[target].native_gates.RX.duration,
)
# update only if chi2 is satisfied
if rabi_output_3.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output_3.results.chi2[target][0]} greater than 2. Stopping."
rabi_output_3 = e.rabi_amplitude(
min_amp_factor=0.5,
max_amp_factor=1.5,
step_amp_factor=0.01,
pulse_length=e.platform.qubits[target].native_gates.RX.duration,
)
rabi_output_3.update_platform(platform)
# update only if chi2 is satisfied
if rabi_output_3.results.chi2[target][0] > 2:
raise RuntimeError(
f"Rabi fit has chi2 {rabi_output_3.results.chi2[target][0]} greater than 2. Stopping."
)

close()
report(executor.path, executor.history)
report(e.path, e.history)
31 changes: 24 additions & 7 deletions runcards/single_shot.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
from qibocal.auto.execute import Executor
from qibocal.cli.report import report
"""Minimal Qibocal script example.

In this example, the default Qibocal executor is used. Additional
configurations can still be passed through the `init()` call, but there
is no explicit API to access the execution details.

If more fine grained control is needed, refer to the `rx_calibration.py` example.

executor = Executor.create(name="myexec", platform="dummy")
.. note::

from myexec import close, init, single_shot_classification
though simple, this example is not limited to single protocol execution, but
multiple protocols can be added as well, essentially in the same fashion of a plain
runcard - still with the advantage of handling execution and results
programmatically
"""

from pathlib import Path

from qibocal.cli.report import report
from qibocal.routines import close, init, single_shot_classification

init("test_x", force=True)
path = Path("test_x")
init(platform="dummy", path=path, force=True)

completed = single_shot_classification(nshots=1000)
# Here
ssc = single_shot_classification(nshots=1000)
print("\nfidelities:\n", ssc.results.fidelity, "\n")

close()
report(executor.path, executor.history)
report(path)
Loading
Loading