def test_analysis_result_attributes(self): """Test analysis result attributes.""" attrs = { "name": "my_type", "device_components": [Qubit(1), Qubit(2)], "experiment_id": "1234", "result_id": "5678", "quality": "Good", "verified": False, } result = DbAnalysisResult(value={"foo": "bar"}, tags=["tag1", "tag2"], **attrs) self.assertEqual({"foo": "bar"}, result.value) self.assertEqual(["tag1", "tag2"], result.tags) for key, val in attrs.items(): self.assertEqual(val, getattr(result, key))
def _extra_database_entry(self, fit_data: curve.FitData) -> List[AnalysisResultData]: """Calculate Hamiltonian coefficients from fit values.""" extra_entries = [] for control in ("z", "i"): for target in ("x", "y", "z"): p0_val = fit_data.fitval(f"p{target}0") p1_val = fit_data.fitval(f"p{target}1") if control == "z": coef_val = 0.5 * (p0_val - p1_val) / (2 * np.pi) else: coef_val = 0.5 * (p0_val + p1_val) / (2 * np.pi) extra_entries.append( AnalysisResultData( name=f"omega_{control}{target}", value=coef_val, chisq=fit_data.reduced_chisq, device_components=[Qubit(q) for q in self._physical_qubits], extra={"unit": "Hz"}, ) ) return extra_entries
def callback1(exp_data): """Callback function that call add_analysis_callback""" exp_data.add_analysis_callback(callback2) result = DbAnalysisResult("result_name", 0, [Qubit(0)], "experiment_id") exp_data.add_analysis_results(result) figure = get_non_gui_ax().get_figure() exp_data.add_figures(figure, "figure.svg") exp_data.add_data({"key": 1.2}) exp_data.data()
def _get_experiment_components(self, experiment_data: ExperimentData): """Subclasses may override this method to specify the experiment components.""" if "physical_qubits" in experiment_data.metadata: experiment_components = [ Qubit(qubit) for qubit in experiment_data.metadata["physical_qubits"] ] else: experiment_components = [] return experiment_components
def run( self, experiment_data: ExperimentData, **options, ) -> ExperimentData: """Run analysis and update ExperimentData with analysis result. Args: experiment_data: the experiment data to analyze. options: additional analysis options. See class documentation for supported options. Returns: An experiment data object containing the analysis results and figures. Raises: QiskitError: if experiment_data container is not valid for analysis. """ if not isinstance(experiment_data, self.__experiment_data__): raise QiskitError( f"Invalid experiment data type, expected {self.__experiment_data__.__name__}" f" but received {type(experiment_data).__name__}") # Get experiment device components if "physical_qubits" in experiment_data.metadata: experiment_components = [ Qubit(qubit) for qubit in experiment_data.metadata["physical_qubits"] ] else: experiment_components = [] # Get analysis options analysis_options = self._default_options() analysis_options.update_options(**options) analysis_options = analysis_options.__dict__ # Run analysis results, figures = self._run_analysis(experiment_data, **analysis_options) # Add components analysis_results = [ self._format_analysis_result(result, experiment_data.experiment_id, experiment_components) for result in results ] # Update experiment data with analysis results experiment_data.add_analysis_results(analysis_results) if figures: experiment_data.add_figures(figures) return experiment_data
def _extra_database_entry( self, fit_data: curve.FitData) -> List[AnalysisResultData]: """Calculate EPC.""" extra_entries = [] # Calculate EPC alpha = fit_data.fitval("alpha") scale = (2**self._num_qubits - 1) / (2**self._num_qubits) epc = scale * (1 - alpha) extra_entries.append( AnalysisResultData( name="EPC", value=epc, chisq=fit_data.reduced_chisq, quality=self._evaluate_quality(fit_data), )) # Calculate EPG if not self.options.gate_error_ratio: # we attempt to get the ratio from the backend properties if not self.options.error_dict: gate_error_ratio = RBUtils.get_error_dict_from_backend( backend=self._backend, qubits=self._physical_qubits) else: gate_error_ratio = self.options.error_dict else: gate_error_ratio = self.options.gate_error_ratio count_ops = [] for meta in self._data(label="raw_data").metadata: count_ops += meta.get("count_ops", []) if len(count_ops) > 0 and gate_error_ratio is not None: gates_per_clifford = RBUtils.gates_per_clifford(count_ops) num_qubits = len(self._physical_qubits) if num_qubits == 1: epg_dict = RBUtils.calculate_1q_epg( epc, self._physical_qubits, gate_error_ratio, gates_per_clifford, ) elif num_qubits == 2: epg_1_qubit = self.options.epg_1_qubit epg_dict = RBUtils.calculate_2q_epg( epc, self._physical_qubits, gate_error_ratio, gates_per_clifford, epg_1_qubit=epg_1_qubit, ) else: # EPG calculation is not supported for more than 3 qubits RB epg_dict = None if epg_dict: for qubits, gate_dict in epg_dict.items(): for gate, value in gate_dict.items(): extra_entries.append( AnalysisResultData( f"EPG_{gate}", value, chisq=fit_data.reduced_chisq, quality=self._evaluate_quality(fit_data), device_components=[Qubit(i) for i in qubits], )) return extra_entries
def test_str(self): """Test string representation.""" q1 = Qubit(1) r1 = Resonator(1) self.assertEqual("Q1", str(q1)) self.assertEqual("R1", str(r1))
def run( self, experiment_data: ExperimentData, replace_results: bool = False, **options, ) -> ExperimentData: """Run analysis and update ExperimentData with analysis result. Args: experiment_data: the experiment data to analyze. replace_results: if True clear any existing analysis results and figures in the experiment data and replace with new results. See note for additional information. options: additional analysis options. See class documentation for supported options. Returns: An experiment data object containing the analysis results and figures. Raises: QiskitError: if experiment_data container is not valid for analysis. .. note:: **Updating Results** If analysis is run with ``replace_results=True`` then any analysis results and figures in the experiment data will be cleared and replaced with the new analysis results. Saving this experiment data will replace any previously saved data in a database service using the same experiment ID. If analysis is run with ``replace_results=False`` and the experiment data being analyzed has already been saved to a database service, or already contains analysis results or figures, a copy with a unique experiment ID will be returned containing only the new analysis results and figures. This data can then be saved as its own experiment to a database service. """ # Make a new copy of experiment data if not updating results if not replace_results and _requires_copy(experiment_data): experiment_data = experiment_data.copy() # Get experiment device components if "physical_qubits" in experiment_data.metadata: experiment_components = [ Qubit(qubit) for qubit in experiment_data.metadata["physical_qubits"] ] else: experiment_components = [] # Set Analysis options if not options: analysis = self else: analysis = self.copy() analysis.set_options(**options) def run_analysis(expdata): results, figures = analysis._run_analysis(expdata) # Add components analysis_results = [ analysis._format_analysis_result(result, expdata.experiment_id, experiment_components) for result in results ] # Update experiment data with analysis results experiment_data._clear_results() if analysis_results: expdata.add_analysis_results(analysis_results) if figures: expdata.add_figures(figures) experiment_data.add_analysis_callback(run_analysis) return experiment_data