diff --git a/.github/workflows/cron-staging.yml b/.github/workflows/cron-staging.yml index 844c7683f5..e2352377bf 100644 --- a/.github/workflows/cron-staging.yml +++ b/.github/workflows/cron-staging.yml @@ -6,6 +6,7 @@ on: jobs: qiskit-main-tests: + if: github.repository_owner == 'Qiskit-Extensions' name: tests-python${{ matrix.python-version }}-${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: @@ -46,6 +47,7 @@ jobs: TEST_TIMEOUT: 120 OMP_NUM_THREADS: 1 docs: + if: github.repository_owner == 'Qiskit-Extensions' name: docs runs-on: ubuntu-latest steps: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 62b6c711d4..0607301851 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,6 +7,7 @@ on: jobs: deploy: + if: github.repository_owner == 'Qiskit-Extensions' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/docs_dev.yml b/.github/workflows/docs_dev.yml index 9dbcecd757..62efff9243 100644 --- a/.github/workflows/docs_dev.yml +++ b/.github/workflows/docs_dev.yml @@ -6,6 +6,7 @@ on: jobs: deploy: + if: github.repository_owner == 'Qiskit-Extensions' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a0f990eaab..40ac08176b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,6 +11,7 @@ concurrency: cancel-in-progress: true jobs: tests: + if: github.repository_owner == 'Qiskit-Extensions' name: tests-python${{ matrix.python-version }}-${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: @@ -62,6 +63,7 @@ jobs: run: stestr history remove all lint: + if: github.repository_owner == 'Qiskit-Extensions' name: lint runs-on: ubuntu-latest steps: @@ -80,6 +82,7 @@ jobs: - name: Run lint run: tox -elint docs: + if: github.repository_owner == 'Qiskit-Extensions' name: docs runs-on: ubuntu-latest steps: diff --git a/.github/workflows/neko.yml b/.github/workflows/neko.yml index f8cfdca16e..c4f3736139 100644 --- a/.github/workflows/neko.yml +++ b/.github/workflows/neko.yml @@ -8,6 +8,7 @@ concurrency: cancel-in-progress: true jobs: neko: + if: github.repository_owner == 'Qiskit-Extensions' name: Qiskit Neko Integration Tests runs-on: ubuntu-latest steps: diff --git a/constraints.txt b/constraints.txt index fffba16557..e69de29bb2 100644 --- a/constraints.txt +++ b/constraints.txt @@ -1,4 +0,0 @@ -# Numpy 1.25 deprecated some behaviours that we used, and caused some -# tests to flake. See https://github.com/Qiskit/qiskit/issues/10305, -# remove pin when resolving that. -numpy<1.25 diff --git a/docs/howtos/cloud_service.rst b/docs/howtos/cloud_service.rst index fb3aebad53..11bce3f7f8 100644 --- a/docs/howtos/cloud_service.rst +++ b/docs/howtos/cloud_service.rst @@ -4,7 +4,7 @@ Save and load experiment data with the cloud service .. note:: This guide is only for those who have access to the cloud service. You can check whether you do by logging into the IBM Quantum interface - and seeing if you can see the `database `__. + and seeing if you can see the `database `__. Problem ------- @@ -44,13 +44,13 @@ backend and not a simulator to be able to save the experiment data. This is done .. jupyter-output:: You can view the experiment online at - https://quantum-computing.ibm.com/experiments/10a43cb0-7cb9-41db-ad74-18ea6cf63704 + https://quantum.ibm.com/experiments/10a43cb0-7cb9-41db-ad74-18ea6cf63704 Loading ~~~~~~~ Let's load a `previous T1 -experiment `__ +experiment `__ (requires login to view), which we've made public by editing the ``Share level`` field: .. jupyter-input:: @@ -59,13 +59,11 @@ experiment Setting ``auto_save = True`` works by triggering :meth:`.ExperimentData.save`. @@ -188,5 +186,5 @@ Web interface ~~~~~~~~~~~~~ You can also view experiment results as well as change the tags and share level at the `IBM Quantum Experiments -pane `__ +pane `__ on the cloud. diff --git a/docs/howtos/experiment_times.rst b/docs/howtos/experiment_times.rst index bc1e331d2c..8be8b1dc8b 100644 --- a/docs/howtos/experiment_times.rst +++ b/docs/howtos/experiment_times.rst @@ -24,7 +24,7 @@ are all of type ``datetime.datetime`` and in your local timezone: .. note:: The below attributes are only relevant for those who have access to the cloud service. You can check whether you do by logging into the IBM Quantum interface - and seeing if you can see the `database `__. + and seeing if you can see the `database `__. - :attr:`.ExperimentData.creation_datetime` is the time when the experiment data was saved via the service. This defaults to ``None`` if experiment data has not yet been saved. diff --git a/docs/howtos/rerun_analysis.rst b/docs/howtos/rerun_analysis.rst index 2f7a1b33d6..b1a7107b6f 100644 --- a/docs/howtos/rerun_analysis.rst +++ b/docs/howtos/rerun_analysis.rst @@ -37,12 +37,14 @@ job IDs: expdata = ExperimentData(experiment = experiment) expdata.add_jobs([provider.retrieve_job(job_id) for job_id in job_ids]) - experiment.analysis.run(expdata) + experiment.analysis.run(expdata, replace_results=True) # Block execution of subsequent code until analysis is complete expdata.block_for_results() -``expdata`` will be the new experiment data object containing results of the rerun analysis. +``expdata`` will be the new experiment data object containing results of the rerun analysis. Note that if +``replace_results`` isn't set, running the analysis will return a new :class:`.ExperimentData` object +instead of overwriting the existing one. If you have the job data in the form of a :class:`~qiskit.result.Result` object, you can invoke the :meth:`.add_data` method instead of :meth:`.add_jobs`: @@ -66,7 +68,7 @@ contain correct results. In the case where jobs are not directly accessible from the provider but you've downloaded the jobs from the -`IQS dashboard `_, you can load them from +`IQS dashboard `_, you can load them from the downloaded directory into :class:`~qiskit.result.Result` objects with this code: .. jupyter-input:: @@ -115,7 +117,7 @@ first component experiment. data = ExperimentData(experiment=pexp) data.add_jobs([provider.retrieve_job(job_id) for job_id in job_ids]) - pexp.analysis.run(data) + pexp.analysis.run(data, replace_results=True) See Also -------- diff --git a/docs/howtos/runtime_sessions.rst b/docs/howtos/runtime_sessions.rst index 9b07705e76..a9519ba3a2 100644 --- a/docs/howtos/runtime_sessions.rst +++ b/docs/howtos/runtime_sessions.rst @@ -5,7 +5,7 @@ Problem ------- You want to run experiments in a `Runtime session -`_ so that jobs can run in close temporal proximity. +`_ so that jobs can run in close temporal proximity. Solution -------- diff --git a/docs/tutorials/calibrations.rst b/docs/tutorials/calibrations.rst index 53aef3d3d9..d3d5967850 100644 --- a/docs/tutorials/calibrations.rst +++ b/docs/tutorials/calibrations.rst @@ -12,9 +12,8 @@ measurement data manually. In this tutorial, we demonstrate how to calibrate single-qubit gates using the calibration framework in Qiskit Experiments. We will run experiments on our test pulse backend, :class:`.SingleTransmonTestBackend`, a backend that simulates the underlying -pulses with `Qiskit Dynamics `_ on a -three-level model of a transmon. You can also run these experiments on any real backend -with Pulse enabled (see +pulses with :mod:`qiskit_dynamics` on a three-level model of a transmon. You can also +run these experiments on any real backend with Pulse enabled (see :external+qiskit:doc:`tutorials/circuits_advanced/08_gathering_system_information`). We will run experiments to @@ -196,8 +195,8 @@ Run the calibration experiment: The instance of ``calibrations`` has been automatically updated with the measured frequency, as shown below. In addition to the columns shown below, ``calibrations`` also -store the group to which a value belongs, whether a values is valid or not and the -experiment id that produce a value. +stores the group to which a value belongs, whether a value is valid or not, and the +experiment id that produced a value. .. jupyter-execute:: diff --git a/qiskit_experiments/calibration_management/__init__.py b/qiskit_experiments/calibration_management/__init__.py index 82be9ae50d..d04e8eb064 100644 --- a/qiskit_experiments/calibration_management/__init__.py +++ b/qiskit_experiments/calibration_management/__init__.py @@ -23,7 +23,7 @@ otherwise indicated. Calibrating qubit setups is the task of finding the pulse shapes and parameter -values that maximizes the fidelity of the resulting quantum operations. This +values that maximize the fidelity of the resulting quantum operations. This therefore requires experiments which are analyzed to extract parameter values. Furthermore, the resulting parameter values and schedules must be managed. The calibration management module in Qiskit experiments allows users to manage diff --git a/qiskit_experiments/calibration_management/calibrations.py b/qiskit_experiments/calibration_management/calibrations.py index 0ee98c707b..4058dcad7e 100644 --- a/qiskit_experiments/calibration_management/calibrations.py +++ b/qiskit_experiments/calibration_management/calibrations.py @@ -1270,12 +1270,12 @@ def schedules(self) -> List[Dict[str, Any]]: Returns: data: A list of dictionaries with all the schedules in it. The key-value pairs are - * 'qubits': the qubits to which this schedule applies. This may be an empty - tuple () if the schedule is the default for all qubits. - * 'schedule': The schedule. - * 'parameters': The parameters in the schedule exposed for convenience. + * ``qubits``: the qubits to which this schedule applies. This may be an empty + tuple () if the schedule is the default for all qubits. + * ``schedule``: The schedule. + * ``parameters``: The parameters in the schedule exposed for convenience. - This list of dictionaries can easily be converted to a data frame. + This list of dictionaries can easily be converted to a data frame. """ data = [] for key, sched in self._schedules.items(): diff --git a/qiskit_experiments/framework/analysis_result_table.py b/qiskit_experiments/framework/analysis_result_table.py index 98c97655bb..16b8716874 100644 --- a/qiskit_experiments/framework/analysis_result_table.py +++ b/qiskit_experiments/framework/analysis_result_table.py @@ -85,13 +85,14 @@ def filter_columns(self, columns: Union[str, List[str]]) -> List[str]: Args: columns: Specifying a set of columns to return. You can pass a list of each - column name to return, otherwise builtin column groups are available. + column name to return, otherwise builtin column groups are available: + + * ``all``: Return all columns, including metadata to communicate + with experiment service, such as entry IDs. + * ``default``: Return columns including analysis result with supplementary + information about experiment. + * ``minimal``: Return only analysis subroutine returns. - * "all": Return all columns, including metadata to communicate - with experiment service, such as entry IDs. - * "default": Return columns including analysis result with supplementary - information about experiment. - * "minimal": Return only analysis subroutine returns. Raises: ValueError: When column is given in string which doesn't match with any builtin group. diff --git a/qiskit_experiments/framework/experiment_data.py b/qiskit_experiments/framework/experiment_data.py index 47cae2d9d9..c9f70a826a 100644 --- a/qiskit_experiments/framework/experiment_data.py +++ b/qiskit_experiments/framework/experiment_data.py @@ -67,6 +67,7 @@ ExperimentDataSaveFailed, ) + if TYPE_CHECKING: # There is a cyclical dependency here, but the name needs to exist for # Sphinx on Python 3.9+ to link type hints correctly. The gating on @@ -192,7 +193,7 @@ def _repr_svg_(self): if isinstance(self.figure, str): return self.figure if isinstance(self.figure, bytes): - return str(self.figure) + return self.figure.decode("utf-8") return None @@ -205,7 +206,7 @@ class ExperimentData: .. note:: Saving experiment data to the cloud database is currently a limited access feature. You can check whether you have access by logging into the IBM Quantum interface - and seeing if you can see the `database `__. + and seeing if you can see the `database `__. This class handles the following: @@ -1071,6 +1072,13 @@ def _retrieve_data(self): """Retrieve job data if missing experiment data.""" # Get job results if missing in experiment data. if self.provider is None: + # 'self._result_data' could be locked, so I check a copy of it. + if not self._result_data.copy(): + # Adding warning so the user will have indication why the analysis may fail. + LOG.warning( + "Provider for ExperimentData object doesn't exist, resulting in a failed attempt to" + " retrieve data from the server; no stored result data exists" + ) return retrieved_jobs = {} jobs_to_retrieve = [] # the list of all jobs to retrieve from the server @@ -1528,25 +1536,25 @@ def analysis_results( index: Index of the analysis result to be returned. Several types are accepted for convenience: - * None: Return all analysis results. - * int: Specific index of the analysis results. - * slice: A list slice of indexes. - * str: ID or name of the analysis result. + * None: Return all analysis results. + * int: Specific index of the analysis results. + * slice: A list slice of indexes. + * str: ID or name of the analysis result. refresh: Retrieve the latest analysis results from the server, if an experiment service is available. - block: If True block for any analysis callbacks to finish running. + block: If ``True``, block for any analysis callbacks to finish running. timeout: max time in seconds to wait for analysis callbacks to finish running. columns: Specifying a set of columns to return. You can pass a list of each - column name to return, otherwise builtin column groups are available. + column name to return, otherwise builtin column groups are available: - * "all": Return all columns, including metadata to communicate - with experiment service, such as entry IDs. - * "default": Return columns including analysis result with supplementary - information about experiment. - * "minimal": Return only analysis subroutine returns. + * ``all``: Return all columns, including metadata to communicate + with the experiment service, such as entry IDs. + * ``default``: Return columns including analysis result with supplementary + information about experiment. + * ``minimal``: Return only analysis subroutine returns. - dataframe: Set True to return analysis results in the dataframe format. + dataframe: Set to ``True`` to return analysis results in the dataframe format. Returns: Analysis results for this experiment. @@ -1681,7 +1689,7 @@ def save( Args: suppress_errors: should the method catch exceptions (true) or - pass them on, potentially aborting the experiment (false) + pass them on, potentially aborting the experiment (false) max_workers: Maximum number of concurrent worker threads (capped by 10) save_figures: Whether to save figures in the database or not save_children: For composite experiments, whether to save children as well @@ -1779,7 +1787,7 @@ def save( if not self.service.local and self.verbose: print( "You can view the experiment online at " - f"https://quantum-computing.ibm.com/experiments/{self.experiment_id}" + f"https://quantum.ibm.com/experiments/{self.experiment_id}" ) # handle children, but without additional prints if save_children: @@ -2293,6 +2301,7 @@ def copy(self, copy_results: bool = True) -> "ExperimentData": new_instance = ExperimentData( backend=self.backend, service=self.service, + provider=self.provider, parent_id=self.parent_id, job_ids=self.job_ids, child_data=list(self._child_data.values()), @@ -2523,7 +2532,7 @@ def get_service_from_backend(backend): @staticmethod def get_service_from_provider(provider): """Initializes the service from the provider data""" - db_url = "https://auth.quantum-computing.ibm.com/api" + db_url = "https://auth.quantum.ibm.com/api" try: # qiskit-ibmq-provider style if hasattr(provider, "credentials"): diff --git a/qiskit_experiments/library/calibration/fine_frequency_cal.py b/qiskit_experiments/library/calibration/fine_frequency_cal.py index 5fe3251f89..13b1c64b62 100644 --- a/qiskit_experiments/library/calibration/fine_frequency_cal.py +++ b/qiskit_experiments/library/calibration/fine_frequency_cal.py @@ -123,7 +123,7 @@ def update_calibrations(self, experiment_data: ExperimentData): The frequency of the qubit is updated according to - ..math:: + .. math:: f \to f - \frac{{\rm d}\theta}{2\pi\tau{\rm d}t} diff --git a/qiskit_experiments/library/calibration/half_angle_cal.py b/qiskit_experiments/library/calibration/half_angle_cal.py index e56ca7f7df..01735fc797 100644 --- a/qiskit_experiments/library/calibration/half_angle_cal.py +++ b/qiskit_experiments/library/calibration/half_angle_cal.py @@ -130,7 +130,7 @@ def update_calibrations(self, experiment_data: ExperimentData): in the complex amplitude of the pulse. The update rule for the half angle calibration is therefore: - ..math:: + .. math:: A \to A \cdot e^{-i{\rm d}\theta_\text{hac}/2} diff --git a/qiskit_experiments/library/characterization/analysis/correlated_readout_error_analysis.py b/qiskit_experiments/library/characterization/analysis/correlated_readout_error_analysis.py index 6e9f31b239..73dece5171 100644 --- a/qiskit_experiments/library/characterization/analysis/correlated_readout_error_analysis.py +++ b/qiskit_experiments/library/characterization/analysis/correlated_readout_error_analysis.py @@ -33,7 +33,7 @@ class CorrelatedReadoutErrorAnalysis(BaseAnalysis): :math:`A` is a :math:`2^n\times 2^n` matrix :math:`A` such that :math:`A_{y,x}` is the probability to observe :math:`y` given the true outcome should be :math:`x`. - In the experiment, for each :math:`x`a circuit is constructed whose expected + In the experiment, for each :math:`x` a circuit is constructed whose expected outcome is :math:`x`. From the observed results on the circuit, the probability for each :math:`y` is determined, and :math:`A_{y,x}` is set accordingly. diff --git a/qiskit_experiments/library/characterization/rabi.py b/qiskit_experiments/library/characterization/rabi.py index 724354f53d..9193b22dd5 100644 --- a/qiskit_experiments/library/characterization/rabi.py +++ b/qiskit_experiments/library/characterization/rabi.py @@ -187,7 +187,7 @@ def _metadata(self): class EFRabi(Rabi): r"""An experiment that scans the amplitude of a pulse inducing rotations on the - :math:`|1\rangle` <-> :math:`|2\rangle` transition. + :math:`|1\rangle` <-> :math:`|2\rangle` transition. # section: overview diff --git a/qiskit_experiments/library/randomized_benchmarking/standard_rb.py b/qiskit_experiments/library/randomized_benchmarking/standard_rb.py index 07ec769b16..e87091fd3f 100644 --- a/qiskit_experiments/library/randomized_benchmarking/standard_rb.py +++ b/qiskit_experiments/library/randomized_benchmarking/standard_rb.py @@ -22,7 +22,7 @@ from numpy.random import Generator, default_rng from numpy.random.bit_generator import BitGenerator, SeedSequence -from qiskit.circuit import QuantumCircuit, Instruction, Barrier +from qiskit.circuit import CircuitInstruction, QuantumCircuit, Instruction, Barrier from qiskit.exceptions import QiskitError from qiskit.providers import BackendV2Converter from qiskit.providers.backend import Backend, BackendV1, BackendV2 @@ -291,7 +291,7 @@ def _sequences_to_circuits( circ = QuantumCircuit(self.num_qubits) for elem in seq: circ.append(self._to_instruction(elem, basis_gates), circ.qubits) - circ.append(Barrier(self.num_qubits), circ.qubits) + circ._append(CircuitInstruction(Barrier(self.num_qubits), circ.qubits)) # Compute inverse, compute only the difference from the previous shorter sequence prev_elem = self.__compose_clifford_seq(prev_elem, seq[len(prev_seq) :]) diff --git a/qiskit_experiments/library/tomography/basis/base_basis.py b/qiskit_experiments/library/tomography/basis/base_basis.py index c116b713b2..59aa14ad85 100644 --- a/qiskit_experiments/library/tomography/basis/base_basis.py +++ b/qiskit_experiments/library/tomography/basis/base_basis.py @@ -100,7 +100,7 @@ class PreparationBasis(BaseBasis): @abstractmethod def matrix_shape(self, qubits: Sequence[int]) -> Tuple[int, ...]: - """Return the shape of subsystem dimensions of the state attr:`~matrix`. + """Return the shape of subsystem dimensions of the state :attr:`~matrix`. Args: qubits: the physical qubit subsystems. @@ -170,7 +170,7 @@ def outcome_shape(self, qubits: Sequence[int]) -> Tuple[int, ...]: @abstractmethod def matrix_shape(self, qubits: Sequence[int]) -> Tuple[int, ...]: - """Return the shape of subsystem dimensions of a POVM attr:`~matrix`. + """Return the shape of subsystem dimensions of a POVM :attr:`~matrix`. Args: qubits: the physical qubit subsystems. diff --git a/qiskit_experiments/test/fake_backend.py b/qiskit_experiments/test/fake_backend.py index 07bab78a78..d9f4772350 100644 --- a/qiskit_experiments/test/fake_backend.py +++ b/qiskit_experiments/test/fake_backend.py @@ -14,6 +14,7 @@ import uuid from qiskit.circuit.library import Measure from qiskit.providers.backend import BackendV2 +from qiskit.providers.fake_provider import FakeProvider from qiskit.providers.options import Options from qiskit.transpiler import Target @@ -27,8 +28,14 @@ class FakeBackend(BackendV2): Fake backend for test purposes only. """ - def __init__(self, backend_name="fake_backend", num_qubits=1, max_experiments=100): - super().__init__(name=backend_name) + def __init__( + self, + provider=FakeProvider(), + backend_name="fake_backend", + num_qubits=1, + max_experiments=100, + ): + super().__init__(provider=provider, name=backend_name) self._target = Target(num_qubits=num_qubits) # Add a measure for each qubit so a simple measure circuit works self.target.add_instruction(Measure()) diff --git a/qiskit_experiments/test/mock_iq_backend.py b/qiskit_experiments/test/mock_iq_backend.py index bd936d7820..09094db37a 100644 --- a/qiskit_experiments/test/mock_iq_backend.py +++ b/qiskit_experiments/test/mock_iq_backend.py @@ -229,7 +229,8 @@ def __init__( Args: experiment_helper(MockIQExperimentHelper): Experiment helper class that contains - 'compute_probabilities' function and 'iq_phase' function for the backend to execute. + :meth:`~MockIQExperimentHelper.compute_probabilities` and + :meth:`~MockIQExperimentHelper.iq_phase` methods for the backend to execute. rng_seed(int): The random seed value. """ diff --git a/qiskit_experiments/test/mock_iq_helpers.py b/qiskit_experiments/test/mock_iq_helpers.py index f583080940..7f093cde95 100644 --- a/qiskit_experiments/test/mock_iq_helpers.py +++ b/qiskit_experiments/test/mock_iq_helpers.py @@ -44,9 +44,9 @@ def __init__( :class:`MockIQBackend` instance. These are used by :meth:`iq_clusters` by default. Subclasses can override :meth:`iq_clusters` to return a modified version of :attr:`iq_cluster_centers` and :attr:`iq_cluster_width`. - `iq_cluster_centers` is a list of tuples. For a given qubit ``i_qbt`` and + :attr:`iq_cluster_centers` is a list of tuples. For a given qubit ``i_qbt`` and computational state ``i_state`` (either `0` or `1`), the centers of the IQ - clusters are found by indexing ``iq_cluster_centers`` as follows: + clusters are found by indexing :attr:`iq_cluster_centers` as follows: .. code-block:: python @@ -69,7 +69,7 @@ def __init__( are different centers for different logical values of the qubit. Defaults to a single qubit with clusters in quadrants 1 and 3. iq_cluster_width: A list of standard deviation values for the sampling of each qubit. - Defaults to widths of 1.0 for each qubit in `iq_cluster_centers`. + Defaults to widths of 1.0 for each qubit in :attr:`iq_cluster_centers`. """ self._iq_cluster_centers = ( @@ -192,15 +192,15 @@ def iq_clusters( Subclasses can override this function to modify the centers and widths of IQ clusters based on the circuits being simulated by a :class:`MockIQBackend`. The base centers and widths are stored internally within the helper object, and can be set in :meth:`__init__` or by modifying - attr:`iq_cluster_centers` and attr:`iq_cluster_width`. The default behaviour for + :attr:`iq_cluster_centers` and :attr:`iq_cluster_width`. The default behavior for :meth:`iq_clusters` is to return the centers and widths unmodified for each circuit in - `circuits`. Subclasses may return different centers and widths based on the circuits provided. + ``circuits``. Subclasses may return different centers and widths based on the circuits provided. The returned list contains a tuple per circuit. Each tuple contains the IQ centers and widths in - the same format as attr:`iq_cluster_centers` and attr:`iq_cluster_width`, passed as + the same format as :attr:`iq_cluster_centers` and :attr:`iq_cluster_width`, passed as arguments to :meth:`__init__`. The format of the centers and widths lists, in the argument - list and in the returned tuples, must match the format of `iq_cluster_centers` and - `iq_cluster_width` in :func:`qiskit_experiments.test.MockIQExperimentHelper.__init__`. + list and in the returned tuples, must match the format of :attr:`iq_cluster_centers` and + :attr:`iq_cluster_width` in :func:`qiskit_experiments.test.MockIQExperimentHelper.__init__`. Args: circuits: The quantum circuits for which the clusters should be modified. @@ -224,8 +224,8 @@ def __init__( Parallel Experiment Helper initializer. The class assumes `exp_helper_list` is ordered to match the corresponding experiment in `exp_list`. - Note that :meth:`__init__` does not have `iq_cluster_centers` and `iq_cluster_width` as in - :func:`MockIQExperimentHelper.__init__`. This is because the centers and widths for + Note that :meth:`__init__` does not have :attr:`iq_cluster_centers` and :attr:`iq_cluster_width` + as in :func:`MockIQExperimentHelper.__init__`. This is because the centers and widths for :class:`MockIQParallelBackend` are stored in multiple experiment helpers in the list `exp_helper_list`. diff --git a/qiskit_experiments/test/pulse_backend.py b/qiskit_experiments/test/pulse_backend.py index 84acf9f7cd..0f0627afbd 100644 --- a/qiskit_experiments/test/pulse_backend.py +++ b/qiskit_experiments/test/pulse_backend.py @@ -452,7 +452,7 @@ class SingleTransmonTestBackend(PulseBackend): H = \hbar \sum_{j=1,2} \left[\omega_j |j\rangle\langle j| + \mathcal{E}(t) \lambda_j (\sigma_j^+ + \sigma_j^-)\right] - Here, :math:`\omega_j` is the transition frequency from level :math`0` to level + Here, :math:`\omega_j` is the transition frequency from level :math:`0` to level :math:`j`. :math:`\mathcal{E}(t)` is the drive field and :math:`\sigma_j^\pm` are the raising and lowering operators between levels :math:`j-1` and :math:`j`. """ diff --git a/releasenotes/notes/bugfix_expdata_copy-2c73a21ad720858d.yaml b/releasenotes/notes/bugfix_expdata_copy-2c73a21ad720858d.yaml new file mode 100644 index 0000000000..cec8f54e99 --- /dev/null +++ b/releasenotes/notes/bugfix_expdata_copy-2c73a21ad720858d.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + 'copy' method under ExperimentData class now copies the provider. + \ No newline at end of file diff --git a/releasenotes/notes/figure_return_SVG-4ad72fc8a3bee3cb.yaml b/releasenotes/notes/figure_return_SVG-4ad72fc8a3bee3cb.yaml new file mode 100644 index 0000000000..bd1bf8104f --- /dev/null +++ b/releasenotes/notes/figure_return_SVG-4ad72fc8a3bee3cb.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Figures loaded from the experiment service are now rendered correctly in Jupyter Notebook. diff --git a/releasenotes/notes/setter-methods-for-experiment-099074e59faffb49.yaml b/releasenotes/notes/setter-methods-for-experiment-099074e59faffb49.yaml index 157002c964..00d66c572c 100644 --- a/releasenotes/notes/setter-methods-for-experiment-099074e59faffb49.yaml +++ b/releasenotes/notes/setter-methods-for-experiment-099074e59faffb49.yaml @@ -4,5 +4,5 @@ features: Added ``experiment_type`` as optional ``__init__`` kwarg in :class:`.BatchExperiment` and :class:`.ParallelExperiment`. - | - :math:'experiment_type' can now be easily set and retrieved from the experiment - object post-construction using the 'experiment_type' property and setter. + ``experiment_type`` can now be easily set and retrieved from the experiment + object post-construction using the ``experiment_type`` property and setter. diff --git a/requirements-dev.txt b/requirements-dev.txt index 3ba0a3a7ec..24c7719517 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ -qiskit-terra>=0.45.0 +qiskit>=0.45.0 black~=22.0 fixtures stestr diff --git a/requirements-extras.txt b/requirements-extras.txt index 25689a0858..a1fc84cc89 100644 --- a/requirements-extras.txt +++ b/requirements-extras.txt @@ -1,5 +1,5 @@ qiskit-ibm-provider>=0.6.1 # for submitting experiments to backends through the IBM provider cvxpy>=1.3.2 # for tomography scikit-learn # for discriminators -qiskit-aer>=0.11.0,<=0.12.2 # temporary version pin until 0.13.1 release +qiskit-aer>=0.11.0 qiskit_dynamics>=0.4.0 # for the PulseBackend diff --git a/test/database_service/test_db_experiment_data.py b/test/database_service/test_db_experiment_data.py index 3d83fa8512..003d21af0f 100644 --- a/test/database_service/test_db_experiment_data.py +++ b/test/database_service/test_db_experiment_data.py @@ -14,6 +14,7 @@ """Test ExperimentData.""" from test.base import QiskitExperimentsTestCase +from test.fake_experiment import FakeExperiment import os from unittest import mock import copy @@ -46,6 +47,7 @@ ExperimentStatus, ) from qiskit_experiments.framework.matplotlib import get_non_gui_ax +from qiskit_experiments.test.fake_backend import FakeBackend class TestDbExperimentData(QiskitExperimentsTestCase): @@ -1044,14 +1046,12 @@ def test_additional_attr(self): def test_copy_metadata(self): """Test copy metadata.""" - exp_data = ExperimentData(experiment_type="qiskit_test") + exp_data = FakeExperiment(experiment_type="qiskit_test").run(backend=FakeBackend()) exp_data.add_data(self._get_job_result(1)) - result = mock.MagicMock() - result.result_id = str(uuid.uuid4()) - exp_data.add_analysis_results(result) copied = exp_data.copy(copy_results=False) self.assertEqual(exp_data.data(), copied.data()) self.assertFalse(copied.analysis_results()) + self.assertEqual(exp_data.provider, copied.provider) def test_copy_metadata_pending_job(self): """Test copy metadata with a pending job.""" diff --git a/test/fake_experiment.py b/test/fake_experiment.py index 5e4a2fa060..f904a7f4c4 100644 --- a/test/fake_experiment.py +++ b/test/fake_experiment.py @@ -48,11 +48,16 @@ def _default_experiment_options(cls) -> Options: options.dummyoption = None return options - def __init__(self, physical_qubits=None): + def __init__(self, physical_qubits=None, backend=None, experiment_type=None): """Initialise the fake experiment.""" if physical_qubits is None: physical_qubits = [0] - super().__init__(physical_qubits, analysis=FakeAnalysis()) + super().__init__( + physical_qubits, + analysis=FakeAnalysis(), + backend=backend, + experiment_type=experiment_type, + ) def circuits(self): """Fake circuits.""" diff --git a/test/library/tomography/tomo_utils.py b/test/library/tomography/tomo_utils.py index 1304876bb9..2a1e75b9ec 100644 --- a/test/library/tomography/tomo_utils.py +++ b/test/library/tomography/tomo_utils.py @@ -87,9 +87,7 @@ def readout_noise_model(num_qubits, seed=None): p1g0s = 0.15 * rng.random(num_qubits) p0g1s = 0.3 * rng.random(num_qubits) amats = np.stack([[1 - p1g0s, p1g0s], [p0g1s, 1 - p0g1s]]).T - # Set `basis_gates` so that reset is included. - # See https://github.com/Qiskit/qiskit-aer/issues/1975 - noise_model = NoiseModel(basis_gates=["id", "rz", "sx", "cx", "reset"]) + noise_model = NoiseModel() for i, amat in enumerate(amats): noise_model.add_readout_error(amat.T, [i]) return noise_model