Skip to content
Draft
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
29 changes: 25 additions & 4 deletions src/qibocal/protocols/flux_dependence/qubit_crosstalk.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
__all__ = ["qubit_crosstalk"]


def drop_targets(target_list: list, qpu_platform: CalibrationPlatform):
"""Return all qubits of a given QPU except the ones we want to target in crosstalk routine"""
return [q for q in qpu_platform.qubits.keys() if q not in target_list]


Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@alecandido should we put drop_targets as a method of QubitCrosstalkParameters class?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is an option, but not a mandatory one.

In particular, the call itself

    flux_qubits = (
        drop_targets(targets, platform)
        if params.flux_qubits is None
        else params.flux_qubits
    )

is quite related to the class.
But the content of drop_targets() is completely unrelated, since it is not making use of any information which is in the class.

Since, for the time being, it is meant to be used only internally (to this module), just prepend a _, to make it clear it is not intended for import. I.e. _drop_targets().

There are more or less three levels for top-level variables:

  • internal (to the module), which are _-prefixed
  • internal (to the qibocal package), just do nothing
  • public (for qibocal users), which should be listed in __all__

@dataclass
class QubitCrosstalkParameters(QubitFluxParameters):
"""Crosstalk runcard inputs."""
Expand All @@ -52,6 +57,14 @@ class QubitCrosstalkParameters(QubitFluxParameters):
Multiple qubits may be measured in each execution as specified by the ``qubits`` option in the runcard.
"""

def fill_bias_points(self, target_list: list, qpu_platform: CalibrationPlatform):
"""if a the bias point for one or more qubit is not inserted in the input parameters the calibrated sewwtspot is used."""
for t in target_list:
if t not in self.bias_point.keys():
self.bias_point[t] = qpu_platform.calibration.single_qubits[
t
].qubit.sweetspot


@dataclass
class QubitCrosstalkData(QubitFluxData):
Expand Down Expand Up @@ -106,10 +119,18 @@ def _acquisition(
) -> QubitCrosstalkData:
"""Data acquisition for Crosstalk Experiment."""

assert set(targets).isdisjoint(set(params.flux_qubits)), (
flux_qubits = (
drop_targets(targets, platform)
if params.flux_qubits is None
else params.flux_qubits
)

assert set(targets).isdisjoint(set(flux_qubits)), (
"Flux qubits must be different from targets."
)

params.fill_bias_points(targets, platform)

sequence = PulseSequence()
ro_pulses = {}
qd_pulses = {}
Expand Down Expand Up @@ -160,7 +181,7 @@ def _acquisition(
)
)

for q in params.flux_qubits:
for q in flux_qubits:
flux_channel = platform.qubits[q].flux
offset0 = platform.config(flux_channel).offset
offset_sweepers.append(
Expand Down Expand Up @@ -198,7 +219,7 @@ def _acquisition(
for q in targets
]

for flux_qubit, offset_sweeper in zip(params.flux_qubits, offset_sweepers):
for flux_qubit, offset_sweeper in zip(flux_qubits, offset_sweepers):
results = platform.execute(
[sequence], [[offset_sweeper], freq_sweepers], **options, updates=updates
)
Expand Down Expand Up @@ -276,7 +297,7 @@ def fit_function(x, crosstalk_element, offset):
crosstalk_matrix[target_qubit][flux_qubit] = (
popt[0] * data.matrix_element[target_qubit]
)
except RuntimeError as e: # pragma: no cover
except (ValueError, RuntimeError) as e: # pragma: no cover
log.error(
f"Off-diagonal flux fit failed for qubit {flux_qubit} due to {e}."
)
Expand Down