Skip to content

Commit 5fdb1f2

Browse files
committed
Adopt database classes and local experiment service from qiskit-ibm-experiment
* Remove the `qiskit-ibm-experiment` dependency + Adopt `DbExperimentData`, `DbAnalysisResultData`, and `ResultQuality` + Adapt `IBMExperimentService` into `LocalExperimentService` which only maintains the local features of the original class. + Remove code for inferring service from backend or provider * Revise the experiment service howto and other comments to refer to the `LocalExperimentService` and not to the retired cloud experiment service. * Add optional pyyaml dependency * Drop IBMProvider protocol * Update `ExperimentData` and `AnalysisResult` not to try to work with the old IBM experiment service. * Remove `FakeService` test class and use `LocalExperimentService` in tests instead. + Additionally, remove all usage of mocking from the tests, using `LocalExperimentService` in place of a mocked service.
1 parent 403c031 commit 5fdb1f2

35 files changed

+2620
-1595
lines changed

docs/howtos/artifacts.rst

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,8 @@ Qiskit Experiments.
106106
Saving and loading artifacts
107107
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108108

109-
.. note::
110-
This feature is only for those who have access to the cloud service. You can
111-
check whether you do by logging into the IBM Quantum interface
112-
and seeing if you can see the `database <https://quantum.ibm.com/experiments>`__.
113-
114-
Artifacts are saved and loaded to and from the cloud service along with the rest of the
115-
:class:`ExperimentData` object. Artifacts are stored as ``.zip`` files in the cloud service grouped by
109+
Artifacts are saved and loaded to and from an experiment service along with the rest of the
110+
:class:`ExperimentData` object. Artifacts are stored as ``.zip`` files in the service grouped by
116111
the artifact name. For example, the composite experiment above will generate two artifact files, ``fit_summary.zip`` and
117112
``curve_data.zip``. Each of these zipfiles will contain serialized artifact data in JSON format named
118113
by their unique artifact ID:
@@ -130,14 +125,8 @@ by their unique artifact ID:
130125
print(f"|- {data.artifacts('experiment_notes').artifact_id}.json")
131126
132127
Note that for performance reasons, the auto save feature does not apply to artifacts. You must still
133-
call :meth:`.ExperimentData.save` once the experiment analysis has completed to upload artifacts to the
134-
cloud service.
135-
136-
Note also though individual artifacts can be deleted, currently artifact files cannot be removed from the
137-
cloud service. Instead, you can delete all artifacts of that name
138-
using :meth:`~.delete_artifact` and then call :meth:`.ExperimentData.save`.
139-
This will save an empty file to the service, and the loaded experiment data will not contain
140-
these artifacts.
128+
call :meth:`.ExperimentData.save` once the experiment analysis has completed to save artifacts in the
129+
service.
141130

142131
See Also
143132
--------

docs/howtos/cloud_service.rst

Lines changed: 0 additions & 150 deletions
This file was deleted.
-44.6 KB
Binary file not shown.

docs/howtos/experiment_service.rst

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
Save and load experiment data with an experiment service
2+
========================================================
3+
4+
.. note::
5+
The cloud service at https://quantum.ibm.com/experiments has been
6+
sunset in the move to the new IBM Quantum cloud platform. Saving and loading
7+
to the cloud will not work.
8+
9+
Problem
10+
-------
11+
12+
You want to save and retrieve experiment data from an experiment service.
13+
14+
Solution
15+
--------
16+
17+
The :class:`~.ExperimentData` supports saving and loading data with an
18+
experiment service class satisfying the :class:`~.ExperimentService` protocol.
19+
Here we demonstrate with the :class:`~.LocalExperimentService` class in Qiskit
20+
Experiments.
21+
22+
Saving
23+
~~~~~~
24+
25+
.. note::
26+
27+
In the examples below, the service is instantiated with
28+
``LocalExperimentService()`` which only saves results to
29+
memory. You might want to use ``LocalExperimentService(db_dir=db_dir)``
30+
instead specifying some local file path ``db_dir`` to save results to. Keep
31+
in mind that :class:`~.LocalExperimentService` was not designed to scale to
32+
saving a large amount of data.
33+
34+
Saving results is done by calling :meth:`.ExperimentData.save`:
35+
36+
.. jupyter-execute::
37+
:hide-code:
38+
39+
# backend
40+
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
41+
from qiskit_aer import AerSimulator
42+
backend = AerSimulator.from_backend(FakeManilaV2())
43+
44+
.. jupyter-execute::
45+
46+
import numpy as np
47+
from qiskit_experiments.library import T1
48+
from qiskit_experiments.database_service import LocalExperimentService
49+
50+
delays = np.arange(1.e-6, 300.e-6, 30.e-6)
51+
exp = T1(physical_qubits=(0, ), delays=delays, backend=backend)
52+
53+
exp_data = exp.run().block_for_results()
54+
service = LocalExperimentService()
55+
exp_data.service = service
56+
exp_data.save()
57+
58+
Loading
59+
~~~~~~~
60+
61+
Let's load the previous experiment again from the service. First, we create a
62+
:class:`~qiskit_experiments.framework.Provider` object that has a
63+
``job(job_id)`` method that can return a
64+
:class:`~qiskit_experiments.framework.Job` instance. Since this is a local
65+
test, a fake provider class that just returns jobs it has been given is used.
66+
Another provider like :class:`~qiskit_ibm_runtime.QiskitRuntimeService` could
67+
be used instead. Also, the provider is only needed for reloading the raw job
68+
data for rerunning analysis. If only the experiment results and figures are
69+
needed, the ``provider`` argument to :meth:`.ExperimentData.load` can omitted.
70+
A warning about not being able to access the job data will be emitted in this
71+
case.
72+
73+
.. jupyter-execute::
74+
75+
from qiskit_experiments.test.utils import FakeProvider
76+
77+
provider = FakeProvider()
78+
for job in exp_data.jobs():
79+
provider.add_job(job)
80+
81+
Now the experiment data can be reloaded:
82+
83+
.. jupyter-execute::
84+
85+
from qiskit_experiments.framework import ExperimentData
86+
load_expdata = ExperimentData.load(exp_data.experiment_id, service=service, provider=provider)
87+
88+
Now we can display the figure from the loaded experiment data:
89+
90+
.. jupyter-execute::
91+
92+
load_expdata.figure(0)
93+
94+
The analysis results have been retrieved as well and can be accessed normally.
95+
96+
.. jupyter-execute::
97+
98+
load_expdata.analysis_results(dataframe=True)
99+
100+
Discussion
101+
----------
102+
103+
Note that calling :meth:`~.ExperimentData.save` before the experiment is complete will
104+
instantiate an experiment entry in the database, but it will not have
105+
complete data. To fix this, you can call :meth:`~.ExperimentData.save` again once the
106+
experiment is done running.
107+
108+
Sometimes the metadata of an experiment can be very large and cannot be stored directly in the database.
109+
In this case, a separate ``metadata.json`` file will be stored along with the experiment. Saving and loading
110+
this file is done automatically in :meth:`~.ExperimentData.save` and :meth:`~.ExperimentData.load`.
111+
112+
Auto-saving an experiment
113+
~~~~~~~~~~~~~~~~~~~~~~~~~
114+
115+
The `auto_save` feature automatically saves changes to the
116+
:class:`.ExperimentData` object to the experiment service whenever it's updated.
117+
118+
.. jupyter-execute::
119+
120+
delays = np.arange(1.e-6, 300.e-6, 30.e-6)
121+
exp = T1(physical_qubits=(0, ), delays=delays, backend=backend)
122+
123+
exp_data = exp.run()
124+
service = LocalExperimentService()
125+
exp_data.service = service
126+
exp_data.auto_save = True
127+
exp_data.block_for_results()
128+
129+
130+
Setting ``auto_save = True`` works by triggering :meth:`.ExperimentData.save`
131+
once the experiment's analysis completes.
132+
133+
When working with composite experiments, setting ``auto_save`` will propagate this
134+
setting to the child experiments.
135+
136+
Deleting an experiment
137+
~~~~~~~~~~~~~~~~~~~~~~
138+
139+
Both figures and analysis results can be deleted. Note that unless you
140+
have auto save on, the update has to be manually saved to the
141+
database by calling :meth:`~.ExperimentData.save`. Because there are two analysis
142+
results, one for the T1 parameter and one for the curve fitting results, we must
143+
delete twice to fully remove the analysis results.
144+
145+
.. jupyter-input::
146+
147+
t1_expdata.delete_figure(0)
148+
t1_expdata.delete_analysis_result(0)
149+
t1_expdata.delete_analysis_result(0)
150+
151+
Tagging experiments
152+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153+
154+
Tags and notes can be added to experiments to help identify specific experiments in the interface.
155+
For example, an experiment can be tagged with the following code.
156+
157+
.. jupyter-input::
158+
159+
t1_expdata.tags = ['tag1', 'tag2']
160+
t1_expdata.notes = "Example note."

docs/howtos/experiment_times.rst

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,6 @@ are all of type ``datetime.datetime`` and in your local timezone:
2121
could not be added to the :class:`.ExperimentData` object for some other reason,
2222
:attr:`.ExperimentData.end_datetime` will not update.
2323

24-
.. note::
25-
The below attributes are only relevant for those who have access to the cloud service. You can
26-
check whether you do by logging into the IBM Quantum interface
27-
and seeing if you can see the `database <https://quantum.ibm.com/experiments>`__.
28-
29-
- :attr:`.ExperimentData.creation_datetime` is the time when the experiment data was saved via the
30-
service. This defaults to ``None`` if experiment data has not yet been saved.
31-
32-
- :attr:`.ExperimentData.updated_datetime` is the time the experiment data entry in the service was
33-
last updated. This defaults to ``None`` if experiment data has not yet been saved.
34-
3524
Discussion
3625
----------
3726

docs/howtos/rerun_analysis.rst

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ execution successfully.
1111
Solution
1212
--------
1313

14-
.. note::
15-
This guide requires :external+qiskit_ibm_runtime:doc:`qiskit-ibm-runtime <index>` version 0.15 and up, which can be installed with ``python -m pip install qiskit-ibm-runtime``.
16-
For how to migrate from the older ``qiskit-ibm-provider`` to :external+qiskit_ibm_runtime:doc:`qiskit-ibm-runtime <index>`,
17-
consult the `migration guide <https://quantum.cloud.ibm.com/docs/migration-guides/qiskit-runtime-from-ibm-provider>`_.\
18-
1914
Once you recreate the exact experiment you ran and all of its parameters and options,
2015
you can call the :meth:`.ExperimentData.add_jobs` method with a list of :class:`Job
2116
<qiskit.providers.JobV1>` objects to generate the new :class:`.ExperimentData` object.
@@ -122,4 +117,4 @@ first component experiment.
122117
See Also
123118
--------
124119

125-
* `Saving and loading experiment data with the cloud service <cloud_service.html>`_
120+
* `Saving and loading experiment data with an experiment service <experiment_service.html>`_

0 commit comments

Comments
 (0)