Skip to content

Commit

Permalink
Fix curve analysis error handling (#412)
Browse files Browse the repository at this point in the history
* fix analysis error handling

* Update qiskit_experiments/curve_analysis/curve_analysis.py

Co-authored-by: Daniel Egger <[email protected]>

Co-authored-by: Daniel Egger <[email protected]>
  • Loading branch information
nkanazawa1989 and eggerdj authored Sep 30, 2021
1 parent 1c3d3e1 commit f859b2d
Showing 1 changed file with 60 additions and 54 deletions.
114 changes: 60 additions & 54 deletions qiskit_experiments/curve_analysis/curve_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import dataclasses
import functools
import inspect
import warnings
from abc import ABC
from typing import Any, Dict, List, Tuple, Callable, Union, Optional

Expand Down Expand Up @@ -850,60 +851,60 @@ def _run_analysis(
except AttributeError:
pass

try:
#
# 2. Setup data processor
#

# No data processor has been provided at run-time we infer one from the job
# metadata and default to the data processor for averaged classified data.
data_processor = self._get_option("data_processor")
#
# 2. Setup data processor
#

if not data_processor:
run_options = self._run_options() or dict()
# No data processor has been provided at run-time we infer one from the job
# metadata and default to the data processor for averaged classified data.
data_processor = self._get_option("data_processor")

try:
meas_level = run_options["meas_level"]
except KeyError as ex:
raise DataProcessorError(
f"Cannot process data without knowing the measurement level: {str(ex)}."
) from ex
if not data_processor:
run_options = self._run_options() or dict()

meas_return = run_options.get("meas_return", None)
normalization = self._get_option("normalization")
try:
meas_level = run_options["meas_level"]
except KeyError as ex:
raise DataProcessorError(
f"Cannot process data without knowing the measurement level: {str(ex)}."
) from ex

data_processor = get_processor(meas_level, meas_return, normalization)
meas_return = run_options.get("meas_return", None)
normalization = self._get_option("normalization")

if isinstance(data_processor, DataProcessor) and not data_processor.is_trained:
# Qiskit DataProcessor instance. May need calibration.
data_processor.train(data=experiment_data.data())
data_processor = get_processor(meas_level, meas_return, normalization)

#
# 3. Extract curve entries from experiment data
#
self._extract_curves(experiment_data=experiment_data, data_processor=data_processor)
if isinstance(data_processor, DataProcessor) and not data_processor.is_trained:
# Qiskit DataProcessor instance. May need calibration.
data_processor.train(data=experiment_data.data())

#
# 4. Run fitting
#
curve_fitter = self._get_option("curve_fitter")
formatted_data = self._data(label="fit_ready")
#
# 3. Extract curve entries from experiment data
#
self._extract_curves(experiment_data=experiment_data, data_processor=data_processor)

# Generate algorithmic initial guesses and boundaries
default_fit_opt = FitOptions(
parameters=self._fit_params(),
default_p0=self._get_option("p0"),
default_bounds=self._get_option("bounds"),
**extra_options,
)
#
# 4. Run fitting
#
curve_fitter = self._get_option("curve_fitter")
formatted_data = self._data(label="fit_ready")

# Generate algorithmic initial guesses and boundaries
default_fit_opt = FitOptions(
parameters=self._fit_params(),
default_p0=self._get_option("p0"),
default_bounds=self._get_option("bounds"),
**extra_options,
)

fit_options = self._generate_fit_guesses(default_fit_opt)
if isinstance(fit_options, FitOptions):
fit_options = [fit_options]
fit_options = self._generate_fit_guesses(default_fit_opt)
if isinstance(fit_options, FitOptions):
fit_options = [fit_options]

# Run fit for each configuration
fit_results = []
for fit_opt in set(fit_options):
# Run fit for each configuration
fit_results = []
for fit_opt in set(fit_options):
try:
fit_result = curve_fitter(
funcs=[series_def.fit_func for series_def in self.__series__],
series=formatted_data.data_index,
Expand All @@ -913,17 +914,22 @@ def _run_analysis(
**fit_opt.options,
)
fit_results.append(fit_result)

# Find best value with chi-squared value
if len(fit_results) == 0:
raise AnalysisError(
"All initial guesses and parameter boundaries failed to fit the data. "
"Please provide better initial guesses or fit parameter boundaries."
)
fit_result = sorted(fit_results, key=lambda r: r.reduced_chisq)[0]

except AnalysisError:
except AnalysisError:
# Some guesses might be too far from the true parameters and may thus fail.
# We ignore initial guesses that fail and continue with the next fit candidate.
pass

# Find best value with chi-squared value
if len(fit_results) == 0:
warnings.warn(
"All initial guesses and parameter boundaries failed to fit the data. "
"Please provide better initial guesses or fit parameter boundaries.",
UserWarning,
)
# at least return raw data points rather than terminating
fit_result = None
else:
fit_result = sorted(fit_results, key=lambda r: r.reduced_chisq)[0]

#
# 5. Create database entry
Expand Down

0 comments on commit f859b2d

Please sign in to comment.