def update_calibrations(self, experiment_data: ExperimentData): r"""Update the amplitude of one or several schedules. The update rule extracts the rate of the oscillation from the fit to the cosine function. Recall that the amplitude is the x-axis in the analysis of the :class:`Rabi` experiment. The value of the amplitude is thus the desired rotation-angle divided by the rate of the oscillation: .. math:: A_i \to \frac{\theta_i}{\omega} where :math:`\theta_i` is the desired rotation angle (e.g. :math:`\pi` and :math:`\pi/2` for "x" and "sx" gates, respectively) and :math:`\omega` is the rate of the oscillation. Args: experiment_data: The experiment data from which to extract the measured Rabi oscillation used to set the pulse amplitude. """ result_index = self.experiment_options.result_index group = experiment_data.metadata["cal_group"] rate = 2 * np.pi * BaseUpdater.get_value( experiment_data, self.__outcome__, result_index) for angle, param, schedule, prev_amp in experiment_data.metadata[ "angles_schedules"]: value = np.round(angle / rate, decimals=8) * np.exp( 1.0j * np.angle(prev_amp)) BaseUpdater.add_parameter_value(self._cals, experiment_data, value, param, schedule, group)
def update_calibrations(self, experiment_data: ExperimentData): """Update the drag parameter of the pulse in the calibrations.""" result_index = self.experiment_options.result_index group = experiment_data.metadata["cal_group"] target_angle = experiment_data.metadata["target_angle"] qubits = experiment_data.metadata["physical_qubits"] schedule = self._cals.get_schedule(self._sched_name, qubits) # Obtain sigma as it is needed for the fine DRAG update rule. sigmas = [] for block in schedule.blocks: if isinstance(block, Play) and hasattr(block.pulse, "sigma"): sigmas.append(getattr(block.pulse, "sigma")) if len(set(sigmas)) != 1: raise CalibrationError( "Cannot run fine Drag calibration on a schedule with multiple values of sigma." ) if len(sigmas) == 0: raise CalibrationError(f"Could not infer sigma from {schedule}.") d_theta = BaseUpdater.get_value(experiment_data, "d_theta", result_index) # See the documentation in fine_drag.py for the derivation of this rule. d_beta = -np.sqrt(np.pi) * d_theta * sigmas[0] / target_angle**2 old_beta = experiment_data.metadata["cal_param_value"] new_beta = old_beta + d_beta BaseUpdater.add_parameter_value(self._cals, experiment_data, new_beta, self._param_name, schedule, group)
def update_calibrations(self, experiment_data: ExperimentData): r"""Update the qubit frequency based on the measured angle deviation. The frequency of the qubit is updated according to ..math:: f \to f - \frac{{\rm d}\theta}{2\pi\tau{\rm d}t} Here, :math:`{\rm d}\theta` is the measured angle error from the fit. The duration of the single qubit-gate is :math:`\tau` in samples and :math:`{\rm d}t` is the duration of a sample. This is also the duration of the time unit ``dt`` of the delay. """ result_index = self.experiment_options.result_index group = experiment_data.metadata["cal_group"] prev_freq = experiment_data.metadata["cal_param_value"] tau = experiment_data.metadata["delay_duration"] dt = experiment_data.metadata["dt"] d_theta = BaseUpdater.get_value(experiment_data, "d_theta", result_index) new_freq = prev_freq - d_theta / (2 * np.pi * tau * dt) BaseUpdater.add_parameter_value( self._cals, experiment_data, new_freq, self._param_name, self._sched_name, group )
def update_calibrations(self, experiment_data: ExperimentData): r"""Update the amplitude of the pulse in the calibrations. The update rule of this experiment is .. math:: A \to A \frac{\theta_\text{target}}{\theta_\text{target} + {\rm d}\theta} Where :math:`A` is the amplitude of the pulse before the update. Args: experiment_data: The experiment data from which to extract the measured over/under rotation used to adjust the amplitude. """ data = experiment_data.data() # No data -> no update if len(data) > 0: result_index = self.experiment_options.result_index group = data[0]["metadata"]["cal_group"] target_angle = data[0]["metadata"]["target_angle"] prev_amp = data[0]["metadata"]["cal_param_value"] d_theta = BaseUpdater.get_value(experiment_data, "d_theta", result_index) BaseUpdater.add_parameter_value( self._cals, experiment_data, prev_amp * target_angle / (target_angle + d_theta), self._param_name, self._sched_name, group, )
def update_calibrations(self, experiment_data: ExperimentData): """Update the beta using the value directly reported from the fit. See :class:`DragCalAnalysis` for details on the fit. """ new_beta = BaseUpdater.get_value(experiment_data, "beta", self.experiment_options.result_index) BaseUpdater.add_parameter_value( self._cals, experiment_data, new_beta, self._param_name, self._sched_name, self.experiment_options.group, )
def update_calibrations(self, experiment_data: ExperimentData): """Update the frequency using the reported frequency less the imparted oscillation.""" result_index = self.experiment_options.result_index osc_freq = experiment_data.metadata["osc_freq"] group = experiment_data.metadata["cal_group"] old_freq = experiment_data.metadata["cal_param_value"] fit_freq = BaseUpdater.get_value(experiment_data, "freq", result_index) new_freq = old_freq + fit_freq - osc_freq BaseUpdater.add_parameter_value( self._cals, experiment_data, new_freq, self._param_name, group=group, )
def update_calibrations(self, experiment_data: ExperimentData): r"""Update the value of the parameter in the calibrations. The parameter that is updated is the phase of the sx pulse. This phase is contained in the complex amplitude of the pulse. The update rule for the half angle calibration is therefore: ..math:: A \to A \cdot e^{-i{\rm d}\theta_\text{hac}/2} where :math:`A` is the complex amplitude of the sx pulse which has an angle which might be different from the angle of the x pulse due to the non-linearity in the mixer's skew. The angle :math:`{\rm d}\theta_\text{hac}` is the angle deviation measured through the error amplifying pulse sequence. Args: experiment_data: The experiment data from which to extract the measured over/under rotation used to adjust the amplitude. """ result_index = self.experiment_options.result_index group = experiment_data.metadata["cal_group"] prev_amp = experiment_data.metadata["cal_param_value"] d_theta = BaseUpdater.get_value(experiment_data, "d_hac", result_index) new_amp = prev_amp * np.exp(-1.0j * d_theta / 2) BaseUpdater.add_parameter_value( self._cals, experiment_data, new_amp, self._param_name, self._sched_name, group, )
def update_calibrations(self, experiment_data: ExperimentData): r"""Update the amplitude of the pulse in the calibrations. The update rule of this experiment is .. math:: A \to A \frac{\theta_\text{target}}{\theta_\text{target} + {\rm d}\theta} Where :math:`A` is the amplitude of the pulse before the update. Args: experiment_data: The experiment data from which to extract the measured over/under rotation used to adjust the amplitude. """ result_index = self.experiment_options.result_index group = experiment_data.metadata["cal_group"] target_angle = experiment_data.metadata["target_angle"] prev_amp = experiment_data.metadata["cal_param_value"] # Protect against cases where the complex amplitude was converted to a list. if isinstance(prev_amp, list) and len(prev_amp) == 2: prev_amp = prev_amp[0] + 1.0j * prev_amp[1] d_theta = BaseUpdater.get_value(experiment_data, "d_theta", result_index) BaseUpdater.add_parameter_value( self._cals, experiment_data, prev_amp * target_angle / (target_angle + d_theta), self._param_name, self._sched_name, group, )