Source code for qiskit_experiments.data_processing.data_action
# 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."""Defines the steps that can be used to analyse data."""fromabcimportABC,abstractmethodfromcollectionsimportOrderedDictfromtypingimportDict,Anyimportnumpyasnpfromqiskit_experiments.framework.store_init_argsimportStoreInitArgsfromqiskit_experiments.frameworkimportOptions
[docs]classDataAction(ABC,StoreInitArgs):"""Abstract action done on measured data to process it. Each subclass of DataAction must define the way it formats, validates and processes data. """def__init__(self,validate:bool=True):"""Create new node. Args: validate: If set to False the DataAction will not validate its input. """self._validate=validate@abstractmethoddef_process(self,data:np.ndarray)->np.ndarray:"""Applies the data processing step to the data. Args: data: A data array to process. This is a single numpy array containing all circuit results input to the data processor. If the elements are ufloat objects consisting of a nominal value and a standard error, then the error propagation is automatically computed. Returns: The processed data. """def_format_data(self,data:np.ndarray)->np.ndarray:"""Format and validate the input. Check that the given data has the correct structure. This method may additionally change the data type, e.g. converting a list to a numpy array. Args: data: A data array to format. This is a single numpy array containing all circuit results input to the data processor. Returns: The data that has been validated and formatted. """returndatadef__json_encode__(self)->Dict[str,Any]:"""Return the config dict for this node."""return{"cls":type(self),"args":tuple(getattr(self,"__init_args__",OrderedDict()).values()),"kwargs":dict(getattr(self,"__init_kwargs__",OrderedDict())),}@classmethoddef__json_decode__(cls,config:Dict[str,Any])->"DataAction":"""Initialize a node from config dict."""init_args=config.get("args",())init_kwargs=config.get("kwargs",{})returncls(*init_args,**init_kwargs)
[docs]def__call__(self,data:np.ndarray)->np.ndarray:"""Call the data action of this node on the data. Args: data: A numpy array with arbitrary dtype. If the elements are ufloat objects consisting of a nominal value and a standard error, then the error propagation is done automatically. Returns: The processed data. """returnself._process(self._format_data(data))
def__repr__(self):"""String representation of the node."""returnf"{self.__class__.__name__}(validate={self._validate})"
[docs]classTrainableDataAction(DataAction):"""A base class for data actions that need training. .. note:: The parameters of trainable nodes computed during training should be listed in the class method :meth:`.TrainableDataAction._default_parameters`. These parameters are initialized at construction time and serialized together with the constructor arguments. All parameters defined in :meth:`.TrainableDataAction._default_parameters` should be assigned a `None` value to indicate that the node has not been trained. Parameter values can be updated with the :meth:`.set_parameters` method and refer to using the :meth:`.TrainableDataAction.parameters` method. This is required to correctly JSON serialize and deserialize a trainable node with parameters set during training. """def__init__(self,validate:bool=True):"""Create new node. Args: validate: If set to False the DataAction will not validate its input. """super().__init__(validate=validate)self._parameters=self._default_parameters()@classmethoddef_default_parameters(cls)->Options:"""Parameters of trainable nodes. The parameters defined here should be assigned a `None` to indicate that the node has not been trained. """returnOptions()@propertydefparameters(self)->Options:"""Return the parameters of the trainable node."""returnself._parameters
[docs]defset_parameters(self,**fields):"""Set parameters for training."""forfieldinfields:ifnothasattr(self._parameters,field):raiseAttributeError(f"{field} is not a valid parameter for {type(self).__name__}.")self._parameters.update_options(**fields)
@propertydefis_trained(self)->bool:"""Return False if the DataAction needs to be trained. A node is considered trained if all its parameters are assigned, or do not have ``None`` values. Return: True if the data action has been trained. """returnall(pisnotNoneforpinself.parameters.__dict__.values())
[docs]@abstractmethoddeftrain(self,data:np.ndarray):"""Train a DataAction. Certain data processing nodes, such as a SVD, require data to first train. Args: data: A data array for training. This is a single numpy array containing all circuit results input to the data processor :meth:`~qiskit_experiments.\ data_processing.data_processor.DataProcessor#train` method. """
def__json_encode__(self)->Dict[str,Any]:"""Return the config dict for this node."""config=super().__json_encode__()config["params"]=self.parameters.__dict__returnconfig@classmethoddef__json_decode__(cls,config:Dict[str,Any])->"TrainableDataAction":"""Initialize a node from config dict."""init_args=config.get("args",())init_kwargs=config.get("kwargs",{})params=config.get("params",{})instance=cls(*init_args,**init_kwargs)instance.set_parameters(**params)returninstancedef__repr__(self):"""String representation of the node."""options_str=f"validate={self._validate}"forpname,pvalinself.parameters.__dict__.items():options_str+=f", {pname}={pval}"returnf"{self.__class__.__name__}({options_str})"