Source code for qiskit_experiments.calibration_management.parameter_value

# This code is part of Qiskit.
#
# (C) Copyright IBM 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Data class for parameter values."""

from dataclasses import dataclass
from datetime import datetime
from typing import Union
import warnings

from qiskit_experiments.exceptions import CalibrationError


[docs] @dataclass class ParameterValue: """A data class to store parameter values.""" # Value assumed by the parameter value: Union[int, float, complex] = None # Data time when the value of the parameter was generated date_time: datetime = datetime.fromtimestamp(0) # A bool indicating if the parameter is valid valid: bool = True # The experiment from which the value of this parameter was generated. exp_id: str = None # The group of calibrations to which this parameter belongs group: str = "default" def __post_init__(self): """ Ensure that the variables in self have the proper types. This allows us to give strings to self.__init__ as input which is useful when loading serialized parameter values. """ if isinstance(self.valid, str): if self.valid == "True": self.valid = True else: self.valid = False if isinstance(self.value, str): self.value = self._validated_value(self.value) if isinstance(self.date_time, str): base_fmt = "%Y-%m-%d %H:%M:%S.%f" zone_fmts = ["%z", "", "Z"] for time_zone in zone_fmts: date_format = base_fmt + time_zone try: self.date_time = datetime.strptime(self.date_time, date_format) break except ValueError: pass else: formats = list(base_fmt + zone for zone in zone_fmts) raise CalibrationError( f"Cannot parse {self.date_time} in either of {formats} formats." ) self.date_time = self.date_time.astimezone() if isinstance(self.value, complex): warnings.warn( "Support of complex parameters is now pending deprecation, following the" "same transition in Qiskit's Pulse module." "The main use of complex parameters was the complex amplitude in SymbolicPulse" "instances. This use could be removed by converting the pulses to the" "ScalableSymbolicPulse class which uses two floats (amp,angle) for the" "complex amplitude.", PendingDeprecationWarning, ) if not isinstance(self.value, (int, float, complex)): raise CalibrationError(f"Values {self.value} must be int, float or complex.") if not isinstance(self.date_time, datetime): raise CalibrationError(f"Datetime {self.date_time} must be a datetime.") if not isinstance(self.valid, bool): raise CalibrationError(f"Valid {self.valid} is not a boolean.") if self.exp_id and not isinstance(self.exp_id, str): raise CalibrationError(f"Experiment id {self.exp_id} is not a string.") if not isinstance(self.group, str): raise CalibrationError(f"Group {self.group} is not a string.") @staticmethod def _validated_value(value: str) -> Union[int, float, complex]: """ Convert the string representation of value to the correct type. Args: value: The string to convert to either an int, float, or complex. Returns: value converted to either int, float, or complex. Raises: CalibrationError: If the conversion fails. """ try: return int(value) except ValueError: pass try: return float(value) except ValueError: pass try: return complex(value) except ValueError as val_err: raise CalibrationError( f"Could not convert {value} to int, float, or complex." ) from val_err