-
Notifications
You must be signed in to change notification settings - Fork 7
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
ro_optimization in autocalibration #392
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
8b8ee51
add ro_frequency in autocalibration
Edoardo-Pedicillo 6248a31
Merge branch 'main' into auto_ro_optimization
Edoardo-Pedicillo 57ebe78
deploy ro freq optimization
Edoardo-Pedicillo ca1379f
add numba dep
Edoardo-Pedicillo 31b6f03
applied stash that had conflicts
Edoardo-Pedicillo 67e35f0
applied stash that had conflicts
Edoardo-Pedicillo e9ab173
applied stash that had conflicts
Edoardo-Pedicillo 973130f
fix cumulative bug and clean code
Edoardo-Pedicillo 11fb556
Delete actions_qm.yml
Edoardo-Pedicillo c10f33e
Delete utils.py
Edoardo-Pedicillo f6ac7fb
Delete calibrate_qubit_states.py
Edoardo-Pedicillo 72d3ba7
Delete fast_reset.py
Edoardo-Pedicillo 9e99a24
Delete ramsey_unrolling.py
Edoardo-Pedicillo f04b0eb
Delete ro_frequency.py
Edoardo-Pedicillo c3b63ac
Revert "Delete ro_frequency.py"
Edoardo-Pedicillo 0a3712d
remove plots in classification
Edoardo-Pedicillo a4c3ba5
update docs
Edoardo-Pedicillo d5b2c7d
add routine in tests
Edoardo-Pedicillo 0f4110a
fix lint bug
Edoardo-Pedicillo b11468f
Merge branch 'main' into auto_ro_optimization
Edoardo-Pedicillo 648e48a
fix tests
Edoardo-Pedicillo 99099b1
remove print
Edoardo-Pedicillo f8d51f6
Merge branch 'auto_ro_optimization' of github.com:qiboteam/qibocal in…
Edoardo-Pedicillo d7660e0
Update src/qibocal/protocols/characterization/readout_optimization/ro…
Edoardo-Pedicillo b78830b
Update src/qibocal/protocols/characterization/readout_optimization/ro…
Edoardo-Pedicillo edba7cb
Update src/qibocal/protocols/characterization/readout_optimization/ro…
Edoardo-Pedicillo e8a3b41
Update src/qibocal/protocols/characterization/readout_optimization/ro…
Edoardo-Pedicillo 42a3dcc
Update src/qibocal/protocols/characterization/readout_optimization/ro…
Edoardo-Pedicillo 948b9c0
from RoFrequency in ResonatorFrequency
Edoardo-Pedicillo af55eb4
change routine name
Edoardo-Pedicillo dfff092
remove sorting
Edoardo-Pedicillo 995b313
fix test
Edoardo-Pedicillo ed4161c
restore i, q
Edoardo-Pedicillo 3ee8a16
Update src/qibocal/protocols/characterization/readout_optimization/re…
Edoardo-Pedicillo fdfeb7e
update docstrings
Edoardo-Pedicillo a2d3cd1
unique_freqs function
Edoardo-Pedicillo 8251dd4
add cumulative test
Edoardo-Pedicillo c3c43aa
Merge branch 'main' into auto_ro_optimization
Edoardo-Pedicillo dad3bc6
change test options
Edoardo-Pedicillo 4cb29bb
fix bug
Edoardo-Pedicillo 48e2476
cast float
Edoardo-Pedicillo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
253 changes: 253 additions & 0 deletions
253
src/qibocal/protocols/characterization/readout_optimization/resonator_frequency.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
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 plotly.subplots import make_subplots | ||
from qibolab import AcquisitionType, ExecutionParameters | ||
from qibolab.platform import Platform | ||
from qibolab.pulses import PulseSequence | ||
from qibolab.qubits import QubitId | ||
from qibolab.sweeper import Parameter, Sweeper, SweeperType | ||
|
||
from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine | ||
from qibocal.protocols.characterization.utils import HZ_TO_GHZ, cumulative | ||
|
||
|
||
@dataclass | ||
class ResonatorFrequencyParameters(Parameters): | ||
"""Optimization RO frequency inputs.""" | ||
|
||
freq_width: int | ||
"""Width [Hz] for frequency sweep relative to the readout frequency (Hz).""" | ||
freq_step: int | ||
"""Frequency step for sweep (Hz).""" | ||
nshots: Optional[int] = None | ||
"""Number of shots.""" | ||
relaxation_time: Optional[int] = None | ||
"""Relaxation time (ns).""" | ||
|
||
|
||
@dataclass | ||
class ResonatorFrequencyResults(Results): | ||
"""Optimization Resonator frequency outputs.""" | ||
|
||
fidelities: dict[QubitId, list] | ||
"""Assignment fidelities.""" | ||
best_freq: dict[QubitId, float] = field(metadata=dict(update="readout_frequency")) | ||
"""Resonator Frequency with the highest assignment fidelity.""" | ||
|
||
|
||
ResonatorFrequencyType = np.dtype( | ||
[ | ||
("freq", np.float64), | ||
("i", np.float64), | ||
("q", np.float64), | ||
] | ||
) | ||
"""Custom dtype for Optimization RO frequency.""" | ||
|
||
|
||
@dataclass | ||
class ResonatorFrequencyData(Data): | ||
""" "Optimization RO frequency acquisition outputs.""" | ||
|
||
resonator_type: str | ||
"""Resonator type.""" | ||
data: dict[tuple[QubitId, int, int], npt.NDArray[ResonatorFrequencyType]] = field( | ||
default_factory=dict | ||
) | ||
|
||
def register_qubit(self, qubit, state, freq, i, q): | ||
"""Store output for single qubit.""" | ||
ar = np.empty(i.shape, dtype=ResonatorFrequencyType) | ||
ar["freq"] = freq | ||
ar["i"] = i | ||
ar["q"] = q | ||
self.data[qubit, state] = np.rec.array(ar) | ||
|
||
def unique_freqs(self, qubit: QubitId) -> np.ndarray: | ||
return np.unique(self.data[qubit, 0].freq) | ||
|
||
|
||
def _acquisition( | ||
params: ResonatorFrequencyParameters, platform: Platform, qubits: Qubits | ||
) -> ResonatorFrequencyData: | ||
r""" | ||
Data acquisition for readout frequency optimization. | ||
While sweeping the readout frequency, the routine performs a single shot | ||
classification and evaluates the assignement fidelity. | ||
At the end, the readout frequency is updated, choosing the one that has | ||
the highest assignment fidelity. | ||
|
||
Args: | ||
params (ResonatorFrequencyParameters): experiment's parameters | ||
platform (Platform): Qibolab platform object | ||
qubits (dict): list of target qubits to perform the action | ||
|
||
""" | ||
|
||
# create 2 sequences of pulses for the experiment: | ||
# sequence_0: I - MZ | ||
# sequence_1: RX - MZ | ||
|
||
# taking advantage of multiplexing, apply the same set of gates to all qubits in parallel | ||
sequence_0 = PulseSequence() | ||
sequence_1 = PulseSequence() | ||
ro_pulses = {} | ||
qd_pulses = {} | ||
for qubit in qubits: | ||
qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) | ||
ro_pulses[qubit] = platform.create_qubit_readout_pulse( | ||
qubit, start=qd_pulses[qubit].finish | ||
) | ||
sequence_0.add(ro_pulses[qubit]) | ||
sequence_1.add(qd_pulses[qubit]) | ||
sequence_1.add(ro_pulses[qubit]) | ||
|
||
# define the parameter to sweep and its range: | ||
delta_frequency_range = np.arange( | ||
-params.freq_width / 2, params.freq_width / 2, params.freq_step | ||
) | ||
|
||
data = ResonatorFrequencyData(platform.resonator_type) | ||
sweeper = Sweeper( | ||
Parameter.frequency, | ||
delta_frequency_range, | ||
pulses=[ro_pulses[qubit] for qubit in qubits], | ||
type=SweeperType.OFFSET, | ||
) | ||
|
||
results_0 = platform.sweep( | ||
sequence_0, | ||
ExecutionParameters( | ||
nshots=params.nshots, | ||
relaxation_time=params.relaxation_time, | ||
acquisition_type=AcquisitionType.INTEGRATION, | ||
), | ||
sweeper, | ||
) | ||
|
||
results_1 = platform.sweep( | ||
sequence_1, | ||
ExecutionParameters( | ||
nshots=params.nshots, | ||
relaxation_time=params.relaxation_time, | ||
acquisition_type=AcquisitionType.INTEGRATION, | ||
), | ||
sweeper, | ||
) | ||
|
||
# retrieve the results for every qubit | ||
for qubit in qubits: | ||
for i, results in enumerate([results_0, results_1]): | ||
result = results[ro_pulses[qubit].serial] | ||
# store the results | ||
data.register_qubit( | ||
qubit=qubit, | ||
state=i, | ||
freq=ro_pulses[qubit].frequency + delta_frequency_range, | ||
i=result.voltage_i, | ||
q=result.voltage_q, | ||
) | ||
return data | ||
|
||
|
||
def _fit(data: ResonatorFrequencyData) -> ResonatorFrequencyResults: | ||
"""Post-Processing for Optimization RO frequency""" | ||
qubits = data.qubits | ||
fidelities_dict = {} | ||
best_freqs = {} | ||
for qubit in qubits: | ||
fidelities = [] | ||
freqs = data.unique_freqs(qubit) | ||
for freq in freqs: | ||
iq_state0 = data[qubit, 0][data[qubit, 0].freq == freq][["i", "q"]] | ||
iq_state1 = data[qubit, 1][data[qubit, 1].freq == freq][["i", "q"]] | ||
iq_state0 = iq_state0.i + 1.0j * iq_state0.q | ||
iq_state1 = iq_state1.i + 1.0j * iq_state1.q | ||
|
||
iq_state1 = np.array(iq_state1) | ||
iq_state0 = np.array(iq_state0) | ||
nshots = len(iq_state0) | ||
|
||
iq_mean_state1 = np.mean(iq_state1) | ||
iq_mean_state0 = np.mean(iq_state0) | ||
|
||
vector01 = iq_mean_state1 - iq_mean_state0 | ||
rotation_angle = np.angle(vector01) | ||
|
||
iq_state1_rotated = iq_state1 * np.exp(-1j * rotation_angle) | ||
iq_state0_rotated = iq_state0 * np.exp(-1j * rotation_angle) | ||
|
||
real_values_state1 = iq_state1_rotated.real | ||
real_values_state0 = iq_state0_rotated.real | ||
|
||
real_values_combined = np.concatenate( | ||
(real_values_state1, real_values_state0) | ||
) | ||
|
||
cum_distribution_state1 = cumulative( | ||
real_values_combined, real_values_state1 | ||
) | ||
cum_distribution_state0 = cumulative( | ||
real_values_combined, real_values_state0 | ||
) | ||
|
||
cum_distribution_diff = np.abs( | ||
np.array(cum_distribution_state1) - np.array(cum_distribution_state0) | ||
) | ||
argmax = np.argmax(cum_distribution_diff) | ||
errors_state1 = nshots - cum_distribution_state1[argmax] | ||
errors_state0 = cum_distribution_state0[argmax] | ||
fidelities.append((errors_state1 + errors_state0) / nshots / 2) | ||
fidelities_dict[qubit] = fidelities | ||
best_freqs[qubit] = freqs[np.argmax(fidelities_dict[qubit])] | ||
|
||
return ResonatorFrequencyResults( | ||
fidelities=fidelities_dict, | ||
best_freq=best_freqs, | ||
) | ||
|
||
|
||
def _plot(data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, qubit): | ||
"""Plotting function for Optimization RO frequency.""" | ||
figures = [] | ||
freqs = data.unique_freqs(qubit) * HZ_TO_GHZ | ||
opacity = 1 | ||
fitting_report = " " | ||
fig = make_subplots( | ||
rows=1, | ||
cols=1, | ||
) | ||
|
||
fig.add_trace( | ||
go.Scatter( | ||
x=freqs, | ||
y=fit.fidelities[qubit], | ||
opacity=opacity, | ||
showlegend=True, | ||
), | ||
row=1, | ||
col=1, | ||
) | ||
|
||
fig.update_layout( | ||
showlegend=True, | ||
uirevision="0", # ``uirevision`` allows zooming while live plotting | ||
xaxis_title="Resonator Frequencies (GHz)", | ||
yaxis_title="Assignment Fidelities", | ||
) | ||
|
||
fitting_report = fitting_report + ( | ||
f"{qubit} | Best Resonator Frequency (GHz) : {fit.best_freq[qubit]*HZ_TO_GHZ:,.4f} Hz.<br>" | ||
) | ||
|
||
figures.append(fig) | ||
|
||
return figures, fitting_report | ||
|
||
|
||
resonator_frequency = Routine(_acquisition, _fit, _plot) | ||
""""Optimization RO frequency Routine object.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import numpy as np | ||
|
||
from qibocal.protocols.characterization.utils import cumulative | ||
|
||
|
||
def test_cumulative(): | ||
data = np.arange(10, dtype=float) | ||
assert np.array_equal(cumulative(data, data), data) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same operation that we are doing for the single shot classification, right?
We should be able to recycle that function in one way or another.
Did you speed up also the fitting in the single shot classification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
If not strictly necessary now, I prefer to do it in the (near) future PR to port the classification models.
Yes, only the cumulative part.