diff --git a/doc/source/getting-started/example.rst b/doc/source/getting-started/example.rst index d8894d69f..2f4441dfe 100644 --- a/doc/source/getting-started/example.rst +++ b/doc/source/getting-started/example.rst @@ -10,9 +10,9 @@ presented in :ref:`runcard`, we can use this runcard. .. code-block:: yaml - platform: qw5q_gold_qblox + platform: qw5q_gold - qubits: [0] + targets: [0] actions: - id: resonator high power high amplitude diff --git a/doc/source/getting-started/runcard.rst b/doc/source/getting-started/runcard.rst index 6ad17ffff..2c2b81eb2 100644 --- a/doc/source/getting-started/runcard.rst +++ b/doc/source/getting-started/runcard.rst @@ -17,7 +17,7 @@ Down below we present how to write a runcard to execute a single protocol using platform: - qubits: + targets: actions: @@ -33,8 +33,8 @@ Here is a description of the global parameters to be specified: * ``platform``: QPU where the experiments will be executed. Possible choices for TII users are available in this `repository `_. For non-TII users it is possible a setup a custom platform using `Qibolab `_. - * ``qubits``: list of qubit names for a specific platform. It can also be a list of qubit pairs - in the case of protocols for qubit pairs. + * ``targets``: list of ``QubitId`` for a specific platform. It can also be a list of ``QubitPairId`` + in the case of protocols for qubit pairs, or a ``list[list[QubitId]]`` for protocols targeting groups of qubits. Under ``actions`` are listed the protocols that will be executed. diff --git a/doc/source/tutorials/advanced.rst b/doc/source/tutorials/advanced.rst index a47d9787e..20d737923 100644 --- a/doc/source/tutorials/advanced.rst +++ b/doc/source/tutorials/advanced.rst @@ -40,14 +40,14 @@ in the following way: After defining the parameters, the user can perform the acquisition using ``experiment.acquisition`` which accepts the following parameters: -* params (`experiment.parameters_type `_): input parameters for the experiment -* platform (`qibolab.platform.Platform `_): Qibolab platform class -* qubits (dict[`QubitId `_, `QubitPairId `_]) dictionary with qubits where the acquisition will run +* ``params`` (`experiment.parameters_type `_): input parameters for the experiment +* ``platform`` (`qibolab.platform.Platform `_): Qibolab platform class +* ``targets`` (Union[list[`QubitId `_],list[`QubitPairId `_], list[list[`QubitId `_]]]) list with qubits where the acquisition will run and returns the following: -* data (`experiment.data_type `_): data acquired -* acquisition_time (float): acquisition time on hardware +* ``data`` (`experiment.data_type `_): data acquired +* ``acquisition_time`` (float): acquisition time on hardware .. code-block:: python @@ -68,22 +68,22 @@ following way: To be more specific the user should pass as input ``data`` which is of type ``experiment.data_type`` and the outputs are the following: -* fit: (`experiment.results_type `_) input parameters for the experiment -* fit_time (float): post-processing time +* ``fit``: (`experiment.results_type `_) input parameters for the experiment +* ``fit_time`` (float): post-processing time It is also possible to access the plots and the tables generated in the report using ``experiment.report`` which accepts the following parameters: -* data: (`experiment.data_type `_) data structure used by ``experiment`` -* qubit (dict[`QubitId `_, `QubitPairId `_]): qubit / qubit pair to be plotted -* fit: (`experiment.results_type `_): data structure for post-processing used by ``experiment`` +* ``data``: (`experiment.data_type `_) data structure used by ``experiment`` +* ``target`` (dict[`QubitId `_, `QubitPairId `_]): qubit / qubit pair to be plotted +* ``fit``: (`experiment.results_type `_): data structure for post-processing used by ``experiment`` .. code-block:: python # Plot for qubit 0 - qubit = 0 - figs, html_content = experiment.report(data=data, qubit=0, fit=fit) + target = 0 + figs, html_content = experiment.report(data=data, target=target, fit=fit) ``experiment.report`` returns the following: @@ -122,16 +122,16 @@ Currently, characterization/calibration protocols are divided in three steps: `a The relationship between steps and data structures are summarized in the following bullets: -* `acquisition` receives as input `parameters` and outputs `data` -* `fit` receives as input `data` and outputs `results` -* `plot` receives as input `data` and `results` to visualize the protocol +* ``acquisition`` receives as input ``parameters`` and outputs ``data`` +* ``fit`` receives as input ``data`` and outputs ``results`` +* ``plot`` receives as input ``data`` and ``results`` to visualize the protocol This approach is flexible enough to allow the data acquisition without performing a post-processing analysis. Step by step tutorial ~~~~~~~~~~~~~~~~~~~~~ -All protocols are located in `src/qibocal/protocols/characterization `_. +All protocols are located in ``src/qibocal/protocols/characterization ``_. Suppose that we want to code a protocol to perform a RX rotation for different angles. @@ -165,7 +165,7 @@ In this case you define a range for the angle to be probed alongside the number of shots. .. note:: - It is advised to use `dataclasses`. If you are not familiar + It is advised to use ``dataclasses``. If you are not familiar have a look at the official `documentation `_. @@ -219,22 +219,22 @@ In the acquisition function we are going to perform the experiment. .. code-block:: python from qibolab.platform import Platform - from ...auto.operation import Qubits + from qibolab.qubits import QubitId,, QubitPairId + from typing import Union - def acquisition(params: RoutineParameters, platform: Platform, qubits: Qubits) -> RoutineData - """ A generic acquisition function.""" + def acquisition(params: RoutineParameters, platform: Platform, targets: Union[list[QubitId], list[QubitPairId], list[list[QubitId]]]) -> RoutineData + """A generic acquisition function.""" - where `Qubits` is a `dict[QubitId, Qubit]`. .. code-block:: python from qibolab.platform import Platform - from ...auto.operation import Qubits + from qibolab.qubits import QubitId def acquisition( params: RotationParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> RotationData: r""" Data acquisition for rotation routine. @@ -242,7 +242,7 @@ In the acquisition function we are going to perform the experiment. Args: params (:class:`RotationParameters`): input parameters platform (:class:`Platform`): Qibolab's platform - qubits (dict): dict of target :class:`Qubit` objects to be characterized + targets (list): list with target qubits Returns: data (:class:`RotationData`) @@ -343,16 +343,16 @@ use `plotly `_ in order to properly generate the rep import plotly.graph_objects as go - def plot(data: RoutineData, fit: RoutineResults, qubit: QubitId) -> list[go.Figure(), str] + def plot(data: RoutineData, fit: RoutineResults, target: QubitId) -> list[go.Figure(), str] """ A generic plotting function.""" - The `str` in output can be used to create a table, which has 3 columns `qubit`, `Fitting Parameter` - and `Value`. Here is the syntax necessary to insert a raw in the table. + The ``str`` in output can be used to create a table, which has 3 columns ``target``, ``Fitting Parameter`` + and ``Value``. Here is the syntax necessary to insert a raw in the table. .. code-block:: python report = "" - qubit = 0 + target = 0 angle = 3.14 report += f" {qubit} | rotation angle: {angle:.3f}
" @@ -365,15 +365,16 @@ Here is the plotting function for the protocol that we are coding: .. code-block:: python import plotly.graph_objects as go + from qibolab.qubits import QubitId - def plot(data: RotationData, fit: RotationResults, qubit): + def plot(data: RotationData, fit: RotationResults, target: QubitId): """Plotting function for rotation.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] fig.add_trace( go.Scatter( @@ -392,7 +393,7 @@ Here is the plotting function for the protocol that we are coding: x=qubit_data.theta, y=cos_fit( qubit_data.theta, - *fit.fitted_parameters[qubit], + *fit.fitted_parameters[target], ), name="Fit", line=go.scatter.Line(dash="dot"), @@ -402,7 +403,6 @@ Here is the plotting function for the protocol that we are coding: # last part fig.update_layout( showlegend=True, - uirevision="0", # ``uirevision`` allows zooming while live plotting xaxis_title="Theta [rad]", yaxis_title="Probability", ) @@ -447,7 +447,7 @@ To launch the protocol a possible runcard could be the following one: platform: dummy - qubits: [0,1] + targets: [0,1] actions: diff --git a/runcards/actions_qq.yml b/runcards/actions_qq.yml index 0ac153191..41b89de54 100644 --- a/runcards/actions_qq.yml +++ b/runcards/actions_qq.yml @@ -1,6 +1,6 @@ platform: dummy -qubits: [0,1] +targets: [0,1] actions: @@ -422,7 +422,7 @@ actions: # - id: standard rb bootstrap # priority: 0 # operation: standard_rb -# qubits: [1] +# targets: [1] # parameters: # depths: [1, 2, 3, 5] # niter: 5 @@ -434,7 +434,7 @@ actions: # - id: standard rb inhomogeneous # priority: 0 # operation: standard_rb -# qubits: [0, 1, 3] +# targets: [0, 1, 3] # parameters: # depths: [1, 3, 3, 5] # niter: 5 @@ -448,7 +448,7 @@ actions: # - id: CHSH with pulses # priority: 0 # operation: chsh_pulses -# qubits: [[0,1],[1,2],[0,3]] +# targets: [[0,1],[1,2],[0,3]] # parameters: # nshots: 1000 # ntheta: 10 @@ -459,7 +459,7 @@ actions: # - id: CHSH with natives # priority: 0 # operation: chsh_circuits -# qubits: [[0,1],[1,2]] +# targets: [[0,1],[1,2]] # parameters: # nshots: 1000 # ntheta: 10 @@ -471,7 +471,7 @@ actions: # - id: CHSH with circuits # priority: 0 # operation: chsh_circuits -# qubits: [[0,1],[1,2]] +# targets: [[0,1],[1,2]] # parameters: # nshots: 1000 # ntheta: 10 @@ -481,7 +481,7 @@ actions: # - id: readout_mitigation_matrix pulses # priority: 0 # operation: readout_mitigation_matrix -# qubits: [[0,1,2],[1,2]] +# targets: [[0,1,2],[1,2]] # parameters: # nshots: 100 # pulses: True @@ -490,7 +490,7 @@ actions: # - id: readout_mitigation_matrix circuits # priority: 0 # operation: readout_mitigation_matrix -# qubits: [[0,1,2],[1,2]] +# targets: [[0,1,2],[1,2]] # parameters: # nshots: 100 # pulses: False diff --git a/src/qibocal/auto/execute.py b/src/qibocal/auto/execute.py index 769a703f9..0e2c24201 100644 --- a/src/qibocal/auto/execute.py +++ b/src/qibocal/auto/execute.py @@ -10,8 +10,8 @@ from .graph import Graph from .history import History -from .runcard import Id, Runcard -from .task import Qubits, Task +from .runcard import Id, Runcard, Targets +from .task import Task @dataclass @@ -24,8 +24,8 @@ class Executor: """The execution history, with results and exit states.""" output: Path """Output path.""" - qubits: Qubits - """Qubits to be calibrated.""" + targets: Targets + """Qubits/Qubit Pairs to be calibrated.""" platform: Platform """Qubits' platform.""" max_iterations: int @@ -44,7 +44,7 @@ def load( card: Runcard, output: Path, platform: Platform = None, - qubits: Qubits = None, + targets: Targets = None, update: bool = True, ): """Load execution graph and associated executor from a runcard.""" @@ -55,7 +55,7 @@ def load( max_iterations=card.max_iterations, output=output, platform=platform, - qubits=qubits, + targets=targets, update=update, ) @@ -142,7 +142,7 @@ def run(self, mode): completed = task.run( max_iterations=self.max_iterations, platform=self.platform, - qubits=self.qubits, + targets=self.targets, folder=self.output, mode=mode, ) diff --git a/src/qibocal/auto/operation.py b/src/qibocal/auto/operation.py index e09b3bbde..5c4ffb435 100644 --- a/src/qibocal/auto/operation.py +++ b/src/qibocal/auto/operation.py @@ -286,9 +286,9 @@ def platform_dependent(self): return "platform" in inspect.signature(self.acquisition).parameters @property - def qubits_dependent(self): + def targets_dependent(self): """Check if acquisition involves qubits.""" - return "qubits" in inspect.signature(self.acquisition).parameters + return "targets" in inspect.signature(self.acquisition).parameters @dataclass diff --git a/src/qibocal/auto/runcard.py b/src/qibocal/auto/runcard.py index f2e360a8e..5ef5492e5 100644 --- a/src/qibocal/auto/runcard.py +++ b/src/qibocal/auto/runcard.py @@ -4,11 +4,10 @@ from functools import cached_property from typing import Any, NewType, Optional, Union -from pydantic import Field from pydantic.dataclasses import dataclass from qibo.backends import Backend, GlobalBackend from qibolab.platform import Platform -from qibolab.qubits import QubitId +from qibolab.qubits import QubitId, QubitPairId from .operation import OperationId from .validation import Validator @@ -16,6 +15,9 @@ Id = NewType("Id", str) """Action identifiers type.""" +Targets = Union[list[QubitId], list[QubitPairId], list[tuple[QubitId, ...]]] +"""Elements to be calibrated by a single protocol.""" + MAX_ITERATIONS = 5 """Default max iterations.""" @@ -34,9 +36,7 @@ class Action: """Alternative subsequent actions, branching from the current one.""" priority: Optional[int] = None """Priority level, determining the execution order.""" - qubits: Union[list[QubitId], list[tuple[QubitId, QubitId]], list[list[QubitId]]] = ( - Field(default_factory=list) - ) + targets: Optional[Targets] = None """Local qubits (optional).""" update: bool = True """Runcard update mechanism.""" @@ -56,7 +56,7 @@ class Runcard: actions: list[Action] """List of action to be executed.""" - qubits: Optional[Union[list[QubitId], list[tuple[QubitId, QubitId]]]] = None + targets: Optional[Targets] = None """Qubits to be calibrated.""" backend: str = "qibolab" """Qibo backend.""" diff --git a/src/qibocal/auto/task.py b/src/qibocal/auto/task.py index 636fdeb5d..bcba708c3 100644 --- a/src/qibocal/auto/task.py +++ b/src/qibocal/auto/task.py @@ -1,33 +1,19 @@ """Action execution tracker.""" import copy -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from statistics import mode -from typing import Optional, Union +from typing import Optional from qibolab.platform import Platform -from qibolab.qubits import QubitId, QubitPairId from qibolab.serialize import dump_platform from ..config import log, raise_error from ..protocols.characterization import Operation -from ..utils import ( - allocate_qubits_pairs, - allocate_single_qubits, - allocate_single_qubits_lists, -) from .mode import ExecutionMode -from .operation import ( - Data, - DummyPars, - Qubits, - QubitsPairs, - Results, - Routine, - dummy_operation, -) -from .runcard import Action, Id +from .operation import Data, DummyPars, Results, Routine, dummy_operation +from .runcard import Action, Id, Targets from .status import Failure, Normal MAX_PRIORITY = int(1e9) @@ -44,35 +30,11 @@ class Task: """Action object parsed from Runcard.""" iteration: int = 0 """Task iteration.""" - qubits: list[QubitId, QubitPairId] = field(default_factory=list) - """List of QubitIds or QubitPairIds for task.""" - def __post_init__(self): - if len(self.qubits) == 0: - self.qubits = self.action.qubits - - # TODO: to be removed in https://github.com/qiboteam/qibocal/pull/682 - def _allocate_local_qubits(self, qubits, platform): - """Create qubits dictionary from QubitIds.""" - if len(self.qubits) > 0: - if platform is not None: - if any(isinstance(i, tuple) for i in self.qubits): - task_qubits = allocate_qubits_pairs(platform, self.qubits) - elif any( - isinstance(i, tuple) or isinstance(i, list) for i in self.qubits - ): - task_qubits = allocate_single_qubits_lists(platform, self.qubits) - else: - task_qubits = allocate_single_qubits(platform, self.qubits) - else: - # None platform use just ids - task_qubits = self.qubits - else: - task_qubits = qubits - - self.qubits = list(task_qubits) - - return task_qubits + @property + def targets(self) -> Targets: + """Protocol targets.""" + return self.action.targets @property def id(self) -> Id: @@ -128,7 +90,7 @@ def run( self, max_iterations: int, platform: Platform = None, - qubits: Union[Qubits, QubitsPairs] = dict, + targets: Targets = list, mode: ExecutionMode = None, folder: Path = None, ): @@ -138,6 +100,9 @@ def run( f"Maximum number of iterations {max_iterations} reached!", ) + if self.targets is None: + self.action.targets = targets + completed = Completed(self, folder) try: @@ -154,15 +119,13 @@ def run( operation = dummy_operation parameters = DummyPars() if mode.name in ["autocalibration", "acquire"]: - if operation.platform_dependent and operation.qubits_dependent: + if operation.platform_dependent and operation.targets_dependent: completed.data, completed.data_time = operation.acquisition( parameters, platform=platform, - qubits=self._allocate_local_qubits(qubits, platform), + targets=self.targets, ) - # need to reassign qubit since when task - # is passed it is deepcopied - completed.task.qubits = self.qubits + else: completed.data, completed.data_time = operation.acquisition( parameters, platform=platform @@ -238,7 +201,7 @@ def data(self, data: Data): def update_platform(self, platform: Platform, update: bool): """Perform update on platform' parameters by looping over qubits or pairs.""" if self.task.update and update: - for qubit in self.task.qubits: + for qubit in self.task.targets: try: self.task.operation.update(self.results, platform, qubit) except KeyError: @@ -252,7 +215,7 @@ def validate(self) -> tuple[Optional[TaskId], Optional[dict]]: """Check status of completed and handle Failure using handler.""" if self.task.action.validator is not None: status = [] - for target in self.task.qubits: + for target in self.task.targets: # TODO: how to handle multiple targets? # dummy solution for now: take the mode. qubit_status, params = self.task.action.validator.validate( diff --git a/src/qibocal/cli/acquisition.py b/src/qibocal/cli/acquisition.py index 0fbc09eeb..0bef7b1ae 100644 --- a/src/qibocal/cli/acquisition.py +++ b/src/qibocal/cli/acquisition.py @@ -8,14 +8,7 @@ from ..auto.execute import Executor from ..auto.history import add_timings_to_meta from ..auto.mode import ExecutionMode -from .utils import ( - META, - PLATFORM, - RUNCARD, - create_qubits_dict, - generate_meta, - generate_output_folder, -) +from .utils import META, PLATFORM, RUNCARD, generate_meta, generate_output_folder def acquire(runcard, folder, force): @@ -32,9 +25,6 @@ def acquire(runcard, folder, force): # generate output folder path = generate_output_folder(folder, force) - # set backend, platform and qubits - qubits = create_qubits_dict(qubits=runcard.qubits, platform=platform) - # generate meta meta = generate_meta(backend, platform, path) # dump platform @@ -47,7 +37,7 @@ def acquire(runcard, folder, force): # dump meta (path / META).write_text(json.dumps(meta, indent=4)) - executor = Executor.load(runcard, path, platform, qubits) + executor = Executor.load(runcard, path, platform, runcard.targets) # connect and initialize platform if platform is not None: diff --git a/src/qibocal/cli/autocalibration.py b/src/qibocal/cli/autocalibration.py index a119b819d..18604f70b 100644 --- a/src/qibocal/cli/autocalibration.py +++ b/src/qibocal/cli/autocalibration.py @@ -14,7 +14,6 @@ PLATFORM, RUNCARD, UPDATED_PLATFORM, - create_qubits_dict, generate_meta, generate_output_folder, ) @@ -35,7 +34,7 @@ def autocalibrate(runcard, folder, force, update): path = generate_output_folder(folder, force) # allocate qubits - qubits = create_qubits_dict(qubits=runcard.qubits, platform=platform) + # qubits = create_qubits_dict(qubits=runcard.qubits, platform=platform) # generate meta meta = generate_meta(backend, platform, path) @@ -50,7 +49,7 @@ def autocalibrate(runcard, folder, force, update): (path / META).write_text(json.dumps(meta, indent=4)) # allocate executor - executor = Executor.load(runcard, path, platform, qubits, update) + executor = Executor.load(runcard, path, platform, runcard.targets, update) # connect and initialize platform if platform is not None: @@ -58,7 +57,7 @@ def autocalibrate(runcard, folder, force, update): # run protocols for _ in executor.run(mode=ExecutionMode.autocalibration): - report = ReportBuilder(path, qubits, executor, meta, executor.history) + report = ReportBuilder(path, runcard.targets, executor, meta, executor.history) report.run(path) # meta needs to be updated after each report to show correct end-time e = datetime.datetime.now(datetime.timezone.utc) diff --git a/src/qibocal/cli/fit.py b/src/qibocal/cli/fit.py index df4891afe..b6f80817a 100644 --- a/src/qibocal/cli/fit.py +++ b/src/qibocal/cli/fit.py @@ -9,7 +9,7 @@ from ..auto.history import add_timings_to_meta from ..auto.mode import ExecutionMode from ..auto.runcard import Runcard -from .utils import META, RUNCARD, UPDATED_PLATFORM, create_qubits_dict +from .utils import META, RUNCARD, UPDATED_PLATFORM def fit(path, update): @@ -29,11 +29,10 @@ def fit(path, update): GlobalBackend.set_backend(backend=meta["backend"], platform=meta["platform"]) backend = GlobalBackend() platform = backend.platform - qubits = create_qubits_dict(qubits=runcard.qubits, platform=platform) # load executor executor = Executor.load( - runcard, path, update=update, platform=platform, qubits=qubits + runcard, path, update=update, platform=platform, targets=runcard.targets ) # perform post-processing diff --git a/src/qibocal/cli/report.py b/src/qibocal/cli/report.py index 287af6720..c60c68371 100644 --- a/src/qibocal/cli/report.py +++ b/src/qibocal/cli/report.py @@ -12,8 +12,6 @@ from qibocal.auto.runcard import Runcard from qibocal.auto.task import TaskId -from .utils import create_qubits_dict - META = "meta.json" RUNCARD = "runcard.yml" UPDATED_PLATFORM = "new_platform.yml" @@ -37,21 +35,20 @@ def report(path): GlobalBackend.set_backend(backend=meta["backend"], platform=meta["platform"]) backend = GlobalBackend() platform = backend.platform - qubits = create_qubits_dict(qubits=runcard.qubits, platform=platform) # load executor - executor = Executor.load(runcard, path, qubits=qubits) + executor = Executor.load(runcard, path, targets=runcard.targets) # produce html - builder = ReportBuilder(path, qubits, executor, meta) + builder = ReportBuilder(path, runcard.targets, executor, meta) builder.run(path) class ReportBuilder: """Builder to produce html report.""" - def __init__(self, path: Path, qubits, executor: Executor, metadata, history=None): + def __init__(self, path: Path, targets, executor: Executor, metadata, history=None): self.path = self.title = path - self.qubits = qubits + self.targets = targets self.executor = executor self.metadata = metadata self._history = history @@ -69,16 +66,16 @@ def routine_name(self, routine, iteration): name = routine.replace("_", " ").title() return f"{name} - {iteration}" - def routine_qubits(self, task_id: TaskId): - """Get local qubits parameter from Task if available otherwise use global one.""" - local_qubits = self.history[task_id].task.qubits - return local_qubits if len(local_qubits) > 0 else self.qubits + def routine_targets(self, task_id: TaskId): + """Get local targets parameter from Task if available otherwise use global one.""" + local_targets = self.history[task_id].task.targets + return local_targets if len(local_targets) > 0 else self.targets def single_qubit_plot(self, task_id: TaskId, qubit: QubitId): """Generate single qubit plot.""" node = self.history[task_id] figures, fitting_report = node.task.operation.report( - data=node.data, fit=node.results, qubit=qubit + data=node.data, fit=node.results, target=qubit ) with tempfile.NamedTemporaryFile(delete=False) as temp: html_list = [] diff --git a/src/qibocal/protocols/characterization/allxy/allxy.py b/src/qibocal/protocols/characterization/allxy/allxy.py index c9a0c6b84..dd14b7013 100644 --- a/src/qibocal/protocols/characterization/allxy/allxy.py +++ b/src/qibocal/protocols/characterization/allxy/allxy.py @@ -8,7 +8,7 @@ from qibolab.pulses import PulseSequence from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine @dataclass @@ -68,7 +68,7 @@ class AllXYData(Data): def _acquisition( params: AllXYParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> AllXYData: r""" Data acquisition for allXY experiment. @@ -87,7 +87,7 @@ def _acquisition( for gates in gatelist: sequences.append(PulseSequence()) all_ro_pulses.append({}) - for qubit in qubits: + 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 ) @@ -105,7 +105,7 @@ def _acquisition( for ig, (gates, ro_pulses) in enumerate(zip(gatelist, all_ro_pulses)): gate = "-".join(gates) - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: z_proj = 2 * results[serial][ig].probability(0) - 1 @@ -216,14 +216,14 @@ def _fit(_data: AllXYData) -> AllXYResults: # allXY -def _plot(data: AllXYData, qubit, fit: AllXYResults = None): +def _plot(data: AllXYData, target: QubitId, fit: AllXYResults = None): """Plotting function for allXY.""" figures = [] fitting_report = "" fig = go.Figure() - qubit_data = data[qubit] + qubit_data = data[target] fig.add_trace( go.Scatter( diff --git a/src/qibocal/protocols/characterization/allxy/allxy_drag_pulse_tuning.py b/src/qibocal/protocols/characterization/allxy/allxy_drag_pulse_tuning.py index a4ed737e9..df76e1ca1 100644 --- a/src/qibocal/protocols/characterization/allxy/allxy_drag_pulse_tuning.py +++ b/src/qibocal/protocols/characterization/allxy/allxy_drag_pulse_tuning.py @@ -9,7 +9,7 @@ from qibolab.pulses import PulseSequence from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from . import allxy @@ -51,7 +51,7 @@ def beta_params(self): def _acquisition( params: AllXYDragParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> AllXYDragData: r""" Data acquisition for allXY experiment varying beta. @@ -73,7 +73,7 @@ def _acquisition( # create a sequence of pulses ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: sequence, ro_pulses[qubit] = allxy.add_gate_pair_pulses_to_sequence( platform, gates, qubit, sequence, beta_param ) @@ -89,7 +89,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: z_proj = 2 * results[ro_pulses[qubit].serial].probability(0) - 1 # store the results gate = "-".join(gates) @@ -106,7 +106,7 @@ def _fit(_data: AllXYDragData) -> AllXYDragResults: return AllXYDragResults() -def _plot(data: AllXYDragData, qubit, fit: AllXYDragResults = None): +def _plot(data: AllXYDragData, target: QubitId, fit: AllXYDragResults = None): """Plotting function for allXYDrag.""" figures = [] @@ -116,7 +116,7 @@ def _plot(data: AllXYDragData, qubit, fit: AllXYDragResults = None): beta_params = data.beta_params for j, beta_param in enumerate(beta_params): - beta_param_data = data[qubit, beta_param] + beta_param_data = data[target, beta_param] fig.add_trace( go.Scatter( x=beta_param_data.gate, diff --git a/src/qibocal/protocols/characterization/allxy/drag_pulse_tuning.py b/src/qibocal/protocols/characterization/allxy/drag_pulse_tuning.py index 0e2e0b603..88c7cbd27 100644 --- a/src/qibocal/protocols/characterization/allxy/drag_pulse_tuning.py +++ b/src/qibocal/protocols/characterization/allxy/drag_pulse_tuning.py @@ -11,7 +11,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Qubits, Results, Routine +from qibocal.auto.operation import Data, Results, Routine from qibocal.config import log from ..utils import table_dict, table_html @@ -54,7 +54,7 @@ class DragPulseTuningData(Data): def _acquisition( params: DragPulseTuningParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> DragPulseTuningData: r""" Data acquisition for drag pulse tuning experiment. @@ -77,7 +77,7 @@ def _acquisition( ro_pulses = {} seq1 = PulseSequence() seq2 = PulseSequence() - for qubit in qubits: + for qubit in targets: # drag pulse RX(pi/2) RX90_drag_pulse = platform.create_RX90_drag_pulse( qubit, start=0, beta=beta_param @@ -135,7 +135,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: r1 = result1[ro_pulses[qubit].serial] r2 = result2[ro_pulses[qubit].serial] # store the results @@ -192,7 +192,7 @@ def _fit(data: DragPulseTuningData) -> DragPulseTuningResults: return DragPulseTuningResults(betas_optimal, fitted_parameters) -def _plot(data: DragPulseTuningData, qubit, fit: DragPulseTuningResults): +def _plot(data: DragPulseTuningData, target: QubitId, fit: DragPulseTuningResults): """Plotting function for DragPulseTuning.""" figures = [] @@ -204,7 +204,7 @@ def _plot(data: DragPulseTuningData, qubit, fit: DragPulseTuningResults): horizontal_spacing=0.01, vertical_spacing=0.01, ) - qubit_data = data[qubit] + qubit_data = data[target] fig.add_trace( go.Scatter( x=qubit_data.beta, @@ -229,17 +229,17 @@ def _plot(data: DragPulseTuningData, qubit, fit: DragPulseTuningResults): x=beta_range, y=drag_fit( beta_range, - float(fit.fitted_parameters[qubit][0]), - float(fit.fitted_parameters[qubit][1]), - float(fit.fitted_parameters[qubit][2]), - float(fit.fitted_parameters[qubit][3]), + float(fit.fitted_parameters[target][0]), + float(fit.fitted_parameters[target][1]), + float(fit.fitted_parameters[target][2]), + float(fit.fitted_parameters[target][3]), ), name="Fit", line=go.scatter.Line(dash="dot"), ), ) fitting_report = table_html( - table_dict(qubit, "Optimal Beta Param", np.round(fit.betas[qubit], 4)) + table_dict(target, "Optimal Beta Param", np.round(fit.betas[target], 4)) ) fig.update_layout( @@ -253,8 +253,8 @@ def _plot(data: DragPulseTuningData, qubit, fit: DragPulseTuningResults): return figures, fitting_report -def _update(results: DragPulseTuningResults, platform: Platform, qubit: QubitId): - update.drag_pulse_beta(results.betas[qubit], platform, qubit) +def _update(results: DragPulseTuningResults, platform: Platform, target: QubitId): + update.drag_pulse_beta(results.betas[target], platform, target) drag_pulse_tuning = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/classification.py b/src/qibocal/protocols/characterization/classification.py index 9962ac608..451047f0e 100644 --- a/src/qibocal/protocols/characterization/classification.py +++ b/src/qibocal/protocols/characterization/classification.py @@ -14,14 +14,7 @@ from sklearn.metrics import roc_auc_score, roc_curve from qibocal import update -from qibocal.auto.operation import ( - RESULTSFILE, - Data, - Parameters, - Qubits, - Results, - Routine, -) +from qibocal.auto.operation import RESULTSFILE, Data, Parameters, Results, Routine from qibocal.auto.serialize import serialize from qibocal.fitting.classifier import run from qibocal.protocols.characterization.utils import ( @@ -137,7 +130,7 @@ def save(self, path): def _acquisition( params: SingleShotClassificationParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> SingleShotClassificationData: """ Args: @@ -180,7 +173,7 @@ def _acquisition( sequence = PulseSequence() RX_pulses = {} ro_pulses = {} - for qubit in qubits: + for qubit in targets: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=RX_pulses[qubit].finish @@ -195,7 +188,7 @@ def _acquisition( data = SingleShotClassificationData( nshots=params.nshots, qubit_frequencies={ - qubit: platform.qubits[qubit].drive_frequency for qubit in qubits + qubit: platform.qubits[qubit].drive_frequency for qubit in targets }, classifiers_list=params.classifiers_list, savedir=params.savedir, @@ -215,7 +208,7 @@ def _acquisition( ] for ig, (state, ro_pulses) in enumerate(zip([0, 1], all_ro_pulses)): - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: result = results[serial][ig] @@ -311,14 +304,16 @@ def _fit(data: SingleShotClassificationData) -> SingleShotClassificationResults: def _plot( - data: SingleShotClassificationData, qubit, fit: SingleShotClassificationResults + data: SingleShotClassificationData, + target: QubitId, + fit: SingleShotClassificationResults, ): fitting_report = "" models_name = data.classifiers_list - figures = plot_results(data, qubit, 2, fit) + figures = plot_results(data, target, 2, fit) if fit is not None: - y_test = fit.y_tests[qubit] - y_pred = fit.y_preds[qubit] + y_test = fit.y_tests[target] + y_pred = fit.y_preds[target] if len(models_name) != 1: # Evaluate the ROC curve @@ -327,7 +322,7 @@ def _plot( type="line", line=dict(dash="dash"), x0=0.0, x1=1.0, y0=0.0, y1=1.0 ) for i, model in enumerate(models_name): - y_pred = fit.y_preds[qubit][i] + y_pred = fit.y_preds[target][i] fpr, tpr, _ = roc_curve(y_test, y_pred) auc_score = roc_auc_score(y_test, y_pred) name = f"{model} (AUC={auc_score:.2f})" @@ -359,7 +354,7 @@ def _plot( if "qubit_fit" in models_name: fitting_report = table_html( table_dict( - qubit, + target, [ "Average State 0", "Average State 1", @@ -370,14 +365,14 @@ def _plot( "Effective Qubit Temperature [K]", ], [ - np.round(fit.mean_gnd_states[qubit], 3), - np.round(fit.mean_exc_states[qubit], 3), - np.round(fit.rotation_angle[qubit], 3), - np.round(fit.threshold[qubit], 6), - np.round(fit.fidelity[qubit], 3), - np.round(fit.assignment_fidelity[qubit], 3), + np.round(fit.mean_gnd_states[target], 3), + np.round(fit.mean_exc_states[target], 3), + np.round(fit.rotation_angle[target], 3), + np.round(fit.threshold[target], 6), + np.round(fit.fidelity[target], 3), + np.round(fit.assignment_fidelity[target], 3), format_error_single_cell( - round_report([fit.effective_temperature[qubit]]) + round_report([fit.effective_temperature[target]]) ), ], ) @@ -387,14 +382,14 @@ def _plot( def _update( - results: SingleShotClassificationResults, platform: Platform, qubit: QubitId + results: SingleShotClassificationResults, platform: Platform, target: QubitId ): - update.iq_angle(results.rotation_angle[qubit], platform, qubit) - update.threshold(results.threshold[qubit], platform, qubit) - update.mean_gnd_states(results.mean_gnd_states[qubit], platform, qubit) - update.mean_exc_states(results.mean_exc_states[qubit], platform, qubit) - update.readout_fidelity(results.fidelity[qubit], platform, qubit) - update.assignment_fidelity(results.assignment_fidelity[qubit], platform, qubit) + update.iq_angle(results.rotation_angle[target], platform, target) + update.threshold(results.threshold[target], platform, target) + update.mean_gnd_states(results.mean_gnd_states[target], platform, target) + update.mean_exc_states(results.mean_exc_states[target], platform, target) + update.readout_fidelity(results.fidelity[target], platform, target) + update.assignment_fidelity(results.assignment_fidelity[target], platform, target) single_shot_classification = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/spin_echo.py b/src/qibocal/protocols/characterization/coherence/spin_echo.py index cacab93fa..d528908ad 100644 --- a/src/qibocal/protocols/characterization/coherence/spin_echo.py +++ b/src/qibocal/protocols/characterization/coherence/spin_echo.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from ..utils import chi2_reduced, table_dict, table_html from . import t1 @@ -49,7 +49,7 @@ class SpinEchoData(t1.T1Data): def _acquisition( params: SpinEchoParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> SpinEchoData: """Data acquisition for SpinEcho""" # create a sequence of pulses for the experiment: @@ -59,7 +59,7 @@ def _acquisition( RX_pulses = {} RX90_pulses2 = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX_pulses[qubit] = platform.create_RX_pulse( qubit, start=RX90_pulses1[qubit].finish @@ -84,12 +84,12 @@ def _acquisition( ) data = SpinEchoData() - probs = {qubit: [] for qubit in qubits} + probs = {qubit: [] for qubit in targets} # sweep the parameter for wait in ro_wait_range: # save data as often as defined by points - for qubit in qubits: + for qubit in targets: RX_pulses[qubit].start = RX90_pulses1[qubit].finish + wait RX90_pulses2[qubit].start = RX_pulses[qubit].finish + wait ro_pulses[qubit].start = RX90_pulses2[qubit].finish @@ -105,11 +105,11 @@ def _acquisition( ), ) - for qubit in qubits: + for qubit in targets: prob = results[ro_pulses[qubit].serial].probability(state=0) probs[qubit].append(prob) - for qubit in qubits: + for qubit in targets: errors = [np.sqrt(prob * (1 - prob) / params.nshots) for prob in probs[qubit]] data.register_qubit( t1.CoherenceProbType, @@ -138,14 +138,14 @@ def _fit(data: SpinEchoData) -> SpinEchoResults: return SpinEchoResults(t2Echos, fitted_parameters, chi2) -def _plot(data: SpinEchoData, qubit, fit: SpinEchoResults = None): +def _plot(data: SpinEchoData, target: QubitId, fit: SpinEchoResults = None): """Plotting for SpinEcho""" figures = [] # iterate over multiple data folders fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] waits = qubit_data.wait probs = qubit_data.prob error_bars = qubit_data.error @@ -180,7 +180,7 @@ def _plot(data: SpinEchoData, qubit, fit: SpinEchoResults = None): max(waits), 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( @@ -192,9 +192,9 @@ def _plot(data: SpinEchoData, qubit, fit: SpinEchoResults = None): ) fitting_report = table_html( table_dict( - qubit, + target, ["T2 Spin Echo [ns]", "chi2 reduced"], - [fit.t2_spin_echo[qubit], fit.chi2[qubit]], + [fit.t2_spin_echo[target], fit.chi2[target]], display_error=True, ) ) @@ -210,8 +210,8 @@ def _plot(data: SpinEchoData, qubit, fit: SpinEchoResults = None): return figures, fitting_report -def _update(results: SpinEchoResults, platform: Platform, qubit: QubitId): - update.t2_spin_echo(results.t2_spin_echo[qubit], platform, qubit) +def _update(results: SpinEchoResults, platform: Platform, target: QubitId): + update.t2_spin_echo(results.t2_spin_echo[target], platform, target) spin_echo = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/spin_echo_sequence.py b/src/qibocal/protocols/characterization/coherence/spin_echo_sequence.py index 6bc367b59..1bf1e6506 100644 --- a/src/qibocal/protocols/characterization/coherence/spin_echo_sequence.py +++ b/src/qibocal/protocols/characterization/coherence/spin_echo_sequence.py @@ -8,7 +8,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from ..utils import table_dict, table_html from . import spin_echo @@ -33,7 +33,7 @@ class SpinEchoSignalData(T1SignalData): def _acquisition( params: SpinEchoSignalParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> SpinEchoSignalData: """Data acquisition for SpinEcho""" # create a sequence of pulses for the experiment: @@ -43,7 +43,7 @@ def _acquisition( RX_pulses = {} RX90_pulses2 = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX_pulses[qubit] = platform.create_RX_pulse( qubit, start=RX90_pulses1[qubit].finish @@ -73,7 +73,7 @@ def _acquisition( for wait in ro_wait_range: # save data as often as defined by points - for qubit in qubits: + for qubit in targets: RX_pulses[qubit].start = RX90_pulses1[qubit].finish + wait RX90_pulses2[qubit].start = RX_pulses[qubit].finish + wait ro_pulses[qubit].start = RX90_pulses2[qubit].finish @@ -89,7 +89,7 @@ def _acquisition( ), ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( CoherenceType, @@ -110,7 +110,7 @@ def _fit(data: SpinEchoSignalData) -> SpinEchoSignalResults: return SpinEchoSignalResults(t2Echos, fitted_parameters) -def _plot(data: SpinEchoSignalData, qubit, fit: SpinEchoSignalResults = None): +def _plot(data: SpinEchoSignalData, target: QubitId, fit: SpinEchoSignalResults = None): """Plotting for SpinEcho""" figures = [] @@ -119,7 +119,7 @@ def _plot(data: SpinEchoSignalData, qubit, fit: SpinEchoSignalResults = None): # iterate over multiple data folders fitting_report = None - qubit_data = data[qubit] + qubit_data = data[target] waits = qubit_data.wait fig.add_trace( @@ -140,7 +140,7 @@ def _plot(data: SpinEchoSignalData, qubit, fit: SpinEchoSignalResults = None): max(waits), 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( @@ -152,7 +152,7 @@ def _plot(data: SpinEchoSignalData, qubit, fit: SpinEchoSignalResults = None): ) fitting_report = table_html( - table_dict(qubit, "T2 Spin Echo [ns]", np.round(fit.t2_spin_echo[qubit])) + table_dict(target, "T2 Spin Echo [ns]", np.round(fit.t2_spin_echo[target])) ) fig.update_layout( @@ -166,8 +166,8 @@ def _plot(data: SpinEchoSignalData, qubit, fit: SpinEchoSignalResults = None): return figures, fitting_report -def _update(results: SpinEchoSignalResults, platform: Platform, qubit: QubitId): - update.t2_spin_echo(results.t2_spin_echo[qubit], platform, qubit) +def _update(results: SpinEchoSignalResults, platform: Platform, target: QubitId): + update.t2_spin_echo(results.t2_spin_echo[target], platform, target) spin_echo_sequence = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/t1.py b/src/qibocal/protocols/characterization/coherence/t1.py index 317a5469c..7bb2b2119 100644 --- a/src/qibocal/protocols/characterization/coherence/t1.py +++ b/src/qibocal/protocols/characterization/coherence/t1.py @@ -11,7 +11,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from ..utils import chi2_reduced, table_dict, table_html from . import utils @@ -60,7 +60,9 @@ class T1Data(Data): """Raw data acquired.""" -def _acquisition(params: T1Parameters, platform: Platform, qubits: Qubits) -> T1Data: +def _acquisition( + params: T1Parameters, platform: Platform, targets: list[QubitId] +) -> T1Data: r"""Data acquisition for T1 experiment. In a T1 experiment, we measure an excited qubit after a delay. Due to decoherence processes (e.g. amplitude damping channel), it is possible that, at the time of measurement, after the delay, @@ -71,7 +73,7 @@ def _acquisition(params: T1Parameters, platform: Platform, qubits: Qubits) -> T1 Args: params: platform (Platform): Qibolab platform object - qubits (list): list of target qubits to perform the action + targets (list): list of target qubits to perform the action delay_before_readout_start (int): Initial time delay before ReadOut delay_before_readout_end (list): Maximum time delay before ReadOut delay_before_readout_step (int): Scan range step for the delay before ReadOut @@ -84,7 +86,7 @@ def _acquisition(params: T1Parameters, platform: Platform, qubits: Qubits) -> T1 qd_pulses = {} ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=qd_pulses[qubit].duration @@ -103,7 +105,7 @@ def _acquisition(params: T1Parameters, platform: Platform, qubits: Qubits) -> T1 sweeper = Sweeper( Parameter.start, ro_wait_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -122,7 +124,7 @@ def _acquisition(params: T1Parameters, platform: Platform, qubits: Qubits) -> T1 sweeper, ) - for qubit in qubits: + for qubit in targets: probs = results[ro_pulses[qubit].serial].probability(state=1) errors = np.sqrt(probs * (1 - probs) / params.nshots) data.register_qubit( @@ -158,12 +160,12 @@ def _fit(data: T1Data) -> T1Results: return T1Results(t1s, fitted_parameters, chi2) -def _plot(data: T1Data, qubit, fit: T1Results = None): +def _plot(data: T1Data, target: QubitId, fit: T1Results = None): """Plotting function for T1 experiment.""" figures = [] fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] waits = qubit_data.wait probs = qubit_data.prob error_bars = qubit_data.error @@ -198,7 +200,7 @@ def _plot(data: T1Data, qubit, fit: T1Results = None): 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -209,12 +211,12 @@ def _plot(data: T1Data, qubit, fit: T1Results = None): ) fitting_report = table_html( table_dict( - qubit, + target, [ "T1 [ns]", "chi2 reduced", ], - [fit.t1[qubit], fit.chi2[qubit]], + [fit.t1[target], fit.chi2[target]], display_error=True, ) ) @@ -230,8 +232,8 @@ def _plot(data: T1Data, qubit, fit: T1Results = None): return figures, fitting_report -def _update(results: T1Results, platform: Platform, qubit: QubitId): - update.t1(results.t1[qubit], platform, qubit) +def _update(results: T1Results, platform: Platform, target: QubitId): + update.t1(results.t1[target], platform, target) t1 = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/t1_sequences.py b/src/qibocal/protocols/characterization/coherence/t1_sequences.py index 3167be79f..f665946fa 100644 --- a/src/qibocal/protocols/characterization/coherence/t1_sequences.py +++ b/src/qibocal/protocols/characterization/coherence/t1_sequences.py @@ -2,14 +2,15 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitId -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from . import t1, t1_signal def _acquisition( - params: t1_signal.T1SignalParameters, platform: Platform, qubits: Qubits + params: t1_signal.T1SignalParameters, platform: Platform, targets: list[QubitId] ) -> t1_signal.T1SignalData: r"""Data acquisition for T1 experiment. In a T1 experiment, we measure an excited qubit after a delay. Due to decoherence processes @@ -21,7 +22,7 @@ def _acquisition( Args: params: platform (Platform): Qibolab platform object - qubits (list): list of target qubits to perform the action + targets (list): list of target qubits to perform the action delay_before_readout_start (int): Initial time delay before ReadOut delay_before_readout_end (list): Maximum time delay before ReadOut delay_before_readout_step (int): Scan range step for the delay before ReadOut @@ -34,7 +35,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=qd_pulses[qubit].duration @@ -55,7 +56,7 @@ def _acquisition( # repeat the experiment as many times as defined by software_averages # sweep the parameter for wait in ro_wait_range: - for qubit in qubits: + for qubit in targets: ro_pulses[qubit].start = qd_pulses[qubit].duration + wait # execute the pulse sequence @@ -68,7 +69,7 @@ def _acquisition( averaging_mode=AveragingMode.CYCLIC, ), ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( t1_signal.CoherenceType, diff --git a/src/qibocal/protocols/characterization/coherence/t1_signal.py b/src/qibocal/protocols/characterization/coherence/t1_signal.py index d1bbf10d1..0c8074968 100644 --- a/src/qibocal/protocols/characterization/coherence/t1_signal.py +++ b/src/qibocal/protocols/characterization/coherence/t1_signal.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Data, Qubits, Routine +from qibocal.auto.operation import Data, Routine from ..utils import table_dict, table_html from . import t1, utils @@ -40,7 +40,7 @@ class T1SignalData(Data): def _acquisition( - params: T1SignalParameters, platform: Platform, qubits: Qubits + params: T1SignalParameters, platform: Platform, targets: list[QubitId] ) -> T1SignalData: r"""Data acquisition for T1 experiment. In a T1 experiment, we measure an excited qubit after a delay. Due to decoherence processes @@ -52,7 +52,7 @@ def _acquisition( Args: params: platform (Platform): Qibolab platform object - qubits (list): list of target qubits to perform the action + targets (list): list of target qubits to perform the action delay_before_readout_start (int): Initial time delay before ReadOut delay_before_readout_end (list): Maximum time delay before ReadOut delay_before_readout_step (int): Scan range step for the delay before ReadOut @@ -65,7 +65,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=qd_pulses[qubit].duration @@ -84,7 +84,7 @@ def _acquisition( sweeper = Sweeper( Parameter.start, ro_wait_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -103,7 +103,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( CoherenceType, @@ -127,14 +127,14 @@ def _fit(data: T1SignalData) -> T1SignalResults: return T1SignalResults(t1s, fitted_parameters) -def _plot(data: T1SignalData, qubit, fit: T1SignalResults = None): +def _plot(data: T1SignalData, target: QubitId, fit: T1SignalResults = None): """Plotting function for T1 experiment.""" figures = [] fig = go.Figure() fitting_report = None - qubit_data = data[qubit] + qubit_data = data[target] waits = qubit_data.wait fig.add_trace( @@ -155,7 +155,7 @@ def _plot(data: T1SignalData, qubit, fit: T1SignalResults = None): 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -165,7 +165,7 @@ def _plot(data: T1SignalData, qubit, fit: T1SignalResults = None): ) ) fitting_report = table_html( - table_dict(qubit, "T1 [ns]", np.round(fit.t1[qubit])) + table_dict(target, "T1 [ns]", np.round(fit.t1[target])) ) # last part diff --git a/src/qibocal/protocols/characterization/coherence/t2.py b/src/qibocal/protocols/characterization/coherence/t2.py index c8346be00..b46b3cf0e 100644 --- a/src/qibocal/protocols/characterization/coherence/t2.py +++ b/src/qibocal/protocols/characterization/coherence/t2.py @@ -10,7 +10,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from ..utils import chi2_reduced, table_dict, table_html from . import t1, utils @@ -49,7 +49,7 @@ class T2Data(t1.T1Data): def _acquisition( params: T2Parameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> T2Data: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -58,7 +58,7 @@ def _acquisition( RX90_pulses1 = {} RX90_pulses2 = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -84,7 +84,7 @@ def _acquisition( sweeper = Sweeper( Parameter.start, waits, - [RX90_pulses2[qubit] for qubit in qubits], + [RX90_pulses2[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -100,7 +100,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: probs = results[ro_pulses[qubit].serial].probability(state=1) errors = np.sqrt(probs * (1 - probs) / params.nshots) data.register_qubit( @@ -130,12 +130,12 @@ def _fit(data: T2Data) -> T2Results: return T2Results(t2s, fitted_parameters, chi2) -def _plot(data: T2Data, qubit, fit: T2Results = None): +def _plot(data: T2Data, target: QubitId, fit: T2Results = None): """Plotting function for Ramsey Experiment.""" figures = [] fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] waits = qubit_data.wait probs = qubit_data.prob error_bars = qubit_data.error @@ -171,7 +171,7 @@ def _plot(data: T2Data, qubit, fit: T2Results = None): 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -185,12 +185,12 @@ def _plot(data: T2Data, qubit, fit: T2Results = None): ) fitting_report = table_html( table_dict( - qubit, + target, [ "T2 [ns]", "chi2 reduced", ], - [fit.t2[qubit], fit.chi2[qubit]], + [fit.t2[target], fit.chi2[target]], display_error=True, ) ) @@ -205,8 +205,8 @@ def _plot(data: T2Data, qubit, fit: T2Results = None): return figures, fitting_report -def _update(results: T2Results, platform: Platform, qubit: QubitId): - update.t2(results.t2[qubit], platform, qubit) +def _update(results: T2Results, platform: Platform, target: QubitId): + update.t2(results.t2[target], platform, target) t2 = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/t2_sequences.py b/src/qibocal/protocols/characterization/coherence/t2_sequences.py index f70a7c1e9..74a2ee0a0 100644 --- a/src/qibocal/protocols/characterization/coherence/t2_sequences.py +++ b/src/qibocal/protocols/characterization/coherence/t2_sequences.py @@ -2,8 +2,9 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitId -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from .t1_signal import CoherenceType from .t2_signal import T2SignalData, T2SignalParameters, _fit, _plot, _update @@ -12,7 +13,7 @@ def _acquisition( params: T2SignalParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> T2SignalData: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -21,7 +22,7 @@ def _acquisition( RX90_pulses1 = {} RX90_pulses2 = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -46,7 +47,7 @@ def _acquisition( # sweep the parameter for wait in waits: - for qubit in qubits: + for qubit in targets: RX90_pulses2[qubit].start = RX90_pulses1[qubit].finish + wait ro_pulses[qubit].start = RX90_pulses2[qubit].finish @@ -60,7 +61,7 @@ def _acquisition( averaging_mode=AveragingMode.CYCLIC, ), ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( CoherenceType, diff --git a/src/qibocal/protocols/characterization/coherence/t2_signal.py b/src/qibocal/protocols/characterization/coherence/t2_signal.py index 2a7b9f1f5..ca11af9da 100644 --- a/src/qibocal/protocols/characterization/coherence/t2_signal.py +++ b/src/qibocal/protocols/characterization/coherence/t2_signal.py @@ -9,7 +9,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from ..utils import table_dict, table_html from . import t1_signal, t2, utils @@ -32,7 +32,7 @@ class T2SignalData(t1_signal.T1SignalData): def _acquisition( params: T2SignalParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> T2SignalData: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -41,7 +41,7 @@ def _acquisition( RX90_pulses1 = {} RX90_pulses2 = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -67,7 +67,7 @@ def _acquisition( sweeper = Sweeper( Parameter.start, waits, - [RX90_pulses2[qubit] for qubit in qubits], + [RX90_pulses2[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -83,7 +83,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( t1_signal.CoherenceType, @@ -103,14 +103,14 @@ def _fit(data: T2SignalData) -> T2SignalResults: return T2SignalResults(t2s, fitted_parameters) -def _plot(data: T2SignalData, qubit, fit: T2SignalResults = None): +def _plot(data: T2SignalData, target: QubitId, fit: T2SignalResults = None): """Plotting function for Ramsey Experiment.""" figures = [] fig = go.Figure() fitting_report = None - qubit_data = data[qubit] + qubit_data = data[target] fig.add_trace( go.Scatter( @@ -131,7 +131,7 @@ def _plot(data: T2SignalData, qubit, fit: T2SignalResults = None): 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -144,7 +144,7 @@ def _plot(data: T2SignalData, qubit, fit: T2SignalResults = None): ) ) fitting_report = table_html( - table_dict(qubit, "T2 [ns]", np.round(fit.t2[qubit])) + table_dict(target, "T2 [ns]", np.round(fit.t2[target])) ) fig.update_layout( @@ -158,8 +158,8 @@ def _plot(data: T2SignalData, qubit, fit: T2SignalResults = None): return figures, fitting_report -def _update(results: T2SignalResults, platform: Platform, qubit: QubitId): - update.t2(results.t2[qubit], platform, qubit) +def _update(results: T2SignalResults, platform: Platform, target: QubitId): + update.t2(results.t2[target], platform, target) t2_signal = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/zeno.py b/src/qibocal/protocols/characterization/coherence/zeno.py index 703ce13ff..62aeb9653 100644 --- a/src/qibocal/protocols/characterization/coherence/zeno.py +++ b/src/qibocal/protocols/characterization/coherence/zeno.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from ..utils import chi2_reduced, table_dict, table_html from . import t1, utils @@ -44,7 +44,7 @@ class ZenoResults(Results): def _acquisition( params: ZenoParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ZenoData: """ In a T1_Zeno experiment, we measure an excited qubit repeatedly. Due to decoherence processes, @@ -60,7 +60,7 @@ def _acquisition( RX_pulses = {} ro_pulses = {} ro_pulse_duration = {} - for qubit in qubits: + for qubit in targets: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) sequence.add(RX_pulses[qubit]) start = RX_pulses[qubit].finish @@ -87,8 +87,8 @@ def _acquisition( ) # retrieve and store the results for every qubit - probs = {qubit: [] for qubit in qubits} - for qubit in qubits: + probs = {qubit: [] for qubit in targets} + for qubit in targets: for ro_pulse in ro_pulses[qubit]: probs[qubit].append(results[ro_pulse.serial].probability(state=1)) errors = [np.sqrt(prob * (1 - prob) / params.nshots) for prob in probs[qubit]] @@ -127,12 +127,12 @@ def _fit(data: ZenoData) -> ZenoResults: return ZenoResults(t1s, fitted_parameters, chi2) -def _plot(data: ZenoData, fit: ZenoResults, qubit): +def _plot(data: ZenoData, fit: ZenoResults, target: QubitId): """Plotting function for T1 experiment.""" figures = [] fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] probs = qubit_data.prob error_bars = qubit_data.error readouts = np.arange(1, len(qubit_data.prob) + 1) @@ -167,7 +167,7 @@ def _plot(data: ZenoData, fit: ZenoResults, qubit): max(readouts), 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -178,12 +178,12 @@ def _plot(data: ZenoData, fit: ZenoResults, qubit): ) fitting_report = table_html( table_dict( - qubit, + target, ["T1 [ns]", "Readout Pulse [ns]", "chi2 reduced"], [ - fit.zeno_t1[qubit], - np.array(fit.zeno_t1[qubit]) * data.readout_duration[qubit], - fit.chi2[qubit], + fit.zeno_t1[target], + np.array(fit.zeno_t1[target]) * data.readout_duration[target], + fit.chi2[target], ], display_error=True, ) @@ -202,8 +202,8 @@ def _plot(data: ZenoData, fit: ZenoResults, qubit): return figures, fitting_report -def _update(results: ZenoResults, platform: Platform, qubit: QubitId): - update.t1(results.zeno_t1[qubit], platform, qubit) +def _update(results: ZenoResults, platform: Platform, target: QubitId): + update.t1(results.zeno_t1[target], platform, target) zeno = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/coherence/zeno_signal.py b/src/qibocal/protocols/characterization/coherence/zeno_signal.py index 95c4341a1..7cd2209b1 100644 --- a/src/qibocal/protocols/characterization/coherence/zeno_signal.py +++ b/src/qibocal/protocols/characterization/coherence/zeno_signal.py @@ -10,7 +10,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from ..utils import table_dict, table_html from . import utils @@ -63,7 +63,7 @@ class ZenoResults(Results): def _acquisition( params: ZenoParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ZenoData: """ In a T1_Zeno experiment, we measure an excited qubit repeatedly. Due to decoherence processes, @@ -79,7 +79,7 @@ def _acquisition( RX_pulses = {} ro_pulses = {} ro_pulse_duration = {} - for qubit in qubits: + for qubit in targets: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) sequence.add(RX_pulses[qubit]) start = RX_pulses[qubit].finish @@ -106,7 +106,7 @@ def _acquisition( ) # retrieve and store the results for every qubit - for qubit in qubits: + for qubit in targets: for ro_pulse in ro_pulses[qubit]: result = results[ro_pulse.serial] data.register_qubit( @@ -129,13 +129,13 @@ def _fit(data: ZenoData) -> ZenoResults: return ZenoResults(t1s, fitted_parameters) -def _plot(data: ZenoData, fit: ZenoResults, qubit): +def _plot(data: ZenoData, fit: ZenoResults, target: QubitId): """Plotting function for T1 experiment.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] readouts = np.arange(1, len(qubit_data.signal) + 1) fig.add_trace( @@ -156,7 +156,7 @@ def _plot(data: ZenoData, fit: ZenoResults, qubit): max(readouts), 2 * len(qubit_data), ) - params = fit.fitted_parameters[qubit] + params = fit.fitted_parameters[target] fig.add_trace( go.Scatter( x=waitrange, @@ -167,11 +167,11 @@ def _plot(data: ZenoData, fit: ZenoResults, qubit): ) fitting_report = table_html( table_dict( - qubit, + target, ["T1", "Readout Pulse"], [ - np.round(fit.zeno_t1[qubit]), - np.round(fit.zeno_t1[qubit] * data.readout_duration[qubit]), + np.round(fit.zeno_t1[target]), + np.round(fit.zeno_t1[target] * data.readout_duration[target]), ], ) ) diff --git a/src/qibocal/protocols/characterization/couplers/coupler_qubit_spectroscopy.py b/src/qibocal/protocols/characterization/couplers/coupler_qubit_spectroscopy.py index 4e88306ca..854b07c16 100644 --- a/src/qibocal/protocols/characterization/couplers/coupler_qubit_spectroscopy.py +++ b/src/qibocal/protocols/characterization/couplers/coupler_qubit_spectroscopy.py @@ -4,9 +4,10 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitPairId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from ..two_qubit_interaction.utils import order_pair from .coupler_resonator_spectroscopy import _fit, _plot, _update @@ -19,7 +20,9 @@ class CouplerSpectroscopyParametersQubit(CouplerSpectroscopyParameters): def _acquisition( - params: CouplerSpectroscopyParametersQubit, platform: Platform, qubits: Qubits + params: CouplerSpectroscopyParametersQubit, + platform: Platform, + targets: list[QubitPairId], ) -> CouplerSpectroscopyData: """ Data acquisition for CouplerQubit spectroscopy. @@ -43,7 +46,7 @@ def _acquisition( ro_pulses = {} qd_pulses = {} couplers = [] - for i, pair in enumerate(qubits): + for i, pair in enumerate(targets): qubit = platform.qubits[params.measured_qubits[i]].name # TODO: Qubit pair patch ordered_pair = order_pair(pair, platform.qubits) @@ -103,7 +106,7 @@ def _acquisition( ) # retrieve the results for every qubit - for i, pair in enumerate(qubits): + for i, pair in enumerate(targets): # TODO: May measure both qubits on the pair qubit = platform.qubits[params.measured_qubits[i]].name result = results[ro_pulses[qubit].serial] diff --git a/src/qibocal/protocols/characterization/couplers/coupler_resonator_spectroscopy.py b/src/qibocal/protocols/characterization/couplers/coupler_resonator_spectroscopy.py index fca7f0ba4..26232af0c 100644 --- a/src/qibocal/protocols/characterization/couplers/coupler_resonator_spectroscopy.py +++ b/src/qibocal/protocols/characterization/couplers/coupler_resonator_spectroscopy.py @@ -4,10 +4,10 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence -from qibolab.qubits import QubitId +from qibolab.qubits import QubitPairId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from ..flux_dependence.utils import flux_dependence_plot from ..two_qubit_interaction.utils import order_pair @@ -24,7 +24,9 @@ class CouplerSpectroscopyParametersResonator(CouplerSpectroscopyParameters): def _acquisition( - params: CouplerSpectroscopyParametersResonator, platform: Platform, qubits: Qubits + params: CouplerSpectroscopyParametersResonator, + platform: Platform, + targets: list[QubitPairId], ) -> CouplerSpectroscopyData: """ Data acquisition for CouplerResonator spectroscopy. @@ -48,8 +50,7 @@ def _acquisition( ro_pulses = {} fx_pulses = {} couplers = [] - - for i, pair in enumerate(qubits): + for i, pair in enumerate(targets): qubit = platform.qubits[params.measured_qubits[i]].name # TODO: Qubit pair patch ordered_pair = order_pair(pair, platform.qubits) @@ -107,7 +108,7 @@ def _acquisition( ) # retrieve the results for every qubit - for i, pair in enumerate(qubits): + for i, pair in enumerate(targets): # TODO: May measure both qubits on the pair qubit = platform.qubits[params.measured_qubits[i]].name result = results[ro_pulses[qubit].serial] @@ -154,14 +155,14 @@ def _fit(data: CouplerSpectroscopyData) -> CouplerSpectroscopyResults: def _plot( data: CouplerSpectroscopyData, - qubit, + target: QubitPairId, fit: CouplerSpectroscopyResults, ): """ We may want to measure both qubits on the pair, that will require a different plotting that takes both. """ - qubit_pair = qubit # TODO: Patch for 2q gate routines + qubit_pair = target # TODO: Patch for 2q gate routines for qubit in qubit_pair: if qubit in data.data.keys(): @@ -177,7 +178,9 @@ def _plot( return [fig], "" -def _update(results: CouplerSpectroscopyResults, platform: Platform, qubit: QubitId): +def _update( + results: CouplerSpectroscopyResults, platform: Platform, target: QubitPairId +): pass diff --git a/src/qibocal/protocols/characterization/dispersive_shift.py b/src/qibocal/protocols/characterization/dispersive_shift.py index 1cced098a..00114ed23 100644 --- a/src/qibocal/protocols/characterization/dispersive_shift.py +++ b/src/qibocal/protocols/characterization/dispersive_shift.py @@ -11,7 +11,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.utils import ( HZ_TO_GHZ, lorentzian, @@ -79,7 +79,7 @@ class DispersiveShiftData(Data): def _acquisition( - params: DispersiveShiftParameters, platform: Platform, qubits: Qubits + params: DispersiveShiftParameters, platform: Platform, targets: list[QubitId] ) -> DispersiveShiftData: r""" Data acquisition for dispersive shift experiment. @@ -89,7 +89,7 @@ def _acquisition( Args: params (DispersiveShiftParameters): experiment's parameters platform (Platform): Qibolab platform object - qubits (dict): list of target qubits to perform the action + targets (list): list of target qubits to perform the action """ @@ -102,7 +102,7 @@ def _acquisition( sequence_1 = PulseSequence() ro_pulses = {} qd_pulses = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=qd_pulses[qubit].duration @@ -121,7 +121,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[ro_pulses[qubit] for qubit in qubits], + pulses=[ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -148,7 +148,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: for i, results in enumerate([results_0, results_1]): result = results[ro_pulses[qubit].serial] # store the results @@ -211,7 +211,7 @@ def _fit(data: DispersiveShiftData) -> DispersiveShiftResults: ) -def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): +def _plot(data: DispersiveShiftData, target: QubitId, fit: DispersiveShiftResults): """Plotting function for dispersive shift.""" figures = [] fig = make_subplots( @@ -228,8 +228,8 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): fitting_report = "" - data_0 = data[qubit, 0] - data_1 = data[qubit, 1] + data_0 = data[target, 0] + data_1 = data[target, 1] fit_data_0 = fit.state_zero if fit is not None else None fit_data_1 = fit.state_one if fit is not None else None @@ -279,7 +279,7 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): if i == 0 else "fitted_parameters_state_one" ) - ][qubit] + ][target] fig.add_trace( go.Scatter( x=freqrange, @@ -294,7 +294,10 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): if fit is not None: fig.add_trace( go.Scatter( - x=[fit.best_freq[qubit] * HZ_TO_GHZ, fit.best_freq[qubit] * HZ_TO_GHZ], + x=[ + fit.best_freq[target] * HZ_TO_GHZ, + fit.best_freq[target] * HZ_TO_GHZ, + ], y=[ np.min(np.concatenate((data_0.signal, data_1.signal))), np.max(np.concatenate((data_0.signal, data_1.signal))), @@ -308,14 +311,14 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): ) fig.add_vline( - x=fit.best_freq[qubit] * HZ_TO_GHZ, + x=fit.best_freq[target] * HZ_TO_GHZ, line=dict(color="orange", width=3, dash="dash"), row=1, col=1, ) fitting_report = table_html( table_dict( - qubit, + target, [ "State Zero Frequency [Hz]", "State One Frequency [Hz]", @@ -324,14 +327,14 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): ], np.round( [ - fit_data_0["frequency_state_zero"][qubit], - fit_data_1["frequency_state_one"][qubit], + fit_data_0["frequency_state_zero"][target], + fit_data_1["frequency_state_one"][target], ( - fit_data_0["frequency_state_zero"][qubit] - - fit_data_1["frequency_state_one"][qubit] + fit_data_0["frequency_state_zero"][target] + - fit_data_1["frequency_state_one"][target] ) / 2, - fit.best_freq[qubit], + fit.best_freq[target], ] ), ) @@ -349,8 +352,8 @@ def _plot(data: DispersiveShiftData, qubit, fit: DispersiveShiftResults): return figures, fitting_report -def _update(results: DispersiveShiftResults, platform: Platform, qubit: QubitId): - update.readout_frequency(results.best_freq[qubit], platform, qubit) +def _update(results: DispersiveShiftResults, platform: Platform, target: QubitId): + update.readout_frequency(results.best_freq[target], platform, target) dispersive_shift = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/dispersive_shift_qutrit.py b/src/qibocal/protocols/characterization/dispersive_shift_qutrit.py index 712ae6c49..eaef0a2dc 100644 --- a/src/qibocal/protocols/characterization/dispersive_shift_qutrit.py +++ b/src/qibocal/protocols/characterization/dispersive_shift_qutrit.py @@ -10,7 +10,7 @@ from qibolab.qubits import QubitId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Results, Routine +from qibocal.auto.operation import Results, Routine from qibocal.protocols.characterization.utils import ( GHZ_TO_HZ, HZ_TO_GHZ, @@ -68,7 +68,7 @@ class DispersiveShiftQutritData(DispersiveShiftData): def _acquisition( - params: DispersiveShiftParameters, platform: Platform, qubits: Qubits + params: DispersiveShiftParameters, platform: Platform, targets: list[QubitId] ) -> DispersiveShiftQutritData: r""" Data acquisition for dispersive shift experiment. @@ -78,7 +78,7 @@ def _acquisition( Args: params (DispersiveShiftParameters): experiment's parameters platform (Platform): Qibolab platform object - qubits (dict): list of target qubits to perform the action + targets (list): list of target qubits to perform the action """ @@ -92,7 +92,7 @@ def _acquisition( sequence_1 = PulseSequence() sequence_2 = PulseSequence() - for qubit in qubits: + for qubit in targets: rx_pulse = platform.create_RX_pulse(qubit, start=0) rx_12_pulse = platform.create_RX12_pulse(qubit, start=rx_pulse.finish) ro_pulse = platform.create_qubit_readout_pulse(qubit, start=0) @@ -129,7 +129,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[qubit] # store the results data.register_qubit( @@ -183,7 +183,9 @@ def _fit(data: DispersiveShiftQutritData) -> DispersiveShiftQutritResults: ) -def _plot(data: DispersiveShiftQutritData, qubit, fit: DispersiveShiftQutritResults): +def _plot( + data: DispersiveShiftQutritData, target: QubitId, fit: DispersiveShiftQutritResults +): """Plotting function for dispersive shift.""" figures = [] fig = make_subplots( @@ -200,9 +202,9 @@ def _plot(data: DispersiveShiftQutritData, qubit, fit: DispersiveShiftQutritResu fitting_report = "" - data_0 = data[qubit, 0] - data_1 = data[qubit, 1] - data_2 = data[qubit, 2] + data_0 = data[target, 0] + data_1 = data[target, 1] + data_2 = data[target, 2] fit_data_0 = fit.state_zero if fit is not None else None fit_data_1 = fit.state_one if fit is not None else None fit_data_2 = fit.state_two if fit is not None else None @@ -256,7 +258,7 @@ def _plot(data: DispersiveShiftQutritData, qubit, fit: DispersiveShiftQutritResu else "fitted_parameters_state_two" ) ) - ][qubit] + ][target] fig.add_trace( go.Scatter( x=freqrange, @@ -271,7 +273,7 @@ def _plot(data: DispersiveShiftQutritData, qubit, fit: DispersiveShiftQutritResu if fit is not None: fitting_report = table_html( table_dict( - qubit, + target, [ "State Zero Frequency [Hz]", "State One Frequency [Hz]", @@ -279,9 +281,9 @@ def _plot(data: DispersiveShiftQutritData, qubit, fit: DispersiveShiftQutritResu ], np.round( [ - fit_data_0["frequency_state_zero"][qubit] * GHZ_TO_HZ, - fit_data_1["frequency_state_one"][qubit] * GHZ_TO_HZ, - fit_data_2["frequency_state_two"][qubit] * GHZ_TO_HZ, + fit_data_0["frequency_state_zero"][target] * GHZ_TO_HZ, + fit_data_1["frequency_state_one"][target] * GHZ_TO_HZ, + fit_data_2["frequency_state_two"][target] * GHZ_TO_HZ, ] ), ) diff --git a/src/qibocal/protocols/characterization/fast_reset/fast_reset.py b/src/qibocal/protocols/characterization/fast_reset/fast_reset.py index cc805e2e7..56032b667 100644 --- a/src/qibocal/protocols/characterization/fast_reset/fast_reset.py +++ b/src/qibocal/protocols/characterization/fast_reset/fast_reset.py @@ -9,7 +9,7 @@ from qibolab.pulses import PulseSequence from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.utils import table_dict, table_html # TODO: IBM Fast Reset until saturation loop @@ -52,7 +52,7 @@ class FastResetData(Data): def _acquisition( - params: FastResetParameters, platform: Platform, qubits: Qubits + params: FastResetParameters, platform: Platform, targets: list[QubitId] ) -> FastResetData: """Data acquisition for resonator spectroscopy.""" @@ -64,7 +64,7 @@ def _acquisition( RX_pulses = {} ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: if state == 1: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( @@ -154,7 +154,7 @@ def _fit(data: FastResetData) -> FastResetResults: return FastResetResults(fidelity_nfr, Lambda_M_nfr, fidelity_fr, Lambda_M_fr) -def _plot(data: FastResetData, fit: FastResetResults, qubit): +def _plot(data: FastResetData, fit: FastResetResults, target: QubitId): """Plotting function for FastReset.""" # Maybe the plot can just be something like a confusion matrix between 0s and 1s ??? @@ -175,7 +175,7 @@ def _plot(data: FastResetData, fit: FastResetResults, qubit): if fit is not None: fig.add_trace( go.Heatmap( - z=fit.Lambda_M_fr[qubit], + z=fit.Lambda_M_fr[target], coloraxis="coloraxis", ), row=1, @@ -183,18 +183,18 @@ def _plot(data: FastResetData, fit: FastResetResults, qubit): ) fitting_report = table_html( table_dict( - qubit, + target, ["Fidelity [Fast Reset]", "Fidelity [Relaxation Time]"], [ - np.round(fit.fidelity_fr[qubit], 6), - np.round(fit.fidelity_nfr[qubit], 6), + np.round(fit.fidelity_fr[target], 6), + np.round(fit.fidelity_nfr[target], 6), ], ) ) fig.add_trace( go.Heatmap( - z=fit.Lambda_M_nfr[qubit], + z=fit.Lambda_M_nfr[target], coloraxis="coloraxis", ), row=1, @@ -202,7 +202,7 @@ def _plot(data: FastResetData, fit: FastResetResults, qubit): ) fig.update_xaxes( - title_text=f"{qubit}: Fast Reset", + title_text=f"{target}: Fast Reset", row=1, col=1, ) diff --git a/src/qibocal/protocols/characterization/flipping.py b/src/qibocal/protocols/characterization/flipping.py index 9d73d851b..ca2ee4a87 100644 --- a/src/qibocal/protocols/characterization/flipping.py +++ b/src/qibocal/protocols/characterization/flipping.py @@ -11,7 +11,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from qibocal.protocols.characterization.utils import table_dict, table_html @@ -65,7 +65,7 @@ class FlippingData(Data): def _acquisition( params: FlippingParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> FlippingData: r""" Data acquisition for flipping. @@ -85,7 +85,7 @@ def _acquisition( data = FlippingData( resonator_type=platform.resonator_type, pi_pulse_amplitudes={ - qubit: qubits[qubit].native_gates.RX.amplitude for qubit in qubits + qubit: platform.qubits[qubit].native_gates.RX.amplitude for qubit in targets }, ) @@ -103,7 +103,7 @@ def _acquisition( # create a sequence of pulses for the experiment sequence = PulseSequence() ro_pulses = {} - for qubit in qubits: + for qubit in targets: RX90_pulse = platform.create_RX90_pulse(qubit, start=0) sequence.add(RX90_pulse) # execute sequence RX(pi/2) - [RX(pi) - RX(pi)] from 0...flips times - RO @@ -133,7 +133,7 @@ def _acquisition( ] for ig, (flips, ro_pulses) in enumerate(zip(flips_sweep, all_ro_pulses)): - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: result = results[serial][0] @@ -233,14 +233,14 @@ def _fit(data: FlippingData) -> FlippingResults: ) -def _plot(data: FlippingData, qubit, fit: FlippingResults = None): +def _plot(data: FlippingData, target: QubitId, fit: FlippingResults = None): """Plotting function for Flipping.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] probs = qubit_data.prob error_bars = qubit_data.error @@ -279,11 +279,11 @@ def _plot(data: FlippingData, qubit, fit: FlippingResults = None): x=flips_range, y=flipping_fit( flips_range, - float(fit.fitted_parameters[qubit][0]), - float(fit.fitted_parameters[qubit][1]), - float(fit.fitted_parameters[qubit][2]), - float(fit.fitted_parameters[qubit][3]), - float(fit.fitted_parameters[qubit][4]), + float(fit.fitted_parameters[target][0]), + float(fit.fitted_parameters[target][1]), + float(fit.fitted_parameters[target][2]), + float(fit.fitted_parameters[target][3]), + float(fit.fitted_parameters[target][4]), ), name="Fit", line=go.scatter.Line(dash="dot"), @@ -291,16 +291,16 @@ def _plot(data: FlippingData, qubit, fit: FlippingResults = None): ) fitting_report = table_html( table_dict( - qubit, + target, [ "Amplitude correction factor", "Corrected amplitude [a.u.]", "chi2 reduced", ], [ - np.round(fit.amplitude_factors[qubit], 4), - np.round(fit.amplitude[qubit], 4), - fit.chi2[qubit], + np.round(fit.amplitude_factors[target], 4), + np.round(fit.amplitude[target], 4), + fit.chi2[target], ], display_error=True, ) @@ -318,8 +318,8 @@ def _plot(data: FlippingData, qubit, fit: FlippingResults = None): return figures, fitting_report -def _update(results: FlippingResults, platform: Platform, qubit: QubitId): - update.drive_amplitude(results.amplitude[qubit], platform, qubit) +def _update(results: FlippingResults, platform: Platform, target: QubitId): + update.drive_amplitude(results.amplitude[target], platform, target) flipping = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/flipping_signal.py b/src/qibocal/protocols/characterization/flipping_signal.py index b6b1358ba..86be36dd2 100644 --- a/src/qibocal/protocols/characterization/flipping_signal.py +++ b/src/qibocal/protocols/characterization/flipping_signal.py @@ -11,7 +11,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from qibocal.config import log from qibocal.protocols.characterization.flipping import ( FlippingData, @@ -46,7 +46,7 @@ class FlippingSignalData(FlippingData): def _acquisition( params: FlippingSignalParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> FlippingSignalData: r""" Data acquisition for flipping. @@ -66,7 +66,7 @@ def _acquisition( data = FlippingSignalData( resonator_type=platform.resonator_type, pi_pulse_amplitudes={ - qubit: qubits[qubit].native_gates.RX.amplitude for qubit in qubits + qubit: platform.qubits[qubit].native_gates.RX.amplitude for qubit in targets }, ) @@ -84,7 +84,7 @@ def _acquisition( # create a sequence of pulses for the experiment sequence = PulseSequence() ro_pulses = {} - for qubit in qubits: + for qubit in targets: RX90_pulse = platform.create_RX90_pulse(qubit, start=0) sequence.add(RX90_pulse) # execute sequence RX(pi/2) - [RX(pi) - RX(pi)] from 0...flips times - RO @@ -114,7 +114,7 @@ def _acquisition( ] for ig, (flips, ro_pulses) in enumerate(zip(flips_sweep, all_ro_pulses)): - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: result = results[serial][0] @@ -214,13 +214,13 @@ def _fit(data: FlippingSignalData) -> FlippingSignalResults: ) -def _plot(data: FlippingSignalData, qubit, fit: FlippingSignalResults = None): +def _plot(data: FlippingSignalData, target, fit: FlippingSignalResults = None): """Plotting function for Flipping.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] fig.add_trace( go.Scatter( @@ -245,11 +245,11 @@ def _plot(data: FlippingSignalData, qubit, fit: FlippingSignalResults = None): x=flips_range, y=flipping_fit( flips_range, - float(fit.fitted_parameters[qubit][0]), - float(fit.fitted_parameters[qubit][1]), - float(fit.fitted_parameters[qubit][2]), - float(fit.fitted_parameters[qubit][3]), - float(fit.fitted_parameters[qubit][4]), + float(fit.fitted_parameters[target][0]), + float(fit.fitted_parameters[target][1]), + float(fit.fitted_parameters[target][2]), + float(fit.fitted_parameters[target][3]), + float(fit.fitted_parameters[target][4]), ), name="Fit", line=go.scatter.Line(dash="dot"), @@ -257,11 +257,11 @@ def _plot(data: FlippingSignalData, qubit, fit: FlippingSignalResults = None): ) fitting_report = table_html( table_dict( - qubit, + target, ["Amplitude correction factor", "Corrected amplitude [a.u.]"], [ - np.round(fit.amplitude_factors[qubit], 4), - np.round(fit.amplitude[qubit], 4), + np.round(fit.amplitude_factors[target], 4), + np.round(fit.amplitude[target], 4), ], ) ) diff --git a/src/qibocal/protocols/characterization/flux_dependence/avoided_crossing.py b/src/qibocal/protocols/characterization/flux_dependence/avoided_crossing.py index a9c00eac9..8e69fc985 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/avoided_crossing.py +++ b/src/qibocal/protocols/characterization/flux_dependence/avoided_crossing.py @@ -8,9 +8,9 @@ import plotly.graph_objects as go from plotly.subplots import make_subplots from qibolab.platform import Platform -from qibolab.qubits import QubitId +from qibolab.qubits import QubitId, QubitPairId -from qibocal.auto.operation import Data, QubitsPairs, Results, Routine +from qibocal.auto.operation import Data, Results, Routine from qibocal.protocols.characterization.two_qubit_interaction.utils import order_pair from qibocal.protocols.characterization.utils import HZ_TO_GHZ, table_dict, table_html @@ -57,7 +57,7 @@ class AvoidedCrossingData(Data): def _acquisition( params: AvoidedCrossingParameters, platform: Platform, - qubits: QubitsPairs, # qubit pairs + targets: list[QubitPairId], # qubit pairs ) -> AvoidedCrossingData: """ Data acquisition for avoided crossing. @@ -70,8 +70,7 @@ def _acquisition( platform (Platform): Qibolab platform object. qubits (dict): list of targets qubit pairs to perform the action. """ - qubit_pairs = list(qubits.keys()) - order_pairs = np.array([order_pair(pair, platform.qubits) for pair in qubit_pairs]) + order_pairs = np.array([order_pair(pair, platform.qubits) for pair in targets]) data = AvoidedCrossingData(qubit_pairs=order_pairs.tolist()) # Extract the qubits in the qubits pairs and evaluate their flux dep unique_qubits = np.unique( @@ -84,7 +83,7 @@ def _acquisition( data_transition = flux_acquisition( params=params, platform=platform, - qubits=new_qubits, + targets=new_qubits, ) for qubit in unique_qubits: qubit_data = data_transition.data[qubit] @@ -155,16 +154,21 @@ def _fit(data: AvoidedCrossingData) -> AvoidedCrossingResults: return AvoidedCrossingResults(curves, fits, cz, iswap) -def _plot(data: AvoidedCrossingData, fit: Optional[AvoidedCrossingResults], qubit): +def _plot( + data: AvoidedCrossingData, + fit: Optional[AvoidedCrossingResults], + target: QubitPairId, +): """Plotting function for avoided crossing""" fitting_report = "" figures = [] - order_pair = tuple(index(data.qubit_pairs, qubit)) + order_pair = tuple(index(data.qubit_pairs, target)) heatmaps = make_subplots( rows=1, cols=2, subplot_titles=[ - f"{i} transition qubit {qubit[0]}" for i in [Excitations.ge, Excitations.gf] + f"{i} transition qubit {target[0]}" + for i in [Excitations.ge, Excitations.gf] ], ) parabolas = make_subplots(rows=1, cols=1, subplot_titles=["Parabolas"]) @@ -207,7 +211,7 @@ def _plot(data: AvoidedCrossingData, fit: Optional[AvoidedCrossingResults], qubi figures.append(parabolas) fitting_report = table_html( table_dict( - qubit, + target, ["CZ bias", "iSwap bias"], [np.round(cz[:, 0], 3), np.round(iswap[:, 0], 3)], ) diff --git a/src/qibocal/protocols/characterization/flux_dependence/qubit_crosstalk.py b/src/qibocal/protocols/characterization/flux_dependence/qubit_crosstalk.py index 0e5905b3b..e24222fd1 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/qubit_crosstalk.py +++ b/src/qibocal/protocols/characterization/flux_dependence/qubit_crosstalk.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Results, Routine +from qibocal.auto.operation import Results, Routine from ..qubit_spectroscopy_ef import DEFAULT_ANHARMONICITY from . import utils @@ -63,7 +63,7 @@ class QubitCrosstalkResult(Results): def _acquisition( params: QubitCrosstalkParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> QubitCrosstalkData: """Data acquisition for Crosstalk Experiment.""" @@ -71,14 +71,14 @@ def _acquisition( sequence = PulseSequence() ro_pulses = {} qd_pulses = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.drive_duration ) if params.transition == "02": - if qubits[qubit].anharmonicity: - qd_pulses[qubit].frequency -= qubits[qubit].anharmonicity / 2 + if platform.qubits[qubit].anharmonicity: + qd_pulses[qubit].frequency -= platform.qubits[qubit].anharmonicity / 2 else: qd_pulses[qubit].frequency -= DEFAULT_ANHARMONICITY / 2 @@ -98,7 +98,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[qd_pulses[qubit] for qubit in qubits], + pulses=[qd_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -130,10 +130,10 @@ def _acquisition( for flux_qubit, bias_sweeper in zip(flux_qubits, bias_sweepers): results = platform.sweep(sequence, options, bias_sweeper, freq_sweeper) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] if flux_qubit is None: - sweetspot = qubits[qubit].sweetspot + sweetspot = platform.qubits[qubit].sweetspot else: sweetspot = platform.qubits[flux_qubit].sweetspot data.register_qubit( @@ -152,9 +152,9 @@ def _fit(data: QubitCrosstalkData) -> QubitCrosstalkResult: return QubitCrosstalkResult() -def _plot(data: QubitFluxData, fit: QubitFluxResults, qubit): +def _plot(data: QubitFluxData, fit: QubitFluxResults, target: QubitId): """Plotting function for Crosstalk Experiment.""" - return utils.flux_crosstalk_plot(data, qubit) + return utils.flux_crosstalk_plot(data, target) qubit_crosstalk = Routine(_acquisition, _fit, _plot) diff --git a/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_dependence.py b/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_dependence.py index c4e3737bb..4e561f8c2 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_dependence.py +++ b/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_dependence.py @@ -11,7 +11,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from qibocal.protocols.characterization.qubit_spectroscopy_ef import ( DEFAULT_ANHARMONICITY, @@ -92,7 +92,7 @@ def register_qubit(self, qubit, freq, bias, signal, phase): def _acquisition( params: QubitFluxParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> QubitFluxData: """Data acquisition for QubitFlux Experiment.""" @@ -101,15 +101,15 @@ def _acquisition( ro_pulses = {} qd_pulses = {} qubit_frequency = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.drive_duration ) qubit_frequency[qubit] = platform.qubits[qubit].drive_frequency if params.transition == "02": - if qubits[qubit].anharmonicity: - qd_pulses[qubit].frequency -= qubits[qubit].anharmonicity / 2 + if platform.qubits[qubit].anharmonicity: + qd_pulses[qubit].frequency -= platform.qubits[qubit].anharmonicity / 2 else: qd_pulses[qubit].frequency -= DEFAULT_ANHARMONICITY / 2 @@ -129,7 +129,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[qd_pulses[qubit] for qubit in qubits], + pulses=[qd_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -140,7 +140,7 @@ def _acquisition( Sweeper( Parameter.bias, delta_bias_range, - qubits=list(qubits.values()), + qubits=[platform.qubits[qubit] for qubit in targets], type=SweeperType.OFFSET, ) ] @@ -157,9 +157,9 @@ def _acquisition( for bias_sweeper in bias_sweepers: results = platform.sweep(sequence, options, bias_sweeper, freq_sweeper) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] - sweetspot = qubits[qubit].sweetspot + sweetspot = platform.qubits[qubit].sweetspot data.register_qubit( qubit, signal=result.magnitude, @@ -236,15 +236,15 @@ def _fit(data: QubitFluxData) -> QubitFluxResults: ) -def _plot(data: QubitFluxData, fit: QubitFluxResults, qubit): +def _plot(data: QubitFluxData, fit: QubitFluxResults, target: QubitId): """Plotting function for QubitFlux Experiment.""" figures = utils.flux_dependence_plot( - data, fit, qubit, fit_function=utils.transmon_frequency + data, fit, target, fit_function=utils.transmon_frequency ) if fit is not None: fitting_report = table_html( table_dict( - qubit, + target, [ "Sweetspot [V]", "Qubit Frequency at Sweetspot [Hz]", @@ -252,10 +252,10 @@ def _plot(data: QubitFluxData, fit: QubitFluxResults, qubit): "V_ii [V]", ], [ - np.round(fit.sweetspot[qubit], 4), - np.round(fit.frequency[qubit], 4), - np.round(fit.asymmetry[qubit], 4), - np.round(fit.matrix_element[qubit], 4), + np.round(fit.sweetspot[target], 4), + np.round(fit.frequency[target], 4), + np.round(fit.asymmetry[target], 4), + np.round(fit.matrix_element[target], 4), ], ) ) diff --git a/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_tracking.py b/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_tracking.py index 3952362bb..fcf7708ba 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_tracking.py +++ b/src/qibocal/protocols/characterization/flux_dependence/qubit_flux_tracking.py @@ -4,9 +4,10 @@ from qibolab import AcquisitionType, AveragingMode, 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 Qubits, Routine +from qibocal.auto.operation import Routine from qibocal.config import raise_error from ..qubit_spectroscopy_ef import DEFAULT_ANHARMONICITY @@ -45,7 +46,7 @@ def register_qubit_track(self, qubit, freq, bias, signal, phase): def _acquisition( params: QubitFluxTrackResults, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> QubitFluxTrackData: """Data acquisition for QubitFlux Experiment.""" # create a sequence of pulses for the experiment: @@ -56,14 +57,14 @@ def _acquisition( ro_pulses = {} qd_pulses = {} qubit_frequency = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.drive_duration ) qubit_frequency[qubit] = platform.qubits[qubit].drive_frequency if params.transition == "02": - if qubits[qubit].anharmonicity != 0: - qd_pulses[qubit].frequency -= qubits[qubit].anharmonicity / 2 + if platform.qubits[qubit].anharmonicity != 0: + qd_pulses[qubit].frequency -= platform.qubits[qubit].anharmonicity / 2 else: qd_pulses[qubit].frequency -= DEFAULT_ANHARMONICITY / 2 @@ -88,7 +89,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[qd_pulses[qubit] for qubit in qubits], + pulses=[qd_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -97,19 +98,19 @@ def _acquisition( ) for bias in delta_bias_range: - for qubit in qubits: + for qubit in targets: try: freq_resonator = utils.transmon_readout_frequency( bias, - qubits[qubit].drive_frequency, - qubits[qubit].asymmetry, - qubits[qubit].Cii, - qubits[qubit].sweetspot, - qubits[qubit].bare_resonator_frequency, - qubits[qubit].g, + platform.qubits[qubit].drive_frequency, + platform.qubits[qubit].asymmetry, + platform.qubits[qubit].crosstalk_matrix[qubit], + platform.qubits[qubit].sweetspot, + platform.qubits[qubit].bare_resonator_frequency, + platform.qubits[qubit].g, ) # modify qubit resonator frequency - qubits[qubit].readout_frequency = freq_resonator + platform.qubits[qubit].readout_frequency = freq_resonator except: raise_error ( @@ -118,7 +119,7 @@ def _acquisition( ) # modify qubit flux - qubits[qubit].flux.offset = bias + platform.qubits[qubit].flux.offset = bias # execute pulse sequence sweeping only qubit resonator results = platform.sweep( @@ -133,14 +134,14 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit_track( qubit, signal=result.magnitude, phase=result.phase, freq=delta_frequency_range + qd_pulses[qubit].frequency, - bias=bias + qubits[qubit].sweetspot, + bias=bias + platform.qubits[qubit].sweetspot, ) return data diff --git a/src/qibocal/protocols/characterization/flux_dependence/resonator_crosstalk.py b/src/qibocal/protocols/characterization/flux_dependence/resonator_crosstalk.py index 94f74788d..238a4b017 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/resonator_crosstalk.py +++ b/src/qibocal/protocols/characterization/flux_dependence/resonator_crosstalk.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Results, Routine +from qibocal.auto.operation import Results, Routine from qibocal.protocols.characterization.flux_dependence.resonator_flux_dependence import ( ResFluxType, ResonatorFluxData, @@ -57,7 +57,7 @@ def register_qubit(self, qubit, flux_qubit, freq, bias, signal, phase): def _acquisition( - params: ResCrosstalkParameters, platform: Platform, qubits: Qubits + params: ResCrosstalkParameters, platform: Platform, targets: list[QubitId] ) -> ResonatorFluxData: """Data acquisition for ResonatorFlux experiment.""" # create a sequence of pulses for the experiment: @@ -68,7 +68,7 @@ def _acquisition( ro_pulses = {} bare_resonator_frequency = {} qubit_frequency = {} - for qubit in qubits: + for qubit in targets: bare_resonator_frequency[qubit] = platform.qubits[ qubit ].bare_resonator_frequency @@ -84,7 +84,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -121,10 +121,10 @@ def _acquisition( for flux_qubit, bias_sweeper in zip(flux_qubits, bias_sweepers): results = platform.sweep(sequence, options, bias_sweeper, freq_sweeper) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] if flux_qubit is None: - sweetspot = qubits[qubit].sweetspot + sweetspot = platform.qubits[qubit].sweetspot else: sweetspot = platform.qubits[flux_qubit].sweetspot data.register_qubit( @@ -143,9 +143,9 @@ def _fit(data: ResCrosstalkData) -> ResCrosstalkResults: return ResCrosstalkResults() -def _plot(data: ResCrosstalkData, fit: ResCrosstalkResults, qubit): +def _plot(data: ResCrosstalkData, fit: ResCrosstalkResults, target: QubitId): """Plotting function for ResonatorFlux Experiment.""" - return utils.flux_crosstalk_plot(data, qubit) + return utils.flux_crosstalk_plot(data, target) resonator_crosstalk = Routine(_acquisition, _fit, _plot) diff --git a/src/qibocal/protocols/characterization/flux_dependence/resonator_flux_dependence.py b/src/qibocal/protocols/characterization/flux_dependence/resonator_flux_dependence.py index 7b1bb6534..3bfb03d5f 100644 --- a/src/qibocal/protocols/characterization/flux_dependence/resonator_flux_dependence.py +++ b/src/qibocal/protocols/characterization/flux_dependence/resonator_flux_dependence.py @@ -10,7 +10,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from ..utils import GHZ_TO_HZ, HZ_TO_GHZ, table_dict, table_html @@ -88,7 +88,7 @@ def register_qubit(self, qubit, freq, bias, signal, phase): def _acquisition( - params: ResonatorFluxParameters, platform: Platform, qubits: Qubits + params: ResonatorFluxParameters, platform: Platform, targets: list[QubitId] ) -> ResonatorFluxData: """Data acquisition for ResonatorFlux experiment.""" # create a sequence of pulses for the experiment: @@ -99,7 +99,7 @@ def _acquisition( ro_pulses = {} qubit_frequency = {} bare_resonator_frequency = {} - for qubit in qubits: + for qubit in targets: qubit_frequency[qubit] = platform.qubits[qubit].drive_frequency bare_resonator_frequency[qubit] = platform.qubits[ qubit @@ -115,7 +115,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -126,7 +126,7 @@ def _acquisition( Sweeper( Parameter.bias, delta_bias_range, - qubits=list(qubits.values()), + qubits=[platform.qubits[qubit] for qubit in targets], type=SweeperType.OFFSET, ) ] @@ -146,9 +146,9 @@ def _acquisition( for bias_sweeper in bias_sweepers: results = platform.sweep(sequence, options, bias_sweeper, freq_sweeper) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] - sweetspot = qubits[qubit].sweetspot + sweetspot = platform.qubits[qubit].sweetspot data.register_qubit( qubit, signal=result.magnitude, @@ -242,15 +242,15 @@ def _fit(data: ResonatorFluxData) -> ResonatorFluxResults: ) -def _plot(data: ResonatorFluxData, fit: ResonatorFluxResults, qubit): +def _plot(data: ResonatorFluxData, fit: ResonatorFluxResults, target: QubitId): """Plotting function for ResonatorFlux Experiment.""" figures = utils.flux_dependence_plot( - data, fit, qubit, utils.transmon_readout_frequency + data, fit, target, utils.transmon_readout_frequency ) if fit is not None: fitting_report = table_html( table_dict( - qubit, + target, [ "Sweetspot [V]", "Bare Resonator Frequency [Hz]", @@ -261,13 +261,13 @@ def _plot(data: ResonatorFluxData, fit: ResonatorFluxResults, qubit): "V_ii [V]", ], [ - np.round(fit.sweetspot[qubit], 4), - np.round(fit.bare_frequency[qubit], 4), - np.round(fit.frequency[qubit], 4), - np.round(fit.drive_frequency[qubit], 4), - np.round(fit.asymmetry[qubit], 4), - np.round(fit.coupling[qubit], 4), - np.round(fit.matrix_element[qubit], 4), + np.round(fit.sweetspot[target], 4), + np.round(fit.bare_frequency[target], 4), + np.round(fit.frequency[target], 4), + np.round(fit.drive_frequency[target], 4), + np.round(fit.asymmetry[target], 4), + np.round(fit.coupling[target], 4), + np.round(fit.matrix_element[target], 4), ], ) ) diff --git a/src/qibocal/protocols/characterization/qubit_spectroscopy.py b/src/qibocal/protocols/characterization/qubit_spectroscopy.py index 539eeee6f..12532e7c4 100644 --- a/src/qibocal/protocols/characterization/qubit_spectroscopy.py +++ b/src/qibocal/protocols/characterization/qubit_spectroscopy.py @@ -9,7 +9,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from .resonator_spectroscopy import ResonatorSpectroscopyData, ResSpecType from .utils import lorentzian_fit, spectroscopy_plot @@ -46,7 +46,7 @@ class QubitSpectroscopyData(ResonatorSpectroscopyData): def _acquisition( - params: QubitSpectroscopyParameters, platform: Platform, qubits: Qubits + params: QubitSpectroscopyParameters, platform: Platform, targets: list[QubitId] ) -> QubitSpectroscopyData: """Data acquisition for qubit spectroscopy.""" # create a sequence of pulses for the experiment: @@ -57,7 +57,7 @@ def _acquisition( ro_pulses = {} qd_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.drive_duration ) @@ -79,7 +79,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[qd_pulses[qubit] for qubit in qubits], + pulses=[qd_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -134,13 +134,13 @@ def _fit(data: QubitSpectroscopyData) -> QubitSpectroscopyResults: ) -def _plot(data: QubitSpectroscopyData, qubit, fit: QubitSpectroscopyResults): +def _plot(data: QubitSpectroscopyData, target: QubitId, fit: QubitSpectroscopyResults): """Plotting function for QubitSpectroscopy.""" - return spectroscopy_plot(data, qubit, fit) + return spectroscopy_plot(data, target, fit) -def _update(results: QubitSpectroscopyResults, platform: Platform, qubit: QubitId): - update.drive_frequency(results.frequency[qubit], platform, qubit) +def _update(results: QubitSpectroscopyResults, platform: Platform, target: QubitId): + update.drive_frequency(results.frequency[target], platform, target) qubit_spectroscopy = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/qubit_spectroscopy_ef.py b/src/qibocal/protocols/characterization/qubit_spectroscopy_ef.py index 30359e74f..21c42b8ba 100644 --- a/src/qibocal/protocols/characterization/qubit_spectroscopy_ef.py +++ b/src/qibocal/protocols/characterization/qubit_spectroscopy_ef.py @@ -8,7 +8,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from .qubit_spectroscopy import ( QubitSpectroscopyData, @@ -55,7 +55,7 @@ def _fit_ef(data: QubitSpectroscopyEFData) -> QubitSpectroscopyEFResults: def _acquisition( - params: QubitSpectroscopyEFParameters, platform: Platform, qubits: Qubits + params: QubitSpectroscopyEFParameters, platform: Platform, targets: list[QubitId] ) -> QubitSpectroscopyEFData: """Data acquisition for qubit spectroscopy ef protocol. @@ -78,7 +78,7 @@ def _acquisition( rx_pulses = {} amplitudes = {} drive_frequencies = {} - for qubit in qubits: + for qubit in targets: rx_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) drive_frequencies[qubit] = rx_pulses[qubit].frequency qd_pulses[qubit] = platform.create_qubit_drive_pulse( @@ -113,7 +113,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[qd_pulses[qubit] for qubit in qubits], + pulses=[qd_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -151,18 +151,20 @@ def _acquisition( return data -def _plot(data: QubitSpectroscopyEFData, qubit, fit: QubitSpectroscopyEFResults): +def _plot( + data: QubitSpectroscopyEFData, target: QubitId, fit: QubitSpectroscopyEFResults +): """Plotting function for QubitSpectroscopy.""" - figures, report = spectroscopy_plot(data, qubit, fit) + figures, report = spectroscopy_plot(data, target, fit) if fit is not None: report = table_html( table_dict( - qubit, + target, ["Frequency 1->2 [Hz]", "Amplitude [a.u.]", "Anharmonicity [Hz]"], [ - np.round(fit.frequency[qubit], 0), - fit.amplitude[qubit], - np.round(fit.anharmonicity[qubit], 0), + np.round(fit.frequency[target], 0), + fit.amplitude[target], + np.round(fit.anharmonicity[target], 0), ], ) ) @@ -170,10 +172,10 @@ def _plot(data: QubitSpectroscopyEFData, qubit, fit: QubitSpectroscopyEFResults) return figures, report -def _update(results: QubitSpectroscopyEFResults, platform: Platform, qubit: QubitId): +def _update(results: QubitSpectroscopyEFResults, platform: Platform, target: QubitId): """Update w12 frequency""" - update.frequency_12_transition(results.frequency[qubit], platform, qubit) - update.anharmonicity(results.anharmonicity[qubit], platform, qubit) + update.frequency_12_transition(results.frequency[target], platform, target) + update.anharmonicity(results.anharmonicity[target], platform, target) qubit_spectroscopy_ef = Routine(_acquisition, _fit_ef, _plot, _update) diff --git a/src/qibocal/protocols/characterization/qutrit_classification.py b/src/qibocal/protocols/characterization/qutrit_classification.py index 071b21ba5..3c947f284 100644 --- a/src/qibocal/protocols/characterization/qutrit_classification.py +++ b/src/qibocal/protocols/characterization/qutrit_classification.py @@ -5,8 +5,9 @@ from qibolab import AcquisitionType, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitId -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from qibocal.fitting.classifier import run from qibocal.protocols.characterization.classification import ( ClassificationType, @@ -48,7 +49,7 @@ class QutritClassificationData(SingleShotClassificationData): def _acquisition( params: QutritClassificationParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> QutritClassificationData: """ This Routine prepares the qubits in 0,1 and 2 states and measures their @@ -70,7 +71,7 @@ def _acquisition( # taking advantage of multiplexing, apply the same set of gates to all qubits in parallel states_sequences = [PulseSequence() for _ in range(3)] ro_pulses = {} - for qubit in qubits: + for qubit in targets: rx_pulse = platform.create_RX_pulse(qubit, start=0) rx12_pulse = platform.create_RX12_pulse(qubit, start=rx_pulse.finish) drive_pulses = [rx_pulse, rx12_pulse] @@ -101,7 +102,7 @@ def _acquisition( ) ) - for qubit in qubits: + for qubit in targets: for state, state_result in enumerate(states_results): result = state_result[ro_pulses[qubit][state].serial] data.register_qubit( @@ -165,8 +166,12 @@ def _fit(data: QutritClassificationData) -> SingleShotClassificationResults: ) -def _plot(data: QutritClassificationData, qubit, fit: SingleShotClassificationResults): - figures = plot_results(data, qubit, 3, fit) +def _plot( + data: QutritClassificationData, + target: QubitId, + fit: SingleShotClassificationResults, +): + figures = plot_results(data, target, 3, fit) fitting_report = "" return figures, fitting_report diff --git a/src/qibocal/protocols/characterization/rabi/amplitude.py b/src/qibocal/protocols/characterization/rabi/amplitude.py index 7bcc8e228..29593440e 100644 --- a/src/qibocal/protocols/characterization/rabi/amplitude.py +++ b/src/qibocal/protocols/characterization/rabi/amplitude.py @@ -12,7 +12,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from ..utils import chi2_reduced @@ -63,7 +63,7 @@ class RabiAmplitudeData(Data): def _acquisition( - params: RabiAmplitudeParameters, platform: Platform, qubits: Qubits + params: RabiAmplitudeParameters, platform: Platform, targets: list[QubitId] ) -> RabiAmplitudeData: r""" Data acquisition for Rabi experiment sweeping amplitude. @@ -76,7 +76,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} durations = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) if params.pulse_length is not None: qd_pulses[qubit].duration = params.pulse_length @@ -98,7 +98,7 @@ def _acquisition( sweeper = Sweeper( Parameter.amplitude, qd_pulse_amplitude_range, - [qd_pulses[qubit] for qubit in qubits], + [qd_pulses[qubit] for qubit in targets], type=SweeperType.FACTOR, ) @@ -115,7 +115,7 @@ def _acquisition( ), sweeper, ) - for qubit in qubits: + for qubit in targets: prob = results[qubit].probability(state=1) data.register_qubit( RabiAmpType, @@ -189,13 +189,13 @@ def _fit(data: RabiAmplitudeData) -> RabiAmplitudeResults: return RabiAmplitudeResults(pi_pulse_amplitudes, durations, fitted_parameters, chi2) -def _plot(data: RabiAmplitudeData, qubit, fit: RabiAmplitudeResults = None): +def _plot(data: RabiAmplitudeData, target: QubitId, fit: RabiAmplitudeResults = None): """Plotting function for RabiAmplitude.""" - return utils.plot_probabilities(data, qubit, fit) + return utils.plot_probabilities(data, target, fit) -def _update(results: RabiAmplitudeResults, platform: Platform, qubit: QubitId): - update.drive_amplitude(results.amplitude[qubit], platform, qubit) +def _update(results: RabiAmplitudeResults, platform: Platform, target: QubitId): + update.drive_amplitude(results.amplitude[target], platform, target) rabi_amplitude = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/rabi/amplitude_signal.py b/src/qibocal/protocols/characterization/rabi/amplitude_signal.py index 5c896f1c0..87d20d069 100644 --- a/src/qibocal/protocols/characterization/rabi/amplitude_signal.py +++ b/src/qibocal/protocols/characterization/rabi/amplitude_signal.py @@ -10,7 +10,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from qibocal.config import log from qibocal.protocols.characterization.rabi.amplitude import ( RabiAmplitudeData, @@ -43,7 +43,7 @@ class RabiAmplitudeVoltData(RabiAmplitudeData): def _acquisition( - params: RabiAmplitudeVoltParameters, platform: Platform, qubits: Qubits + params: RabiAmplitudeVoltParameters, platform: Platform, targets: list[QubitId] ) -> RabiAmplitudeVoltData: r""" Data acquisition for Rabi experiment sweeping amplitude. @@ -56,7 +56,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} durations = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) if params.pulse_length is not None: qd_pulses[qubit].duration = params.pulse_length @@ -78,7 +78,7 @@ def _acquisition( sweeper = Sweeper( Parameter.amplitude, qd_pulse_amplitude_range, - [qd_pulses[qubit] for qubit in qubits], + [qd_pulses[qubit] for qubit in targets], type=SweeperType.FACTOR, ) @@ -95,7 +95,7 @@ def _acquisition( ), sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( RabiAmpVoltType, @@ -174,13 +174,15 @@ def _fit(data: RabiAmplitudeVoltData) -> RabiAmplitudeVoltResults: ) -def _plot(data: RabiAmplitudeVoltData, qubit, fit: RabiAmplitudeVoltResults = None): +def _plot( + data: RabiAmplitudeVoltData, target: QubitId, fit: RabiAmplitudeVoltResults = None +): """Plotting function for RabiAmplitude.""" - return utils.plot(data, qubit, fit) + return utils.plot(data, target, fit) -def _update(results: RabiAmplitudeVoltResults, platform: Platform, qubit: QubitId): - update.drive_amplitude(results.amplitude[qubit], platform, qubit) +def _update(results: RabiAmplitudeVoltResults, platform: Platform, target: QubitId): + update.drive_amplitude(results.amplitude[target], platform, target) rabi_amplitude_signal = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/rabi/ef.py b/src/qibocal/protocols/characterization/rabi/ef.py index 2bb9b4807..e6df8c47e 100644 --- a/src/qibocal/protocols/characterization/rabi/ef.py +++ b/src/qibocal/protocols/characterization/rabi/ef.py @@ -8,7 +8,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from . import amplitude_signal, utils @@ -29,7 +29,7 @@ class RabiAmplitudeEFData(amplitude_signal.RabiAmplitudeVoltData): def _acquisition( - params: RabiAmplitudeEFParameters, platform: Platform, qubits: Qubits + params: RabiAmplitudeEFParameters, platform: Platform, targets: list[QubitId] ) -> RabiAmplitudeEFData: r""" Data acquisition for Rabi EF experiment sweeping amplitude. @@ -46,7 +46,7 @@ def _acquisition( ro_pulses = {} rx_pulses = {} durations = {} - for qubit in qubits: + for qubit in targets: rx_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) qd_pulses[qubit] = platform.create_RX_pulse( qubit, start=rx_pulses[qubit].finish @@ -72,7 +72,7 @@ def _acquisition( sweeper = Sweeper( Parameter.amplitude, qd_pulse_amplitude_range, - [qd_pulses[qubit] for qubit in qubits], + [qd_pulses[qubit] for qubit in targets], type=SweeperType.FACTOR, ) @@ -89,7 +89,7 @@ def _acquisition( ), sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( amplitude_signal.RabiAmpVoltType, @@ -103,17 +103,19 @@ def _acquisition( return data -def _plot(data: RabiAmplitudeEFData, qubit, fit: RabiAmplitudeEFResults = None): +def _plot( + data: RabiAmplitudeEFData, target: QubitId, fit: RabiAmplitudeEFResults = None +): """Plotting function for RabiAmplitude.""" - figures, report = utils.plot(data, qubit, fit) + figures, report = utils.plot(data, target, fit) if report is not None: report = report.replace("Pi pulse", "Pi pulse 12") return figures, report -def _update(results: RabiAmplitudeEFResults, platform: Platform, qubit: QubitId): +def _update(results: RabiAmplitudeEFResults, platform: Platform, target: QubitId): """Update RX2 amplitude_signal""" - update.drive_12_amplitude(results.amplitude[qubit], platform, qubit) + update.drive_12_amplitude(results.amplitude[target], platform, target) rabi_amplitude_ef = Routine(_acquisition, amplitude_signal._fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/rabi/length.py b/src/qibocal/protocols/characterization/rabi/length.py index a0a8f0662..950883915 100644 --- a/src/qibocal/protocols/characterization/rabi/length.py +++ b/src/qibocal/protocols/characterization/rabi/length.py @@ -12,7 +12,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from ..utils import chi2_reduced @@ -63,7 +63,7 @@ class RabiLengthData(Data): def _acquisition( - params: RabiLengthParameters, platform: Platform, qubits: Qubits + params: RabiLengthParameters, platform: Platform, targets: list[QubitId] ) -> RabiLengthData: r""" Data acquisition for RabiLength Experiment. @@ -76,7 +76,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: # TODO: made duration optional for qd pulse? qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.pulse_duration_start @@ -102,7 +102,7 @@ def _acquisition( sweeper = Sweeper( Parameter.duration, qd_pulse_duration_range, - [qd_pulses[qubit] for qubit in qubits], + [qd_pulses[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -120,7 +120,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: prob = results[qubit].probability(state=1) data.register_qubit( RabiLenType, @@ -190,13 +190,13 @@ def _fit(data: RabiLengthData) -> RabiLengthResults: return RabiLengthResults(durations, amplitudes, fitted_parameters, chi2) -def _update(results: RabiLengthResults, platform: Platform, qubit: QubitId): - update.drive_duration(results.length[qubit], platform, qubit) +def _update(results: RabiLengthResults, platform: Platform, target: QubitId): + update.drive_duration(results.length[target], platform, target) -def _plot(data: RabiLengthData, fit: RabiLengthResults, qubit): +def _plot(data: RabiLengthData, fit: RabiLengthResults, target: QubitId): """Plotting function for RabiLength experiment.""" - return utils.plot_probabilities(data, qubit, fit) + return utils.plot_probabilities(data, target, fit) rabi_length = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/rabi/length_sequences.py b/src/qibocal/protocols/characterization/rabi/length_sequences.py index 1e1bc0aed..6dc74705f 100644 --- a/src/qibocal/protocols/characterization/rabi/length_sequences.py +++ b/src/qibocal/protocols/characterization/rabi/length_sequences.py @@ -2,8 +2,9 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitId -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from .length_signal import ( RabiLengthVoltData, @@ -16,7 +17,7 @@ def _acquisition( - params: RabiLengthVoltParameters, platform: Platform, qubits: Qubits + params: RabiLengthVoltParameters, platform: Platform, targets: list[QubitId] ) -> RabiLengthVoltData: r""" Data acquisition for RabiLength Experiment. @@ -29,7 +30,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: # TODO: made duration optional for qd pulse? qd_pulses[qubit] = platform.create_qubit_drive_pulse(qubit, start=0, duration=4) if params.pulse_amplitude is not None: @@ -54,7 +55,7 @@ def _acquisition( # sweep the parameter for duration in qd_pulse_duration_range: - for qubit in qubits: + for qubit in targets: qd_pulses[qubit].duration = duration ro_pulses[qubit].start = qd_pulses[qubit].finish @@ -69,7 +70,7 @@ def _acquisition( ), ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( RabiLenVoltType, diff --git a/src/qibocal/protocols/characterization/rabi/length_signal.py b/src/qibocal/protocols/characterization/rabi/length_signal.py index 9e635cbbb..f31cc466e 100644 --- a/src/qibocal/protocols/characterization/rabi/length_signal.py +++ b/src/qibocal/protocols/characterization/rabi/length_signal.py @@ -10,7 +10,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from qibocal.config import log from qibocal.protocols.characterization.rabi.length import ( RabiLengthData, @@ -43,7 +43,7 @@ class RabiLengthVoltData(RabiLengthData): def _acquisition( - params: RabiLengthVoltParameters, platform: Platform, qubits: Qubits + params: RabiLengthVoltParameters, platform: Platform, targets: list[QubitId] ) -> RabiLengthVoltData: r""" Data acquisition for RabiLength Experiment. @@ -56,7 +56,7 @@ def _acquisition( qd_pulses = {} ro_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: # TODO: made duration optional for qd pulse? qd_pulses[qubit] = platform.create_qubit_drive_pulse( qubit, start=0, duration=params.pulse_duration_start @@ -82,7 +82,7 @@ def _acquisition( sweeper = Sweeper( Parameter.duration, qd_pulse_duration_range, - [qd_pulses[qubit] for qubit in qubits], + [qd_pulses[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -100,7 +100,7 @@ def _acquisition( sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( RabiLenVoltType, @@ -177,13 +177,13 @@ def _fit(data: RabiLengthVoltData) -> RabiLengthVoltResults: return RabiLengthVoltResults(durations, data.amplitudes, fitted_parameters) -def _update(results: RabiLengthVoltResults, platform: Platform, qubit: QubitId): - update.drive_duration(results.length[qubit], platform, qubit) +def _update(results: RabiLengthVoltResults, platform: Platform, target: QubitId): + update.drive_duration(results.length[target], platform, target) -def _plot(data: RabiLengthVoltData, fit: RabiLengthVoltResults, qubit): +def _plot(data: RabiLengthVoltData, fit: RabiLengthVoltResults, target: QubitId): """Plotting function for RabiLength experiment.""" - return utils.plot(data, qubit, fit) + return utils.plot(data, target, fit) rabi_length_signal = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/ramsey.py b/src/qibocal/protocols/characterization/ramsey.py index e1f9a3e17..e4f519158 100644 --- a/src/qibocal/protocols/characterization/ramsey.py +++ b/src/qibocal/protocols/characterization/ramsey.py @@ -13,7 +13,7 @@ from scipy.signal import find_peaks from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from .utils import GHZ_TO_HZ, chi2_reduced, table_dict, table_html @@ -93,7 +93,7 @@ def waits(self): def _acquisition( params: RamseyParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> RamseyData: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -119,7 +119,7 @@ def _acquisition( RX90_pulses2 = {} freqs = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -128,7 +128,7 @@ def _acquisition( ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=RX90_pulses2[qubit].finish ) - freqs[qubit] = qubits[qubit].drive_frequency + freqs[qubit] = platform.qubits[qubit].drive_frequency sequence.add(RX90_pulses1[qubit]) sequence.add(RX90_pulses2[qubit]) sequence.add(ro_pulses[qubit]) @@ -143,7 +143,7 @@ def _acquisition( sweeper = Sweeper( Parameter.start, waits, - [RX90_pulses2[qubit] for qubit in qubits], + [RX90_pulses2[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -153,7 +153,7 @@ def _acquisition( options, sweeper, ) - for qubit in qubits: + for qubit in targets: probs = results[qubit].probability() # The probability errors are the standard errors of the binomial distribution errors = [np.sqrt(prob * (1 - prob) / params.nshots) for prob in probs] @@ -174,7 +174,7 @@ def _acquisition( RX90_pulses2 = {} freqs = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -194,7 +194,7 @@ def _acquisition( / params.delay_between_pulses_end ) - freqs[qubit] = qubits[qubit].drive_frequency + freqs[qubit] = platform.qubits[qubit].drive_frequency sequence.add(RX90_pulses1[qubit]) sequence.add(RX90_pulses2[qubit]) sequence.add(ro_pulses[qubit]) @@ -220,7 +220,7 @@ def _acquisition( # We dont need ig as every serial is different for ig, (wait, ro_pulses) in enumerate(zip(waits, all_ro_pulses)): - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: result = results[serial][0] @@ -301,14 +301,14 @@ def _fit(data: RamseyData) -> RamseyResults: return RamseyResults(freq_measure, t2_measure, delta_phys_measure, popts, chi2) -def _plot(data: RamseyData, qubit, fit: RamseyResults = None): +def _plot(data: RamseyData, target: QubitId, fit: RamseyResults = None): """Plotting function for Ramsey Experiment.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data.data[qubit] + qubit_data = data.data[target] waits = data.waits probs = qubit_data["prob"] error_bars = qubit_data["errors"] @@ -341,11 +341,11 @@ def _plot(data: RamseyData, qubit, fit: RamseyResults = None): x=waits, y=ramsey_fit( waits, - float(fit.fitted_parameters[qubit][0]), - float(fit.fitted_parameters[qubit][1]), - float(fit.fitted_parameters[qubit][2]), - float(fit.fitted_parameters[qubit][3]), - float(fit.fitted_parameters[qubit][4]), + float(fit.fitted_parameters[target][0]), + float(fit.fitted_parameters[target][1]), + float(fit.fitted_parameters[target][2]), + float(fit.fitted_parameters[target][3]), + float(fit.fitted_parameters[target][4]), ), name="Fit", line=go.scatter.Line(dash="dot"), @@ -353,7 +353,7 @@ def _plot(data: RamseyData, qubit, fit: RamseyResults = None): ) fitting_report = table_html( table_dict( - qubit, + target, [ "Delta Frequency [Hz]", "Drive Frequency [Hz]", @@ -361,10 +361,10 @@ def _plot(data: RamseyData, qubit, fit: RamseyResults = None): "chi2 reduced", ], [ - fit.delta_phys[qubit], - fit.frequency[qubit], - fit.t2[qubit], - fit.chi2[qubit], + fit.delta_phys[target], + fit.frequency[target], + fit.t2[target], + fit.chi2[target], ], display_error=True, ) @@ -381,8 +381,8 @@ def _plot(data: RamseyData, qubit, fit: RamseyResults = None): return figures, fitting_report -def _update(results: RamseyResults, platform: Platform, qubit: QubitId): - update.drive_frequency(results.frequency[qubit][0], platform, qubit) +def _update(results: RamseyResults, platform: Platform, target: QubitId): + update.drive_frequency(results.frequency[target][0], platform, target) ramsey = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/ramsey_sequences.py b/src/qibocal/protocols/characterization/ramsey_sequences.py index 547b97597..ce285ca58 100644 --- a/src/qibocal/protocols/characterization/ramsey_sequences.py +++ b/src/qibocal/protocols/characterization/ramsey_sequences.py @@ -2,8 +2,9 @@ from qibolab import AcquisitionType, AveragingMode, ExecutionParameters from qibolab.platform import Platform from qibolab.pulses import PulseSequence +from qibolab.qubits import QubitId -from qibocal.auto.operation import Qubits, Routine +from qibocal.auto.operation import Routine from .ramsey import RamseyData, RamseyParameters, RamseyType, _fit, _plot, _update @@ -11,7 +12,7 @@ def _acquisition( params: RamseyParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> RamseyData: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -21,7 +22,7 @@ def _acquisition( RX90_pulses2 = {} freqs = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -30,7 +31,7 @@ def _acquisition( ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=RX90_pulses2[qubit].finish ) - freqs[qubit] = qubits[qubit].drive_frequency + freqs[qubit] = platform.qubits[qubit].drive_frequency sequence.add(RX90_pulses1[qubit]) sequence.add(RX90_pulses2[qubit]) sequence.add(ro_pulses[qubit]) @@ -52,7 +53,7 @@ def _acquisition( # sweep the parameter for wait in waits: - for qubit in qubits: + for qubit in targets: RX90_pulses2[qubit].start = RX90_pulses1[qubit].finish + wait ro_pulses[qubit].start = RX90_pulses2[qubit].finish if params.n_osc != 0: @@ -76,7 +77,7 @@ def _acquisition( ), ) - for qubit in qubits: + for qubit in targets: prob = results[qubit].probability() error = np.sqrt(prob * (1 - prob) / params.nshots) data.register_qubit( diff --git a/src/qibocal/protocols/characterization/ramsey_signal.py b/src/qibocal/protocols/characterization/ramsey_signal.py index 8e990ba5f..0dc04a45a 100644 --- a/src/qibocal/protocols/characterization/ramsey_signal.py +++ b/src/qibocal/protocols/characterization/ramsey_signal.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibolab.sweeper import Parameter, Sweeper, SweeperType -from qibocal.auto.operation import Qubits, Results, Routine +from qibocal.auto.operation import Results, Routine from .ramsey import ( PERR_EXCEPTION, @@ -74,7 +74,7 @@ def waits(self): def _acquisition( params: RamseySignalParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> RamseySignalData: """Data acquisition for Ramsey Experiment (detuned).""" # create a sequence of pulses for the experiment @@ -100,7 +100,7 @@ def _acquisition( RX90_pulses2 = {} freqs = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -109,7 +109,7 @@ def _acquisition( ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=RX90_pulses2[qubit].finish ) - freqs[qubit] = qubits[qubit].drive_frequency + freqs[qubit] = platform.qubits[qubit].drive_frequency sequence.add(RX90_pulses1[qubit]) sequence.add(RX90_pulses2[qubit]) sequence.add(ro_pulses[qubit]) @@ -117,7 +117,7 @@ def _acquisition( sweeper = Sweeper( Parameter.start, waits, - [RX90_pulses2[qubit] for qubit in qubits], + [RX90_pulses2[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -133,7 +133,7 @@ def _acquisition( options, sweeper, ) - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] # The probability errors are the standard errors of the binomial distribution data.register_qubit( @@ -150,7 +150,7 @@ def _acquisition( RX90_pulses2 = {} freqs = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: RX90_pulses1[qubit] = platform.create_RX90_pulse(qubit, start=0) RX90_pulses2[qubit] = platform.create_RX90_pulse( qubit, @@ -170,7 +170,7 @@ def _acquisition( / params.delay_between_pulses_end ) - freqs[qubit] = qubits[qubit].drive_frequency + freqs[qubit] = platform.qubits[qubit].drive_frequency sequence.add(RX90_pulses1[qubit]) sequence.add(RX90_pulses2[qubit]) sequence.add(ro_pulses[qubit]) @@ -196,7 +196,7 @@ def _acquisition( # We dont need ig as everty serial is different for ig, (wait, ro_pulses) in enumerate(zip(waits, all_ro_pulses)): - for qubit in qubits: + for qubit in targets: serial = ro_pulses[qubit].serial if params.unrolling: result = results[serial][0] @@ -253,14 +253,14 @@ def _fit(data: RamseySignalData) -> RamseySignalResults: return RamseySignalResults(freq_measure, t2_measure, delta_phys_measure, popts) -def _plot(data: RamseySignalData, qubit, fit: RamseySignalResults = None): +def _plot(data: RamseySignalData, target: QubitId, fit: RamseySignalResults = None): """Plotting function for Ramsey Experiment.""" figures = [] fig = go.Figure() fitting_report = "" - qubit_data = data.data[qubit] + qubit_data = data.data[target] waits = data.waits signal = qubit_data["signal"] fig = go.Figure( @@ -283,11 +283,11 @@ def _plot(data: RamseySignalData, qubit, fit: RamseySignalResults = None): x=waits, y=ramsey_fit( waits, - float(fit.fitted_parameters[qubit][0]), - float(fit.fitted_parameters[qubit][1]), - float(fit.fitted_parameters[qubit][2]), - float(fit.fitted_parameters[qubit][3]), - float(fit.fitted_parameters[qubit][4]), + float(fit.fitted_parameters[target][0]), + float(fit.fitted_parameters[target][1]), + float(fit.fitted_parameters[target][2]), + float(fit.fitted_parameters[target][3]), + float(fit.fitted_parameters[target][4]), ), name="Fit", line=go.scatter.Line(dash="dot"), @@ -295,16 +295,16 @@ def _plot(data: RamseySignalData, qubit, fit: RamseySignalResults = None): ) fitting_report = table_html( table_dict( - qubit, + target, [ "Delta Frequency [Hz]", "Drive Frequency [Hz]", "T2* [ns]", ], [ - np.round(fit.delta_phys[qubit][0], 3), - np.round(fit.frequency[qubit][0], 3), - np.round(fit.t2[qubit][0], 3), + np.round(fit.delta_phys[target][0], 3), + np.round(fit.frequency[target][0], 3), + np.round(fit.t2[target][0], 3), ], ) ) diff --git a/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb.py b/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb.py index fdcc660e7..b6372b739 100644 --- a/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb.py +++ b/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb.py @@ -9,7 +9,7 @@ from qibolab.platform import Platform from qibolab.qubits import QubitId -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from qibocal.bootstrap import bootstrap, data_uncertainties from qibocal.config import log, raise_error from qibocal.protocols.characterization.randomized_benchmarking import noisemodels @@ -137,13 +137,13 @@ def resample_p0(data, sample_size=100, homogeneous: bool = True): def setup_scan( - params: StandardRBParameters, qubits: Union[Qubits, list[QubitId]], nqubits: int + params: StandardRBParameters, targets: list[QubitId], nqubits: int ) -> Iterable: """Returns an iterator of single-qubit random self-inverting Clifford circuits. Args: params (StandardRBParameters): Parameters of the RB protocol. - qubits (dict[int, Union[str, int]] or list[Union[str, int]]): + targets (list[QubitId]): list of qubits the circuit is executed on. nqubits (int, optional): Number of qubits of the resulting circuits. If ``None``, sets ``len(qubits)``. Defaults to ``None``. @@ -152,8 +152,6 @@ def setup_scan( Iterable: The iterator of circuits. """ - qubit_ids = list(qubits) if isinstance(qubits, dict) else qubits - def make_circuit(depth): """Returns a random Clifford circuit with inverse of ``depth``.""" @@ -162,12 +160,12 @@ def make_circuit(depth): # Clifford gates. Could also be a generator, it just has to be callable. def layer_gen(): """Returns a circuit with a random single-qubit clifford unitary.""" - return random_clifford(len(qubit_ids), params.seed) + return random_clifford(len(targets), params.seed) circuit = layer_circuit(layer_gen, depth) add_inverse_layer(circuit) add_measurement_layer(circuit) - return embed_circuit(circuit, nqubits, qubit_ids) + return embed_circuit(circuit, nqubits, targets) return map(make_circuit, params.depths * params.niter) @@ -175,7 +173,7 @@ def layer_gen(): def _acquisition( params: StandardRBParameters, platform: Platform, - qubits: Union[Qubits, list[QubitId]], + targets: list[QubitId], ) -> RBData: """The data acquisition stage of Standard Randomized Benchmarking. @@ -219,8 +217,8 @@ def _acquisition( backend = GlobalBackend() # 1. Set up the scan (here an iterator of circuits of random clifford gates with an inverse). - nqubits = platform.nqubits if platform else max(qubits) + 1 - scan = setup_scan(params, qubits, nqubits) + nqubits = platform.nqubits if platform else max(targets) + 1 + scan = setup_scan(params, targets, nqubits) # Iterate through the scan and create circuits circuits = [] @@ -341,14 +339,16 @@ def _fit(data: RBData) -> StandardRBResult: return StandardRBResult(fidelity, pulse_fidelity, popt, perr, error_bars) -def _plot(data: RBData, fit: StandardRBResult, qubit) -> tuple[list[go.Figure], str]: +def _plot( + data: RBData, fit: StandardRBResult, target: QubitId +) -> tuple[list[go.Figure], str]: """Builds the table for the qq pipe, calls the plot function of the result object and returns the figure es list. Args: data (RBData): Data object used for the table. fit (StandardRBResult): Is called for the plot. - qubit (_type_): Not used yet. + target (_type_): Not used yet. Returns: tuple[list[go.Figure], str]: diff --git a/src/qibocal/protocols/characterization/readout_characterization.py b/src/qibocal/protocols/characterization/readout_characterization.py index 5f63300a0..32671e5d0 100644 --- a/src/qibocal/protocols/characterization/readout_characterization.py +++ b/src/qibocal/protocols/characterization/readout_characterization.py @@ -9,7 +9,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.utils import ( effective_qubit_temperature, format_error_single_cell, @@ -64,13 +64,15 @@ class ReadoutCharacterizationData(Data): def _acquisition( - params: ReadoutCharacterizationParameters, platform: Platform, qubits: Qubits + params: ReadoutCharacterizationParameters, + platform: Platform, + targets: list[QubitId], ) -> ReadoutCharacterizationData: """Data acquisition for resonator spectroscopy.""" data = ReadoutCharacterizationData( qubit_frequencies={ - qubit: platform.qubits[qubit].drive_frequency for qubit in qubits + qubit: platform.qubits[qubit].drive_frequency for qubit in targets } ) @@ -82,7 +84,7 @@ def _acquisition( RX_pulses = {} ro_pulses = {} sequence = PulseSequence() - for qubit in qubits: + for qubit in targets: start = 0 if state == 1: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) @@ -113,7 +115,7 @@ def _acquisition( ) # Save the data - for qubit in qubits: + for qubit in targets: for i, ro_pulse in enumerate(ro_pulses[qubit]): result = results[ro_pulse.serial] data.register_qubit( @@ -195,7 +197,9 @@ def _fit(data: ReadoutCharacterizationData) -> ReadoutCharacterizationResults: def _plot( - data: ReadoutCharacterizationData, fit: ReadoutCharacterizationResults, qubit + data: ReadoutCharacterizationData, + fit: ReadoutCharacterizationResults, + target: QubitId, ): """Plotting function for ReadoutCharacterization.""" @@ -206,7 +210,7 @@ def _plot( fig = go.Figure() for state in range(2): for measure in range(2): - shots = data.data[qubit, state, measure] + shots = data.data[target, state, measure] fig.add_trace( go.Scatter( @@ -225,12 +229,12 @@ def _plot( fig2.add_trace( go.Heatmap( - z=fit.Lambda_M[qubit], + z=fit.Lambda_M[target], ) ) fitting_report = table_html( table_dict( - qubit, + target, [ "Assignment Fidelity", "Fidelity", @@ -238,11 +242,11 @@ def _plot( "Effective Qubit Temperature [K]", ], [ - np.round(fit.assignment_fidelity[qubit], 6), - np.round(fit.fidelity[qubit], 6), - np.round(fit.qnd[qubit], 6), + np.round(fit.assignment_fidelity[target], 6), + np.round(fit.fidelity[target], 6), + np.round(fit.qnd[target], 6), format_error_single_cell( - round_report([fit.effective_temperature[qubit]]) + round_report([fit.effective_temperature[target]]) ), ], ) @@ -252,10 +256,10 @@ def _plot( def _update( - results: ReadoutCharacterizationResults, platform: Platform, qubit: QubitId + results: ReadoutCharacterizationResults, platform: Platform, target: QubitId ): - update.readout_fidelity(results.fidelity[qubit], platform, qubit) - update.assignment_fidelity(results.assignment_fidelity[qubit], platform, qubit) + update.readout_fidelity(results.fidelity[target], platform, target) + update.assignment_fidelity(results.assignment_fidelity[target], platform, target) readout_characterization = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_mitigation_matrix.py b/src/qibocal/protocols/characterization/readout_mitigation_matrix.py index cf4fcda57..9c8f563ad 100644 --- a/src/qibocal/protocols/characterization/readout_mitigation_matrix.py +++ b/src/qibocal/protocols/characterization/readout_mitigation_matrix.py @@ -11,7 +11,7 @@ from qibolab.pulses import PulseSequence from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from .utils import calculate_frequencies @@ -45,7 +45,7 @@ class ReadoutMitigationMatrixResults(Results): class ReadoutMitigationMatrixData(Data): """ReadoutMitigationMatrix acquisition outputs.""" - qubits_list: list + qubit_list: list[QubitId] """List of qubit ids""" nshots: int """Number of shots""" @@ -90,13 +90,13 @@ def __getitem__(self, qubits): def _acquisition( params: ReadoutMitigationMatrixParameters, platform: Platform, - qubits: list[Qubits], + targets: list[list[QubitId]], ) -> ReadoutMitigationMatrixData: data = ReadoutMitigationMatrixData( - nshots=params.nshots, qubits_list=[list(qq) for qq in qubits] + nshots=params.nshots, qubit_list=[list(qq) for qq in targets] ) - for qubit_list in qubits: - nqubits = len(qubit_list) + for qubits in targets: + nqubits = len(qubits) for i in range(2**nqubits): state = format(i, f"0{nqubits}b") if params.pulses: @@ -105,28 +105,30 @@ def _acquisition( if bit == "1": sequence.add( platform.create_RX_pulse( - qubit_list[q], start=0, relative_phase=0 + qubits[q], start=0, relative_phase=0 ) ) measurement_start = sequence.finish for q in range(len(state)): MZ_pulse = platform.create_MZ_pulse( - qubit_list[q], start=measurement_start + qubits[q], start=measurement_start ) sequence.add(MZ_pulse) results = platform.execute_pulse_sequence( sequence, ExecutionParameters(nshots=params.nshots) ) - data.add(qubit_list, state, calculate_frequencies(results, qubit_list)) + data.add( + tuple(qubits), state, calculate_frequencies(results, tuple(qubits)) + ) else: c = Circuit(platform.nqubits) for q, bit in enumerate(state): if bit == "1": - c.add(gates.X(qubit_list[q])) - c.add(gates.M(qubit_list[q])) + c.add(gates.X(qubits[q])) + c.add(gates.M(qubits[q])) results = c(nshots=params.nshots) - data.add(qubit_list, state, dict(results.frequencies())) + data.add(tuple(qubits), state, dict(results.frequencies())) return data @@ -134,7 +136,7 @@ def _fit(data: ReadoutMitigationMatrixData) -> ReadoutMitigationMatrixResults: """Post processing for readout mitigation matrix protocol.""" readout_mitigation_matrix = {} measurement_matrix = {} - for qubit in data.qubits_list: + for qubit in data.qubit_list: qubit_data = data[qubit] matrix = np.zeros((2 ** len(qubit), 2 ** len(qubit))) computational_basis = [ @@ -167,16 +169,18 @@ def _fit(data: ReadoutMitigationMatrixData) -> ReadoutMitigationMatrixResults: def _plot( - data: ReadoutMitigationMatrixData, fit: ReadoutMitigationMatrixResults, qubit + data: ReadoutMitigationMatrixData, + fit: ReadoutMitigationMatrixResults, + target: list[QubitId], ): """Plotting function for readout mitigation matrix.""" fitting_report = "" figs = [] if fit is not None: computational_basis = [ - format(i, f"0{len(qubit)}b") for i in range(2 ** len(qubit)) + format(i, f"0{len(target)}b") for i in range(2 ** len(target)) ] - z = fit.measurement_matrix[tuple(qubit)] + z = fit.measurement_matrix[tuple(target)] fig = px.imshow( z, diff --git a/src/qibocal/protocols/characterization/readout_optimization/resonator_amplitude.py b/src/qibocal/protocols/characterization/readout_optimization/resonator_amplitude.py index 1142256f7..8badb8db7 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/resonator_amplitude.py +++ b/src/qibocal/protocols/characterization/readout_optimization/resonator_amplitude.py @@ -11,7 +11,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.fitting.classifier.qubit_fit import QubitFit from qibocal.protocols.characterization.utils import table_dict, table_html @@ -65,7 +65,7 @@ class ResonatorAmplitudeResults(Results): def _acquisition( params: ResonatorAmplitudeParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorAmplitudeData: r""" Data acquisition for resoantor amplitude optmization. @@ -76,14 +76,14 @@ def _acquisition( Args: params (:class:`ResonatorAmplitudeParameters`): input parameters platform (:class:`Platform`): Qibolab's platform - qubits (dict): dict of target :class:`Qubit` objects to be characterized + targets (list): list of QubitIds to be characterized Returns: data (:class:`ResonatorAmplitudeData`) """ data = ResonatorAmplitudeData() - for qubit in qubits: + for qubit in targets: error = 1 old_amp = platform.qubits[qubit].native_gates.MZ.amplitude new_amp = params.amplitude_start @@ -160,7 +160,9 @@ def _fit(data: ResonatorAmplitudeData) -> ResonatorAmplitudeResults: return ResonatorAmplitudeResults(lowest_err, best_amps, best_angle, best_threshold) -def _plot(data: ResonatorAmplitudeData, fit: ResonatorAmplitudeResults, qubit): +def _plot( + data: ResonatorAmplitudeData, fit: ResonatorAmplitudeResults, target: QubitId +): """Plotting function for Optimization RO amplitude.""" figures = [] opacity = 1 @@ -172,8 +174,8 @@ def _plot(data: ResonatorAmplitudeData, fit: ResonatorAmplitudeResults, qubit): if fit is not None: fig.add_trace( go.Scatter( - x=data[qubit]["amp"], - y=data[qubit]["error"], + x=data[target]["amp"], + y=data[target]["error"], opacity=opacity, showlegend=True, mode="lines+markers", @@ -184,9 +186,9 @@ def _plot(data: ResonatorAmplitudeData, fit: ResonatorAmplitudeResults, qubit): fitting_report = table_html( table_dict( - qubit, + target, "Best Readout Amplitude [a.u.]", - np.round(fit.best_amp[qubit], 4), + np.round(fit.best_amp[target], 4), ) ) @@ -201,10 +203,10 @@ def _plot(data: ResonatorAmplitudeData, fit: ResonatorAmplitudeResults, qubit): return figures, fitting_report -def _update(results: ResonatorAmplitudeResults, platform: Platform, qubit: QubitId): - update.readout_amplitude(results.best_amp[qubit], platform, qubit) - update.iq_angle(results.best_angle[qubit], platform, qubit) - update.threshold(results.best_threshold[qubit], platform, qubit) +def _update(results: ResonatorAmplitudeResults, platform: Platform, target: QubitId): + update.readout_amplitude(results.best_amp[target], platform, target) + update.iq_angle(results.best_angle[target], platform, target) + update.threshold(results.best_threshold[target], platform, target) resonator_amplitude = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_optimization/resonator_frequency.py b/src/qibocal/protocols/characterization/readout_optimization/resonator_frequency.py index 5ff474db4..fdd042398 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/resonator_frequency.py +++ b/src/qibocal/protocols/characterization/readout_optimization/resonator_frequency.py @@ -11,7 +11,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.fitting.classifier.qubit_fit import QubitFit from qibocal.protocols.characterization.utils import HZ_TO_GHZ, table_dict, table_html @@ -66,7 +66,7 @@ def unique_freqs(self, qubit: QubitId) -> np.ndarray: def _acquisition( - params: ResonatorFrequencyParameters, platform: Platform, qubits: Qubits + params: ResonatorFrequencyParameters, platform: Platform, targets: list[QubitId] ) -> ResonatorFrequencyData: r""" Data acquisition for readout frequency optimization. @@ -78,7 +78,7 @@ def _acquisition( Args: params (ResonatorFrequencyParameters): experiment's parameters platform (Platform): Qibolab platform object - qubits (dict): list of target qubits to perform the action + qubits (list): list of target qubits to perform the action """ @@ -91,7 +91,7 @@ def _acquisition( sequence_1 = PulseSequence() ro_pulses = {} qd_pulses = {} - for qubit in qubits: + for qubit in targets: qd_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=qd_pulses[qubit].finish @@ -109,7 +109,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[ro_pulses[qubit] for qubit in qubits], + pulses=[ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -134,7 +134,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: for k, freq in enumerate(delta_frequency_range): i_values = [] q_values = [] @@ -183,10 +183,12 @@ def _fit(data: ResonatorFrequencyData) -> ResonatorFrequencyResults: ) -def _plot(data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, qubit): +def _plot( + data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, target: QubitId +): """Plotting function for Optimization RO frequency.""" figures = [] - freqs = data[qubit]["freq"] + freqs = data[target]["freq"] opacity = 1 fitting_report = "" fig = make_subplots( @@ -197,7 +199,7 @@ def _plot(data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, qubit): fig.add_trace( go.Scatter( x=freqs, - y=data[qubit]["assignment_fidelity"], + y=data[target]["assignment_fidelity"], opacity=opacity, showlegend=True, ), @@ -207,9 +209,9 @@ def _plot(data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, qubit): fitting_report = table_html( table_dict( - qubit, + target, "Best Resonator Frequency [Hz]", - np.round(fit.best_freq[qubit], 4), + np.round(fit.best_freq[target], 4), ) ) @@ -224,10 +226,10 @@ def _plot(data: ResonatorFrequencyData, fit: ResonatorFrequencyResults, qubit): return figures, fitting_report -def _update(results: ResonatorFrequencyResults, platform: Platform, qubit: QubitId): - update.readout_frequency(results.best_freq[qubit], platform, qubit) - update.threshold(results.best_threshold[qubit], platform, qubit) - update.iq_angle(results.best_angle[qubit], platform, qubit) +def _update(results: ResonatorFrequencyResults, platform: Platform, target: QubitId): + update.readout_frequency(results.best_freq[target], platform, target) + update.threshold(results.best_threshold[target], platform, target) + update.iq_angle(results.best_angle[target], platform, target) resonator_frequency = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency.py b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency.py index eebc08cc3..b0185fc10 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency.py +++ b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency.py @@ -7,7 +7,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization import classification from qibocal.protocols.characterization.readout_optimization.resonator_frequency import ( ResonatorFrequencyType, @@ -50,7 +50,7 @@ class TwpaFrequencyResults(Results): def _acquisition( params: TwpaFrequencyParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> TwpaFrequencyData: r""" Data acquisition for TWPA power optmization. @@ -74,7 +74,7 @@ def _acquisition( ).astype(int) initial_twpa_freq = {} - for qubit in qubits: + for qubit in targets: initial_twpa_freq[qubit] = float( platform.qubits[qubit].twpa.local_oscillator.frequency ) @@ -83,7 +83,7 @@ def _acquisition( ) for freq in freq_range: - for qubit in qubits: + for qubit in targets: platform.qubits[qubit].twpa.local_oscillator.frequency = ( initial_twpa_freq[qubit] + freq ) @@ -93,10 +93,10 @@ def _acquisition( {"nshots": params.nshots} ), platform, - qubits, + targets, ) classification_result = classification._fit(classification_data) - for qubit in qubits: + for qubit in targets: data.register_qubit( ResonatorFrequencyType, (qubit), @@ -137,23 +137,23 @@ def _fit(data: TwpaFrequencyData) -> TwpaFrequencyResults: ) -def _plot(data: TwpaFrequencyData, fit: TwpaFrequencyResults, qubit): +def _plot(data: TwpaFrequencyData, fit: TwpaFrequencyResults, target: QubitId): """Plotting function that shows the assignment fidelity for different values of the twpa frequency for a single qubit""" figures = [] fitting_report = "" if fit is not None: - qubit_data = data.data[qubit] + qubit_data = data.data[target] fidelities = qubit_data["assignment_fidelity"] frequencies = qubit_data["freq"] fitting_report = table_html( table_dict( - qubit, + target, ["Best assignment fidelity", "TWPA Frequency [Hz]"], [ - np.round(fit.best_fidelities[qubit], 3), - fit.best_freqs[qubit], + np.round(fit.best_fidelities[target], 3), + fit.best_freqs[target], ], ) ) @@ -172,10 +172,10 @@ def _plot(data: TwpaFrequencyData, fit: TwpaFrequencyResults, qubit): return figures, fitting_report -def _update(results: TwpaFrequencyResults, platform: Platform, qubit: QubitId): - update.twpa_frequency(results.best_freqs[qubit], platform, qubit) - update.iq_angle(results.best_angles[qubit], platform, qubit) - update.threshold(results.best_thresholds[qubit], platform, qubit) +def _update(results: TwpaFrequencyResults, platform: Platform, target: QubitId): + update.twpa_frequency(results.best_freqs[target], platform, target) + update.iq_angle(results.best_angles[target], platform, target) + update.threshold(results.best_thresholds[target], platform, target) twpa_frequency = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_SNR.py b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_SNR.py index 170567861..eb2a63079 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_SNR.py +++ b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_SNR.py @@ -8,7 +8,7 @@ from qibolab.platform import Platform from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.resonator_spectroscopy import ( resonator_spectroscopy, ) @@ -91,7 +91,7 @@ def load(cls, path): def _acquisition( params: ResonatorTWPAFrequencyParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorTWPAFrequencyData: r""" Data acquisition for TWPA frequency optmization using SNR. @@ -118,14 +118,14 @@ def _acquisition( ) initial_twpa_freq = {} - for qubit in qubits: + for qubit in targets: initial_twpa_freq[qubit] = float( platform.qubits[qubit].twpa.local_oscillator.frequency ) for _freq in TWPAFrequency_range: - for qubit in qubits: - qubits[qubit].twpa.local_oscillator.frequency = ( + for qubit in targets: + platform.qubits[qubit].twpa.local_oscillator.frequency = ( initial_twpa_freq[qubit] + _freq ) @@ -139,10 +139,10 @@ def _acquisition( } ), platform, - qubits, + targets, ) - for qubit in qubits: + for qubit in targets: data.register_qubit( ResonatorTWPAFrequencyType, (qubit), @@ -188,7 +188,7 @@ def _fit(data: ResonatorTWPAFrequencyData) -> ResonatorTWPAFrequencyResults: ) -def _plot(data: ResonatorTWPAFrequencyData, fit: ResonatorTWPAFrequencyResults, qubit): +def _plot(data: ResonatorTWPAFrequencyData, fit: ResonatorTWPAFrequencyResults, target): """Plotting for ResonatorTWPAFrequency.""" figures = [] @@ -205,7 +205,7 @@ def _plot(data: ResonatorTWPAFrequencyData, fit: ResonatorTWPAFrequencyResults, ) fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] resonator_frequencies = qubit_data.freq * HZ_TO_GHZ twpa_frequencies = qubit_data.twpa_freq * HZ_TO_GHZ @@ -236,16 +236,16 @@ def _plot(data: ResonatorTWPAFrequencyData, fit: ResonatorTWPAFrequencyResults, if fit is not None: label_1 = "TWPA Frequency [Hz]" - twpa_frequency = np.round(fit.twpa_frequency[qubit]) - if qubit in fit.bare_frequency: + twpa_frequency = np.round(fit.twpa_frequency[target]) + if target in fit.bare_frequency: label_2 = "High Power Resonator Frequency [Hz]" - resonator_frequency = np.round(fit.bare_frequency[qubit]) + resonator_frequency = np.round(fit.bare_frequency[target]) else: label_2 = "Low Power Resonator Frequency [Hz]" - resonator_frequency = np.round(fit.frequency[qubit]) + resonator_frequency = np.round(fit.frequency[target]) summary = table_dict( - qubit, + target, [ label_2, label_1, diff --git a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_power.py b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_power.py index d86ec06bd..c47fef499 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_power.py +++ b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/frequency_power.py @@ -7,7 +7,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization import classification from qibocal.protocols.characterization.utils import HZ_TO_GHZ, table_dict, table_html @@ -65,7 +65,7 @@ class TwpaFrequencyPowerResults(Results): def _acquisition( params: TwpaFrequencyPowerParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> TwpaFrequencyPowerData: r""" Data acquisition for TWPA frequency vs. power optmization. @@ -76,7 +76,7 @@ def _acquisition( Args: params (:class:`TwpaFrequencyPowerParameters`): input parameters platform (:class:`Platform`): Qibolab's platform - qubits (dict): dict of target :class:`Qubit` objects to be characterized + targets (list): list of qubit to be characterized Returns: data (:class:`TwpaFrequencyPowerData`) @@ -94,7 +94,7 @@ def _acquisition( initial_twpa_freq = {} initial_twpa_power = {} - for qubit in qubits: + for qubit in targets: initial_twpa_freq[qubit] = platform.qubits[ qubit ].twpa.local_oscillator.frequency @@ -106,7 +106,7 @@ def _acquisition( ) for power in power_range: - for qubit in qubits: + for qubit in targets: platform.qubits[qubit].twpa.local_oscillator.power = ( initial_twpa_power[qubit] + power ) @@ -116,7 +116,7 @@ def _acquisition( {"nshots": params.nshots} ), platform, - qubits, + targets, ) classification_result = classification._fit(classification_data) @@ -172,25 +172,27 @@ def _fit(data: TwpaFrequencyPowerData) -> TwpaFrequencyPowerResults: ) -def _plot(data: TwpaFrequencyPowerData, fit: TwpaFrequencyPowerResults, qubit): +def _plot( + data: TwpaFrequencyPowerData, fit: TwpaFrequencyPowerResults, target: QubitId +): """Plotting function that shows the assignment fidelity for different values of the twpa frequency for a single qubit""" figures = [] fitting_report = "" if fit is not None: - qubit_data = data.data[qubit] + qubit_data = data.data[target] fidelities = qubit_data["assignment_fidelity"] frequencies = qubit_data["freq"] powers = qubit_data["power"] fitting_report = table_html( table_dict( - qubit, + target, ["Best assignment fidelity", "TWPA Frequency [Hz]", "TWPA Power [dBm]"], [ - np.round(fit.best_fidelities[qubit], 3), - fit.best_freqs[qubit], - np.round(fit.best_powers[qubit], 3), + np.round(fit.best_fidelities[target], 3), + fit.best_freqs[target], + np.round(fit.best_powers[target], 3), ], ) ) @@ -214,11 +216,11 @@ def _plot(data: TwpaFrequencyPowerData, fit: TwpaFrequencyPowerResults, qubit): return figures, fitting_report -def _update(results: TwpaFrequencyPowerResults, platform: Platform, qubit: QubitId): - update.twpa_frequency(results.best_freqs[qubit], platform, qubit) - update.twpa_power(results.best_powers[qubit], platform, qubit) - update.iq_angle(results.best_angles[qubit], platform, qubit) - update.threshold(results.best_thresholds[qubit], platform, qubit) +def _update(results: TwpaFrequencyPowerResults, platform: Platform, target: QubitId): + update.twpa_frequency(results.best_freqs[target], platform, target) + update.twpa_power(results.best_powers[target], platform, target) + update.iq_angle(results.best_angles[target], platform, target) + update.threshold(results.best_thresholds[target], platform, target) twpa_frequency_power = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power.py b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power.py index 5540fae40..463d6201f 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power.py +++ b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power.py @@ -6,7 +6,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from qibocal.protocols.characterization import classification from qibocal.protocols.characterization.utils import table_dict, table_html @@ -54,7 +54,7 @@ class TwpaPowerResults(Results): def _acquisition( params: TwpaPowerParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> TwpaPowerData: r""" Data acquisition for TWPA power optmization. @@ -65,7 +65,7 @@ def _acquisition( Args: params (:class:`TwpaPowerParameters`): input parameters platform (:class:`Platform`): Qibolab's platform - qubits (dict): dict of target :class:`Qubit` objects to be characterized + targets (list): list of QubitId to be characterized Returns: data (:class:`TwpaFrequencyData`) @@ -78,14 +78,14 @@ def _acquisition( ) initial_twpa_power = {} - for qubit in qubits: + for qubit in targets: initial_twpa_power[qubit] = platform.qubits[qubit].twpa.local_oscillator.power data.powers[qubit] = list( platform.qubits[qubit].twpa.local_oscillator.power + power_range ) for power in power_range: - for qubit in qubits: + for qubit in targets: platform.qubits[qubit].twpa.local_oscillator.power = ( initial_twpa_power[qubit] + power ) @@ -95,11 +95,11 @@ def _acquisition( {"nshots": params.nshots} ), platform, - qubits, + targets, ) classification_result = classification._fit(classification_data) - for qubit in qubits: + for qubit in targets: data.register_qubit( TwpaPowerType, (qubit), @@ -141,7 +141,7 @@ def _fit(data: TwpaPowerData) -> TwpaPowerResults: ) -def _plot(data: TwpaPowerData, fit: TwpaPowerResults, qubit): +def _plot(data: TwpaPowerData, fit: TwpaPowerResults, target: QubitId): """Plotting function that shows the assignment fidelity for different values of the twpa power for a single qubit.""" @@ -149,16 +149,16 @@ def _plot(data: TwpaPowerData, fit: TwpaPowerResults, qubit): fitting_report = "" if fit is not None: - qubit_data = data.data[qubit] + qubit_data = data.data[target] fidelities = qubit_data["assignment_fidelity"] powers = qubit_data["power"] fitting_report = table_html( table_dict( - qubit, + target, ["Best assignment fidelity", "TWPA Power [dBm]"], [ - np.round(fit.best_fidelities[qubit], 3), - np.round(fit.best_powers[qubit], 3), + np.round(fit.best_fidelities[target], 3), + np.round(fit.best_powers[target], 3), ], ) ) @@ -174,10 +174,10 @@ def _plot(data: TwpaPowerData, fit: TwpaPowerResults, qubit): return figures, fitting_report -def _update(results: TwpaPowerResults, platform: Platform, qubit: QubitId): - update.twpa_power(results.best_powers[qubit], platform, qubit) - update.iq_angle(results.best_angles[qubit], platform, qubit) - update.threshold(results.best_thresholds[qubit], platform, qubit) +def _update(results: TwpaPowerResults, platform: Platform, target: QubitId): + update.twpa_power(results.best_powers[target], platform, target) + update.iq_angle(results.best_angles[target], platform, target) + update.threshold(results.best_thresholds[target], platform, target) twpa_power = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power_SNR.py b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power_SNR.py index ce929abfa..3f96b71c0 100644 --- a/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power_SNR.py +++ b/src/qibocal/protocols/characterization/readout_optimization/twpa_calibration/power_SNR.py @@ -8,7 +8,7 @@ from qibolab.platform import Platform from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.resonator_spectroscopy import ( resonator_spectroscopy, ) @@ -91,7 +91,7 @@ def load(cls, path): def _acquisition( params: ResonatorTWPAPowerParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorTWPAPowerData: r""" Data acquisition for TWPA power optmization using SNR. @@ -118,14 +118,16 @@ def _acquisition( ) initial_twpa_pow = {} - for qubit in qubits: + for qubit in targets: initial_twpa_pow[qubit] = float( platform.qubits[qubit].twpa.local_oscillator.power ) for _pow in TWPAPower_range: - for qubit in qubits: - qubits[qubit].twpa.local_oscillator.power = initial_twpa_pow[qubit] + _pow + for qubit in targets: + platform.qubits[qubit].twpa.local_oscillator.power = ( + initial_twpa_pow[qubit] + _pow + ) resonator_spectroscopy_data, _ = resonator_spectroscopy.acquisition( resonator_spectroscopy.parameters_type.load( @@ -137,10 +139,10 @@ def _acquisition( } ), platform, - qubits, + targets, ) - for qubit in qubits: + for qubit in targets: data.register_qubit( ResonatorTWPAPowerType, (qubit), @@ -186,7 +188,7 @@ def _fit(data: ResonatorTWPAPowerData, fit_type="att") -> ResonatorTWPAPowerResu ) -def _plot(data: ResonatorTWPAPowerData, fit: ResonatorTWPAPowerResults, qubit): +def _plot(data: ResonatorTWPAPowerData, fit: ResonatorTWPAPowerResults, target): """Plotting for ResonatorTWPAPower.""" figures = [] @@ -203,7 +205,7 @@ def _plot(data: ResonatorTWPAPowerData, fit: ResonatorTWPAPowerResults, qubit): ) fitting_report = "" - qubit_data = data[qubit] + qubit_data = data[target] frequencies = qubit_data.freq * HZ_TO_GHZ powers = qubit_data.twpa_pow @@ -234,16 +236,16 @@ def _plot(data: ResonatorTWPAPowerData, fit: ResonatorTWPAPowerResults, qubit): if fit is not None: label_1 = "TWPA Power" - twpa_power = np.round(fit.twpa_power[qubit]) - if qubit in fit.bare_frequency: + twpa_power = np.round(fit.twpa_power[target]) + if target in fit.bare_frequency: label_2 = "High Power Resonator Frequency [Hz]" - resonator_frequency = np.round(fit.bare_frequency[qubit]) + resonator_frequency = np.round(fit.bare_frequency[target]) else: label_2 = "Low Power Resonator Frequency [Hz]" - resonator_frequency = np.round(fit.frequency[qubit]) + resonator_frequency = np.round(fit.frequency[target]) summary = table_dict( - qubit, + target, [ label_2, label_1, diff --git a/src/qibocal/protocols/characterization/resonator_punchout.py b/src/qibocal/protocols/characterization/resonator_punchout.py index a97c26091..3d3f3c956 100644 --- a/src/qibocal/protocols/characterization/resonator_punchout.py +++ b/src/qibocal/protocols/characterization/resonator_punchout.py @@ -12,7 +12,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from .utils import HZ_TO_GHZ, fit_punchout, norm, table_dict, table_html @@ -84,7 +84,7 @@ def register_qubit(self, qubit, freq, amp, signal, phase): def _acquisition( params: ResonatorPunchoutParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorPunchoutData: """Data acquisition for Punchout over amplitude.""" # create a sequence of pulses for the experiment: @@ -95,7 +95,7 @@ def _acquisition( ro_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: ro_pulses[qubit] = platform.create_qubit_readout_pulse(qubit, start=0) if params.amplitude is not None: ro_pulses[qubit].amplitude = params.amplitude @@ -111,7 +111,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -122,7 +122,7 @@ def _acquisition( amp_sweeper = Sweeper( Parameter.amplitude, amplitude_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.FACTOR, ) @@ -164,7 +164,9 @@ def _fit(data: ResonatorPunchoutData, fit_type="amp") -> ResonatorPunchoutResult return ResonatorPunchoutResults(*fit_punchout(data, fit_type)) -def _plot(data: ResonatorPunchoutData, qubit, fit: ResonatorPunchoutResults = None): +def _plot( + data: ResonatorPunchoutData, target: QubitId, fit: ResonatorPunchoutResults = None +): """Plotting function for ResonatorPunchout.""" figures = [] fitting_report = "" @@ -178,7 +180,7 @@ def _plot(data: ResonatorPunchoutData, qubit, fit: ResonatorPunchoutResults = No "phase [rad]", ), ) - qubit_data = data[qubit] + qubit_data = data[target] frequencies = qubit_data.freq * HZ_TO_GHZ amplitudes = qubit_data.amp n_amps = len(np.unique(qubit_data.amp)) @@ -214,10 +216,10 @@ def _plot(data: ResonatorPunchoutData, qubit, fit: ResonatorPunchoutResults = No fig.add_trace( go.Scatter( x=[ - fit.readout_frequency[qubit] * HZ_TO_GHZ, + fit.readout_frequency[target] * HZ_TO_GHZ, ], y=[ - fit.readout_amplitude[qubit], + fit.readout_amplitude[target], ], mode="markers", marker=dict( @@ -231,16 +233,16 @@ def _plot(data: ResonatorPunchoutData, qubit, fit: ResonatorPunchoutResults = No ) fitting_report = table_html( table_dict( - qubit, + target, [ "Low Power Resonator Frequency [Hz]", "Low Power readout amplitude [a.u.]", "High Power Resonator Frequency [Hz]", ], [ - np.round(fit.readout_frequency[qubit]), - np.round(fit.readout_amplitude[qubit], 3), - np.round(fit.bare_frequency[qubit]), + np.round(fit.readout_frequency[target]), + np.round(fit.readout_amplitude[target], 3), + np.round(fit.bare_frequency[target]), ], ) ) @@ -259,10 +261,10 @@ def _plot(data: ResonatorPunchoutData, qubit, fit: ResonatorPunchoutResults = No return figures, fitting_report -def _update(results: ResonatorPunchoutResults, platform: Platform, qubit: QubitId): - update.readout_frequency(results.readout_frequency[qubit], platform, qubit) - update.bare_resonator_frequency(results.bare_frequency[qubit], platform, qubit) - update.readout_amplitude(results.readout_amplitude[qubit], platform, qubit) +def _update(results: ResonatorPunchoutResults, platform: Platform, target: QubitId): + update.readout_frequency(results.readout_frequency[target], platform, target) + update.bare_resonator_frequency(results.bare_frequency[target], platform, target) + update.readout_amplitude(results.readout_amplitude[target], platform, target) resonator_punchout = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/resonator_punchout_attenuation.py b/src/qibocal/protocols/characterization/resonator_punchout_attenuation.py index ab4ebfe52..f9daa6b3d 100644 --- a/src/qibocal/protocols/characterization/resonator_punchout_attenuation.py +++ b/src/qibocal/protocols/characterization/resonator_punchout_attenuation.py @@ -12,7 +12,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from .utils import HZ_TO_GHZ, fit_punchout, norm, table_dict, table_html @@ -80,7 +80,7 @@ def register_qubit(self, qubit, freq, att, signal, phase): def _acquisition( params: ResonatorPunchoutAttenuationParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorPunchoutAttenuationData: """Data acquisition for Punchout over attenuation.""" # create a sequence of pulses for the experiment: @@ -90,7 +90,7 @@ def _acquisition( sequence = PulseSequence() ro_pulses = {} - for qubit in qubits: + for qubit in targets: ro_pulses[qubit] = platform.create_qubit_readout_pulse(qubit, start=0) sequence.add(ro_pulses[qubit]) @@ -102,7 +102,7 @@ def _acquisition( freq_sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - [ro_pulses[qubit] for qubit in qubits], + [ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -111,7 +111,7 @@ def _acquisition( att_sweeper = Sweeper( Parameter.attenuation, attenuation_range, - qubits=list(qubits.values()), + qubits=[platform.qubits[qubit] for qubit in targets], type=SweeperType.ABSOLUTE, ) @@ -130,7 +130,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] data.register_qubit( qubit, @@ -158,7 +158,7 @@ def _fit( def _plot( data: ResonatorPunchoutAttenuationData, - qubit, + target: QubitId, fit: ResonatorPunchoutAttenuationResults = None, ): """Plotting for ResonatorPunchoutAttenuation.""" @@ -176,7 +176,7 @@ def _plot( ), ) - qubit_data = data[qubit] + qubit_data = data[target] frequencies = qubit_data.freq * HZ_TO_GHZ attenuations = qubit_data.att n_att = len(np.unique(qubit_data.att)) @@ -214,10 +214,10 @@ def _plot( fig.add_trace( go.Scatter( x=[ - fit.readout_frequency[qubit] * HZ_TO_GHZ, + fit.readout_frequency[target] * HZ_TO_GHZ, ], y=[ - fit.readout_attenuation[qubit], + fit.readout_attenuation[target], ], mode="markers", marker=dict( @@ -231,16 +231,16 @@ def _plot( ) fitting_report = table_html( table_dict( - qubit, + target, [ "Low Power Resonator Frequency [Hz]", "Readout Attenuation [dB]", "High Power Resonator Frequency [Hz]", ], [ - np.round(fit.readout_frequency[qubit], 0), - fit.readout_attenuation[qubit], - np.round(fit.bare_frequency[qubit]), + np.round(fit.readout_frequency[target], 0), + fit.readout_attenuation[target], + np.round(fit.bare_frequency[target]), ], ) ) @@ -255,11 +255,11 @@ def _plot( def _update( - results: ResonatorPunchoutAttenuationResults, platform: Platform, qubit: QubitId + results: ResonatorPunchoutAttenuationResults, platform: Platform, target: QubitId ): - update.readout_frequency(results.readout_frequency[qubit], platform, qubit) - update.bare_resonator_frequency(results.bare_frequency[qubit], platform, qubit) - update.readout_attenuation(results.readout_attenuation[qubit], platform, qubit) + update.readout_frequency(results.readout_frequency[target], platform, target) + update.bare_resonator_frequency(results.bare_frequency[target], platform, target) + update.readout_attenuation(results.readout_attenuation[target], platform, target) resonator_punchout_attenuation = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/resonator_spectroscopy.py b/src/qibocal/protocols/characterization/resonator_spectroscopy.py index d16c038bd..19c527d91 100644 --- a/src/qibocal/protocols/characterization/resonator_spectroscopy.py +++ b/src/qibocal/protocols/characterization/resonator_spectroscopy.py @@ -10,7 +10,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from .utils import PowerLevel, lorentzian_fit, spectroscopy_plot @@ -86,7 +86,7 @@ def load(cls, path): def _acquisition( - params: ResonatorSpectroscopyParameters, platform: Platform, qubits: Qubits + params: ResonatorSpectroscopyParameters, platform: Platform, targets: list[QubitId] ) -> ResonatorSpectroscopyData: """Data acquisition for resonator spectroscopy.""" # create a sequence of pulses for the experiment: @@ -97,7 +97,7 @@ def _acquisition( ro_pulses = {} amplitudes = {} - for qubit in qubits: + for qubit in targets: ro_pulses[qubit] = platform.create_qubit_readout_pulse(qubit, start=0) if params.amplitude is not None: ro_pulses[qubit].amplitude = params.amplitude @@ -112,7 +112,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[ro_pulses[qubit] for qubit in qubits], + pulses=[ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) @@ -134,7 +134,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] # store the results data.register_qubit( @@ -151,6 +151,7 @@ def _acquisition( def _fit(data: ResonatorSpectroscopyData) -> ResonatorSpectroscopyResults: """Post-processing function for ResonatorSpectroscopy.""" + # TODO: change data.qubits qubits = data.qubits bare_frequency = {} frequency = {} @@ -180,20 +181,24 @@ def _fit(data: ResonatorSpectroscopyData) -> ResonatorSpectroscopyResults: ) -def _plot(data: ResonatorSpectroscopyData, qubit, fit: ResonatorSpectroscopyResults): +def _plot( + data: ResonatorSpectroscopyData, target: QubitId, fit: ResonatorSpectroscopyResults +): """Plotting function for ResonatorSpectroscopy.""" - return spectroscopy_plot(data, qubit, fit) + return spectroscopy_plot(data, target, fit) -def _update(results: ResonatorSpectroscopyResults, platform: Platform, qubit: QubitId): - update.readout_frequency(results.frequency[qubit], platform, qubit) +def _update(results: ResonatorSpectroscopyResults, platform: Platform, target: QubitId): + update.readout_frequency(results.frequency[target], platform, target) # if this condition is satifisfied means that we are in the low power regime # therefore we update also the readout amplitude if len(results.bare_frequency) == 0: - update.readout_amplitude(results.amplitude[qubit], platform, qubit) + update.readout_amplitude(results.amplitude[target], platform, target) else: - update.bare_resonator_frequency(results.bare_frequency[qubit], platform, qubit) + update.bare_resonator_frequency( + results.bare_frequency[target], platform, target + ) resonator_spectroscopy = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/resonator_spectroscopy_attenuation.py b/src/qibocal/protocols/characterization/resonator_spectroscopy_attenuation.py index 9c7c8f370..46c0fb634 100644 --- a/src/qibocal/protocols/characterization/resonator_spectroscopy_attenuation.py +++ b/src/qibocal/protocols/characterization/resonator_spectroscopy_attenuation.py @@ -9,7 +9,7 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibocal import update -from qibocal.auto.operation import Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Parameters, Results, Routine from .resonator_spectroscopy import ResonatorSpectroscopyData, ResSpecType from .utils import PowerLevel, lorentzian_fit, spectroscopy_plot @@ -70,7 +70,7 @@ class ResonatorSpectroscopyAttenuationData(ResonatorSpectroscopyData): def _acquisition( params: ResonatorSpectroscopyAttenuationParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitId], ) -> ResonatorSpectroscopyAttenuationData: """Data acquisition for resonator spectroscopy attenuation.""" # create a sequence of pulses for the experiment: @@ -82,7 +82,7 @@ def _acquisition( amplitudes = {} attenuations = {} - for qubit in qubits: + for qubit in targets: ro_pulses[qubit] = platform.create_qubit_readout_pulse(qubit, start=0) if params.amplitude is not None: ro_pulses[qubit].amplitude = params.amplitude @@ -90,9 +90,9 @@ def _acquisition( amplitudes[qubit] = ro_pulses[qubit].amplitude if params.attenuation is not None: - qubits[qubit].readout.attenuation = params.attenuation + platform.qubits[qubit].readout.attenuation = params.attenuation - attenuations[qubit] = qubits[qubit].readout.attenuation + attenuations[qubit] = platform.qubits[qubit].readout.attenuation sequence.add(ro_pulses[qubit]) @@ -103,7 +103,7 @@ def _acquisition( sweeper = Sweeper( Parameter.frequency, delta_frequency_range, - pulses=[ro_pulses[qubit] for qubit in qubits], + pulses=[ro_pulses[qubit] for qubit in targets], type=SweeperType.OFFSET, ) data = ResonatorSpectroscopyAttenuationData( @@ -125,7 +125,7 @@ def _acquisition( ) # retrieve the results for every qubit - for qubit in qubits: + for qubit in targets: result = results[ro_pulses[qubit].serial] # store the results data.register_qubit( @@ -177,25 +177,29 @@ def _fit( def _plot( data: ResonatorSpectroscopyAttenuationData, - qubit, + target: QubitId, fit: ResonatorSpectroscopyAttenuationResults, ): """Plotting function for ResonatorSpectroscopyAttenuation.""" - return spectroscopy_plot(data, qubit, fit) + return spectroscopy_plot(data, target, fit) def _update( - results: ResonatorSpectroscopyAttenuationResults, platform: Platform, qubit: QubitId + results: ResonatorSpectroscopyAttenuationResults, + platform: Platform, + target: QubitId, ): - update.readout_frequency(results.frequency[qubit], platform, qubit) + update.readout_frequency(results.frequency[target], platform, target) # if this condition is satifisfied means that we are in the low power regime # therefore we update also the readout amplitude if len(results.bare_frequency) == 0: - update.readout_amplitude(results.amplitude[qubit], platform, qubit) - update.readout_attenuation(results.attenuation[qubit], platform, qubit) + update.readout_amplitude(results.amplitude[target], platform, target) + update.readout_attenuation(results.attenuation[target], platform, target) else: - update.bare_resonator_frequency(results.bare_frequency[qubit], platform, qubit) + update.bare_resonator_frequency( + results.bare_frequency[target], platform, target + ) resonator_spectroscopy_attenuation = Routine(_acquisition, _fit, _plot, _update) diff --git a/src/qibocal/protocols/characterization/signal_experiments/calibrate_state_discrimination.py b/src/qibocal/protocols/characterization/signal_experiments/calibrate_state_discrimination.py index da542c54d..89c02242d 100644 --- a/src/qibocal/protocols/characterization/signal_experiments/calibrate_state_discrimination.py +++ b/src/qibocal/protocols/characterization/signal_experiments/calibrate_state_discrimination.py @@ -11,7 +11,7 @@ from qibolab.qubits import QubitId from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine SAMPLES_FACTOR = 16 @@ -68,7 +68,9 @@ class CalibrateStateDiscriminationData(Data): def _acquisition( - params: CalibrateStateDiscriminationParameters, platform: Platform, qubits: Qubits + params: CalibrateStateDiscriminationParameters, + platform: Platform, + targets: list[QubitId], ) -> CalibrateStateDiscriminationData: r""" Data acquisition for Calibrate State Discrimination experiment. @@ -89,7 +91,7 @@ def _acquisition( data = CalibrateStateDiscriminationData(resonator_type=platform.resonator_type) # TODO: test if qibolab supports multiplex with raw acquisition - for qubit in qubits: + for qubit in targets: sequence_0 = PulseSequence() sequence_1 = PulseSequence() sequence_1.add(platform.create_RX_pulse(qubit, start=0)) @@ -179,7 +181,7 @@ def _fit(data: CalibrateStateDiscriminationData) -> CalibrateStateDiscrimination def _plot( data: CalibrateStateDiscriminationData, - qubit, + target, fit: CalibrateStateDiscriminationResults, ): """Plotting function for Calibrate State Discrimination.""" @@ -198,8 +200,8 @@ def _plot( fig.add_trace( go.Scatter( - x=np.arange(len(fit.data[qubit])), - y=np.abs(fit.data[qubit]), + x=np.arange(len(fit.data[target])), + y=np.abs(fit.data[target]), opacity=1, name="kernel state 0", showlegend=True, diff --git a/src/qibocal/protocols/characterization/signal_experiments/time_of_flight_readout.py b/src/qibocal/protocols/characterization/signal_experiments/time_of_flight_readout.py index 6c701b362..cc04123a3 100644 --- a/src/qibocal/protocols/characterization/signal_experiments/time_of_flight_readout.py +++ b/src/qibocal/protocols/characterization/signal_experiments/time_of_flight_readout.py @@ -9,7 +9,7 @@ from qibolab.pulses import PulseSequence from qibolab.qubits import QubitId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.utils import S_TO_NS, table_dict, table_html @@ -46,7 +46,7 @@ class TimeOfFlightReadoutData(Data): def _acquisition( - params: TimeOfFlightReadoutParameters, platform: Platform, qubits: Qubits + params: TimeOfFlightReadoutParameters, platform: Platform, targets: list[QubitId] ) -> TimeOfFlightReadoutData: """Data acquisition for time of flight experiment.""" @@ -54,7 +54,7 @@ def _acquisition( RX_pulses = {} ro_pulses = {} - for qubit in qubits: + for qubit in targets: RX_pulses[qubit] = platform.create_RX_pulse(qubit, start=0) ro_pulses[qubit] = platform.create_qubit_readout_pulse( qubit, start=RX_pulses[qubit].finish @@ -78,7 +78,7 @@ def _acquisition( ) # retrieve and store the results for every qubit - for qubit in qubits: + for qubit in targets: samples = results[ro_pulses[qubit].serial].magnitude # store the results data.register_qubit(TimeOfFlightReadoutType, (qubit), dict(samples=samples)) @@ -110,13 +110,15 @@ def _fit(data: TimeOfFlightReadoutData) -> TimeOfFlightReadoutResults: return TimeOfFlightReadoutResults(fitted_parameters) -def _plot(data: TimeOfFlightReadoutData, qubit, fit: TimeOfFlightReadoutResults): +def _plot( + data: TimeOfFlightReadoutData, target: QubitId, fit: TimeOfFlightReadoutResults +): """Plotting function for TimeOfFlightReadout.""" figures = [] fitting_report = "" fig = go.Figure() - qubit_data = data[qubit] + qubit_data = data[target] sampling_rate = data.sampling_rate y = qubit_data.samples @@ -137,14 +139,14 @@ def _plot(data: TimeOfFlightReadoutData, qubit, fit: TimeOfFlightReadoutResults) ) if fit is not None: fig.add_vline( - x=fit.fitted_parameters[qubit] * sampling_rate, + x=fit.fitted_parameters[target] * sampling_rate, line_width=2, line_dash="dash", line_color="grey", ) fitting_report = table_html( table_dict( - qubit, "Time of flights [ns]", fit.fitted_parameters[qubit] * S_TO_NS + target, "Time of flights [ns]", fit.fitted_parameters[target] * S_TO_NS ) ) fig.update_layout( diff --git a/src/qibocal/protocols/characterization/two_qubit_interaction/chevron.py b/src/qibocal/protocols/characterization/two_qubit_interaction/chevron.py index b4bb77991..e0af96ef7 100644 --- a/src/qibocal/protocols/characterization/two_qubit_interaction/chevron.py +++ b/src/qibocal/protocols/characterization/two_qubit_interaction/chevron.py @@ -15,7 +15,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.protocols.characterization.utils import table_dict, table_html from .utils import fit_flux_amplitude, order_pair @@ -87,7 +87,7 @@ def register_qubit(self, low_qubit, high_qubit, length, amp, prob_low, prob_high def _aquisition( params: ChevronParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitPairId], ) -> ChevronData: r""" Perform an iSWAP/CZ experiment between pairs of qubits by changing its frequency. @@ -95,7 +95,7 @@ def _aquisition( Args: platform: Platform to use. params: Experiment parameters. - qubits: Qubits to use. + targets (list): List of pairs to use sequentially. Returns: ChevronData: Acquisition data. @@ -103,7 +103,7 @@ def _aquisition( # create a DataUnits object to store the results, data = ChevronData() - for pair in qubits: + for pair in targets: # order the qubits so that the low frequency one is the first sequence = PulseSequence() ordered_pair = order_pair(pair, platform.qubits) @@ -229,21 +229,21 @@ def _fit(data: ChevronData) -> ChevronResults: return ChevronResults(amplitude=amplitudes, duration=durations) -def _plot(data: ChevronData, fit: ChevronResults, qubit): +def _plot(data: ChevronData, fit: ChevronResults, target: QubitPairId): """Plot the experiment result for a single pair.""" # reverse qubit order if not found in data - if qubit not in data.data: - qubit = (qubit[1], qubit[0]) + if target not in data.data: + target = (target[1], target[0]) - pair_data = data[qubit] + pair_data = data[target] fig = make_subplots( rows=1, cols=2, subplot_titles=( - f"Qubit {qubit[0]} - Low Frequency", - f"Qubit {qubit[1]} - High Frequency", + f"Qubit {target[0]} - Low Frequency", + f"Qubit {target[1]} - High Frequency", ), ) fitting_report = "" @@ -270,15 +270,15 @@ def _plot(data: ChevronData, fit: ChevronResults, qubit): col=2, ) - for measured_qubit in qubit: + for measured_qubit in target: if fit is not None: fig.add_trace( go.Scatter( x=[ - fit.duration[qubit], + fit.duration[target], ], y=[ - fit.amplitude[qubit], + fit.amplitude[target], ], mode="markers", marker=dict( @@ -287,11 +287,11 @@ def _plot(data: ChevronData, fit: ChevronResults, qubit): symbol="cross", ), name="CZ estimate", - showlegend=True if measured_qubit == qubit[0] else False, + showlegend=True if measured_qubit == target[0] else False, legendgroup="Voltage", ), row=1, - col=1 if measured_qubit == qubit[0] else 2, + col=1 if measured_qubit == target[0] else 2, ) fig.update_layout( @@ -308,20 +308,20 @@ def _plot(data: ChevronData, fit: ChevronResults, qubit): if fit is not None: fitting_report = table_html( table_dict( - qubit[1], + target[1], ["CZ amplitude", "CZ duration"], - [fit.amplitude[qubit], fit.duration[qubit]], + [fit.amplitude[target], fit.duration[target]], ) ) return [fig], fitting_report -def _update(results: ChevronResults, platform: Platform, qubit_pair: QubitPairId): - if qubit_pair not in results.duration: - qubit_pair = (qubit_pair[1], qubit_pair[0]) - update.CZ_duration(results.duration[qubit_pair], platform, qubit_pair) - update.CZ_amplitude(results.amplitude[qubit_pair], platform, qubit_pair) +def _update(results: ChevronResults, platform: Platform, target: QubitPairId): + if target not in results.duration: + target = (target[1], target[0]) + update.CZ_duration(results.duration[target], platform, target) + update.CZ_amplitude(results.amplitude[target], platform, target) chevron = Routine(_aquisition, _fit, _plot, _update, two_qubit_gates=True) diff --git a/src/qibocal/protocols/characterization/two_qubit_interaction/chsh/protocol.py b/src/qibocal/protocols/characterization/two_qubit_interaction/chsh/protocol.py index 2436384cd..762a688ed 100644 --- a/src/qibocal/protocols/characterization/two_qubit_interaction/chsh/protocol.py +++ b/src/qibocal/protocols/characterization/two_qubit_interaction/chsh/protocol.py @@ -8,9 +8,9 @@ import plotly.graph_objects as go from qibolab import ExecutionParameters from qibolab.platform import Platform -from qibolab.qubits import QubitId +from qibolab.qubits import QubitId, QubitPairId -from qibocal.auto.operation import Data, Parameters, Qubits, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from ...readout_mitigation_matrix import ( ReadoutMitigationMatrixParameters as mitigation_params, @@ -115,20 +115,19 @@ class CHSHResults(Results): def _acquisition_pulses( params: CHSHParameters, platform: Platform, - qubits: Qubits, + targets: list[list[QubitId]], ) -> CHSHData: r"""Data acquisition for CHSH protocol using pulse sequences.""" - thetas = np.linspace(0, 2 * np.pi, params.ntheta) data = CHSHData(bell_states=params.bell_states, thetas=thetas.tolist()) if params.apply_error_mitigation: mitigation_data = mitigation_acquisition( - mitigation_params(pulses=True, nshots=params.nshots), platform, qubits + mitigation_params(pulses=True, nshots=params.nshots), platform, targets ) mitigation_results = mitigation_fit(mitigation_data) - for pair in qubits: + for pair in targets: if params.apply_error_mitigation: data.mitigation_matrix[pair] = mitigation_results.readout_mitigation_matrix[ pair @@ -153,7 +152,7 @@ def _acquisition_pulses( def _acquisition_circuits( params: CHSHParameters, platform: Platform, - qubits: Qubits, + targets: list[QubitPairId], ) -> CHSHData: """Data acquisition for CHSH protocol using circuits.""" thetas = np.linspace(0, 2 * np.pi, params.ntheta) @@ -164,10 +163,10 @@ def _acquisition_circuits( if params.apply_error_mitigation: mitigation_data = mitigation_acquisition( - mitigation_params(pulses=False, nshots=params.nshots), platform, qubits + mitigation_params(pulses=False, nshots=params.nshots), platform, targets ) mitigation_results = mitigation_fit(mitigation_data) - for pair in qubits: + for pair in targets: if params.apply_error_mitigation: data.mitigation_matrix[pair] = mitigation_results.readout_mitigation_matrix[ pair @@ -189,7 +188,7 @@ def _acquisition_circuits( return data -def _plot(data: CHSHData, fit: CHSHResults, qubit): +def _plot(data: CHSHData, fit: CHSHResults, target: QubitPairId): """Plotting function for CHSH protocol.""" figures = [] @@ -199,7 +198,7 @@ def _plot(data: CHSHData, fit: CHSHResults, qubit): fig.add_trace( go.Scatter( x=data.thetas, - y=fit.chsh[qubit[0], qubit[1], bell_state], + y=fit.chsh[target[0], target[1], bell_state], name="Bare", ) ) @@ -207,7 +206,7 @@ def _plot(data: CHSHData, fit: CHSHResults, qubit): fig.add_trace( go.Scatter( x=data.thetas, - y=fit.chsh_mitigated[qubit[0], qubit[1], bell_state], + y=fit.chsh_mitigated[target[0], target[1], bell_state], name="Mitigated", ) ) @@ -268,7 +267,6 @@ def _fit(data: CHSHData) -> CHSHResults: for j, val in enumerate(matrix @ freq_array): mitigated_freq[format(j, f"0{2}b")].append(float(val)) mitigated_freq_list.append(mitigated_freq) - results[pair[0], pair[1], bell_state] = [ compute_chsh(freq, bell_state, l) for l in range(len(data.thetas)) ] diff --git a/src/qibocal/protocols/characterization/two_qubit_interaction/cz_virtualz.py b/src/qibocal/protocols/characterization/two_qubit_interaction/cz_virtualz.py index ef2356122..1a430ff5b 100644 --- a/src/qibocal/protocols/characterization/two_qubit_interaction/cz_virtualz.py +++ b/src/qibocal/protocols/characterization/two_qubit_interaction/cz_virtualz.py @@ -15,7 +15,7 @@ from scipy.optimize import curve_fit from qibocal import update -from qibocal.auto.operation import Data, Parameters, QubitsPairs, Results, Routine +from qibocal.auto.operation import Data, Parameters, Results, Routine from qibocal.config import log from qibocal.protocols.characterization.two_qubit_interaction.chevron import order_pair from qibocal.protocols.characterization.utils import table_dict, table_html @@ -148,7 +148,7 @@ def create_sequence( def _acquisition( params: CZVirtualZParameters, platform: Platform, - qubits: QubitsPairs, + targets: list[QubitPairId], ) -> CZVirtualZData: r""" Acquisition for CZVirtualZ. @@ -169,7 +169,7 @@ def _acquisition( theta_absolute = np.arange(params.theta_start, params.theta_end, params.theta_step) data = CZVirtualZData(thetas=theta_absolute.tolist()) - for pair in qubits: + for pair in targets: # order the qubits so that the low frequency one is the first ord_pair = order_pair(pair, platform.qubits) @@ -295,9 +295,9 @@ def _fit( # TODO: remove str -def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): +def _plot(data: CZVirtualZData, fit: CZVirtualZResults, target: QubitPairId): """Plot routine for CZVirtualZ.""" - pair_data = data[qubit] + pair_data = data[target] qubits = next(iter(pair_data))[:2] fig1 = make_subplots( rows=1, @@ -319,13 +319,13 @@ def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): fitting_report = "" thetas = data.thetas - for target, control, setup in pair_data: - target_prob = pair_data[target, control, setup].target - control_prob = pair_data[target, control, setup].control - fig = fig1 if (target, control) == qubits else fig2 + for target_q, control_q, setup in pair_data: + target_prob = pair_data[target_q, control_q, setup].target + control_prob = pair_data[target_q, control_q, setup].control + fig = fig1 if (target_q, control_q) == qubits else fig2 fig.add_trace( go.Scatter( - x=np.array(thetas) + data.vphases[qubits][target], + x=np.array(thetas) + data.vphases[qubits][target_q], y=target_prob, name=f"{setup} sequence", legendgroup=setup, @@ -336,7 +336,7 @@ def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): fig.add_trace( go.Scatter( - x=np.array(thetas) + data.vphases[qubits][control], + x=np.array(thetas) + data.vphases[qubits][control_q], y=control_prob, name=f"{setup} sequence", legendgroup=setup, @@ -346,12 +346,12 @@ def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): ) if fit is not None: angle_range = np.linspace(thetas[0], thetas[-1], 100) - fitted_parameters = fit.fitted_parameters[target, control, setup] + fitted_parameters = fit.fitted_parameters[target_q, control_q, setup] fig.add_trace( go.Scatter( - x=angle_range + data.vphases[qubits][target], + x=angle_range + data.vphases[qubits][target_q], y=fit_function( - angle_range + data.vphases[qubits][target], + angle_range + data.vphases[qubits][target_q], *fitted_parameters, ), name="Fit", @@ -363,15 +363,15 @@ def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): fitting_report = table_html( table_dict( - [target, target, qubits[1]], + [target_q, target_q, qubits[1]], [ "CZ angle [rad]", "Virtual Z phase [rad]", "Flux pulse amplitude [a.u.]", ], [ - np.round(fit.cz_angle[target, control], 4), - np.round(fit.virtual_phase[tuple(sorted(qubit))][target], 4), + np.round(fit.cz_angle[target_q, control_q], 4), + np.round(fit.virtual_phase[tuple(sorted(target))][target_q], 4), np.round(data.amplitudes[qubits]), ], ) @@ -396,10 +396,10 @@ def _plot(data: CZVirtualZData, fit: CZVirtualZResults, qubit): return [fig1, fig2], fitting_report -def _update(results: CZVirtualZResults, platform: Platform, qubit_pair: QubitPairId): +def _update(results: CZVirtualZResults, platform: Platform, target: QubitPairId): # FIXME: quick fix for qubit order - qubit_pair = tuple(sorted(qubit_pair)) - update.virtual_phases(results.virtual_phase[qubit_pair], platform, qubit_pair) + target = tuple(sorted(target)) + update.virtual_phases(results.virtual_phase[target], platform, target) cz_virtualz = Routine(_acquisition, _fit, _plot, _update, two_qubit_gates=True) diff --git a/src/qibocal/web/templates/template.html b/src/qibocal/web/templates/template.html index fb1daefda..b55998374 100644 --- a/src/qibocal/web/templates/template.html +++ b/src/qibocal/web/templates/template.html @@ -134,7 +134,7 @@

{{ report.title }}

{{ report.routine_name(*task_uid) }}

- {% for qubit in report.routine_qubits(task_uid) %} + {% for qubit in report.routine_targets(task_uid) %}
diff --git a/tests/runcards/protocols.yml b/tests/runcards/protocols.yml index b98adbe99..85e6a80c4 100644 --- a/tests/runcards/protocols.yml +++ b/tests/runcards/protocols.yml @@ -1,6 +1,6 @@ platform: dummy -qubits: [0,1] +targets: [0,1] actions: @@ -83,7 +83,7 @@ actions: - id: coupler_resonator_spectroscopy priority: 0 operation: coupler_resonator_spectroscopy - qubits: [[1, 2], [0, 2]] + targets: [[1, 2], [0, 2]] parameters: bias_width: 1 bias_step: 0.1 @@ -108,7 +108,7 @@ actions: - id: coupler qubit spectroscopy priority: 0 operation: coupler_qubit_spectroscopy - qubits: [[1, 2], [0, 2]] + targets: [[1, 2], [0, 2]] parameters: bias_width: 1 bias_step: 0.1 @@ -124,7 +124,7 @@ actions: priority: 0 operation: qubit_spectroscopy_ef #FIXME: add RX12 for qubit 4 - qubits: [0, 1, 2, 3] + targets: [0, 1, 2, 3] parameters: drive_amplitude: 0.001 drive_duration: 1000 @@ -248,7 +248,7 @@ actions: priority: 0 operation: rabi_amplitude_ef #FIXME: add RX12 for qubit 4 - qubits: [0, 1, 2, 3] + targets: [0, 1, 2, 3] parameters: min_amp_factor: 0.0 max_amp_factor: 1.0 @@ -559,7 +559,7 @@ actions: priority: 0 operation: dispersive_shift_qutrit #FIXME: add qubit 4 with new release of Qibolab - qubits: [0, 1, 2, 3] + targets: [0, 1, 2, 3] parameters: freq_width: 10_000_000 freq_step: 100_000 @@ -595,7 +595,7 @@ actions: - id: standard rb bootstrap priority: 0 operation: standard_rb - qubits: [1] + targets: [1] parameters: depths: [1, 2, 3, 5] niter: 5 @@ -606,7 +606,7 @@ actions: - id: chevron id priority: 0 operation: chevron - qubits: [[0, 2],[1,2]] + targets: [[0, 2],[1,2]] parameters: amplitude_min: 0.1 amplitude_max: 0.6 @@ -620,7 +620,7 @@ actions: - id: tune landscape priority: 0 operation: cz_virtualz - qubits: [[0, 2],[1,2],[3,2]] + targets: [[0, 2],[1,2],[3,2]] parameters: theta_start: 0 theta_end: 180 @@ -632,7 +632,7 @@ actions: - id: standard rb inhomogeneous priority: 0 operation: standard_rb - qubits: [0, 1, 3] + targets: [0, 1, 3] parameters: depths: [1, 3, 3, 5] niter: 5 @@ -659,7 +659,7 @@ actions: - id: CHSH with pulses priority: 0 operation: chsh_pulses - qubits: [[0,2],[1,2],[2,3]] + targets: [[0,2],[1,2],[2,3]] parameters: nshots: 1000 ntheta: 10 @@ -669,7 +669,7 @@ actions: - id: CHSH with natives priority: 0 operation: chsh_circuits - qubits: [[0,2],[1,2]] + targets: [[0,2],[1,2]] parameters: nshots: 1000 ntheta: 10 @@ -681,7 +681,7 @@ actions: - id: CHSH with circuits priority: 0 operation: chsh_circuits - qubits: [[0,2],[1,2]] + targets: [[0,2],[1,2]] parameters: nshots: 1000 ntheta: 2 @@ -692,7 +692,7 @@ actions: - id: readout_mitigation_matrix pulses priority: 0 operation: readout_mitigation_matrix - qubits: [[0,1,2],[1,2]] + targets: [[0,1,2],[1,2]] parameters: nshots: 100 pulses: True @@ -700,7 +700,7 @@ actions: - id: readout_mitigation_matrix circuits priority: 0 operation: readout_mitigation_matrix - qubits: [[0,1,2],[1,2]] + targets: [[0,1,2],[1,2]] parameters: nshots: 100 pulses: False @@ -724,7 +724,7 @@ actions: - id: twpa frequency power priority: 0 operation: twpa_frequency_power - qubits: [0] + targets: [0] parameters: frequency_width: 1_000_000 frequency_step: 100_000 @@ -764,7 +764,7 @@ actions: - id: qutrit priority: 0 - qubits: [0,1] + targets: [0,1] operation: qutrit_classification parameters: nshots: 100 @@ -773,7 +773,7 @@ actions: - id: avoided crossing priority: 0 operation: avoided_crossing - qubits: [[2,1],[0,2]] + targets: [[2,1],[0,2]] parameters: freq_width: 100_000_000 freq_step: 50_000_000 diff --git a/tests/test_auto.py b/tests/test_auto.py index 763046852..158c100f9 100644 --- a/tests/test_auto.py +++ b/tests/test_auto.py @@ -39,7 +39,7 @@ def test_execution(card: pathlib.Path, tmp_path): executor = Executor.load( testcard.runcard, output=tmp_path, - qubits=testcard.runcard.qubits, + targets=testcard.runcard.targets, ) list(executor.run(mode=ExecutionMode.acquire)) diff --git a/tests/test_protocols.py b/tests/test_protocols.py index c08c44353..aacaa6f61 100644 --- a/tests/test_protocols.py +++ b/tests/test_protocols.py @@ -29,7 +29,7 @@ def generate_runcard_single_protocol(): with open(PATH_TO_RUNCARD) as file: actions = yaml.safe_load(file) for action in actions["actions"]: - card = {"actions": [action], "qubits": list(PLATFORM.qubits)} + card = {"actions": [action], "targets": list(PLATFORM.qubits)} yield card diff --git a/tests/test_task_options.py b/tests/test_task_options.py index de5e0f46f..a0cab2c2a 100644 --- a/tests/test_task_options.py +++ b/tests/test_task_options.py @@ -16,7 +16,6 @@ from qibocal.protocols.characterization.readout_mitigation_matrix import ( ReadoutMitigationMatrixParameters, ) -from qibocal.utils import allocate_single_qubits PLATFORM = create_platform("dummy") QUBITS = list(PLATFORM.qubits) @@ -38,32 +37,35 @@ } -def modify_card(card, qubits=None, update=None): - """Modify runcard to change local qubits or update.""" +def modify_card(card, targets=None, update=None): + """Modify runcard to change local targets or update.""" for action in card["actions"]: - if qubits is not None: - action["qubits"] = qubits + if targets is not None: + action["targets"] = targets elif update is not None: action["update"] = update return card @pytest.mark.parametrize("platform", [None, PLATFORM]) -@pytest.mark.parametrize("local_qubits", [[], [0, 1]]) -def test_qubits_argument(platform, local_qubits): +@pytest.mark.parametrize("local_targets", [None, [0, 1]]) +def test_qubits_argument(platform, local_targets, tmp_path): """Test possible qubits combinations between global and local.""" - runcard = Runcard.load(modify_card(DUMMY_CARD, qubits=local_qubits)) + runcard = Runcard.load(modify_card(DUMMY_CARD, targets=local_targets)) + print(runcard) task = Task(runcard.actions[0]) - global_qubits = ( - allocate_single_qubits(platform, QUBITS) if platform is not None else QUBITS - ) - task._allocate_local_qubits(global_qubits, platform) - _, _ = task.operation.acquisition(task.parameters, platform, global_qubits) - if local_qubits: - assert task.qubits == local_qubits + completed = task.run( + max_iterations=1, + platform=platform, + targets=list(QUBITS), + mode=ExecutionMode.acquire, + folder=tmp_path, + ) + if local_targets: + assert completed.task.targets == local_targets else: - assert task.qubits == QUBITS + assert completed.task.targets == list(QUBITS) UPDATE_CARD = {