Skip to content

Commit

Permalink
Merge pull request #632 from qiboteam/fix_op_mode
Browse files Browse the repository at this point in the history
Fix operational modes
  • Loading branch information
Edoardo-Pedicillo authored Dec 5, 2023
2 parents 9b307a4 + c1cf650 commit 9cac7a9
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 106 deletions.
4 changes: 1 addition & 3 deletions src/qibocal/auto/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ def run(
):
completed = Completed(self, Normal(), folder)
task_qubits = self._allocate_local_qubits(qubits, platform)

try:
if self.parameters.nshots is None:
self.action.parameters["nshots"] = platform.settings.nshots
Expand All @@ -157,10 +156,9 @@ def run(
] = platform.settings.relaxation_time
operation: Routine = self.operation
parameters = self.parameters
except RuntimeError:
except (RuntimeError, AttributeError):
operation = dummy_operation
parameters = DummyPars()

if mode.name in ["autocalibration", "acquire"]:
if operation.platform_dependent and operation.qubits_dependent:
completed.data, completed.data_time = operation.acquisition(
Expand Down
1 change: 0 additions & 1 deletion src/qibocal/cli/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ def report(path):

# load executor
executor = Executor.load(runcard, path, qubits=qubits)

# produce html
builder = ReportBuilder(path, qubits, executor, meta)
builder.run(path)
Expand Down
2 changes: 1 addition & 1 deletion src/qibocal/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def generate_meta(backend, platform, path):
meta = {}
meta["title"] = path.name
meta["backend"] = backend.name
meta["platform"] = str(platform)
meta["platform"] = platform.name
meta["date"] = e.strftime("%Y-%m-%d")
meta["start-time"] = e.strftime("%H:%M:%S")
meta["end-time"] = e.strftime("%H:%M:%S")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from copy import deepcopy
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -76,8 +78,8 @@ def _acquisition(
order_pairs[:, 1]
) # select qubits with high freq in each couple
new_qubits = {key: platform.qubits[key] for key in unique_qubits}

for transition in ["01", "02"]:
excitations = [Excitations.ge, Excitations.gf]
for transition in excitations:
params.transition = transition
data_transition = flux_acquisition(
params=params,
Expand Down Expand Up @@ -117,22 +119,23 @@ def _fit(data: AvoidedCrossingData) -> AvoidedCrossingResults:
fits = {}
cz = {}
iswap = {}
curves = {key: find_parabola(val) for key, val in qubit_data.items()}
curves = {tuple(key): find_parabola(val) for key, val in qubit_data.items()}
for qubit_pair in data.qubit_pairs:
qubit_pair = tuple(qubit_pair)
fits[qubit_pair] = {}
low = qubit_pair[0]
high = qubit_pair[1]
# Fit the 02*2 curve
curve_02 = np.array(curves[high, "02"]) * 2
x_02 = np.unique(qubit_data[high, "02"]["bias"])
curve_02 = np.array(curves[high, Excitations.gf]) * 2
x_02 = np.unique(qubit_data[high, Excitations.gf]["bias"])
fit_02 = np.polyfit(x_02, curve_02, 2)
fits[qubit_pair, "02"] = fit_02.tolist()
fits[qubit_pair][Excitations.gf] = fit_02.tolist()

# Fit the 01+10 curve
curve_01 = np.array(curves[high, "01"])
x_01 = np.unique(qubit_data[high, "01"]["bias"])
curve_01 = np.array(curves[high, Excitations.ge])
x_01 = np.unique(qubit_data[high, Excitations.ge]["bias"])
fit_01_10 = np.polyfit(x_01, curve_01 + data.drive_frequency_low[str(low)], 2)
fits[qubit_pair, "01+10"] = fit_01_10.tolist()
fits[qubit_pair][Excitations.all_ge] = fit_01_10.tolist()
# find the intersection of the two parabolas
delta_fit = fit_02 - fit_01_10
x1, x2 = solve_eq(delta_fit)
Expand All @@ -142,47 +145,147 @@ def _fit(data: AvoidedCrossingData) -> AvoidedCrossingResults:
]
# find the intersection of the 01 parabola and the 10 line
fit_01 = np.polyfit(x_01, curve_01, 2)
fits[qubit_pair, "01"] = fit_01.tolist()
fits[qubit_pair][Excitations.ge] = fit_01.tolist()
fit_pars = deepcopy(fit_01)
line_val = data.drive_frequency_low[str(low)]
fit_pars[2] -= line_val
x1, x2 = solve_eq(fit_pars)
iswap[qubit_pair] = [[x1, line_val], [x2, line_val]]

return AvoidedCrossingResults(curves, fits, cz, iswap)


def _plot(data: AvoidedCrossingData, fit: AvoidedCrossingResults, qubit):
def _plot(data: AvoidedCrossingData, fit: Optional[AvoidedCrossingResults], qubit):
"""Plotting function for avoided crossing"""
fitting_report = ""
figures = []
order_pair = tuple(index(data.qubit_pairs, qubit))
heatmaps = make_subplots(
rows=1,
cols=2,
subplot_titles=[f"{i} transition qubit {qubit[0]}" for i in ["01", "02"]],
subplot_titles=[
f"{i} transition qubit {qubit[0]}" for i in [Excitations.ge, Excitations.gf]
],
)
parabolas = make_subplots(rows=1, cols=1, subplot_titles=["Parabolas"])
for i, transition in enumerate(["01", "02"]):
for i, transition in enumerate([Excitations.ge, Excitations.gf]):
data_high = data.data[order_pair[1], transition]
bias_unique = np.unique(data_high.bias)
min_bias = min(bias_unique)
max_bias = max(bias_unique)
heatmaps.add_trace(
go.Heatmap(
x=data_high.freq * HZ_TO_GHZ,
y=data_high.bias,
z=data_high.signal,
coloraxis="coloraxis",
plot_heatmap(
heatmaps, fit, transition, bias_unique, order_pair, data_high, i + 1
)

figures.append(heatmaps)

if fit is not None:
cz = np.array(fit.cz[order_pair])
iswap = np.array(fit.iswap[order_pair])
min_bias = min(min_bias, *cz[:, 0], *iswap[:, 0])
max_bias = max(max_bias, *cz[:, 0], *iswap[:, 0])
bias_range = np.linspace(min_bias, max_bias, STEP)
plot_curves(parabolas, fit, data, order_pair, bias_range)
plot_intersections(parabolas, cz, iswap)

parabolas.update_layout(
xaxis_title="Bias[V]",
yaxis_title="Frequency[GHz]",
)
heatmaps.update_layout(
coloraxis_colorbar=dict(
yanchor="top",
y=1,
x=-0.08,
ticks="outside",
),
row=1,
col=i + 1,
xaxis_title="Frequency[GHz]",
yaxis_title="Bias[V]",
xaxis2_title="Frequency[GHz]",
yaxis2_title="Bias[V]",
)
figures.append(parabolas)
fitting_report = table_html(
table_dict(
qubit,
["CZ bias", "iSwap bias"],
[np.round(cz[:, 0], 3), np.round(iswap[:, 0], 3)],
)
)
return figures, fitting_report


avoided_crossing = Routine(_acquisition, _fit, _plot)


def find_parabola(data: dict) -> list:
"""
Finds the parabola in `data`
"""
freqs = data["freq"]
currs = data["bias"]
biass = sorted(np.unique(currs))
frequencies = []
for bias in biass:
data_bias = data[currs == bias]
index = data_bias["signal"].argmax()
frequencies.append(freqs[index])
return frequencies


def solve_eq(pars: list) -> tuple:
"""
Solver of the quadratic equation
.. math::
a x^2 + b x + c = 0
`pars` is the list [a, b, c].
"""
first_term = -1 * pars[1]
second_term = np.sqrt(pars[1] ** 2 - 4 * pars[0] * pars[2])
x1 = (first_term + second_term) / pars[0] / 2
x2 = (first_term - second_term) / pars[0] / 2
return x1, x2


def index(pairs: list, item: list) -> list:
"""Find the ordered pair"""
for pair in pairs:
if set(pair) == set(item):
return pair
raise ValueError(f"{item} not in pairs")


class Excitations(str, Enum):
"""
Excited two qubits states.
"""

ge = "01"
"""First qubit in ground state, second qubit in excited state"""
gf = "02"
"""First qubit in ground state, second qubit in the first excited state out
of the computational basis."""
all_ge = "01+10"
"""One of the qubit in the ground state and the other one in the excited state."""


def plot_heatmap(heatmaps, fit, transition, bias_unique, order_pair, data_high, col):
heatmaps.add_trace(
go.Heatmap(
x=data_high.freq * HZ_TO_GHZ,
y=data_high.bias,
z=data_high.signal,
coloraxis="coloraxis",
),
row=1,
col=col,
)
if fit is not None:
# the fit of the parabola in 02 transition was done doubling the frequencies
heatmaps.add_trace(
go.Scatter(
x=np.polyval(fit.fits[order_pair, transition], bias_unique)
/ (i + 1)
x=np.polyval(fit.fits[order_pair][transition], bias_unique)
/ col
* HZ_TO_GHZ,
y=bias_unique,
mode="markers",
Expand All @@ -192,7 +295,7 @@ def _plot(data: AvoidedCrossingData, fit: AvoidedCrossingResults, qubit):
name=f"Curve estimation {transition}",
),
row=1,
col=i + 1,
col=col,
)
heatmaps.add_trace(
go.Scatter(
Expand All @@ -205,18 +308,16 @@ def _plot(data: AvoidedCrossingData, fit: AvoidedCrossingResults, qubit):
name=f"Parabola {transition}",
),
row=1,
col=i + 1,
col=col,
)
cz = np.array(fit.cz[order_pair])
iswap = np.array(fit.iswap[order_pair])
min_bias = min(min_bias, *cz[:, 0], *iswap[:, 0])
max_bias = max(max_bias, *cz[:, 0], *iswap[:, 0])
bias_range = np.linspace(min_bias, max_bias, STEP)
for transition in ["01", "02", "01+10"]:


def plot_curves(parabolas, fit, data, order_pair, bias_range):
for transition in [Excitations.ge, Excitations.gf, Excitations.all_ge]:
parabolas.add_trace(
go.Scatter(
x=bias_range,
y=np.polyval(fit.fits[order_pair, transition], bias_range) * HZ_TO_GHZ,
y=np.polyval(fit.fits[order_pair][transition], bias_range) * HZ_TO_GHZ,
showlegend=True,
name=transition,
)
Expand All @@ -230,6 +331,9 @@ def _plot(data: AvoidedCrossingData, fit: AvoidedCrossingResults, qubit):
name="10",
)
)


def plot_intersections(parabolas, cz, iswap):
parabolas.add_trace(
go.Scatter(
x=cz[:, 0],
Expand All @@ -252,69 +356,3 @@ def _plot(data: AvoidedCrossingData, fit: AvoidedCrossingResults, qubit):
marker=dict(symbol="cross", size=10),
)
)
parabolas.update_layout(
xaxis_title="Bias[V]",
yaxis_title="Frequency[GHz]",
)
heatmaps.update_layout(
coloraxis_colorbar=dict(
yanchor="top",
y=1,
x=-0.08,
ticks="outside",
),
xaxis_title="Frequency [GHz]",
yaxis_title="Bias [V]",
xaxis2_title="Frequency [GHz]",
yaxis2_title="Bias [V]",
)
figures.append(heatmaps)
figures.append(parabolas)
fitting_report = table_html(
table_dict(
qubit,
["CZ bias", "iSwap bias"],
[np.round(cz[:, 0], 3), np.round(iswap[:, 0], 3)],
)
)
return figures, fitting_report


avoided_crossing = Routine(_acquisition, _fit, _plot)


def find_parabola(data: dict) -> list:
"""
Finds the parabola in `data`
"""
freqs = data["freq"]
currs = data["bias"]
biass = sorted(np.unique(currs))
frequencies = []
for bias in biass:
data_bias = data[currs == bias]
index = data_bias["signal"].argmax()
frequencies.append(freqs[index])
return frequencies


def solve_eq(pars: list) -> tuple:
"""
Solver of the quadratic equation
.. math::
a x^2 + b x + c = 0
`pars` is the list [a, b, c].
"""
first_term = -1 * pars[1]
second_term = np.sqrt(pars[1] ** 2 - 4 * pars[0] * pars[2])
x1 = (first_term + second_term) / pars[0] / 2
x2 = (first_term - second_term) / pars[0] / 2
return x1, x2


def index(pairs: list, item: list) -> list:
"""Find the ordered pair"""
for pair in pairs:
if set(pair) == set(item):
return pair
raise ValueError(f"{item} not in pairs")
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ def _plot(
)
)
figures.append(fig2)

return figures, fitting_report


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def _plot(
):
"""Plotting function for readout mitigation matrix."""
fitting_report = ""

figs = []
if fit is not None:
computational_basis = [
format(i, f"0{len(qubit)}b") for i in range(2 ** len(qubit))
Expand All @@ -191,7 +191,8 @@ def _plot(
width=700,
height=700,
)
return [fig], fitting_report
figs.append(fig)
return figs, fitting_report


readout_mitigation_matrix = Routine(_acquisition, _fit, _plot)
Expand Down

0 comments on commit 9cac7a9

Please sign in to comment.