qubitclient 0.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qubitclient/__init__.py +5 -0
- qubitclient/draw/__init__.py +0 -0
- qubitclient/draw/optpipulsepltplotter.py +75 -0
- qubitclient/draw/optpipulseplyplotter.py +114 -0
- qubitclient/draw/pltmanager.py +50 -0
- qubitclient/draw/pltplotter.py +20 -0
- qubitclient/draw/plymanager.py +57 -0
- qubitclient/draw/plyplotter.py +21 -0
- qubitclient/draw/powershiftpltplotter.py +108 -0
- qubitclient/draw/powershiftplyplotter.py +194 -0
- qubitclient/draw/rabicospltplotter.py +74 -0
- qubitclient/draw/rabicosplyplotter.py +90 -0
- qubitclient/draw/rabipltplotter.py +66 -0
- qubitclient/draw/rabiplyplotter.py +86 -0
- qubitclient/draw/s21peakpltplotter.py +67 -0
- qubitclient/draw/s21peakplyplotter.py +124 -0
- qubitclient/draw/s21vfluxpltplotter.py +84 -0
- qubitclient/draw/s21vfluxplyplotter.py +163 -0
- qubitclient/draw/singleshotpltplotter.py +149 -0
- qubitclient/draw/singleshotplyplotter.py +324 -0
- qubitclient/draw/spectrum2dpltplotter.py +107 -0
- qubitclient/draw/spectrum2dplyplotter.py +244 -0
- qubitclient/draw/spectrum2dscopepltplotter.py +72 -0
- qubitclient/draw/spectrum2dscopeplyplotter.py +195 -0
- qubitclient/draw/spectrumpltplotter.py +106 -0
- qubitclient/draw/spectrumplyplotter.py +133 -0
- qubitclient/draw/t1fitpltplotter.py +76 -0
- qubitclient/draw/t1fitplyplotter.py +109 -0
- qubitclient/draw/t2fitpltplotter.py +70 -0
- qubitclient/draw/t2fitplyplotter.py +111 -0
- qubitclient/nnscope/nnscope.py +51 -0
- qubitclient/nnscope/nnscope_api/curve/__init__.py +0 -0
- qubitclient/nnscope/nnscope_api/curve/curve_type.py +15 -0
- qubitclient/nnscope/task.py +170 -0
- qubitclient/nnscope/utils/data_convert.py +114 -0
- qubitclient/nnscope/utils/data_parser.py +41 -0
- qubitclient/nnscope/utils/request_tool.py +41 -0
- qubitclient/nnscope/utils/result_parser.py +55 -0
- qubitclient/scope/scope.py +50 -0
- qubitclient/scope/scope_api/__init__.py +8 -0
- qubitclient/scope/scope_api/api/__init__.py +1 -0
- qubitclient/scope/scope_api/api/defined_tasks/__init__.py +1 -0
- qubitclient/scope/scope_api/api/defined_tasks/get_task_result_api_v1_tasks_demo_pk_get.py +155 -0
- qubitclient/scope/scope_api/api/defined_tasks/get_task_result_api_v1_tasks_scope_pk_get.py +155 -0
- qubitclient/scope/scope_api/api/defined_tasks/optpipulse_api_v1_tasks_scope_optpipulse_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/powershift_api_v1_tasks_scope_powershift_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/rabi_api_v1_tasks_scope_rabi_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/rabicos_api_v1_tasks_scope_rabicospeak_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/s21peak_api_v1_tasks_scope_s21peak_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/s21vflux_api_v1_tasks_scope_s21vflux_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/singleshot_api_v1_tasks_scope_singleshot_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/spectrum2d_api_v1_tasks_scope_spectrum2d_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/spectrum_api_v1_tasks_scope_spectrum_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/t1fit_api_v1_tasks_scope_t1fit_post.py +218 -0
- qubitclient/scope/scope_api/api/defined_tasks/t1fit_api_v1_tasks_scope_t2fit_post.py +218 -0
- qubitclient/scope/scope_api/client.py +268 -0
- qubitclient/scope/scope_api/errors.py +16 -0
- qubitclient/scope/scope_api/models/__init__.py +31 -0
- qubitclient/scope/scope_api/models/body_optpipulse_api_v1_tasks_scope_optpipulse_post.py +83 -0
- qubitclient/scope/scope_api/models/body_powershift_api_v1_tasks_scope_powershift_post.py +83 -0
- qubitclient/scope/scope_api/models/body_rabi_api_v1_tasks_scope_rabi_post.py +83 -0
- qubitclient/scope/scope_api/models/body_rabicos_api_v1_tasks_scope_rabicospeak_post.py +83 -0
- qubitclient/scope/scope_api/models/body_s21_peak_api_v1_tasks_scope_s21_peak_post.py +83 -0
- qubitclient/scope/scope_api/models/body_s21_vflux_api_v1_tasks_scope_s21_vflux_post.py +83 -0
- qubitclient/scope/scope_api/models/body_singleshot_api_v1_tasks_scope_singleshot_post.py +83 -0
- qubitclient/scope/scope_api/models/body_spectrum_2d_api_v1_tasks_scope_spectrum_2d_post.py +83 -0
- qubitclient/scope/scope_api/models/body_spectrum_api_v1_tasks_scope_spectrum_post.py +83 -0
- qubitclient/scope/scope_api/models/body_t1_fit_api_v1_tasks_scope_t1_fit_post.py +83 -0
- qubitclient/scope/scope_api/models/body_t1_fit_api_v1_tasks_scope_t2_fit_post.py +83 -0
- qubitclient/scope/scope_api/models/http_validation_error.py +75 -0
- qubitclient/scope/scope_api/models/validation_error.py +88 -0
- qubitclient/scope/scope_api/types.py +54 -0
- qubitclient/scope/task.py +163 -0
- qubitclient/scope/utils/__init__.py +0 -0
- qubitclient/scope/utils/data_parser.py +20 -0
- qubitclient-0.1.4.dist-info/METADATA +173 -0
- qubitclient-0.1.4.dist-info/RECORD +81 -0
- qubitclient-0.1.4.dist-info/WHEEL +5 -0
- qubitclient-0.1.4.dist-info/licenses/LICENSE +674 -0
- qubitclient-0.1.4.dist-info/top_level.txt +1 -0
- qubitclient-0.1.4.dist-info/zip-safe +1 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from .plyplotter import QuantumDataPlyPlotter
|
|
2
|
+
import numpy as np
|
|
3
|
+
import plotly.graph_objects as go
|
|
4
|
+
from plotly.subplots import make_subplots
|
|
5
|
+
|
|
6
|
+
from scipy.stats import norm
|
|
7
|
+
|
|
8
|
+
class S21VfluxDataPlyPlotter(QuantumDataPlyPlotter):
|
|
9
|
+
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__("s21vflux")
|
|
12
|
+
|
|
13
|
+
def plot_result_npy(self, **kwargs):
|
|
14
|
+
result = kwargs.get('result')
|
|
15
|
+
dict_param = kwargs.get('dict_param')
|
|
16
|
+
|
|
17
|
+
data = dict_param.item()
|
|
18
|
+
image = data["image"]
|
|
19
|
+
q_list = image.keys()
|
|
20
|
+
|
|
21
|
+
# 数据提取
|
|
22
|
+
volt_list = []
|
|
23
|
+
freq_list = []
|
|
24
|
+
s_list = []
|
|
25
|
+
q_name_list = []
|
|
26
|
+
|
|
27
|
+
for idx, q_name in enumerate(q_list):
|
|
28
|
+
image_q = image[q_name]
|
|
29
|
+
volt = image_q[0]
|
|
30
|
+
freq = image_q[1]
|
|
31
|
+
s = image_q[2]
|
|
32
|
+
|
|
33
|
+
volt_list.append(volt)
|
|
34
|
+
freq_list.append(freq)
|
|
35
|
+
s_list.append(s)
|
|
36
|
+
q_name_list.append(q_name)
|
|
37
|
+
|
|
38
|
+
# 结果数据
|
|
39
|
+
coscurves_list = result['coscurves_list']
|
|
40
|
+
cosconfs_list = result['cosconfs_list']
|
|
41
|
+
lines_list = result['lines_list']
|
|
42
|
+
lineconfs_list = result['lineconfs_list']
|
|
43
|
+
|
|
44
|
+
# 计算子图布局
|
|
45
|
+
nums = len(volt_list) * 2
|
|
46
|
+
rows = (nums // 2) + 1 if nums % 2 != 0 else nums // 2
|
|
47
|
+
cols = 2
|
|
48
|
+
|
|
49
|
+
# 创建子图布局
|
|
50
|
+
fig = make_subplots(
|
|
51
|
+
rows=rows,
|
|
52
|
+
cols=cols,
|
|
53
|
+
shared_xaxes=True, # 共享X轴以增强交互一致性
|
|
54
|
+
shared_yaxes=True,
|
|
55
|
+
subplot_titles=[f"{q_name_list[i // 2]}_Heatmap" if i % 2 == 0
|
|
56
|
+
else f"{q_name_list[i // 2]}_WithCurves" for i in range(nums)],
|
|
57
|
+
horizontal_spacing=0.1,
|
|
58
|
+
vertical_spacing=0.01
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# 遍历所有子图位置
|
|
62
|
+
for ii in range(nums):
|
|
63
|
+
row_pos = (ii // cols) + 1
|
|
64
|
+
col_pos = (ii % cols) + 1
|
|
65
|
+
|
|
66
|
+
volt = volt_list[ii // 2]
|
|
67
|
+
freq = freq_list[ii // 2]
|
|
68
|
+
s = s_list[ii // 2]
|
|
69
|
+
q_name = q_name_list[ii // 2]
|
|
70
|
+
|
|
71
|
+
# 热力图数据
|
|
72
|
+
heatmap_trace = go.Heatmap(
|
|
73
|
+
x=freq,
|
|
74
|
+
y=volt,
|
|
75
|
+
z=s.T,
|
|
76
|
+
colorscale='Viridis',
|
|
77
|
+
showscale=True,
|
|
78
|
+
colorbar=dict(title='Intensity')
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
fig.add_trace(heatmap_trace, row=row_pos, col=col_pos)
|
|
82
|
+
|
|
83
|
+
# 在奇数编号的子图中添加曲线和线条
|
|
84
|
+
if (ii % 2 != 0):
|
|
85
|
+
centcol = len(freq) // 2
|
|
86
|
+
|
|
87
|
+
# 添加余弦曲线
|
|
88
|
+
for j, curve in enumerate(coscurves_list[ii // 2]):
|
|
89
|
+
if curve: # 确保曲线数据不为空
|
|
90
|
+
final_x_cos = [item[0] for item in curve]
|
|
91
|
+
final_y_cos = [item[1] for item in curve]
|
|
92
|
+
|
|
93
|
+
# 余弦曲线轨迹
|
|
94
|
+
cos_trace = go.Scatter(
|
|
95
|
+
x=final_x_cos,
|
|
96
|
+
y=final_y_cos,
|
|
97
|
+
mode='lines',
|
|
98
|
+
line=dict(color='red', width=2),
|
|
99
|
+
name=f'Cosine Curve {j + 1}'
|
|
100
|
+
)
|
|
101
|
+
fig.add_trace(cos_trace, row=row_pos, col=col_pos)
|
|
102
|
+
|
|
103
|
+
# 添加置信度文本
|
|
104
|
+
if centcol < len(final_x_cos):
|
|
105
|
+
fig.add_annotation(
|
|
106
|
+
x=final_x_cos[centcol],
|
|
107
|
+
y=final_y_cos[centcol],
|
|
108
|
+
text=f"conf:{cosconfs_list[ii // 2][j]:.2f}",
|
|
109
|
+
showarrow=False,
|
|
110
|
+
font=dict(color='red', size=12),
|
|
111
|
+
row=row_pos,
|
|
112
|
+
col=col_pos
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# 添加直线
|
|
116
|
+
if lines_list[ii // 2]:
|
|
117
|
+
for j, line in enumerate(lines_list[ii // 2]):
|
|
118
|
+
if line: # 确保直线数据不为空
|
|
119
|
+
final_x_line = [item[0] for item in line]
|
|
120
|
+
final_y_line = [item[1] for item in line]
|
|
121
|
+
|
|
122
|
+
line_trace = go.Scatter(
|
|
123
|
+
x=final_x_line,
|
|
124
|
+
y=final_y_line,
|
|
125
|
+
mode='lines',
|
|
126
|
+
line=dict(color='blue', width=2),
|
|
127
|
+
name=f'Line {j + 1}'
|
|
128
|
+
)
|
|
129
|
+
fig.add_trace(line_trace, row=row_pos, col=col_pos)
|
|
130
|
+
if centcol < len(final_x_line):
|
|
131
|
+
fig.add_annotation(
|
|
132
|
+
x=final_x_line[centcol],
|
|
133
|
+
y=final_y_line[centcol],
|
|
134
|
+
text=f"conf:{lineconfs_list[ii // 2][j]:.2f}",
|
|
135
|
+
showarrow=False,
|
|
136
|
+
font=dict(color='red', size=12),
|
|
137
|
+
row=row_pos,
|
|
138
|
+
col=col_pos
|
|
139
|
+
)
|
|
140
|
+
# 更新布局设置
|
|
141
|
+
fig.update_layout(
|
|
142
|
+
height=500 * rows,
|
|
143
|
+
width=900 * cols,
|
|
144
|
+
margin=dict(r=60, t=60, b=60, l=60),
|
|
145
|
+
legend=dict(
|
|
146
|
+
font=dict(family="Courier", size=12, color="black"),
|
|
147
|
+
borderwidth=1
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# 更新坐标轴标签
|
|
152
|
+
fig.update_xaxes(title_text="频率", row=rows, col=1)
|
|
153
|
+
fig.update_yaxes(title_text="电压", col=1)
|
|
154
|
+
|
|
155
|
+
# 隐藏未使用的子图
|
|
156
|
+
for ii in range(nums, rows * cols):
|
|
157
|
+
row_pos = (ii // cols) + 1
|
|
158
|
+
col_pos = (ii % cols) + 1
|
|
159
|
+
fig.update_xaxes(visible=False, row=row_pos, col=col_pos)
|
|
160
|
+
fig.update_yaxes(visible=False, row=row_pos, col=col_pos)
|
|
161
|
+
|
|
162
|
+
return fig
|
|
163
|
+
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
from .pltplotter import QuantumDataPltPlotter
|
|
4
|
+
|
|
5
|
+
from scipy.stats import norm
|
|
6
|
+
|
|
7
|
+
class SingleShotDataPltPlotter(QuantumDataPltPlotter):
|
|
8
|
+
def __init__(self):
|
|
9
|
+
super().__init__("singleshot")
|
|
10
|
+
|
|
11
|
+
def plotEllipse(self, c0, a, b, phi, ax, **kwargs):
|
|
12
|
+
t = np.linspace(0, 1, 1001) * 2 * np.pi # 生成1001个角度点
|
|
13
|
+
c = np.exp(1j * t) # 计算椭圆坐标点(包含旋转)
|
|
14
|
+
s = c0 + (c.real * a + 1j * c.imag * b) * np.exp(1j * phi)
|
|
15
|
+
ax.plot(s.real, s.imag, **kwargs)
|
|
16
|
+
def plot_result_npy(self, **kwargs):
|
|
17
|
+
result = kwargs.get('result')
|
|
18
|
+
dict_param = kwargs.get('dict_param')
|
|
19
|
+
|
|
20
|
+
dict_param = dict_param.item()
|
|
21
|
+
|
|
22
|
+
image = dict_param["image"]
|
|
23
|
+
q_list = image.keys()
|
|
24
|
+
s0_list = []
|
|
25
|
+
s1_list = []
|
|
26
|
+
q_name_list =[]
|
|
27
|
+
|
|
28
|
+
for idx, q_name in enumerate(q_list):
|
|
29
|
+
image_q = image[q_name]
|
|
30
|
+
|
|
31
|
+
s0 = image_q[0]
|
|
32
|
+
s1 = image_q[1]
|
|
33
|
+
s0_list.append(s0)
|
|
34
|
+
s1_list.append(s1)
|
|
35
|
+
q_name_list.append(q_name)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
sep_score_list = result['sep_score_list']
|
|
39
|
+
threshold_list = result['threshold_list']
|
|
40
|
+
phi_list = result['phi_list']
|
|
41
|
+
signal_list = result['signal_list']
|
|
42
|
+
idle_list = result['idle_list']
|
|
43
|
+
params_list = result['params_list']
|
|
44
|
+
std_list = result['std_list']
|
|
45
|
+
cdf_list = result['cdf_list']
|
|
46
|
+
hotThresh = 10000 # 切换为热力图模式的样本数阈值
|
|
47
|
+
nums = len(s0_list) * 2
|
|
48
|
+
row = (nums // 6) + 1 if nums % 6 != 0 else nums // 6
|
|
49
|
+
col = 6
|
|
50
|
+
fig = plt.figure(figsize=(20, 20)) # 创建Figure
|
|
51
|
+
for i in range(len(s0_list)):
|
|
52
|
+
s0 = s0_list[i]
|
|
53
|
+
s1 = s1_list[i]
|
|
54
|
+
_, *bins = np.histogram2d(np.real(np.hstack([s0, s1])),
|
|
55
|
+
np.imag(np.hstack([s0, s1])),
|
|
56
|
+
bins=50) # 构建二维直方图
|
|
57
|
+
H0, *_ = np.histogram2d(np.real(s0),
|
|
58
|
+
np.imag(s0),
|
|
59
|
+
bins=bins,
|
|
60
|
+
density=True) # 计算各组密度分
|
|
61
|
+
H1, *_ = np.histogram2d(np.real(s1),
|
|
62
|
+
np.imag(s1),
|
|
63
|
+
bins=bins,
|
|
64
|
+
density=True)
|
|
65
|
+
vlim = max(np.max(np.abs(H0)), np.max(np.abs(H1))) # 确定可视化范围
|
|
66
|
+
|
|
67
|
+
sep_score = sep_score_list[i]
|
|
68
|
+
|
|
69
|
+
thr = threshold_list[i]
|
|
70
|
+
phi = phi_list[i]
|
|
71
|
+
|
|
72
|
+
# 子图1:复平面图
|
|
73
|
+
ax1 = fig.add_subplot(row, col, 2 * i + 1)
|
|
74
|
+
if (len(s0) + len(s1)) < hotThresh:
|
|
75
|
+
ax1.plot(np.real(s0), np.imag(s0), '.', alpha=0.8)
|
|
76
|
+
ax1.plot(np.real(s1), np.imag(s1), '.', alpha=0.8)
|
|
77
|
+
else:
|
|
78
|
+
ax1.imshow(H1.T - H0.T,
|
|
79
|
+
alpha=(np.fmax(H0.T, H1.T) / vlim).clip(0, 1),
|
|
80
|
+
interpolation='nearest',
|
|
81
|
+
origin='lower',
|
|
82
|
+
cmap='coolwarm',
|
|
83
|
+
vmin=-vlim,
|
|
84
|
+
vmax=vlim,
|
|
85
|
+
extent=(bins[0][0], bins[0][-1], bins[1][0], bins[1][-1]))
|
|
86
|
+
ax1.text(0.95, 0.95, f'Separation Degree: {sep_score:.3f}',
|
|
87
|
+
transform=ax1.transAxes, ha='right', va='top',
|
|
88
|
+
bbox=dict(facecolor='white', alpha=0.8, edgecolor='gray'))
|
|
89
|
+
ax1.axis('equal')
|
|
90
|
+
for s in ax1.spines.values():
|
|
91
|
+
s.set_visible(False)
|
|
92
|
+
|
|
93
|
+
# 椭圆参数提取和绘制
|
|
94
|
+
params = params_list[i]
|
|
95
|
+
r0, i0, r1, i1 = params[0][0], params[1][0], params[0][1], params[1][1]
|
|
96
|
+
a0, b0, a1, b1 = params[0][2], params[1][2], params[0][3], params[1][3]
|
|
97
|
+
c0 = (r0 + 1j * i0) * np.exp(1j * phi)
|
|
98
|
+
c1 = (r1 + 1j * i1) * np.exp(1j * phi)
|
|
99
|
+
phi0 = phi + params[0][6]
|
|
100
|
+
phi1 = phi + params[1][6]
|
|
101
|
+
self.plotEllipse(c0, 2 * a0, 2 * b0, phi0, ax1)
|
|
102
|
+
self.plotEllipse(c1, 2 * a1, 2 * b1, phi1, ax1)
|
|
103
|
+
im0, im1 = idle_list[i]
|
|
104
|
+
im0 = np.array(im0)
|
|
105
|
+
im1 = np.array(im1)
|
|
106
|
+
lim = min(im0.min(), im1.min()), max(im0.max(), im1.max())
|
|
107
|
+
t = (np.linspace(lim[0], lim[1], 3) + 1j * thr) * np.exp(-1j * phi)
|
|
108
|
+
ax1.plot(t.imag, t.real, 'k--')
|
|
109
|
+
ax1.plot(np.real(c0), np.imag(c0), 'o', color='C3')
|
|
110
|
+
ax1.plot(np.real(c1), np.imag(c1), 'o', color='C4')
|
|
111
|
+
ax1.axis('off')
|
|
112
|
+
|
|
113
|
+
# 子图2:投影信号分布图 + CDF
|
|
114
|
+
re0, re1 = signal_list[i]
|
|
115
|
+
x, a, b, c = cdf_list[i]
|
|
116
|
+
re0 = np.array(re0)
|
|
117
|
+
re1 = np.array(re1)
|
|
118
|
+
xrange = (min(re0.min(), re1.min()), max(re0.max(), re1.max()))
|
|
119
|
+
|
|
120
|
+
ax2 = fig.add_subplot(row, col, 2 * i + 2)
|
|
121
|
+
n0, bins0, *_ = ax2.hist(re0, bins=100, density=True, range=xrange, alpha=0.5)
|
|
122
|
+
n1, bins1, *_ = ax2.hist(re1, bins=100, density=True, range=xrange, alpha=0.5)
|
|
123
|
+
|
|
124
|
+
mu1_y, std1_y = norm.fit(re0)
|
|
125
|
+
mu2_y, std2_y = norm.fit(re1)
|
|
126
|
+
y_range = np.linspace(min(min(re0), min(re1)), max(max(re0), max(re1)), 100)
|
|
127
|
+
pdf1_y = norm.pdf(y_range, mu1_y, std1_y)
|
|
128
|
+
pdf2_y = norm.pdf(y_range, mu2_y, std2_y)
|
|
129
|
+
ax2.plot(y_range, pdf1_y, 'b-', linewidth=2)
|
|
130
|
+
ax2.plot(y_range, pdf2_y, 'r-', linewidth=2)
|
|
131
|
+
|
|
132
|
+
x = np.array(x)
|
|
133
|
+
x_range = np.linspace(x.min(), x.max(), 1001)
|
|
134
|
+
*_, cov0, cov1 = std_list[i]
|
|
135
|
+
|
|
136
|
+
ax3 = ax2.twinx()
|
|
137
|
+
ax3.plot(x, a, '--', lw=1, color='C0')
|
|
138
|
+
ax3.plot(x, b, '--', lw=1, color='C1')
|
|
139
|
+
ax3.plot(x, c, 'k--', alpha=0.5, lw=1)
|
|
140
|
+
ax3.set_ylim(0, 1.1)
|
|
141
|
+
ax3.vlines(thr, 0, 1.1, 'k', alpha=0.5)
|
|
142
|
+
ax3.set_ylabel('Probability')
|
|
143
|
+
|
|
144
|
+
ax2.axis('off')
|
|
145
|
+
|
|
146
|
+
plt.tight_layout()
|
|
147
|
+
return fig # ✅ 返回 Figure 对象
|
|
148
|
+
|
|
149
|
+
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
from .plyplotter import QuantumDataPlyPlotter
|
|
2
|
+
import numpy as np
|
|
3
|
+
import plotly.graph_objects as go
|
|
4
|
+
from plotly.subplots import make_subplots
|
|
5
|
+
from scipy.stats import norm
|
|
6
|
+
|
|
7
|
+
class SingleShotDataPlyPlotter(QuantumDataPlyPlotter):
|
|
8
|
+
|
|
9
|
+
def __init__(self):
|
|
10
|
+
super().__init__("singleshot")
|
|
11
|
+
|
|
12
|
+
def plotEllipse(self, c0, a, b, phi):
|
|
13
|
+
"""生成椭圆坐标点"""
|
|
14
|
+
t = np.linspace(0, 1, 1001) * 2 * np.pi
|
|
15
|
+
c = np.exp(1j * t)
|
|
16
|
+
s = c0 + (c.real * a + 1j * c.imag * b) * np.exp(1j * phi)
|
|
17
|
+
return s.real, s.imag
|
|
18
|
+
|
|
19
|
+
def plot_result_npy(self, **kwargs):
|
|
20
|
+
|
|
21
|
+
result = kwargs.get('result')
|
|
22
|
+
dict_param = kwargs.get('dict_param')
|
|
23
|
+
|
|
24
|
+
dict_param = dict_param.item()
|
|
25
|
+
image = dict_param["image"]
|
|
26
|
+
q_list = image.keys()
|
|
27
|
+
s0_list = []
|
|
28
|
+
s1_list = []
|
|
29
|
+
q_name_list = []
|
|
30
|
+
|
|
31
|
+
# 提取数据
|
|
32
|
+
for idx, q_name in enumerate(q_list):
|
|
33
|
+
image_q = image[q_name]
|
|
34
|
+
s0 = image_q[0]
|
|
35
|
+
s1 = image_q[1]
|
|
36
|
+
s0_list.append(s0)
|
|
37
|
+
s1_list.append(s1)
|
|
38
|
+
q_name_list.append(q_name)
|
|
39
|
+
|
|
40
|
+
sep_score_list = result['sep_score_list']
|
|
41
|
+
threshold_list = result['threshold_list']
|
|
42
|
+
phi_list = result['phi_list']
|
|
43
|
+
signal_list = result['signal_list']
|
|
44
|
+
idle_list = result['idle_list']
|
|
45
|
+
params_list = result['params_list']
|
|
46
|
+
cdf_list = result['cdf_list']
|
|
47
|
+
num_qubits = len(s0_list)
|
|
48
|
+
|
|
49
|
+
# 创建子图布局 - 每行最多3个量子比特,每个量子比特2个子图
|
|
50
|
+
rows = (num_qubits + 2) // 3 # 每行最多3个量子比特
|
|
51
|
+
cols = 6 # 每个量子比特2列
|
|
52
|
+
|
|
53
|
+
# 创建子图
|
|
54
|
+
fig = make_subplots(
|
|
55
|
+
rows=rows,
|
|
56
|
+
cols=cols,
|
|
57
|
+
subplot_titles=[f'{q_name_list[i // 2]} - {"复平面" if i % 2 == 0 else "投影分布"}'
|
|
58
|
+
for i in range(rows * cols)],
|
|
59
|
+
horizontal_spacing=0.05,
|
|
60
|
+
vertical_spacing=0.08
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
hotThresh = 10000
|
|
64
|
+
|
|
65
|
+
for i in range(len(s0_list)):
|
|
66
|
+
s0 = s0_list[i]
|
|
67
|
+
s1 = s1_list[i]
|
|
68
|
+
|
|
69
|
+
sep_score = sep_score_list[i]
|
|
70
|
+
thr = threshold_list[i]
|
|
71
|
+
phi = phi_list[i]
|
|
72
|
+
|
|
73
|
+
# 计算行和列位置
|
|
74
|
+
row_pos = (i // 3) + 1
|
|
75
|
+
col_pos_left = (i % 3) * 2 + 1
|
|
76
|
+
col_pos_right = col_pos_left + 1
|
|
77
|
+
|
|
78
|
+
# 子图1:复平面图
|
|
79
|
+
if (len(s0) + len(s1)) < hotThresh:
|
|
80
|
+
# 散点图模式
|
|
81
|
+
fig.add_trace(
|
|
82
|
+
go.Scatter(
|
|
83
|
+
x=np.real(s0), y=np.imag(s0),
|
|
84
|
+
mode='markers',
|
|
85
|
+
marker=dict(size=7, color='blue', opacity=0.6),
|
|
86
|
+
name=f'{q_name_list[i]}|0⟩'
|
|
87
|
+
),
|
|
88
|
+
row=row_pos, col=col_pos_left
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
fig.add_trace(
|
|
92
|
+
go.Scatter(
|
|
93
|
+
x=np.real(s1), y=np.imag(s1),
|
|
94
|
+
mode='markers',
|
|
95
|
+
marker=dict(size=7, color='red', opacity=0.6),
|
|
96
|
+
name=f'{q_name_list[i]}|1⟩'
|
|
97
|
+
),
|
|
98
|
+
row=row_pos, col=col_pos_left
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
# 热力图模式
|
|
102
|
+
_, *bins = np.histogram2d(
|
|
103
|
+
np.real(np.hstack([s0, s1])),
|
|
104
|
+
np.imag(np.hstack([s0, s1])),
|
|
105
|
+
bins=50
|
|
106
|
+
)
|
|
107
|
+
H0, *_ = np.histogram2d(
|
|
108
|
+
np.real(s0), np.imag(s0),
|
|
109
|
+
bins=bins, density=True
|
|
110
|
+
)
|
|
111
|
+
H1, *_ = np.histogram2d(
|
|
112
|
+
np.real(s1), np.imag(s1),
|
|
113
|
+
bins=bins, density=True
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
heatmap_data = H1.T - H0.T
|
|
117
|
+
fig.add_trace(
|
|
118
|
+
go.Heatmap(
|
|
119
|
+
z=heatmap_data,
|
|
120
|
+
x=bins[0],
|
|
121
|
+
y=bins[1],
|
|
122
|
+
colorscale='RdBu',
|
|
123
|
+
showscale=False
|
|
124
|
+
),
|
|
125
|
+
row=row_pos, col=col_pos_left
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# 添加分离度文本注释
|
|
129
|
+
fig.add_annotation(
|
|
130
|
+
x=0.95, y=0.95,
|
|
131
|
+
xref="paper",
|
|
132
|
+
yref="paper",
|
|
133
|
+
text=f'Separation: {sep_score:.3f}',
|
|
134
|
+
showarrow=False,
|
|
135
|
+
bgcolor="white",
|
|
136
|
+
bordercolor="gray",
|
|
137
|
+
borderwidth=1,
|
|
138
|
+
row=row_pos, col=col_pos_left
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# 椭圆绘制
|
|
142
|
+
params = params_list[i]
|
|
143
|
+
r0, i0, r1, i1 = params[0][0], params[1][0], params[0][1], params[1][1]
|
|
144
|
+
a0, b0, a1, b1 = params[0][2], params[1][2], params[0][3], params[1][3]
|
|
145
|
+
c0 = (r0 + 1j * i0) * np.exp(1j * phi)
|
|
146
|
+
c1 = (r1 + 1j * i1) * np.exp(1j * phi)
|
|
147
|
+
phi0 = phi + params[0][6]
|
|
148
|
+
phi1 = phi + params[1][6]
|
|
149
|
+
|
|
150
|
+
# 绘制两个椭圆
|
|
151
|
+
ellipse0_x, ellipse0_y = self.plotEllipse(c0, 2 * a0, 2 * b0, phi0)
|
|
152
|
+
ellipse1_x, ellipse1_y = self.plotEllipse(c1, 2 * a1, 2 * b1, phi1)
|
|
153
|
+
|
|
154
|
+
fig.add_trace(
|
|
155
|
+
go.Scatter(
|
|
156
|
+
x=ellipse0_x, y=ellipse0_y,
|
|
157
|
+
mode='lines',
|
|
158
|
+
line=dict(color='darkblue', width=2),
|
|
159
|
+
showlegend=False
|
|
160
|
+
),
|
|
161
|
+
row=row_pos, col=col_pos_left
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
fig.add_trace(
|
|
165
|
+
go.Scatter(
|
|
166
|
+
x=ellipse1_x, y=ellipse1_y,
|
|
167
|
+
mode='lines',
|
|
168
|
+
line=dict(color='darkred', width=2),
|
|
169
|
+
showlegend=False
|
|
170
|
+
),
|
|
171
|
+
row=row_pos, col=col_pos_left
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
im0, im1 = idle_list[i]
|
|
175
|
+
im0 = np.array(im0)
|
|
176
|
+
im1 = np.array(im1)
|
|
177
|
+
lim = min(im0.min(), im1.min()), max(im0.max(), im1.max())
|
|
178
|
+
t = (np.linspace(lim[0], lim[1], 3) + 1j * thr) * np.exp(-1j * phi)
|
|
179
|
+
fig.add_trace(go.Scatter(
|
|
180
|
+
x=t.imag, # x轴数据
|
|
181
|
+
y=t.real, # y轴数据
|
|
182
|
+
mode='lines',
|
|
183
|
+
line=dict(dash='dash', color='black')),
|
|
184
|
+
row=row_pos,
|
|
185
|
+
col=col_pos_left
|
|
186
|
+
)
|
|
187
|
+
# 绘制中心点
|
|
188
|
+
fig.add_trace(
|
|
189
|
+
go.Scatter(
|
|
190
|
+
x=[np.real(c0)], y=[np.imag(c0)],
|
|
191
|
+
mode='markers',
|
|
192
|
+
marker=dict(size=8, color='darkblue', symbol='circle'),
|
|
193
|
+
showlegend=False
|
|
194
|
+
),
|
|
195
|
+
row=row_pos, col=col_pos_left
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
fig.add_trace(
|
|
199
|
+
go.Scatter(
|
|
200
|
+
x=[np.real(c1)], y=[np.imag(c1)],
|
|
201
|
+
mode='markers',
|
|
202
|
+
marker=dict(size=8, color='darkred', symbol='circle'),
|
|
203
|
+
showlegend=False
|
|
204
|
+
),
|
|
205
|
+
row=row_pos, col=col_pos_left
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# 子图2:投影信号分布图
|
|
209
|
+
re0, re1 = signal_list[i]
|
|
210
|
+
x, a, b, c = cdf_list[i]
|
|
211
|
+
re0 = np.array(re0)
|
|
212
|
+
re1 = np.array(re1)
|
|
213
|
+
xrange = (min(re0.min(), re1.min()), max(re0.max(), re1.max()))
|
|
214
|
+
|
|
215
|
+
# 直方图
|
|
216
|
+
fig.add_trace(
|
|
217
|
+
go.Histogram(
|
|
218
|
+
x=re0,
|
|
219
|
+
nbinsx=100,
|
|
220
|
+
opacity=0.5,
|
|
221
|
+
xbins=dict(start=xrange[0], end=xrange[1]), # 对应 range=xrange
|
|
222
|
+
name='|0⟩',
|
|
223
|
+
marker_color='blue',
|
|
224
|
+
histnorm="probability density"
|
|
225
|
+
),
|
|
226
|
+
row=row_pos, col=col_pos_right
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
fig.add_trace(
|
|
230
|
+
go.Histogram(
|
|
231
|
+
x=re1,
|
|
232
|
+
nbinsx=100,
|
|
233
|
+
opacity=0.5,
|
|
234
|
+
xbins=dict(start=xrange[0], end=xrange[1]), # 对应 range=xrange
|
|
235
|
+
name='|1⟩',
|
|
236
|
+
marker_color='red',
|
|
237
|
+
histnorm="probability density"
|
|
238
|
+
),
|
|
239
|
+
row=row_pos, col=col_pos_right
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# 高斯拟合曲线
|
|
243
|
+
mu1_y, std1_y = norm.fit(re0)
|
|
244
|
+
mu2_y, std2_y = norm.fit(re1)
|
|
245
|
+
y_range = np.linspace(
|
|
246
|
+
min(min(re0), min(re1)),
|
|
247
|
+
max(max(re0), max(re1)),
|
|
248
|
+
100
|
|
249
|
+
)
|
|
250
|
+
pdf1_y = norm.pdf(y_range, mu1_y, std1_y)
|
|
251
|
+
pdf2_y = norm.pdf(y_range, mu2_y, std2_y)
|
|
252
|
+
|
|
253
|
+
fig.add_trace(
|
|
254
|
+
go.Scatter(
|
|
255
|
+
x=y_range, y=pdf1_y,
|
|
256
|
+
mode='lines',
|
|
257
|
+
line=dict(color='darkblue', width=3),
|
|
258
|
+
name='|0⟩拟合'
|
|
259
|
+
),
|
|
260
|
+
row=row_pos, col=col_pos_right
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
fig.add_trace(
|
|
264
|
+
go.Scatter(
|
|
265
|
+
x=y_range, y=pdf2_y,
|
|
266
|
+
mode='lines',
|
|
267
|
+
line=dict(color='darkred', width=3),
|
|
268
|
+
name='|1⟩拟合'
|
|
269
|
+
),
|
|
270
|
+
row=row_pos, col=col_pos_right
|
|
271
|
+
)
|
|
272
|
+
#
|
|
273
|
+
# CDF 曲线 - 使用次坐标轴
|
|
274
|
+
fig.add_trace(
|
|
275
|
+
go.Scatter(
|
|
276
|
+
x=x, y=a,
|
|
277
|
+
mode='lines',
|
|
278
|
+
line=dict(color='blue', width=2, dash='dash'),
|
|
279
|
+
name='|0⟩ CDF',
|
|
280
|
+
yaxis=f"y{len(fig.data)}"
|
|
281
|
+
),
|
|
282
|
+
row=row_pos, col=col_pos_right
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
fig.add_trace(
|
|
286
|
+
go.Scatter(
|
|
287
|
+
x=x, y=b,
|
|
288
|
+
mode='lines',
|
|
289
|
+
line=dict(color='red', width=2, dash='dash'),
|
|
290
|
+
name='|1⟩ CDF',
|
|
291
|
+
yaxis=f"y{len(fig.data)}"
|
|
292
|
+
),
|
|
293
|
+
row=row_pos, col=col_pos_right
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
fig.add_trace(
|
|
297
|
+
go.Scatter(
|
|
298
|
+
x=x, y=c,
|
|
299
|
+
mode='lines',
|
|
300
|
+
line=dict(color='black', width=2, dash='dot'),
|
|
301
|
+
name='阈值 CDF',
|
|
302
|
+
yaxis=f"y{len(fig.data)}"
|
|
303
|
+
),
|
|
304
|
+
row=row_pos, col=col_pos_right
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# 阈值线
|
|
308
|
+
fig.add_vline(
|
|
309
|
+
x=thr,
|
|
310
|
+
line_dash="dash",
|
|
311
|
+
line_color="black",
|
|
312
|
+
opacity=0.7,
|
|
313
|
+
row=row_pos, col=col_pos_right
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
# 更新布局
|
|
317
|
+
fig.update_layout(
|
|
318
|
+
height=400 * rows,
|
|
319
|
+
width=1600,
|
|
320
|
+
showlegend=False
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
return fig
|