Skip to content

Commit

Permalink
Update old pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
nkanazawa1989 committed Jan 31, 2024
1 parent fc9273e commit 0cae116
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 59 deletions.
2 changes: 1 addition & 1 deletion qiskit_experiments/curve_analysis/curve_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def _format_data(
)
try:
uid = model_names.index(name)
except IndexError:
except ValueError:
uid = pd.NA
curve_data.add_row(
name=name,
Expand Down
2 changes: 1 addition & 1 deletion qiskit_experiments/curve_analysis/scatter_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def category(self, new_values: np.ndarray):
@property
def shots(self) -> np.ndarray:
"""Shot number used to acquire data points."""
return self._data.shots.to_numpy(dtype=object, na_value=None)
return self._data.shots.to_numpy(dtype=object, na_value=np.nan)

@shots.setter
def shots(self, new_values: np.ndarray):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ def _generate_fit_guesses(
user_opt.bounds.set_if_empty(t_off=(0, np.inf), b=(-1, 1))
user_opt.p0.set_if_empty(b=1e-9)

x_data = curve_data.get_subset_of("x")
y_data = curve_data.get_subset_of("y")
z_data = curve_data.get_subset_of("z")
x_data = curve_data.filter(kind="x")
y_data = curve_data.filter(kind="y")
z_data = curve_data.filter(kind="z")

omega_xyz = []
for data in (x_data, y_data, z_data):
Expand Down
6 changes: 3 additions & 3 deletions qiskit_experiments/curve_analysis/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def shot_weighted_average(
# Shot number is unknown
return np.mean(yvals), np.nan, pd.NA

total_shots = np.sum(shots.astype(float))
total_shots = np.sum(shots)
weights = shots / total_shots

avg_yval = np.sum(weights * yvals)
Expand Down Expand Up @@ -277,7 +277,7 @@ def inverse_weighted_variance(
if len(yvals) == 1:
return yvals[0], yerrs[0], shots[0]

total_shots = np.sum(shots.astype(float))
total_shots = np.sum(shots)
weights = 1 / yerrs**2
yvar = 1 / np.sum(weights)

Expand Down Expand Up @@ -308,7 +308,7 @@ def sample_average(
if len(yvals) == 1:
return yvals[0], 0.0, shots[0]

total_shots = np.sum(shots.astype(float))
total_shots = np.sum(shots)

avg_yval = np.mean(yvals)
avg_yerr = np.sqrt(np.mean((avg_yval - yvals) ** 2) / len(yvals))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ def _generate_fit_guesses(
List of fit options that are passed to the fitter function.
"""
# Use the highest-frequency curve to estimate the oscillation frequency.
max_rep_model_name = self._models[-1]._name
max_rep_model_name = self.model_names()[-1]
max_rep = self.options.data_subfit_map[max_rep_model_name]["nrep"]
curve_data = curve_data.get_subset_of(max_rep_model_name)
curve_data = curve_data.filter(kind=max_rep_model_name)

x_data = curve_data.x
min_beta, max_beta = min(x_data), max(x_data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ def _generate_fit_guesses(
Returns:
List of fit options that are passed to the fitter function.
"""
ramx_data = curve_data.get_subset_of("X")
ramy_data = curve_data.get_subset_of("Y")
ramx_data = curve_data.filter(kind="X")
ramy_data = curve_data.filter(kind="Y")

# At very low frequency, y value of X (Y) curve stay at P=1.0 (0.5) for all x values.
# Computing y peak-to-peak with combined data gives fake amplitude of 0.25.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ def _generate_fit_guesses(
y_ptp = y_max - y_min
x_max = np.max(curve_data.x)

data_0 = curve_data.get_subset_of("0")
data_1 = curve_data.get_subset_of("1")
data_0 = curve_data.filter(kind="0")
data_1 = curve_data.filter(kind="1")

def typical_step(arr):
"""Find the typical step size of an array"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def __eq__(self, other):
self.neg_coef_o1 == other.neg_coef_o1,
self.neg_coef_o2 == other.neg_coef_o2,
self.neg_coef_o3 == other.neg_coef_o3,
self.offset == other.offset,
]
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,26 +254,21 @@ def _format_data(
) -> curve.ScatterTable:

curve_data = super()._format_data(curve_data, category="ramsey_xy")
ramsey_xy = curve_data[curve_data.category == "ramsey_xy"]
ramsey_xy = curve_data.filter(category="ramsey_xy")
y_mean = ramsey_xy.y.mean()

# Create phase data by arctan(Y/X)
columns = list(curve_data.columns)
phase_data = np.empty((0, len(columns)))
y_mean = ramsey_xy.yval.mean()

grouped = ramsey_xy.groupby("name")
for m_id, direction in enumerate(("pos", "neg")):
x_quadrature = grouped.get_group(f"X{direction}")
y_quadrature = grouped.get_group(f"Y{direction}")
if not np.array_equal(x_quadrature.xval, y_quadrature.xval):
x_quadrature = ramsey_xy.filter(kind=f"X{direction}")
y_quadrature = ramsey_xy.filter(kind=f"Y{direction}")
if not np.array_equal(x_quadrature.x, y_quadrature.x):
raise ValueError(
"Amplitude values of X and Y quadrature are different. "
"Same values must be used."
)
x_uarray = unp.uarray(x_quadrature.yval, x_quadrature.yerr)
y_uarray = unp.uarray(y_quadrature.yval, y_quadrature.yerr)

amplitudes = x_quadrature.xval.to_numpy()
x_uarray = unp.uarray(x_quadrature.y, x_quadrature.y_err)
y_uarray = unp.uarray(y_quadrature.y, y_quadrature.y_err)
amplitudes = x_quadrature.x

# pylint: disable=no-member
phase = unp.arctan2(y_uarray - y_mean, x_uarray - y_mean)
Expand All @@ -288,17 +283,24 @@ def _format_data(
unwrapped_phase = unwrapped_phase + (phase_n[-1] - unwrapped_phase[-1])

# Store new data
tmp = np.empty((len(amplitudes), len(columns)), dtype=object)
tmp[:, columns.index("xval")] = amplitudes
tmp[:, columns.index("yval")] = unwrapped_phase / self._freq_phase_coef()
tmp[:, columns.index("yerr")] = phase_s / self._freq_phase_coef()
tmp[:, columns.index("name")] = f"FREQ{direction}"
tmp[:, columns.index("class_id")] = m_id
tmp[:, columns.index("shots")] = x_quadrature.shots + y_quadrature.shots
tmp[:, columns.index("category")] = category
phase_data = np.r_[phase_data, tmp]

return curve_data.append_list_values(other=phase_data)
unwrapped_phase /= self._freq_phase_coef()
phase_s /= self._freq_phase_coef()
shot_sums = x_quadrature.shots + y_quadrature.shots
for new_x, new_y, new_y_err, shot in zip(
amplitudes, unwrapped_phase, phase_s, shot_sums
):
curve_data.add_row(
x=new_x,
y=new_y,
y_err=new_y_err,
name=f"FREQ{direction}",
class_id=m_id,
shots=shot,
category=category,
analysis=self.name,
)

return curve_data

def _generate_fit_guesses(
self,
Expand Down Expand Up @@ -355,39 +357,39 @@ def _create_figures(
) -> List["matplotlib.figure.Figure"]:

# plot unwrapped phase on first axis
for d in ("pos", "neg"):
sub_data = curve_data[(curve_data.name == f"FREQ{d}") & (curve_data.category == "freq")]
for direction in ("pos", "neg"):
sub_data = curve_data.filter(kind=f"FREQ{direction}", category="freq")
self.plotter.set_series_data(
series_name=f"F{d}",
x_formatted=sub_data.xval.to_numpy(),
y_formatted=sub_data.yval.to_numpy(),
y_formatted_err=sub_data.yerr.to_numpy(),
series_name=f"F{direction}",
x_formatted=sub_data.x,
y_formatted=sub_data.y,
y_formatted_err=sub_data.y_err,
)

# plot raw RamseyXY plot on second axis
for name in ("Xpos", "Ypos", "Xneg", "Yneg"):
sub_data = curve_data[(curve_data.name == name) & (curve_data.category == "ramsey_xy")]
sub_data = curve_data.filter(kind=name, category="ramsey_xy")
self.plotter.set_series_data(
series_name=name,
x_formatted=sub_data.xval.to_numpy(),
y_formatted=sub_data.yval.to_numpy(),
y_formatted_err=sub_data.yerr.to_numpy(),
x_formatted=sub_data.x,
y_formatted=sub_data.y,
y_formatted_err=sub_data.y_err,
)

# find base and amplitude guess
ramsey_xy = curve_data[curve_data.category == "ramsey_xy"]
offset_guess = 0.5 * (ramsey_xy.yval.min() + ramsey_xy.yval.max())
amp_guess = 0.5 * np.ptp(ramsey_xy.yval)
ramsey_xy = curve_data.filter(category="ramsey_xy")
offset_guess = 0.5 * (np.min(ramsey_xy.y) + np.max(ramsey_xy.y))
amp_guess = 0.5 * np.ptp(ramsey_xy.y)

# plot frequency and Ramsey fit lines
line_data = curve_data[curve_data.category == "fitted"]
line_data = curve_data.filter(category="fitted")
for direction in ("pos", "neg"):
sub_data = line_data[line_data.name == f"FREQ{direction}"]
sub_data = line_data.filter(kind=f"FREQ{direction}")
if len(sub_data) == 0:
continue
xval = sub_data.xval.to_numpy()
yn = sub_data.yval.to_numpy()
ys = sub_data.yerr.to_numpy()
xval = sub_data.x
yn = sub_data.y
ys = sub_data.y_err
yval = unp.uarray(yn, ys) * self._freq_phase_coef()

# Ramsey fit lines are predicted from the phase fit line.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ def _generate_fit_guesses(
b_guess = 1 / 2**self._num_qubits

# for standard RB curve
std_curve = curve_data.get_subset_of("standard")
std_curve = curve_data.filter(kind="standard")
alpha_std = curve.guess.rb_decay(std_curve.x, std_curve.y, b=b_guess)
a_std = (std_curve.y[0] - b_guess) / (alpha_std ** std_curve.x[0])

# for interleaved RB curve
int_curve = curve_data.get_subset_of("interleaved")
int_curve = curve_data.filter(kind="interleaved")
alpha_int = curve.guess.rb_decay(int_curve.x, int_curve.y, b=b_guess)
a_int = (int_curve.y[0] - b_guess) / (alpha_int ** int_curve.x[0])

Expand Down
8 changes: 7 additions & 1 deletion test/curve_analysis/test_scatter_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,13 @@ def test_add_row(self):
np.testing.assert_array_equal(obj.name, np.array(["model1", None]))
np.testing.assert_array_equal(obj.class_id, np.array([0, None]))
np.testing.assert_array_equal(obj.category, np.array(["raw", "raw"]))
np.testing.assert_array_equal(obj.shots, np.array([1000, None], dtype=object))
np.testing.assert_array_equal(
# Numpy tries to handle nan strictly, but isnan only works for float dtype.
# Original data is object type, because we want to keep shot number integer,
# and there is no Numpy nullable integer.
obj.shots.astype(float),
np.array([1000, np.nan], dtype=float),
)
np.testing.assert_array_equal(obj.analysis, np.array(["Test", None]))

def test_set_values(self):
Expand Down

0 comments on commit 0cae116

Please sign in to comment.