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

RX90 calibration implementation #1044

Merged
merged 81 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
14f80b4
first test for swittching from pi to pi-half
ElStabilini Nov 19, 2024
ec4b7ad
fixed pi half calibration sequence
ElStabilini Nov 20, 2024
9f63c69
modified classes and methods for running rabi for RX90
ElStabilini Nov 20, 2024
33db217
added option to save duration of RX90 pulse
ElStabilini Nov 21, 2024
32cceda
started modifying rabi ef for using RX90
ElStabilini Nov 21, 2024
7661361
modified pihalf_pulse to rx90 in parameters
ElStabilini Nov 21, 2024
d03f383
Update rabi.rst
ElStabilini Nov 21, 2024
d0c1228
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 21, 2024
e6a2395
set pi calibration as default and change rx90 dtype
ElStabilini Nov 21, 2024
144f468
Saving modified documentation
ElStabilini Nov 21, 2024
c112748
fix ordering error
ElStabilini Nov 21, 2024
f083434
moved all pihalf_pulses in Rabi-Data class
ElStabilini Nov 21, 2024
f52765f
moved all pihalf_pulses in Rabi-Data class
ElStabilini Nov 21, 2024
efcb55a
fixed errors
ElStabilini Nov 21, 2024
66f0b71
Update rabi.rst
ElStabilini Nov 21, 2024
1f16f50
fixed amplitude_sequence and length_sequence inputs
ElStabilini Nov 21, 2024
f8e9021
Sync remote and local branches
ElStabilini Nov 21, 2024
a08cf3c
fixed acquisition error
ElStabilini Nov 21, 2024
0f9ec82
fixed error
ElStabilini Nov 21, 2024
6111a46
fix rabi length signal
ElStabilini Nov 22, 2024
973b318
fix rabi length signal
ElStabilini Nov 22, 2024
3164fd8
align True
ElStabilini Nov 22, 2024
393d039
Update rabi.rst
ElStabilini Nov 22, 2024
1742dc1
Add rabi_amplitude_rx90
ElStabilini Nov 22, 2024
30dd98c
Update rabi.rst
ElStabilini Nov 22, 2024
f521abc
rename pi_half to rx90
ElStabilini Nov 22, 2024
bf70bf6
Sync local and remote branches
ElStabilini Nov 22, 2024
349e312
force ef rabi protocol with pihalf
ElStabilini Nov 22, 2024
07a62b8
Delete rabi_length_signal.yaml
ElStabilini Nov 25, 2024
1873ccb
Update src/qibocal/protocols/rabi/utils.py
ElStabilini Nov 25, 2024
ef2e21a
Update src/qibocal/protocols/rabi/amplitude_frequency.py
ElStabilini Nov 25, 2024
7deade0
Update src/qibocal/protocols/rabi/length_frequency.py
ElStabilini Nov 25, 2024
222539d
Update src/qibocal/protocols/rabi/length_frequency.py
ElStabilini Nov 25, 2024
62230c9
Update src/qibocal/protocols/rabi/length.py
ElStabilini Nov 25, 2024
23ae111
Update src/qibocal/protocols/rabi/ef.py
ElStabilini Nov 25, 2024
4dbcc34
Update src/qibocal/protocols/rabi/length.py
ElStabilini Nov 25, 2024
3427756
Update update.py
ElStabilini Nov 25, 2024
3c676ff
Update protocols.yml
ElStabilini Nov 26, 2024
df453df
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 26, 2024
92e0d71
Update pyproject.toml
ElStabilini Nov 26, 2024
1f9d532
Update length_frequency.py
ElStabilini Nov 26, 2024
31db8b7
Update ef.py
ElStabilini Nov 26, 2024
c579cbb
Update flipping.py
ElStabilini Nov 26, 2024
64e5352
Update pyproject.toml
ElStabilini Nov 26, 2024
3c4e0d9
Update poetry.lock
ElStabilini Nov 27, 2024
04cf0f9
Update flipping.py
ElStabilini Nov 27, 2024
cf73084
modify amplitude_sequence and length_sequence for rx90, add flipping …
ElStabilini Nov 27, 2024
f6bfcaf
Update flipping.py
ElStabilini Nov 27, 2024
454f5b5
Update flipping.py
ElStabilini Nov 27, 2024
47a22b5
Update flipping.py
ElStabilini Nov 27, 2024
96dd44e
Update flipping.py
ElStabilini Nov 27, 2024
07a4bcd
Update flipping.py
ElStabilini Nov 27, 2024
e8cea9a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 27, 2024
4052755
Update flipping.py
ElStabilini Nov 27, 2024
12fedb5
fix FlippingResults and FlippingData class definition
ElStabilini Nov 28, 2024
b58e13a
fix globalbackends error: downgrade qibo
ElStabilini Nov 28, 2024
32308e2
Update flipping.rst
ElStabilini Nov 28, 2024
57904a1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 28, 2024
3b6769d
fix error in _fit method
ElStabilini Nov 28, 2024
29a1296
update documentation for flipping
ElStabilini Nov 28, 2024
022240d
fix tests for rx90
ElStabilini Nov 28, 2024
8b0995d
Update flipping.rst
ElStabilini Nov 28, 2024
98bcf1d
modify plot function in utils to have the correct name of the pulse c…
ElStabilini Nov 29, 2024
17ba606
'sync remote and local branch'
ElStabilini Nov 29, 2024
7b907ae
improve code for printing pulse names on reports
ElStabilini Nov 30, 2024
7660fde
fix compatibility with qibo v0.2.14
ElStabilini Dec 3, 2024
2d8c8f7
fix conflict with pyproject.toml for branch 0.2
ElStabilini Dec 3, 2024
1bac594
fix error in flipping sequence construction for rx90
ElStabilini Dec 3, 2024
af82fec
Merge branch '0.2' into pi_half
ElStabilini Dec 3, 2024
228a02e
Update src/qibocal/protocols/flipping.py
ElStabilini Dec 6, 2024
35c7178
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 6, 2024
8950008
Update src/qibocal/protocols/flipping.py
ElStabilini Dec 6, 2024
b90f887
fix test definition and improve code for flipping with rx90 gate
ElStabilini Dec 6, 2024
23ee280
'sync remote and local fixes'
ElStabilini Dec 6, 2024
01a4d1a
Update utils.py
ElStabilini Dec 6, 2024
c5bb28f
improve documentation for flipping and rabi protocols
ElStabilini Dec 6, 2024
f62bbc3
Update doc/source/protocols/rabi/rabi.rst
ElStabilini Dec 7, 2024
832d0e9
create first RX90 of the sequence always using R.(theta=pi/2)
ElStabilini Dec 11, 2024
05c2886
fix tabs
ElStabilini Dec 11, 2024
478c864
sync remote and local update
ElStabilini Dec 11, 2024
837cc08
Update src/qibocal/protocols/flipping.py
ElStabilini Dec 11, 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
34 changes: 25 additions & 9 deletions doc/source/protocols/flipping.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
Flipping
========

The flipping experiment corrects the amplitude in the qubit drive pulse. In this experiment,
we applying an :math:`R_x(\pi/2)` rotation followed by :math:`N` flips (two :math:`R_x(\pi)` rotations)
The flipping experiment corrects the amplitude in the qubit drive pulse for :math:`R_x(\pi)` rotations. In this experiment,
we apply an :math:`R_x(\pi/2)` rotation followed by :math:`N` flips (two :math:`R_x(\pi)` rotations)
and we measure the qubit state.
The first :math:`R_x(\pi/2)` is necessary to discriminate the over rotations and under rotations of the :math:`R_x(\pi)` pulse:
without it the difference between the two cases is just a global phase, i.e., the
probabilities are the same. With the :math:`R_x(\pi/2)` pulse, in case of under rotations the state will be closer to :math:`\ket{0}`
after the initial flip, in the over rotations one the final state will be closer to :math:`\ket{1}`.

By fitting the resulting data with a sinusoidal function, we can determine the delta amplitude, which allows us to refine the
:math:`\pi` pulse amplitue.
:math:`\pi` pulse amplitude.

We implemented also a version of the flipping protocol to calibrate the drive pulse amplitude of the :math:`R_x(\pi/2)` rotations,
in this case each :math:`R_x(\pi)` rotation is replaced by two :math:`R_x(\pi/2)` rotations.
The main reasons for implementing protocols to fine tune the `R_x(\pi/2)` rotations are explained in :ref:`rabi`.

Parameters
^^^^^^^^^^
Expand All @@ -24,17 +28,29 @@ It follows a runcard example of this experiment.

.. code-block:: yaml

- id: flipping
operation: flipping
parameters:
delta_amplitude: 0.05
nflips_max: 30
nflips_step: 1
- id: flipping
operation: flipping
parameters:
delta_amplitude: 0.05
nflips_max: 30
nflips_step: 1

The expected output is the following:

.. image:: flipping.png

If the same experiment is run setting the `rx90: True` the flipping is performed to calibrate the amplitude of the :math:`R_x(\pi/2)` rotation

.. code-block:: yaml

- id: flipping
operation: flipping
parameters:
delta_amplitude: 0.05
nflips_max: 30
nflips_step: 1
rx90: True

Requirements
^^^^^^^^^^^^

Expand Down
34 changes: 34 additions & 0 deletions doc/source/protocols/rabi/rabi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ Rabi rate is larger than the decay and the pure dephasing rate,

where :math:`\Omega_R` is the Rabi frequency and :math:`\tau` the decay time.


Since many routines and protocols in quantum computing are based on `R_x(\pi/2)` rotations, in qibocal we implemented
also another version of the Rabi experiment which can be used to tune the amplitude (duration) of the drive pulse in order
to excite the qubit from the ground state up to state :math:`\frac{\ket{0}-i\ket{1}}{\sqrt{2}}`.

The possibility to calibrate an `R_x(\pi/2)` rotation as native gate allows us to remove the errors that could arise from assuming that the `R_x(\pi/2)` amplitude (duration)
is exactly half that of the `R_x(\pi)` amplitude (duration). This assumption presumes a perfectly linear response of the qubit to the drive pulse, which is
often not the case due to nonlinearities in the qubit's response or imperfections in the pulse shaping :cite:p:`Chen2018MetrologyOQ`.

In this case the pulse sequence is the same as before with the only difference that instead of a single `R_x(\pi)` pulse we use two concatenated `R_x(\pi/2)` pulses.

Parameters
^^^^^^^^^^

Expand Down Expand Up @@ -103,6 +114,29 @@ It follows an example runcard and plot for the signal exepriment

.. image:: rabi_signal.png

In all the previous examples we run Rabi experiments for calibrating the amplitude (duration) of the drive pulse
to excite the qubit from the ground state up to state :math:`\ket{1}`.
All these example runcards can be modified to calibrate the amplitude (duration) of the drive pulse
to excite the qubit from the ground state up to state :math:`\frac{\ket{0}-i\ket{1}}{\sqrt{2}}` by simply setting the `rx90` parameter to `True`.
Comment on lines +117 to +120
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of mentioning the experiment in the general section, and describe it only in the example, you may move this description up, and just cite here you're performing the pi/2 described above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moreover, a description of the sequence (i.e. "same, but replace each pi with two pi/2") and a brief motivation may be appreciated. Then, you may cite this section in the flipping, instead of repeating it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even a reference to the literature you consulted may be appreciated as well :)


In the following we show an example runcard for the amplitude calibration of the `R_x(\pi/2)`.

.. code-block:: yaml


- id: Rabi signal
operation: rabi_amplitude_signal
parameters:
min_amp: 0.01
max_amp: 0.16
step_amp: 0.002
pulse_length: 40
nshots: 1024
relaxation_time: 50000
rx90: True

.. image:: rabi_amplitude_rx90

Requirements
^^^^^^^^^^^^
- :ref:`qubit-spectroscopy`
Expand Down
Binary file added doc/source/protocols/rabi/rabi_amplitude_rx90.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
223 changes: 112 additions & 111 deletions poetry.lock

Large diffs are not rendered by default.

63 changes: 43 additions & 20 deletions src/qibocal/protocols/flipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,35 @@


def flipping_sequence(
platform: CalibrationPlatform, qubit: QubitId, delta_amplitude: float, flips: int
platform: CalibrationPlatform,
qubit: QubitId,
delta_amplitude: float,
flips: int,
rx90: bool,
):
"""Pulse sequence for flipping experiment."""

sequence = PulseSequence()
natives = platform.natives.single_qubit[qubit]

sequence |= natives.R(theta=np.pi / 2)

for _ in range(flips):

qd_channel, rx_pulse = natives.RX()[0]
if rx90:
qd_channel, qd_pulse = natives.RX90()[0]
else:
qd_channel, qd_pulse = natives.RX()[0]

rx_detuned = update.replace(
rx_pulse, amplitude=rx_pulse.amplitude + delta_amplitude
qd_detuned = update.replace(
qd_pulse, amplitude=qd_pulse.amplitude + delta_amplitude
)
sequence.append((qd_channel, rx_detuned))
sequence.append((qd_channel, rx_detuned))
sequence.append((qd_channel, qd_detuned))
sequence.append((qd_channel, qd_detuned))

if rx90:
sequence.append((qd_channel, qd_detuned))
sequence.append((qd_channel, qd_detuned))

sequence |= natives.MZ()

Expand All @@ -59,6 +71,8 @@ class FlippingParameters(Parameters):
Defaults to ``False``."""
delta_amplitude: float = 0
"""Amplitude detuning."""
rx90: bool = False
"""Calibration of native pi pulse, if true calibrates pi/2 pulse"""


@dataclass
Expand All @@ -73,6 +87,8 @@ class FlippingResults(Results):
"""Difference in amplitude between detuned value and fit."""
fitted_parameters: dict[QubitId, dict[str, float]]
"""Raw fitting output."""
rx90: bool
"""Pi or Pi_half calibration"""
chi2: dict[QubitId, list[float]] = field(default_factory=dict)
"""Chi squared estimate mean value and error. """

Expand All @@ -90,8 +106,10 @@ class FlippingData(Data):
"""Resonator type."""
delta_amplitude: float
"""Amplitude detuning."""
pi_pulse_amplitudes: dict[QubitId, float]
"""Pi pulse amplitudes for each qubit."""
pulse_amplitudes: dict[QubitId, float]
"""Pulse amplitudes for each qubit."""
rx90: bool
"""Pi or Pi_half calibration"""
data: dict[QubitId, npt.NDArray[FlippingType]] = field(default_factory=dict)
"""Raw data acquired."""

Expand Down Expand Up @@ -120,10 +138,13 @@ def _acquisition(
data = FlippingData(
resonator_type=platform.resonator_type,
delta_amplitude=params.delta_amplitude,
pi_pulse_amplitudes={
qubit: platform.natives.single_qubit[qubit].RX[0][1].amplitude
pulse_amplitudes={
qubit: getattr(
platform.natives.single_qubit[qubit], "RX90" if params.rx90 else "RX"
)[0][1].amplitude
for qubit in targets
},
rx90=params.rx90,
)

options = {
Expand All @@ -144,6 +165,7 @@ def _acquisition(
qubit=qubit,
delta_amplitude=params.delta_amplitude,
flips=flips,
rx90=params.rx90,
)

sequences.append(sequence)
Expand Down Expand Up @@ -197,9 +219,7 @@ def _fit(data: FlippingData) -> FlippingResults:
chi2 = {}
for qubit in qubits:
qubit_data = data[qubit]
detuned_pi_pulse_amplitude = (
data.pi_pulse_amplitudes[qubit] + data.delta_amplitude
)
detuned_pulse_amplitude = data.pulse_amplitudes[qubit] + data.delta_amplitude
y = qubit_data.prob
x = qubit_data.flips

Expand All @@ -222,10 +242,14 @@ def _fit(data: FlippingData) -> FlippingResults:
perr = np.sqrt(np.diag(perr)).tolist()
popt = popt.tolist()
correction = popt[2] / 2

if data.rx90:
correction /= 2

corrected_amplitudes[qubit] = [
float(detuned_pi_pulse_amplitude * np.pi / (np.pi + correction)),
float(detuned_pulse_amplitude * np.pi / (np.pi + correction)),
float(
detuned_pi_pulse_amplitude
detuned_pulse_amplitude
* np.pi
* 1
/ (np.pi + correction) ** 2
Expand All @@ -237,11 +261,9 @@ def _fit(data: FlippingData) -> FlippingResults:
fitted_parameters[qubit] = popt

delta_amplitude_detuned[qubit] = [
-correction * detuned_pi_pulse_amplitude / (np.pi + correction),
-correction * detuned_pulse_amplitude / (np.pi + correction),
np.abs(
np.pi
* detuned_pi_pulse_amplitude
* np.power(np.pi + correction, -2)
np.pi * detuned_pulse_amplitude * np.power(np.pi + correction, -2)
)
* perr[2]
/ 2,
Expand All @@ -267,6 +289,7 @@ def _fit(data: FlippingData) -> FlippingResults:
delta_amplitude,
delta_amplitude_detuned,
fitted_parameters,
data.rx90,
chi2,
)

Expand Down Expand Up @@ -358,7 +381,7 @@ def _plot(data: FlippingData, target: QubitId, fit: FlippingResults = None):


def _update(results: FlippingResults, platform: CalibrationPlatform, qubit: QubitId):
update.drive_amplitude(results.amplitude[qubit], platform, qubit)
update.drive_amplitude(results.amplitude[qubit], results.rx90, platform, qubit)


flipping = Routine(_acquisition, _fit, _plot, _update)
Expand Down
16 changes: 10 additions & 6 deletions src/qibocal/protocols/rabi/amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RabiAmplitudeResults(RabiAmplitudeSignalResults):
class RabiAmplitudeData(Data):
"""RabiAmplitude data acquisition."""

rx90: bool
"""Pi or Pi_half calibration"""
durations: dict[QubitId, float] = field(default_factory=dict)
"""Pulse durations provided by the user."""
data: dict[QubitId, npt.NDArray[RabiAmpType]] = field(default_factory=dict)
Expand All @@ -55,7 +57,7 @@ def _acquisition(
"""

sequence, qd_pulses, ro_pulses, durations = utils.sequence_amplitude(
targets, params, platform
targets, params, platform, params.rx90
)

sweeper = Sweeper(
Expand All @@ -64,7 +66,7 @@ def _acquisition(
pulses=[qd_pulses[qubit] for qubit in targets],
)

data = RabiAmplitudeData(durations=durations)
data = RabiAmplitudeData(durations=durations, rx90=params.rx90)

# sweep the parameter
results = platform.execute(
Expand Down Expand Up @@ -128,19 +130,21 @@ def _fit(data: RabiAmplitudeData) -> RabiAmplitudeResults:

except Exception as e:
log.warning(f"Rabi fit failed for qubit {qubit} due to {e}.")
return RabiAmplitudeResults(pi_pulse_amplitudes, durations, fitted_parameters, chi2)
return RabiAmplitudeResults(
pi_pulse_amplitudes, durations, fitted_parameters, data.rx90, chi2
)


def _plot(data: RabiAmplitudeData, target: QubitId, fit: RabiAmplitudeResults = None):
"""Plotting function for RabiAmplitude."""
return utils.plot_probabilities(data, target, fit)
return utils.plot_probabilities(data, target, fit, data.rx90)


def _update(
results: RabiAmplitudeResults, platform: CalibrationPlatform, target: QubitId
):
update.drive_amplitude(results.amplitude[target], platform, target)
update.drive_duration(results.length[target], platform, target)
update.drive_amplitude(results.amplitude[target], results.rx90, platform, target)
update.drive_duration(results.length[target], results.rx90, platform, target)


rabi_amplitude = Routine(_acquisition, _fit, _plot, _update)
Expand Down
9 changes: 6 additions & 3 deletions src/qibocal/protocols/rabi/amplitude_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def _acquisition(
"""Data acquisition for Rabi experiment sweeping amplitude."""

sequence, qd_pulses, ro_pulses, durations = sequence_amplitude(
targets, params, platform
targets, params, platform, params.rx90
)
frequency_range = np.arange(
params.min_freq,
Expand All @@ -101,7 +101,7 @@ def _acquisition(
pulses=[qd_pulses[qubit] for qubit in targets],
)

data = RabiAmplitudeFreqData(durations=durations)
data = RabiAmplitudeFreqData(durations=durations, rx90=params.rx90)

results = platform.execute(
[sequence],
Expand Down Expand Up @@ -186,6 +186,7 @@ def _fit(data: RabiAmplitudeFreqData) -> RabiAmplitudeFrequencyResults:
fitted_parameters=fitted_parameters,
frequency=fitted_frequencies,
chi2=chi2,
rx90=data.rx90,
)


Expand Down Expand Up @@ -234,10 +235,12 @@ def _plot(
row=1,
col=1,
)
pulse_name = "Pi-half pulse" if data.rx90 else "Pi pulse"

fitting_report = table_html(
table_dict(
target,
["Optimal rabi frequency", "Pi-pulse amplitude"],
["Optimal rabi frequency", f"{pulse_name} amplitude"],
[
fit.frequency[target],
f"{fit.amplitude[target][0]:.6f} +- {fit.amplitude[target][1]:.6f} [a.u.]",
Expand Down
Loading
Loading