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,170 @@
|
|
|
1
|
+
|
|
2
|
+
import os
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
import io
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from qubitclient.nnscope.utils.data_convert import convert_spectrum_npy2npz,convert_spectrum_dict2npz
|
|
10
|
+
|
|
11
|
+
# load from npz file path
|
|
12
|
+
def load_from_npz_path(file_path_list:list[str]):
|
|
13
|
+
files = []
|
|
14
|
+
npydata = {}
|
|
15
|
+
npydata['id'] = 0
|
|
16
|
+
image_qs = {}
|
|
17
|
+
index = 0
|
|
18
|
+
for file_path in file_path_list:
|
|
19
|
+
if file_path.endswith('.npz'):
|
|
20
|
+
index+=1
|
|
21
|
+
with np.load(file_path, allow_pickle=True) as data: # 修改:添加 allow_pickle=True 参数
|
|
22
|
+
# file_contents[file_name] = dict(data) # 将 .npz 文件内容转换为字典
|
|
23
|
+
content = dict(data) # 将 .npz 文件内容转换为字典
|
|
24
|
+
image_qs[str(index)] = (content['iq_avg'],content['bias'],content['frequency'])
|
|
25
|
+
npydata['image'] = image_qs
|
|
26
|
+
with io.BytesIO() as buffer:
|
|
27
|
+
np.save(buffer, npydata)
|
|
28
|
+
bytes_obj = buffer.getvalue()
|
|
29
|
+
files.append(("request", ("None.npy", bytes_obj, "application/octet-stream")))
|
|
30
|
+
return files
|
|
31
|
+
# def load_from_npz_path(file_path_list:list[str]):
|
|
32
|
+
# files = []
|
|
33
|
+
# npydata = {}
|
|
34
|
+
# npydata['id'] = 0
|
|
35
|
+
# index = 0
|
|
36
|
+
# for file_path in file_path_list:
|
|
37
|
+
# if file_path.endswith('.npz'):
|
|
38
|
+
# index+=1
|
|
39
|
+
# with np.load(file_path, allow_pickle=True) as data: # 修改:添加 allow_pickle=True 参数
|
|
40
|
+
# # file_contents[file_name] = dict(data) # 将 .npz 文件内容转换为字典
|
|
41
|
+
# content = dict(data) # 将 .npz 文件内容转换为字典
|
|
42
|
+
# allq = content['image'].item()
|
|
43
|
+
# allq_downsample={}
|
|
44
|
+
# for q in allq.keys():
|
|
45
|
+
# singleq = allq[q]
|
|
46
|
+
# singleq_downsampe = (singleq[0][::1,::1],singleq[1][::1],singleq[2][::1])
|
|
47
|
+
# # iq = zoom(singleq[0],(2,1),order=1)
|
|
48
|
+
# # zero_arr = np.zeros((45,40))
|
|
49
|
+
# # iq = np.vstack((singleq[0],zero_arr))
|
|
50
|
+
# # # iq = np.vstack((singleq[0],singleq[0]))
|
|
51
|
+
# #
|
|
52
|
+
# # arr_2d = singleq[2].reshape(1,-1)
|
|
53
|
+
# # arr_zoomed = zoom(arr_2d,(1,2),order=1)
|
|
54
|
+
# # freq = arr_zoomed.flatten()
|
|
55
|
+
# #
|
|
56
|
+
# #
|
|
57
|
+
# # singleq_downsampe = (iq[::1,::1],singleq[1][::1],freq)
|
|
58
|
+
#
|
|
59
|
+
#
|
|
60
|
+
# # singleq_downsampe = (singleq[0],singleq[1],singleq[2])
|
|
61
|
+
#
|
|
62
|
+
# allq_downsample[q] = singleq_downsampe
|
|
63
|
+
# # allq_downsample = np.array(allq_downsample,dtype=object).reshape(())
|
|
64
|
+
# # npydata['image'] = (content['image'])
|
|
65
|
+
# npydata['image'] = allq_downsample
|
|
66
|
+
# with io.BytesIO() as buffer:
|
|
67
|
+
# np.save(buffer, npydata)
|
|
68
|
+
# bytes_obj = buffer.getvalue()
|
|
69
|
+
# files.append(("request", ("None.npy", bytes_obj, "application/octet-stream")))
|
|
70
|
+
# return files
|
|
71
|
+
def load_from_npy_path(file_path_list:list[str]):
|
|
72
|
+
files = []
|
|
73
|
+
for file_path in file_path_list:
|
|
74
|
+
if file_path.endswith('.npy'):
|
|
75
|
+
data = np.load(file_path, allow_pickle=True)
|
|
76
|
+
data = data.item() if isinstance(data, np.ndarray) else data
|
|
77
|
+
with io.BytesIO() as buffer:
|
|
78
|
+
np.save(buffer, data)
|
|
79
|
+
bytes_obj = buffer.getvalue()
|
|
80
|
+
files.append(("request", ("None.npy", bytes_obj, "application/octet-stream")))
|
|
81
|
+
return files
|
|
82
|
+
def load_from_npz_dict(dict_list:list[dict]):
|
|
83
|
+
files = []
|
|
84
|
+
npydata = {}
|
|
85
|
+
npydata['id'] = 0
|
|
86
|
+
image_qs = {}
|
|
87
|
+
for index,dict_obj in enumerate(dict_list):
|
|
88
|
+
image_qs[str(index)] = (dict_obj['iq_avg'], dict_obj['bias'], dict_obj['frequency'])
|
|
89
|
+
npydata['image'] = image_qs
|
|
90
|
+
with io.BytesIO() as buffer:
|
|
91
|
+
np.save(buffer, npydata)
|
|
92
|
+
bytes_obj = buffer.getvalue()
|
|
93
|
+
files.append(("request", ("None.npy", bytes_obj, "application/octet-stream")))
|
|
94
|
+
return files
|
|
95
|
+
def load_from_npy_dict(dict_list:list[dict]):
|
|
96
|
+
files = []
|
|
97
|
+
for dict_obj in dict_list:
|
|
98
|
+
with io.BytesIO() as buffer:
|
|
99
|
+
np.save(buffer, dict_obj)
|
|
100
|
+
bytes_obj = buffer.getvalue()
|
|
101
|
+
files.append(("request", ("None.npy",bytes_obj, "application/octet-stream")))
|
|
102
|
+
return files
|
|
103
|
+
def request_task(files,url,api_key,curve_type:str=None):
|
|
104
|
+
headers = {'Authorization': f'Bearer {api_key}'} # 添加API密钥到请求头
|
|
105
|
+
data = {
|
|
106
|
+
"curve_type":curve_type.value if curve_type else None
|
|
107
|
+
}
|
|
108
|
+
response = requests.post(url, files=files, headers=headers,data=data)
|
|
109
|
+
return response
|
|
110
|
+
def load_files(filepath_list: list[str|dict[str,np.ndarray]|np.ndarray]):
|
|
111
|
+
if len(filepath_list)<=0:
|
|
112
|
+
return []
|
|
113
|
+
else:
|
|
114
|
+
if isinstance(filepath_list[0], dict):
|
|
115
|
+
if "image" in filepath_list[0]:
|
|
116
|
+
return load_from_npy_dict(filepath_list)
|
|
117
|
+
else:
|
|
118
|
+
return load_from_npz_dict(filepath_list)
|
|
119
|
+
elif isinstance(filepath_list[0], np.ndarray):
|
|
120
|
+
filepath_list = [filepath_list[i].item() for i in range(len(filepath_list))]
|
|
121
|
+
return load_files(filepath_list)
|
|
122
|
+
elif isinstance(filepath_list[0], str):
|
|
123
|
+
if filepath_list[0].endswith('.npz'):
|
|
124
|
+
return load_from_npz_path(filepath_list)
|
|
125
|
+
elif filepath_list[0].endswith('.npy'):
|
|
126
|
+
return load_from_npy_path(filepath_list)
|
|
127
|
+
else:
|
|
128
|
+
return []
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
DEFINED_TASKS = {}
|
|
133
|
+
def task_register(func):
|
|
134
|
+
DEFINED_TASKS[func.__name__.lower()] = func
|
|
135
|
+
return func
|
|
136
|
+
|
|
137
|
+
def run_task(file_list: list[str|dict[str,np.ndarray]|np.ndarray],url,api_key,task_type:str,*args,**kwargs):
|
|
138
|
+
files = load_files(file_list)
|
|
139
|
+
response = DEFINED_TASKS[task_type.value](files,url,api_key,*args,**kwargs)
|
|
140
|
+
return response
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@task_register
|
|
144
|
+
def test(files):
|
|
145
|
+
|
|
146
|
+
return "hello"
|
|
147
|
+
|
|
148
|
+
@task_register
|
|
149
|
+
def spectrum2d(files,url,api_key,curve_type):
|
|
150
|
+
spectrum2d_url = url + "/api/v1/tasks/nnscope/seglines"
|
|
151
|
+
response = request_task(files,spectrum2d_url,api_key,curve_type)
|
|
152
|
+
return response
|
|
153
|
+
|
|
154
|
+
from enum import Enum, unique
|
|
155
|
+
@unique
|
|
156
|
+
class NNTaskName(Enum):
|
|
157
|
+
# S21PEAK = "s21peak"
|
|
158
|
+
# OPTPIPULSE = "optpipulse"
|
|
159
|
+
# RABI = "rabi"
|
|
160
|
+
# RABICOS = "rabicos"
|
|
161
|
+
# S21VFLUX = "s21vflux"
|
|
162
|
+
# SINGLESHOT = "singleshot"
|
|
163
|
+
# SPECTRUM = "spectrum"
|
|
164
|
+
# T1FIT = "t1fit"
|
|
165
|
+
# T2FIT = "t2fit"
|
|
166
|
+
SPECTRUM2D = "spectrum2d"
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2025 yaqiang.sun.
|
|
3
|
+
# This source code is licensed under the license found in the LICENSE file
|
|
4
|
+
# in the root directory of this source tree.
|
|
5
|
+
#########################################################################
|
|
6
|
+
# Author: yaqiangsun
|
|
7
|
+
# Created Time: 2025/10/24 15:54:07
|
|
8
|
+
########################################################################
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import io
|
|
13
|
+
import os
|
|
14
|
+
import numpy as np
|
|
15
|
+
import cv2
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def load_npz_file(file_path):
|
|
19
|
+
with np.load(file_path, allow_pickle=True) as data: # 修改:添加 allow_pickle=True 参数
|
|
20
|
+
# file_contents[file_name] = dict(data) # 将 .npz 文件内容转换为字典
|
|
21
|
+
content = dict(data) # 将 .npz 文件内容转换为字典
|
|
22
|
+
return content
|
|
23
|
+
def convert_data_to_image(npz_content):
|
|
24
|
+
content = npz_content
|
|
25
|
+
iq_avg = content["iq_avg"] # 二维数据
|
|
26
|
+
iq_avg_normalized = convert_complex_map__to_image(iq_avg=iq_avg)
|
|
27
|
+
return iq_avg_normalized
|
|
28
|
+
def convert_complex_map__to_image(iq_avg):
|
|
29
|
+
# 检查并转置
|
|
30
|
+
rows, cols = iq_avg.shape
|
|
31
|
+
if rows < cols:
|
|
32
|
+
iq_avg = iq_avg.T # 转置矩阵
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# 取相位
|
|
36
|
+
phase = np.angle(iq_avg)
|
|
37
|
+
phase_normalized = ((phase + np.pi) / (2 * np.pi)) * 255
|
|
38
|
+
# 纵向归一化
|
|
39
|
+
phase_mean = phase_normalized.mean(axis=0, keepdims=True) # 形状(1,30)
|
|
40
|
+
ppase_std = phase_normalized.std(axis=0, keepdims=True) # 形状(1,30)
|
|
41
|
+
phase_normalized = (phase_normalized - phase_mean) / (ppase_std+1e-8)
|
|
42
|
+
# phase_normalized = phase_normalized.astype(np.uint8)
|
|
43
|
+
# 全局归一化
|
|
44
|
+
phase_normalized = cv2.normalize(phase_normalized, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
|
|
45
|
+
|
|
46
|
+
# 取幅度
|
|
47
|
+
iq_avg = np.abs(iq_avg)
|
|
48
|
+
|
|
49
|
+
# iq_avg = phase_normalized
|
|
50
|
+
# 纵向归一化
|
|
51
|
+
# mean = iq_avg.mean(axis=0, keepdims=True) # 形状(1,30)
|
|
52
|
+
# std = iq_avg.std(axis=0, keepdims=True) # 形状(1,30)
|
|
53
|
+
# iq_avg = (iq_avg - mean) / (std+1e-8)
|
|
54
|
+
# 幅度全局归一化
|
|
55
|
+
iq_avg_normalized = cv2.normalize(iq_avg, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
|
|
56
|
+
# return iq_avg_normalized
|
|
57
|
+
|
|
58
|
+
#取幅度的梯度
|
|
59
|
+
gradient_y, gradient_x = np.gradient(iq_avg)
|
|
60
|
+
gradient_y = np.abs(gradient_y)
|
|
61
|
+
gradient_y_normalized = cv2.normalize(gradient_y, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
|
|
62
|
+
|
|
63
|
+
# iq_avg_normalized = cv2.merge([iq_avg_normalized, phase_normalized, gradient_y_normalized])
|
|
64
|
+
iq_avg_normalized = cv2.merge([iq_avg_normalized, iq_avg_normalized, iq_avg_normalized])
|
|
65
|
+
return iq_avg_normalized
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def load_npz_to_image(file_path):
|
|
69
|
+
npz_content = load_npz_file(file_path)
|
|
70
|
+
image = convert_data_to_image(npz_content)
|
|
71
|
+
return image
|
|
72
|
+
|
|
73
|
+
def convert_spectrum_npy2npz(npy_file_path:str):
|
|
74
|
+
data = np.load(npy_file_path, allow_pickle=True)
|
|
75
|
+
data = data.item() if isinstance(data, np.ndarray) else data
|
|
76
|
+
dict_list, name_list = convert_spectrum_dict2npz(data,npy_file_path)
|
|
77
|
+
return dict_list, name_list
|
|
78
|
+
def convert_spectrum_dict2npz(data:dict,npy_file_path:str="None.npy"):
|
|
79
|
+
if not isinstance(data, dict) or 'image' not in data:
|
|
80
|
+
raise ValueError("数据格式无效,缺少 'image' 键")
|
|
81
|
+
image = data["image"]
|
|
82
|
+
q_list = image.keys()
|
|
83
|
+
|
|
84
|
+
dict_list = []
|
|
85
|
+
name_list = []
|
|
86
|
+
|
|
87
|
+
for idx, q_name in enumerate(q_list):
|
|
88
|
+
image_q = image[q_name]
|
|
89
|
+
|
|
90
|
+
data = image_q[0]
|
|
91
|
+
if data.ndim != 2:
|
|
92
|
+
raise ValueError("数据格式无效,data不是二维数组")
|
|
93
|
+
data = np.array(data)
|
|
94
|
+
data = np.abs(data)
|
|
95
|
+
height_axis = image_q[1]
|
|
96
|
+
width_axis = image_q[2]
|
|
97
|
+
new_dict = {}
|
|
98
|
+
new_dict["iq_avg"] = data
|
|
99
|
+
new_dict["frequency"] = image_q[2]
|
|
100
|
+
new_dict["bias"] = image_q[1]
|
|
101
|
+
|
|
102
|
+
npz_file_path = npy_file_path.replace(".npy", f"{q_name}.npz")
|
|
103
|
+
dict_list.append(new_dict)
|
|
104
|
+
name_list.append(npz_file_path)
|
|
105
|
+
# npz_file_path = npz_file_path.replace("npyfile","npyconverted")
|
|
106
|
+
# np.savez(npz_file_path,**new_dict)
|
|
107
|
+
# np.savez(npz_file_path,iq_avg=image_q[0],frequency=image_q[2],bias=image_q[1])
|
|
108
|
+
return dict_list, name_list
|
|
109
|
+
|
|
110
|
+
if __name__ == '__main__':
|
|
111
|
+
npy_file_path = "tmp/npyfile/tmp0ffc025b.py_4905.npy"
|
|
112
|
+
convert_spectrum_npy2npz(npy_file_path)
|
|
113
|
+
|
|
114
|
+
image = load_npz_to_image("tmp/npyconverted/tmp0ffc025b.py_4905Q6.npz")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2025 yaqiang.sun.
|
|
3
|
+
# This source code is licensed under the license found in the LICENSE file
|
|
4
|
+
# in the root directory of this source tree.
|
|
5
|
+
#########################################################################
|
|
6
|
+
# Author: yaqiangsun
|
|
7
|
+
# Created Time: 2025/04/11 17:58:29
|
|
8
|
+
########################################################################
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import numpy as np
|
|
12
|
+
import cv2
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_npz_file(file_path):
|
|
16
|
+
with np.load(file_path, allow_pickle=True) as data:
|
|
17
|
+
content = dict(data)
|
|
18
|
+
return content
|
|
19
|
+
def convert_data_to_image(npz_content):
|
|
20
|
+
content = npz_content
|
|
21
|
+
iq_avg = content["iq_avg"]
|
|
22
|
+
rows, cols = iq_avg.shape
|
|
23
|
+
if rows < cols:
|
|
24
|
+
iq_avg = iq_avg.T
|
|
25
|
+
iq_avg = np.abs(iq_avg)
|
|
26
|
+
iq_avg_normalized = cv2.normalize(iq_avg, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
|
|
27
|
+
return iq_avg_normalized
|
|
28
|
+
|
|
29
|
+
def load_npz_to_image(file_path):
|
|
30
|
+
npz_content = load_npz_file(file_path)
|
|
31
|
+
image = convert_data_to_image(npz_content)
|
|
32
|
+
return image
|
|
33
|
+
|
|
34
|
+
def load_npz_to_images(file_path_list):
|
|
35
|
+
images = []
|
|
36
|
+
for file_path in file_path_list:
|
|
37
|
+
print(file_path)
|
|
38
|
+
image = load_npz_to_image(file_path)
|
|
39
|
+
images.append(image)
|
|
40
|
+
# cv2.imwrite("tmp/client/test.jpg",image)
|
|
41
|
+
return images
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2025 yaqiang.sun.
|
|
3
|
+
# This source code is licensed under the license found in the LICENSE file
|
|
4
|
+
# in the root directory of this source tree.
|
|
5
|
+
#########################################################################
|
|
6
|
+
# Author: yaqiangsun
|
|
7
|
+
# Created Time: 2025/04/15 10:31:23
|
|
8
|
+
########################################################################
|
|
9
|
+
import os
|
|
10
|
+
import requests
|
|
11
|
+
import io
|
|
12
|
+
import numpy as np
|
|
13
|
+
from qubitclient.nnscope.nnscope_api.curve.curve_type import CurveType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def file_request(file_path_list,url,api_key,curve_type:CurveType=None):
|
|
17
|
+
files = []
|
|
18
|
+
for file_path in file_path_list:
|
|
19
|
+
if file_path.endswith('.npz'):
|
|
20
|
+
file_name = os.path.basename(file_path)
|
|
21
|
+
files.append(("request", (file_name, open(file_path, "rb"), "image/jpeg")))
|
|
22
|
+
headers = {'Authorization': f'Bearer {api_key}'} # 添加API密钥到请求头
|
|
23
|
+
data = {
|
|
24
|
+
"curve_type":curve_type.value if curve_type else None
|
|
25
|
+
}
|
|
26
|
+
response = requests.post(url, files=files, headers=headers,data=data)
|
|
27
|
+
return response
|
|
28
|
+
|
|
29
|
+
def file_request_with_dict(dict_list,url,api_key,curve_type:str=None):
|
|
30
|
+
files = []
|
|
31
|
+
for index,dict_obj in enumerate(dict_list):
|
|
32
|
+
with io.BytesIO() as buffer:
|
|
33
|
+
np.savez(buffer, **dict_obj)
|
|
34
|
+
bytes_obj = buffer.getvalue()
|
|
35
|
+
files.append(("request", ("None"+str(index)+".npz", bytes_obj, "application/octet-stream")))
|
|
36
|
+
headers = {'Authorization': f'Bearer {api_key}'} # 添加API密钥到请求头
|
|
37
|
+
data = {
|
|
38
|
+
"curve_type":curve_type.value if curve_type else None
|
|
39
|
+
}
|
|
40
|
+
response = requests.post(url, files=files, headers=headers,data=data)
|
|
41
|
+
return response
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2025 yaqiang.sun.
|
|
3
|
+
# This source code is licensed under the license found in the LICENSE file
|
|
4
|
+
# in the root directory of this source tree.
|
|
5
|
+
#########################################################################
|
|
6
|
+
# Author: yaqiangsun
|
|
7
|
+
# Created Time: 2025/04/15 10:23:27
|
|
8
|
+
########################################################################
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
import cv2
|
|
12
|
+
|
|
13
|
+
def parser_result(result, images):
|
|
14
|
+
result_images = []
|
|
15
|
+
for i in range(len(result)):
|
|
16
|
+
image = images[i]
|
|
17
|
+
if len(image.shape) == 2:
|
|
18
|
+
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
|
|
19
|
+
# input_image_reshape = (512, 512)
|
|
20
|
+
input_image_reshape = (image.shape[1]*10,image.shape[0])
|
|
21
|
+
image = cv2.resize(image, input_image_reshape, interpolation=cv2.INTER_NEAREST)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
image_result = result[i]
|
|
25
|
+
linepoints_list = image_result["linepoints_list"]
|
|
26
|
+
for linepoints in linepoints_list:
|
|
27
|
+
for j in range(len(linepoints) - 1):
|
|
28
|
+
cv2.line(image, tuple([int(linepoints[j][0]*10),int(linepoints[j][1])]), tuple([int(linepoints[j + 1][0]*10),int(linepoints[j + 1][1])]), (0, 255, 0), 2)
|
|
29
|
+
|
|
30
|
+
# cv2.imwrite(f"tmp/client/result_{i}.jpg", image)
|
|
31
|
+
result_images.append(image)
|
|
32
|
+
return result_images
|
|
33
|
+
|
|
34
|
+
def convet_axis(points,x_dim,y_dim):
|
|
35
|
+
reflection_points = []
|
|
36
|
+
for point in points:
|
|
37
|
+
x = point[0]
|
|
38
|
+
y = point[1]
|
|
39
|
+
|
|
40
|
+
x_grid_start = x_dim[int(x)]
|
|
41
|
+
x_grid_end = x_dim[min(int(x)+1,len(x_dim)-1)]
|
|
42
|
+
x_refletion = (x_grid_end-x_grid_start)* math.modf(x)[0] + x_grid_start
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# y_index = min(max(0,int(y)),len(y_dim)-2)
|
|
46
|
+
y_index = int(y)
|
|
47
|
+
if y_index<0 or y_index>len(y_dim)-2:
|
|
48
|
+
continue
|
|
49
|
+
y_grid_start = y_dim[y_index]
|
|
50
|
+
y_grid_end = y_dim[y_index+1]
|
|
51
|
+
y_refletion = (y_grid_end-y_grid_start)* math.modf(y)[0] + y_grid_start
|
|
52
|
+
reflection_points.append([x_refletion,y_refletion])
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
return reflection_points
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2025 yaqiang.sun.
|
|
3
|
+
# This source code is licensed under the license found in the LICENSE file
|
|
4
|
+
# in the root directory of this source tree.
|
|
5
|
+
#########################################################################
|
|
6
|
+
# Author: yaqiangsun
|
|
7
|
+
# Created Time: 2025/10/20 18:13:37
|
|
8
|
+
########################################################################
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
# import cv2
|
|
13
|
+
import numpy as np
|
|
14
|
+
import sys
|
|
15
|
+
# 获取当前文件的绝对路径,向上两层就是项目根目录
|
|
16
|
+
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
17
|
+
if project_root not in sys.path:
|
|
18
|
+
sys.path.insert(0, project_root)
|
|
19
|
+
#
|
|
20
|
+
# `scope_api_client`: this package is generated by `openapi-python-client`
|
|
21
|
+
from .scope_api import Client, AuthenticatedClient
|
|
22
|
+
from .task import run_task
|
|
23
|
+
import logging
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
logging.basicConfig(level=logging.INFO)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class QubitScopeClient(object):
|
|
32
|
+
def __init__(self, url, api_key):
|
|
33
|
+
self.url = url
|
|
34
|
+
self.api_key = api_key
|
|
35
|
+
self.client = AuthenticatedClient(base_url=url, token=api_key)
|
|
36
|
+
|
|
37
|
+
def request(self, file_list:list[str|dict[str,np.ndarray]],task_type:str="s21peak"):
|
|
38
|
+
if len(file_list)>0:
|
|
39
|
+
response = run_task(self.client,file_list,task_type)
|
|
40
|
+
else:
|
|
41
|
+
raise ValueError("file_list must not be empty")
|
|
42
|
+
return response
|
|
43
|
+
def get_result(self,response):
|
|
44
|
+
if response.status_code == 200:
|
|
45
|
+
logging.info("Result: %s", response.parsed)
|
|
46
|
+
result = response.parsed
|
|
47
|
+
return result
|
|
48
|
+
else:
|
|
49
|
+
logging.error("Error: %s %s", response.status_code, response.parsed)
|
|
50
|
+
return []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains methods for accessing the API"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains endpoint functions for accessing the API"""
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any, Optional, Union
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from ... import errors
|
|
7
|
+
from ...client import AuthenticatedClient, Client
|
|
8
|
+
from ...models.http_validation_error import HTTPValidationError
|
|
9
|
+
from ...types import Response
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_kwargs(
|
|
13
|
+
pk: int,
|
|
14
|
+
) -> dict[str, Any]:
|
|
15
|
+
_kwargs: dict[str, Any] = {
|
|
16
|
+
"method": "get",
|
|
17
|
+
"url": f"/api/v1/tasks/demo/{pk}",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return _kwargs
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _parse_response(
|
|
24
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
25
|
+
) -> Optional[Union[Any, HTTPValidationError]]:
|
|
26
|
+
if response.status_code == 200:
|
|
27
|
+
response_200 = response.json()
|
|
28
|
+
return response_200
|
|
29
|
+
|
|
30
|
+
if response.status_code == 422:
|
|
31
|
+
response_422 = HTTPValidationError.from_dict(response.json())
|
|
32
|
+
|
|
33
|
+
return response_422
|
|
34
|
+
|
|
35
|
+
if client.raise_on_unexpected_status:
|
|
36
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
37
|
+
else:
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _build_response(
|
|
42
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
43
|
+
) -> Response[Union[Any, HTTPValidationError]]:
|
|
44
|
+
return Response(
|
|
45
|
+
status_code=HTTPStatus(response.status_code),
|
|
46
|
+
content=response.content,
|
|
47
|
+
headers=response.headers,
|
|
48
|
+
parsed=_parse_response(client=client, response=response),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def sync_detailed(
|
|
53
|
+
pk: int,
|
|
54
|
+
*,
|
|
55
|
+
client: Union[AuthenticatedClient, Client],
|
|
56
|
+
) -> Response[Union[Any, HTTPValidationError]]:
|
|
57
|
+
"""获取任务结果详情
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
pk (int): 任务结果 ID
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
64
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Response[Union[Any, HTTPValidationError]]
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
kwargs = _get_kwargs(
|
|
71
|
+
pk=pk,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
response = client.get_httpx_client().request(
|
|
75
|
+
**kwargs,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return _build_response(client=client, response=response)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def sync(
|
|
82
|
+
pk: int,
|
|
83
|
+
*,
|
|
84
|
+
client: Union[AuthenticatedClient, Client],
|
|
85
|
+
) -> Optional[Union[Any, HTTPValidationError]]:
|
|
86
|
+
"""获取任务结果详情
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
pk (int): 任务结果 ID
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
93
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Union[Any, HTTPValidationError]
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
return sync_detailed(
|
|
100
|
+
pk=pk,
|
|
101
|
+
client=client,
|
|
102
|
+
).parsed
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def asyncio_detailed(
|
|
106
|
+
pk: int,
|
|
107
|
+
*,
|
|
108
|
+
client: Union[AuthenticatedClient, Client],
|
|
109
|
+
) -> Response[Union[Any, HTTPValidationError]]:
|
|
110
|
+
"""获取任务结果详情
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
pk (int): 任务结果 ID
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
117
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Response[Union[Any, HTTPValidationError]]
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
kwargs = _get_kwargs(
|
|
124
|
+
pk=pk,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
128
|
+
|
|
129
|
+
return _build_response(client=client, response=response)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
async def asyncio(
|
|
133
|
+
pk: int,
|
|
134
|
+
*,
|
|
135
|
+
client: Union[AuthenticatedClient, Client],
|
|
136
|
+
) -> Optional[Union[Any, HTTPValidationError]]:
|
|
137
|
+
"""获取任务结果详情
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
pk (int): 任务结果 ID
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
144
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Union[Any, HTTPValidationError]
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
await asyncio_detailed(
|
|
152
|
+
pk=pk,
|
|
153
|
+
client=client,
|
|
154
|
+
)
|
|
155
|
+
).parsed
|