Пример #1
0
    def _run_analysis(
        self,
        experiment_data,
        t1_guess=None,
        amplitude_guess=None,
        offset_guess=None,
        plot=True,
        ax=None,
    ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]:
        """
        Calculate T1

        Args:
            experiment_data (ExperimentData): the experiment data to analyze
            t1_guess (float): Optional, an initial guess of T1
            amplitude_guess (float): Optional, an initial guess of the coefficient
                                     of the exponent
            offset_guess (float): Optional, an initial guess of the offset
            plot (bool): Generator plot of exponential fit.
            ax (AxesSubplot): Optional, axes to add figure to.

        Returns:
            The analysis result with the estimated T1

        Raises:
            AnalysisError: if the analysis fails.
        """
        data = experiment_data.data()
        unit = data[0]["metadata"]["unit"]
        conversion_factor = data[0]["metadata"].get("dt_factor", None)
        qubit = data[0]["metadata"]["qubit"]

        if conversion_factor is None:
            conversion_factor = 1 if unit == "s" else apply_prefix(1, unit)

        xdata, ydata, sigma = process_curve_data(data, lambda datum: level2_probability(datum, "1"))
        xdata *= conversion_factor

        if t1_guess is None:
            t1_guess = np.mean(xdata)
        else:
            t1_guess = t1_guess * conversion_factor
        if offset_guess is None:
            offset_guess = ydata[-1]
        if amplitude_guess is None:
            amplitude_guess = ydata[0] - offset_guess

        # Perform fit
        def fit_fun(x, a, tau, c):
            return a * np.exp(-x / tau) + c

        init = {"a": amplitude_guess, "tau": t1_guess, "c": offset_guess}
        fit_result = curve_fit(fit_fun, xdata, ydata, init, sigma=sigma)
        fit_result = dataclasses.asdict(fit_result)
        fit_result["circuit_unit"] = unit
        if unit == "dt":
            fit_result["dt"] = conversion_factor

        # Construct analysis result
        name = "T1"
        unit = "s"
        value = FitVal(fit_result["popt"][1], fit_result["popt_err"][1], unit="s")
        chisq = fit_result["reduced_chisq"]
        quality = self._fit_quality(
            fit_result["popt"], fit_result["popt_err"], fit_result["reduced_chisq"]
        )
        analysis_results = [
            AnalysisResultData(
                name,
                value,
                chisq=chisq,
                quality=quality,
                extra=fit_result,
            )
        ]

        # Generate fit plot
        figures = []
        if plot:
            ax = plot_curve_fit(fit_fun, fit_result, ax=ax, fit_uncertainty=True)
            ax = plot_errorbar(xdata, ydata, sigma, ax=ax)
            self._format_plot(ax, fit_result, qubit=qubit)
            figures.append(ax.get_figure())

        return analysis_results, figures
Пример #2
0
    def _format_plot(hop_result: AnalysisResultData,
                     ax: Optional["matplotlib.pyplot.AxesSubplot"] = None):
        """Format the QV plot

        Args:
            hop_result: the heavy output probability analysis result.
            ax: matplotlib axis to add plot to.

        Returns:
            AxesSubPlot: the matplotlib axes containing the plot.
        """
        trials = hop_result.extra["trials"]
        heavy_probs = hop_result.extra["HOPs"]
        trial_list = np.arange(1, trials + 1)  # x data

        hop_accumulative = np.cumsum(heavy_probs) / trial_list
        two_sigma = 2 * (hop_accumulative *
                         (1 - hop_accumulative) / trial_list)**0.5

        # Plot individual HOP as scatter
        ax = plot_scatter(
            trial_list,
            heavy_probs,
            ax=ax,
            s=3,
            zorder=3,
            label="Individual HOP",
        )
        # Plot accumulative HOP
        ax.plot(trial_list,
                hop_accumulative,
                color="r",
                label="Cumulative HOP")

        # Plot two-sigma shaded area
        ax = plot_errorbar(
            trial_list,
            hop_accumulative,
            two_sigma,
            ax=ax,
            fmt="none",
            ecolor="lightgray",
            elinewidth=20,
            capsize=0,
            alpha=0.5,
            label="2$\\sigma$",
        )
        # Plot 2/3 success threshold
        ax.axhline(2 / 3,
                   color="k",
                   linestyle="dashed",
                   linewidth=1,
                   label="Threshold")

        ax.set_ylim(
            max(hop_accumulative[-1] - 4 * two_sigma[-1], 0),
            min(hop_accumulative[-1] + 4 * two_sigma[-1], 1),
        )

        ax.set_xlabel("Number of Trials", fontsize=14)
        ax.set_ylabel("Heavy Output Probability", fontsize=14)

        ax.set_title(
            "Quantum Volume experiment for depth " +
            str(hop_result.extra["depth"]) + " - accumulative hop",
            fontsize=14,
        )

        # Re-arrange legend order
        handles, labels = ax.get_legend_handles_labels()
        handles = [handles[1], handles[2], handles[0], handles[3]]
        labels = [labels[1], labels[2], labels[0], labels[3]]
        ax.legend(handles, labels)
        return ax
    def _run_analysis(
        self,
        experiment_data: ExperimentData,
        user_p0: Optional[Dict[str, float]] = None,
        user_bounds: Optional[Tuple[List[float], List[float]]] = None,
        plot: bool = False,
        ax: Optional["AxesSubplot"] = None,
        **kwargs,
    ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]:
        r"""Calculate T2Ramsey experiment.

        Args:
            experiment_data (ExperimentData): the experiment data to analyze
            user_p0: contains initial values given by the user, for the
            fit parameters :math:`(a, t2ramsey, f, \phi, b)`
            user_bounds: lower and upper bounds on the parameters in p0,
                         given by the user.
                         The first tuple is the lower bounds,
                         The second tuple is the upper bounds.
                         For both params, the order is :math:`a, t2ramsey, f, \phi, b`.
            plot: if True, create the plot, otherwise, do not create the plot.
            ax: the plot object
            **kwargs: additional parameters for curve fit.

        Returns:
            The analysis result with the estimated :math:`t2ramsey` and 'f' (frequency)
            The graph of the function.
        """
        def osc_fit_fun(x, a, t2ramsey, f, phi, c):
            """Decay cosine fit function"""
            return a * np.exp(
                -x / t2ramsey) * np.cos(2 * np.pi * f * x + phi) + c

        def _format_plot(ax, unit, fit_result, conversion_factor):
            """Format curve fit plot"""
            # Formatting
            ax.tick_params(labelsize=14)
            ax.set_xlabel("Delay (s)", fontsize=12)
            ax.ticklabel_format(axis="x", style="sci", scilimits=(0, 0))
            ax.set_ylabel("Probability of measuring 0", fontsize=12)
            t2ramsey = fit_result["popt"][1] / conversion_factor
            t2_err = fit_result["popt_err"][1] / conversion_factor
            box_text = "$T_2Ramsey$ = {:.2f} \u00B1 {:.2f} {}".format(
                t2ramsey, t2_err, unit)
            bbox_props = dict(boxstyle="square,pad=0.3",
                              fc="white",
                              ec="black",
                              lw=1)
            ax.text(
                0.6,
                0.9,
                box_text,
                ha="center",
                va="center",
                size=12,
                bbox=bbox_props,
                transform=ax.transAxes,
            )
            return ax

        # implementation of  _run_analysis

        data = experiment_data.data()
        circ_metadata = data[0]["metadata"]
        unit = circ_metadata["unit"]
        conversion_factor = circ_metadata.get("dt_factor", None)
        osc_freq = circ_metadata.get("osc_freq", None)
        if conversion_factor is None:
            conversion_factor = 1 if unit in ("s",
                                              "dt") else apply_prefix(1, unit)

        xdata, ydata, sigma = process_curve_data(
            data, lambda datum: level2_probability(datum, "0"))

        t2ramsey_estimate = np.mean(xdata)
        p0, bounds = self._t2ramsey_default_params(conversion_factor, user_p0,
                                                   user_bounds,
                                                   t2ramsey_estimate, osc_freq)
        xdata *= conversion_factor
        fit_result = curve_fit(osc_fit_fun,
                               xdata,
                               ydata,
                               p0=list(p0.values()),
                               sigma=sigma,
                               bounds=bounds)
        fit_result = dataclasses.asdict(fit_result)
        fit_result["circuit_unit"] = unit
        if osc_freq is not None:
            fit_result["osc_freq"] = osc_freq
        if unit == "dt":
            fit_result["dt"] = conversion_factor
        quality = self._fit_quality(fit_result["popt"], fit_result["popt_err"],
                                    fit_result["reduced_chisq"])
        chisq = fit_result["reduced_chisq"]

        if plot:
            ax = plot_curve_fit(osc_fit_fun, fit_result, ax=ax)
            ax = plot_scatter(xdata, ydata, ax=ax)
            ax = plot_errorbar(xdata, ydata, sigma, ax=ax)
            _format_plot(ax, unit, fit_result, conversion_factor)
            figures = [ax.get_figure()]
        else:
            figures = None

        # Output unit is 'sec', regardless of the unit used in the input
        result_t2star = AnalysisResultData(
            "T2star",
            value=FitVal(fit_result["popt"][1], fit_result["popt_err"][1],
                         "s"),
            quality=quality,
            chisq=chisq,
            extra=fit_result,
        )
        result_freq = AnalysisResultData(
            "Frequency",
            value=FitVal(fit_result["popt"][2], fit_result["popt_err"][2],
                         "Hz"),
            quality=quality,
            chisq=chisq,
            extra=fit_result,
        )

        return [result_t2star, result_freq], figures