Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CurveAnalysis refactoring #265

5 changes: 4 additions & 1 deletion docs/_ext/custom_styles/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,14 @@ def _extra_sections(self) -> Dict[str, List[str]]:
analysis_option_desc = []

if analysis_class:
default_analysis_options = self._target_cls._default_analysis_options().__dict__

analysis_docs_config = copy.copy(self._config)
analysis_docs_config.napoleon_custom_sections = [("analysis options", "args")]
analysis_option = _generate_options_documentation(
current_class=analysis_class,
method_name="_default_options",
target_args=list(default_analysis_options.keys()),
config=analysis_docs_config,
indent=self._indent,
)
Expand All @@ -230,7 +233,7 @@ def _extra_sections(self) -> Dict[str, List[str]]:
analysis_option_desc.append("")
analysis_option_desc.extend(
_format_default_options(
defaults=analysis_class._default_options().__dict__,
defaults=default_analysis_options,
indent=self._indent,
)
)
Expand Down
57 changes: 40 additions & 17 deletions qiskit_experiments/calibration_management/update_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from qiskit.circuit import Parameter
from qiskit.pulse import ScheduleBlock

from qiskit_experiments.curve_analysis.curve_analysis import PARAMS_ENTRY_PREFIX
from qiskit_experiments.framework.experiment_data import ExperimentData
from qiskit_experiments.calibration_management.backend_calibrations import BackendCalibrations
from qiskit_experiments.calibration_management.calibrations import Calibrations
Expand Down Expand Up @@ -101,7 +102,7 @@ def update(
exp_data: ExperimentData,
parameter: str,
schedule: Optional[Union[ScheduleBlock, str]],
result_index: int = -1,
result_index: Optional[int] = None,
group: str = "default",
):
"""Update the calibrations based on the data.
Expand All @@ -112,23 +113,27 @@ def update(
parameter: The name of the parameter in the calibrations to update.
schedule: The ScheduleBlock instance or the name of the instance to which the parameter
is attached.
result_index: The result index to use, defaults to -1.
result_index: The result index to use. By default search entry by name.
group: The calibrations group to update. Defaults to "default."

Raises:
CalibrationError: If the analysis result does not contain a frequency variable.
"""
if result_index is None:
result = [
r for r in exp_data.analysis_results() if r.name.startswith(PARAMS_ENTRY_PREFIX)
][0]
else:
result = exp_data.analysis_results(index=result_index)

result = exp_data.analysis_results(result_index).extra

if cls.__fit_parameter__ not in result["popt_keys"]:
if cls.__fit_parameter__ not in result.extra["popt_keys"]:
raise CalibrationError(
f"{cls.__name__} updates from analysis classes "
f"which report {cls.__fit_parameter__} in popt."
)

param = parameter
value = result["popt"][result["popt_keys"].index(cls.__fit_parameter__)]
value = result.value.value[result.extra["popt_keys"].index(cls.__fit_parameter__)]

cls._add_parameter_value(
calibrations, exp_data, value, param, schedule=schedule, group=group
Expand All @@ -146,14 +151,29 @@ def update(
cls,
calibrations: BackendCalibrations,
exp_data: ExperimentData,
parameter: str = BackendCalibrations.__qubit_freq_parameter__,
result_index: int = -1,
result_index: Optional[int] = None,
group: str = "default",
**options,
):
"""Update a qubit frequency from, e.g., QubitSpectroscopy."""
"""Update a qubit frequency from, e.g., QubitSpectroscopy

The value of the amplitude must be derived from the fit so the base method cannot be used.

Args:
calibrations: The calibrations to update.
exp_data: The experiment data from which to update.
result_index: The result index to use. By default search entry by name.
group: The calibrations group to update. Defaults to "default."
options: Trailing options.

"""
super().update(
calibrations, exp_data, parameter, schedule=None, result_index=result_index, group=group
calibrations=calibrations,
exp_data=exp_data,
parameter=calibrations.__qubit_freq_parameter__,
schedule=None,
result_index=result_index,
group=group,
)


Expand All @@ -172,7 +192,7 @@ def update(
cls,
calibrations: Calibrations,
exp_data: ExperimentData,
result_index: int = -1,
result_index: Optional[int] = None,
group: str = "default",
angles_schedules: List[Tuple[float, str, Union[str, ScheduleBlock]]] = None,
**options,
Expand All @@ -184,7 +204,7 @@ def update(
Args:
calibrations: The calibrations to update.
exp_data: The experiment data from which to update.
result_index: The result index to use, defaults to -1.
result_index: The result index to use. By default search entry by name.
group: The calibrations group to update. Defaults to "default."
angles_schedules: A list of tuples specifying which angle to update for which
pulse schedule. Each tuple is of the form: (angle, parameter_name,
Expand All @@ -202,11 +222,15 @@ def update(
if angles_schedules is None:
angles_schedules = [(np.pi, "amp", "xp")]

result = exp_data.analysis_results(result_index).extra
if result_index is None:
result = [
r for r in exp_data.analysis_results() if r.name.startswith(PARAMS_ENTRY_PREFIX)
][0]
else:
result = exp_data.analysis_results(index=result_index)

if isinstance(exp_data.experiment, Rabi):
freq = result["popt"][result["popt_keys"].index("freq")]
rate = 2 * np.pi * freq
rate = 2 * np.pi * result.value.value[result.extra["popt_keys"].index("freq")]

for angle, param, schedule in angles_schedules:
qubits = exp_data.data(0)["metadata"]["qubits"]
Expand All @@ -217,10 +241,9 @@ def update(
cls._add_parameter_value(calibrations, exp_data, value, param, schedule, group)

elif isinstance(exp_data.experiment, FineAmplitude):
d_theta = result["popt"][result["popt_keys"].index("d_theta")]
d_theta = result.value.value[result.extra["popt_keys"].index("d_theta")]

for target_angle, param, schedule in angles_schedules:

qubits = exp_data.data(0)["metadata"]["qubits"]

prev_amp = calibrations.get_parameter_value(param, qubits, schedule, group=group)
Expand Down
15 changes: 3 additions & 12 deletions qiskit_experiments/curve_analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
:toctree: ../stubs/

CurveAnalysis
CurveAnalysisResultData
SeriesDef
CurveData
FitData
ParameterRepr

Functions
=========
Expand Down Expand Up @@ -71,25 +72,15 @@
plot_curve_fit
plot_errorbar
plot_scatter

Utility
*******
.. autosummary::
:toctree: ../stubs/

get_opt_error
get_opt_value
"""
from .curve_analysis import CurveAnalysis
from .curve_analysis_result_data import CurveAnalysisResultData
from .curve_data import CurveData, SeriesDef
from .curve_data import CurveData, SeriesDef, FitData, ParameterRepr
from .curve_fit import (
curve_fit,
multi_curve_fit,
process_curve_data,
process_multi_curve_data,
)
from .visualization import plot_curve_fit, plot_errorbar, plot_scatter
from .utils import get_opt_error, get_opt_value
from . import guess
from . import fit_function
Loading