Skip to content

Commit 3d7a5e4

Browse files
review comments
Co-authored-by: Christopher J. Wood <[email protected]>
1 parent 3a86a25 commit 3d7a5e4

File tree

6 files changed

+109
-95
lines changed

6 files changed

+109
-95
lines changed

docs/tutorials/experiment_cloud_service.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ experiment database.
1919

2020
from qiskit_experiments.library.characterization import T1
2121
import numpy as np
22-
22+
2323
t1_delays = np.arange(1e-6, 600e-6, 50e-6)
24-
24+
2525
# Create an experiment for qubit 0,
2626
# setting the unit to microseconds,
2727
# with the specified time intervals
@@ -158,7 +158,7 @@ on by default at the experiment service level.
158158
.. jupyter-execute::
159159

160160
exp = T1(qubit=0, delays=t1_delays)
161-
161+
162162
t1_expdata = exp.run(backend=backend, shots=1000)
163163
t1_expdata.auto_save = True
164164
t1_expdata.block_for_results()
@@ -189,7 +189,7 @@ Tags and notes can be added to experiments to help identify specific experiments
189189
For example, an experiment can be tagged and made public with the following code.
190190

191191
.. jupyter-execute::
192-
192+
193193
t1_expdata.tags = ['tag1', 'tag2']
194194
t1_expdata.share_level = "public"
195195
t1_expdata.notes = "Example note."
@@ -201,7 +201,7 @@ These fields can also be updated in the web interface from the menu on the right
201201

202202
.. |web_tags_share.png| image:: ./experiment_cloud_service/web_tags_share.png
203203

204-
For more information about using the cloud database interface, please take a look at its `documentation <https://quantum-computing.ibm.com/lab/docs/iql/manage/experiments/>`__.
204+
For more information about using the cloud database interface, please take a look at its `documentation <https://quantum-computing.ibm.com/lab/docs/iql/manage/experiments/>`__.
205205

206206
Randomized Benchmarking experiment
207207
----------------------------------
@@ -211,11 +211,11 @@ Let’s now do a standard RB experiment and save the results to ResultsDB.
211211
.. jupyter-execute::
212212

213213
from qiskit_experiments.library import randomized_benchmarking as rb
214-
214+
215215
lengths = list(range(1, 1000, 200))
216216
num_samples = 10
217217
seed = 1010
218-
218+
219219
rb_exp = rb.StandardRB([0], lengths, num_samples=num_samples, seed=seed)
220220
rb_expdata = rb_exp.run(backend).block_for_results()
221221
rb_expdata.save()
@@ -242,15 +242,15 @@ Let’s do state tomography on a Hadamard state.
242242

243243
from qiskit_experiments.library import StateTomography
244244
import qiskit
245-
245+
246246
# Construct state by applying H gate
247247
qc_h = qiskit.QuantumCircuit(1)
248248
qc_h.h(0)
249-
249+
250250
qstexp = StateTomography(qc_h)
251251
qst_expdata = qstexp.run(backend).block_for_results()
252252
qst_expdata.save()
253-
253+
254254
for result in qst_expdata.analysis_results():
255255
print(result)
256256

@@ -262,7 +262,7 @@ graphical interface, but the other analysis parameters are:
262262
.. image:: ./experiment_cloud_service/tomo_experiment.png
263263

264264
|
265-
265+
266266
.. jupyter-execute::
267267

268268
import qiskit.tools.jupyter

qiskit_experiments/curve_analysis/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,13 +272,13 @@ class AnalysisB(CurveAnalysis):
272272
Typically curve analysis performs fitting as follows.
273273
This workflow is defined in the method :meth:`CurveAnalysis._run_analysis`.
274274
275-
1. Preparation
275+
1. Initialization
276276
277-
Curve analysis calls :meth:`_preparation` method where it initializes
277+
Curve analysis calls :meth:`_initialization` method where it initializes
278278
some internal states and optionally populate analysis options
279279
with the input experiment data.
280280
In some case it may train the data processor with fresh outcomes.
281-
A developer can override this method to perform extra preparation.
281+
A developer can override this method to perform initialization of analysis-specific variables.
282282
283283
2. Data processing
284284

qiskit_experiments/curve_analysis/base_curve_analysis.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,62 +49,64 @@ class BaseCurveAnalysis(BaseAnalysis, ABC):
4949
5050
.. rubric:: _generate_fit_guesses
5151
52-
An abstract method to create initial guesses for the fit parameters.
53-
This should be implemented by subclass.
52+
This method creates initial guesses for the fit parameters.
53+
This might be overridden by subclass.
5454
See :ref:`curve_analysis_init_guess` for details.
5555
5656
.. rubric:: _format_data
5757
58-
A method to format curve data. By default, this method takes the average of y values
59-
over the same x values and then sort the entire data by x values.
58+
This method consumes the processed dataset and outputs the formatted dataset.
59+
By default, this method takes the average of y values over
60+
the same x values and then sort the entire data by x values.
6061
6162
.. rubric:: _evaluate_quality
6263
63-
A method to evaluate the quality of the fit based on the fit result.
64+
This method evaluates the quality of the fit based on the fit result.
6465
This returns "good" when reduced chi-squared is less than 3.0.
6566
Usually it returns string "good" or "bad" according to the evaluation.
6667
This criterion can be updated by subclass.
6768
6869
.. rubric:: _run_data_processing
6970
70-
A method to perform data processing, i.e. create data arrays from
71-
a list of experiment data payload.
71+
This method performs data processing and returns the processed dataset.
72+
By default, it internally calls :class:`DataProcessor` instance from the analysis options
73+
and processes experiment data payload to create Y data with uncertainty.
74+
X data and other metadata are generated within this method by inspecting the
75+
circuit metadata. The series classification is also performed by based upon the
76+
matching of circuit metadata and :attr:`SeriesDef.filter_kwargs`.
7277
7378
.. rubric:: _run_curve_fit
7479
75-
A method to perform fitting with predefined fit models and formatted data.
76-
This method internally calls :meth:`_generate_fit_guesses`.
80+
This method performs the fitting with predefined fit models and the formatted dataset.
81+
This method internally calls :meth:`_generate_fit_guesses` method.
7782
Note that this is a core functionality of the :meth:`_run_analysis` method,
78-
that creates fit result object from the processed curve data.
83+
that creates fit result object from the formatted dataset.
7984
8085
.. rubric:: _create_analysis_results
8186
82-
A method to create analysis results for important fit parameters
87+
This method to creates analysis results for important fit parameters
8388
that might be defined by analysis options ``result_parameters``.
8489
In addition, another entry for all fit parameters is created when
8590
the analysis option ``return_fit_parameters`` is ``True``.
8691
8792
.. rubric:: _create_curve_data
8893
89-
A method to create analysis results for data points used for the fitting.
94+
This method to creates analysis results for the formatted dataset, i.e. data used for the fitting.
9095
Entries are created when the analysis option ``return_data_points`` is ``True``.
9196
If analysis consists of multiple series, analysis result is created for
92-
each curve data in the series.
97+
each curve data in the series definitions.
9398
94-
.. rubric:: _preparation
99+
.. rubric:: _initialize
95100
96-
A method that should be called before other methods are called.
97101
This method initializes analysis options against input experiment data.
102+
Usually this method is called before other methods are called.
98103
99104
"""
100105

101106
def __init__(self):
102107
"""Initialize data fields that are privately accessed by methods."""
103108
super().__init__()
104109

105-
#: List[int]: Index of physical qubits
106-
self._physical_qubits = None
107-
108110
@property
109111
@abstractmethod
110112
def parameters(self) -> List[str]:
@@ -522,11 +524,13 @@ def _create_curve_data(
522524

523525
return samples
524526

525-
def _preparation(
527+
def _initialize(
526528
self,
527529
experiment_data: ExperimentData,
528530
):
529-
"""Prepare for curve analysis. This method is called ahead of other processing.
531+
"""Initialize curve analysis with experiment data.
532+
533+
This method is called ahead of other processing.
530534
531535
Args:
532536
experiment_data: Experiment data to analyze.
@@ -542,9 +546,3 @@ def _preparation(
542546
if not data_processor.is_trained:
543547
data_processor.train(data=experiment_data.data())
544548
self.set_options(data_processor=data_processor)
545-
546-
# get experiment metadata
547-
try:
548-
self._physical_qubits = experiment_data.metadata["physical_qubits"]
549-
except KeyError:
550-
pass

qiskit_experiments/curve_analysis/curve_analysis.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,6 @@ def parameters(self) -> List[str]:
9090
"""Return parameters of this curve analysis."""
9191
return [s for s in self._fit_params() if s not in self.options.fixed_parameters]
9292

93-
@property
94-
def _num_qubits(self) -> int:
95-
"""Getter for qubit number."""
96-
return len(self._physical_qubits)
97-
9893
# pylint: disable=bad-docstring-quotes
9994
@deprecated_function(
10095
last_version="0.4",
@@ -156,7 +151,7 @@ def _run_analysis(
156151
self.__series__ = assigned_series
157152

158153
# Prepare for fitting
159-
self._preparation(experiment_data)
154+
self._initialize(experiment_data)
160155
analysis_results = []
161156

162157
# Run data processing

qiskit_experiments/curve_analysis/curve_data.py

Lines changed: 64 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,39 @@
2525

2626
@dataclasses.dataclass(frozen=True)
2727
class SeriesDef:
28-
"""Description of curve."""
28+
"""A dataclass to describe the definition of the curve.
29+
30+
Args:
31+
fit_func: A callable that defines the fit model of this curve. The argument names
32+
in the callable are parsed to create the fit parameter list, which will appear
33+
in the analysis results. The first argument should be ``x`` that represents
34+
X-values that the experiment sweeps.
35+
filter_kwargs: Optional. Dictionary of properties that uniquely identifies this series.
36+
This dictionary is used for data processing.
37+
This must be provided when the curve analysis consists of multiple series.
38+
name: Optional. Name of this series.
39+
plot_color: Optional. String representation of the color that is used to draw fit data
40+
and data points in the output figure. This depends on the drawer class
41+
being set to the curve analysis options. Usually this conforms to the
42+
Matplotlib color names.
43+
plot_symbol: Optional. String representation of the marker shape that is used to draw
44+
data points in the output figure. This depends on the drawer class
45+
being set to the curve analysis options. Usually this conforms to the
46+
Matplotlib symbol names.
47+
canvas: Optional. Index of sub-axis in the output figure that draws this curve.
48+
This option is valid only when the drawer instance provides multi-axis drawing.
49+
model_description: Optional. Arbitrary string representation of this fit model.
50+
This string will appear in the analysis results as a part of metadata.
51+
"""
2952

30-
# Arbitrary callback to define the fit function. First argument should be x.
3153
fit_func: Callable
32-
33-
# Keyword dictionary to define the series with circuit metadata
3454
filter_kwargs: Dict[str, Any] = dataclasses.field(default_factory=dict)
35-
36-
# Name of this series. This name will appear in the figure and raw x-y value report.
3755
name: str = "Series-0"
38-
39-
# Color of this line.
4056
plot_color: str = "black"
41-
42-
# Symbol to represent data points of this line.
4357
plot_symbol: str = "o"
44-
45-
# Latex description of this fit model
46-
model_description: Optional[str] = None
47-
48-
# Index of canvas if the result figure is multi-panel
4958
canvas: Optional[int] = None
50-
51-
# Automatically extracted signature of the fit function
52-
signature: Tuple[str] = dataclasses.field(init=False)
59+
model_description: Optional[str] = None
60+
signature: Tuple[str, ...] = dataclasses.field(init=False)
5361

5462
def __post_init__(self):
5563
"""Parse the fit function signature to extract the names of the variables.
@@ -65,24 +73,30 @@ def __post_init__(self):
6573

6674
@dataclasses.dataclass(frozen=True)
6775
class CurveData:
68-
"""Set of extracted experiment data."""
76+
"""A dataclass that manages the multiple arrays comprising the dataset for fitting.
77+
78+
This dataset can consist of X, Y values from multiple series.
79+
To extract curve data of the particular series, :meth:`get_subset_of` can be used.
80+
81+
Args:
82+
x: X-values that experiment sweeps.
83+
y: Y-values that observed and processed by the data processor.
84+
y_err: Uncertainty of the Y-values which is created by the data processor.
85+
Usually this assumes standard error.
86+
shots: Number of shots used in the experiment to obtain the Y-values.
87+
data_allocation: List with identical size with other arrays.
88+
The value indicates the series index of the corresponding element.
89+
This is classified based upon the matching of :attr:`SeriesDef.filter_kwargs`
90+
with the circuit metadata of the corresponding data index.
91+
If metadata doesn't match with any series definition, element is filled with ``-1``.
92+
labels: List of curve labels. The list index corresponds to the series index.
93+
"""
6994

70-
# X data
7195
x: np.ndarray
72-
73-
# Y data
7496
y: np.ndarray
75-
76-
# Error bar
7797
y_err: np.ndarray
78-
79-
# Shots number
8098
shots: np.ndarray
81-
82-
# Maping of data index to series index
8399
data_allocation: np.ndarray
84-
85-
# List of curve names
86100
labels: List[str]
87101

88102
def get_subset_of(self, index: Union[str, int]) -> "CurveData":
@@ -114,37 +128,34 @@ def get_subset_of(self, index: Union[str, int]) -> "CurveData":
114128

115129
@dataclasses.dataclass(frozen=True)
116130
class FitData:
117-
"""Set of data generated by the fit function."""
131+
"""A dataclass to store the outcome of the fitting.
132+
133+
Args:
134+
popt: List of optimal parameter values with uncertainties if available.
135+
popt_keys: List of parameter names being fit.
136+
pcov: Covariance matrix from the least square fitting.
137+
reduced_chisq: Reduced Chi-squared value for the fit curve.
138+
dof: Degree of freedom in this fit model.
139+
x_data: X-values provided to the fitter.
140+
y_data: Y-values provided to the fitter.
141+
"""
118142

119-
# Order sensitive fit parameter values
120143
popt: List[uncertainties.UFloat]
121-
122-
# Order sensitive parameter name list
123144
popt_keys: List[str]
124-
125-
# Covariance matrix
126145
pcov: np.ndarray
127-
128-
# Reduced Chi-squared value of fit curve
129146
reduced_chisq: float
130-
131-
# Degree of freedom
132147
dof: int
133-
134-
# X data
135148
x_data: np.ndarray
136-
137-
# Y data
138149
y_data: np.ndarray
139150

140151
@property
141152
def x_range(self) -> Tuple[float, float]:
142-
"""Return range of x values."""
153+
"""Range of x values."""
143154
return np.min(self.x_data), np.max(self.x_data)
144155

145156
@property
146157
def y_range(self) -> Tuple[float, float]:
147-
"""Return range of y values."""
158+
"""Range of y values."""
148159
return np.min(self.y_data), np.max(self.y_data)
149160

150161
def fitval(self, key: str) -> uncertainties.UFloat:
@@ -169,7 +180,13 @@ def fitval(self, key: str) -> uncertainties.UFloat:
169180

170181
@dataclasses.dataclass
171182
class ParameterRepr:
172-
"""Detailed description of fitting parameter."""
183+
"""Detailed description of fitting parameter.
184+
185+
Args:
186+
name: Original name of the fit parameter being defined in the fit model.
187+
repr: Optional. Human-readable parameter name shown in the analysis result and in the figure.
188+
unit: Optional. Physical unit of this parameter if applicable.
189+
"""
173190

174191
# Fitter argument name
175192
name: str

0 commit comments

Comments
 (0)