import numpy as np import pandas as pd import scipy.linalg as sl import matplotlib.pyplot as plt from matplotlib.pyplot import MultipleLocator, FormatStrFormatter from matplotlib.patches import Ellipse import matplotlib.transforms as transforms # import seaborn as sns import os import math # plt.style.use('seaborn') plt.rcParams['font.family'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 pd.set_option('display.max_columns', None) #显示所有列,把行显示设置成最大 pd.set_option('display.max_rows', None) #显示所有行,把列显示设置成最大 #YDD def die1234(data_calc,DieType): """ 输入中科飞测量测结果及Die类型,输出4个Mark的量测结果,并与之前EVG量测数据保持一致 """ Refer_EVG_data = data_calc[data_calc['Die type']==DieType] Refer_EVG_data = Refer_EVG_data.pivot_table(values=['Misreg X','Misreg Y'], index='Die NO.', columns='Mark NO.').sort_index(axis=1,level=1) Refer_EVG_data.columns = ['M1X','M1Y', 'M2X','M2Y', 'M3X','M3Y', 'M4X','M4Y',] Refer_EVG_data.index.names = ["QX8800SP_Index"] Refer_EVG_data.index = Refer_EVG_data.index.astype(int) # 当前数据为Top坐标减去 Bottom坐标,除以-1000,与EVG保持一致 return Refer_EVG_data/-1000, describe_3s(Refer_EVG_data) def Mis_T(df,DieType,UseMark): """ 输入要进行误差分解的原始数据、Die类型以及使用的Mark个数,输出误差分解后的结果。 """ # if Die == 'Die1': # 80um风车Mark坐标 # DieM1 = (-5008.778,6004.225) # DieM2 = (5994.129,6252.542) # DieM3 = (-5548.967,-6166.277) # DieM4 = (5951.212,-6111.258) # elif Die == 'Die2': # DieM1 = (-5340.8,6295) # DieM2 = (6170,6295) # DieM3 = (-5450.8,-5995.8) # DieM4 = (6140,-5954.8) # elif Die == 'Die3': # DieM1 = (-5014.16,5831.341) # DieM2 = (5968.837,6100.804) # DieM3 = (-5535,-6325) # DieM4 = (5461.545,-6246.118) # elif Die == 'Die4': # DieM1 = (-5100.8,5945.8) # DieM2 = (6170,5945.8) # DieM3 = (-5450.8,-6345) # DieM4 = (6170,-6345) ##EVG量测顺序 # if DieType == 'Die1': # 80um圆环Mark坐标 # DieM1 = (-5128.778,6004.225) # DieM2 = (5874.13,6252.542) # DieM3 = (-5668.967,-6166.277) # DieM4 = (5831.21,-6111.258) # elif DieType == 'Die2': # DieM1 = (-5220.8,6295) # DieM2 = (6050,6295) # DieM3 = (-5570.8,-5995.8) # DieM4 = (6020,-5954.8) # elif DieType == 'Die3': # DieM1 = (-5134.16,5831.341) # DieM2 = (5848.84,6100.804) # DieM3 = (-5655,-6325) # DieM4 = (5341.55,-6246.118) # elif DieType == 'Die4': # DieM1 = (-5220.8,5945.8) # DieM2 = (6050,5945.8) # DieM3 = (-5570.8,-6345) # DieM4 = (6050,-6345) ## ZKFC量测顺序 if DieType == 'Die1': # 80um圆环Mark坐标 DieM1 = (4808.778,5924.225) DieM2 = (-5274.129,6217.542) DieM3 = (5348.967,-6246.277) DieM4 = (-6115.212,-6191.258) elif DieType == 'Die2': DieM1 = (5300.8,6215) DieM2 = (-6210,6215) DieM3 = (5410.8,-6075.8) DieM4 = (-6210,-6025.8) elif DieType == 'Die3': DieM1 = (4814.16,5911.341) DieM2 = (-6168.837,6180.804) DieM3 = (5335,-6245) DieM4 = (-5661.545,-6166.118) elif DieType == 'Die4': DieM1 = (5060.8,6025.8) DieM2 = (-6210,6025.8) DieM3 = (5410.8,-6265) DieM4 = (-6210,-6265) if UseMark == 2: Mis_T = np.array([ [1,0,-DieM1[1],-DieM1[0]], [0,1, DieM1[0],-DieM1[1]], [1,0,-DieM4[1],-DieM4[0]], [0,1, DieM4[0],-DieM4[1]], ]) EVG_T1 = np.linalg.inv(Mis_T) T4 = np.dot(EVG_T1,df[['M1X','M1Y','M4X','M4Y']].T).T elif UseMark == 4: Mis_T = np.array([ [1,0,-DieM1[1],-DieM1[0]], [0,1, DieM1[0],-DieM1[1]], [1,0,-DieM2[1],-DieM2[0]], [0,1, DieM2[0],-DieM2[1]], [1,0,-DieM3[1],-DieM3[0]], [0,1, DieM3[0],-DieM3[1]], [1,0,-DieM4[1],-DieM4[0]], [0,1, DieM4[0],-DieM4[1]], ]) EVG_T1 = np.linalg.pinv(Mis_T) T4 = np.dot(EVG_T1,df.T).T TG_D4 = pd.DataFrame(T4,index=df.index,columns=['TX','TY',r'$\theta$','R']) TG_D4_copy = TG_D4.copy() #EVG测量值MisAlignment分解后转到设备方向 TG_D4['TX'],TG_D4['TY']=TG_D4['TY'], -TG_D4['TX'] #角度值从弧度变为角度值 TG_D4[r'$\theta$'] = np.arcsin(TG_D4[r'$\theta$'])*180/np.pi # runout缩放系数变更为实际长度 TG_D4['RL'] = TG_D4['R']*((DieM1[1]-DieM4[1])**2 + (DieM1[0]-DieM4[0])**2)**0.5/2 return TG_D4,TG_D4_copy def Data_ETL(EVG,Die_Type,Mark_Type): df_EVG = EVG.sort_index().copy() df_EVG = df_EVG[df_EVG.applymap(isnumber)].astype(np.float64) df_EVG_new = pd.DataFrame() df_EVG_new["X"] = df_EVG.iloc[:,1] df_EVG_new["Y"] = -df_EVG.iloc[:,0] df_EVG_new["Die_Type"] = Die_Type df_EVG_new["Mark_Type"] = Mark_Type df_EVG_new = df_EVG_new.rename_axis("EVG_Index") return df_EVG_new def Data_ETL_Cat(folder,path,*dfs): df = pd.concat([i for i in dfs]) df.to_excel(folder+path+'.xlsx') def read_html_SP_1(path): """ 读取QX8800SP第 1 批EVG测量html文件数据。 文件夹内有两个html,一个是Mark1,另一个是Mark4 """ # 指定文件夹路径 folder_path = path # 获取文件夹中的所有文件名 file_names = os.listdir(folder_path) # 创建一个字典来存储读取的Excel文件 html_data = {'M1':[],'M2':[],'M4':[],'M3':[],} # 逐个读取Excel文件 for file_name in file_names: # 检查文件扩展名是否为Excel文件 if file_name.endswith('.html'): # 使用Pandas读取Excel文件 file_path = os.path.join(folder_path, file_name) df = pd.read_html(file_path) try: if ('MARK1' in df[0].loc[3][1]): df[2]['Identifier'] = np.array([i[6:] for i in df[2]['Identifier']], dtype=int) M1 = df[2].iloc[::-1,[0,5,6]].set_index('Identifier') M1.columns = ["M1X","M1Y"] M1.index.names = ["EVG"] html_data['M1'] = M1 elif ('MARK2' in df[0].loc[3][1]): df[2]['Identifier'] = np.array([i[6:] for i in df[2]['Identifier']], dtype=int) M2 = df[2].iloc[::-1,[0,5,6]].set_index('Identifier') M2.columns = ["M2X","M2Y"] M2.index.names = ["EVG"] html_data['M3'] = M2 elif ('MARK3' in df[0].loc[3][1]): df[2]['Identifier'] = np.array([i[6:] for i in df[2]['Identifier']], dtype=int) M3 = df[2].iloc[::-1,[0,5,6]].set_index('Identifier') M3.columns = ["M3X","M3Y"] M3.index.names = ["EVG"] html_data['M3'] = M3 elif ('MARK4' in df[0].loc[3][1]): df[2]['Identifier'] = np.array([i[6:] for i in df[2]['Identifier']], dtype=int) M4 = df[2].iloc[::-1,[0,5,6]].set_index('Identifier') M4.columns = ["M4X","M4Y"] M4.index.names = ["EVG"] html_data['M4'] = M4 except: continue return html_data def read_html_SP_2(path): """ 读取QX8800SP第 2 批EVG测量html文件数据。 文件夹内有两个html,一个是Mark1,另一个是Mark4 """ # 指定文件夹路径 folder_path = path # 获取文件夹中的所有文件名 file_names = os.listdir(folder_path) # 创建一个字典来存储读取的Excel文件 html_data = {'M1':[],'M2':[],'M3':[],'M4':[]} # 逐个读取Excel文件 for file_name in file_names: # 检查文件扩展名是否为Excel文件 if file_name.endswith('.html'): # 使用Pandas读取Excel文件 file_path = os.path.join(folder_path, file_name) df = pd.read_html(file_path) try: if ('MARK1' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M1 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') M1.columns = ["M1X","M1Y"] M1.index.names = ["EVG"] html_data['M1'] = M1 elif ('MARK2' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M2 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') M2.columns = ["M2X","M2Y"] M2.index.names = ["EVG"] html_data['M2'] = M2 elif ('MARK3' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M3 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') M3.columns = ["M3X","M3Y"] M3.index.names = ["EVG"] html_data['M3'] = M3 elif ('MARK4' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M4 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') M4.columns = ["M4X","M4Y"] M4.index.names = ["EVG"] html_data['M4'] = M4 except: continue return html_data def read_html_SP_3(path): """ 读取QX8800SP第 2 批EVG测量html文件数据。 文件夹内有两个html,一个是Mark1,另一个是Mark4 """ # 指定文件夹路径 folder_path = path # 获取文件夹中的所有文件名 file_names = os.listdir(folder_path) # 创建一个字典来存储读取的Excel文件 html_data = {'M1':[],'M2':[],'M3':[]} # 逐个读取Excel文件 for file_name in file_names: # 检查文件扩展名是否为Excel文件 if file_name.endswith('.html'): # 使用Pandas读取Excel文件 file_path = os.path.join(folder_path, file_name) df = pd.read_html(file_path) try: if ('MARK1' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[3:] for i in df[4]['Identifier']], dtype=int) M1 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') ID = df[0].loc[0][1] file_name = ID + 'M1' html_data['M1'] = M1 elif ('MARK4' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M2 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') ID = df[0].loc[0][1] file_name = ID + 'M2' html_data['M2'] = M2 elif ('MARK3' in df[0].loc[3][1]): df[4]['Identifier'] = np.array([i[6:] for i in df[4]['Identifier']], dtype=int) M3 = df[4].iloc[::-1,[0,5,6]].set_index('Identifier') html_data['M3'] = M3 except: continue return html_data def describe_3s(df): des_df = df.describe() des_df.loc["range"] = des_df.loc['max']-des_df.loc['min'] des_df.loc["3sigma"] = des_df.loc['std']*3 return des_df def result_show(df): df = describe_3s(df) df_show = df[['TX','TY','$\\theta$','R']].loc[['mean','3sigma']] df_show['TX'],df_show['TY'] = df_show['TX']*1000,df_show['TY']*1000 df_show['$\\theta$'] = df_show['$\\theta$']*np.pi/180*1000000 df_show['R'] = df_show['R']*1000000 df_show.columns = ['TX(nm)','TY(nm)','theta(μrad)','R(ppm)'] return df_show.T def isnumber(x): try: float(x) return True except: return False def calc_theta(M1X,M1Y,M2X,M2Y): w = 11545.5 h = 11739 w2 = w - M1X + M2X h2 = h - M1Y + M2Y a1 = np.arctan2(h,w)*180/np.pi a2 = np.arctan2(h2,w2)*180/np.pi return a2-a1 def calc_center(M1X,M1Y,M2X,M2Y): MCX = (M2X-M1X)/2+M1X MCY = (M2Y-M1Y)/2+M1Y return MCX,MCY def angle2offset(angle): return 2*np.sin(angle/2*np.pi/180)*16841.364 def confidence_ellipse(x, y, ax, n_std=3.0, facecolor='none', **kwargs): """ Create a plot of the covariance confidence ellipse of *x* and *y*. Parameters ---------- x, y : array-like, shape (n, ) Input data. ax : matplotlib.axes.Axes The axes object to draw the ellipse into. n_std : float The number of standard deviations to determine the ellipse's radiuses. **kwargs Forwarded to `~matplotlib.patches.Ellipse` Returns ------- matplotlib.patches.Ellipse """ if x.size != y.size: raise ValueError("x and y must be the same size") cov = np.cov(x, y) pearson = cov[0, 1]/np.sqrt(cov[0, 0] * cov[1, 1]) # Using a special case to obtain the eigenvalues of this # two-dimensional dataset. ell_radius_x = np.sqrt(1 + pearson) ell_radius_y = np.sqrt(1 - pearson) ellipse = Ellipse((0, 0), width=ell_radius_x * 2, height=ell_radius_y * 2, facecolor=facecolor, **kwargs) # Calculating the standard deviation of x from # the squareroot of the variance and multiplying # with the given number of standard deviations. scale_x = np.sqrt(cov[0, 0]) * n_std mean_x = np.mean(x) # calculating the standard deviation of y ... scale_y = np.sqrt(cov[1, 1]) * n_std mean_y = np.mean(y) transf = transforms.Affine2D() \ .rotate_deg(45) \ .scale(scale_x, scale_y) \ .translate(mean_x, mean_y) ellipse.set_transform(transf + ax.transData) return ax.add_patch(ellipse) def plt_3sigma(data_calc,Data_ID): theta = np.linspace(0, 2*np.pi, 100) radius1 = 0.533 a1 = radius1*np.cos(theta) b1 = radius1*np.sin(theta) radius2 = 1.067 a2 = radius2*np.cos(theta) b2 = radius2*np.sin(theta) radius3 = 1.6 a3 = radius3*np.cos(theta) b3 = radius3*np.sin(theta) fig, ax_nstd = plt.subplots(1,2) ax_nstd[0].axvline(c='grey', lw=1) ax_nstd[0].axhline(c='grey', lw=1) x1, y1 = data_calc['M1X'].dropna().values,data_calc['M1Y'].dropna().values ax_nstd[0].scatter(x1, y1, s=3) for i in data_calc.dropna().index: ax_nstd[0].annotate(i, xy=(data_calc.loc[i,"M1X"],data_calc.loc[i,"M1Y"]), xytext=(data_calc.loc[i,"M1X"],data_calc.loc[i,"M1Y"]), color="k") ax_nstd[0].plot(a3,b3,color='r',label=r'$3\sigma$ 1.6um') ax_nstd[0].plot(a2,b2,color='b',label=r'$2\sigma$ 1.067um') ax_nstd[0].plot(a1,b1,color='g',label=r'$1\sigma$ 0.533um') confidence_ellipse(x1, y1, ax_nstd[0], n_std=1, linewidth=1.5, label=r'$1\sigma$', edgecolor='firebrick') confidence_ellipse(x1, y1, ax_nstd[0], n_std=2, linewidth=2, label=r'$2\sigma$', edgecolor='fuchsia', linestyle='--') confidence_ellipse(x1, y1, ax_nstd[0], n_std=3, linewidth=2, label=r'$3\sigma$', edgecolor='orange', linestyle='-.') ax_nstd[0].set_xlim((-3,3)) ax_nstd[0].set_ylim((-3,3)) ax_nstd[0].set_title(fr'{Data_ID} Die1 Mark1 $3\sigma$分布') ax_nstd[0].legend() ax_nstd[1].axvline(c='grey', lw=1) ax_nstd[1].axhline(c='grey', lw=1) x2, y2 = data_calc['M4X'].dropna().values,data_calc['M4Y'].dropna().values ax_nstd[1].scatter(x2, y2, s=3) for i in data_calc.dropna().index: ax_nstd[1].annotate(i, xy=(data_calc.loc[i,"M4X"],data_calc.loc[i,"M4Y"]), xytext=(data_calc.loc[i,"M4X"],data_calc.loc[i,"M4Y"]), color="k") ax_nstd[1].plot(a3,b3,color='r',label=r'$3\sigma$ 1.6um') ax_nstd[1].plot(a2,b2,color='b',label=r'$2\sigma$ 1.067um') ax_nstd[1].plot(a1,b1,color='g',label=r'$1\sigma$ 0.533um') confidence_ellipse(x2, y2, ax_nstd[1], n_std=1, linewidth=1.5, label=r'$1\sigma$', edgecolor='firebrick') confidence_ellipse(x2, y2, ax_nstd[1], n_std=2, linewidth=2, label=r'$2\sigma$', edgecolor='fuchsia', linestyle='--') confidence_ellipse(x2, y2, ax_nstd[1], n_std=3, linewidth=2, label=r'$3\sigma$', edgecolor='orange', linestyle='-.') ax_nstd[1].set_xlim((-3,3)) ax_nstd[1].set_ylim((-3,3)) ax_nstd[1].set_title(fr'{Data_ID} Mark4 $3\sigma$分布') ax_nstd[1].legend() plt.show() def plt_data(plt_data,name): fig, ax = plt.subplots(3,3) keys = [i for i in plt_data] #plot_X = plt_data.index[1] ax[0][0].plot(plt_data.index, plt_data[keys[0]], linestyle = '-', # 折线类型 linewidth = 1, color = 'steelblue', # 折线颜色 marker = 'o', markersize = 5, # 点的形状大小 markeredgecolor='black', # 点的边框色 markerfacecolor='brown') # 点的填充色 ax[0][0].xaxis.set_major_locator(MultipleLocator(5)) ax[0][0].yaxis.set_major_locator(MultipleLocator(0.5)) ax[0][0].set_title(keys[0]) ax[0][1].plot(plt_data.index, plt_data[keys[2]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='b') ax[0][1].xaxis.set_major_locator(MultipleLocator(5)) ax[0][1].yaxis.set_major_locator(MultipleLocator(0.5)) ax[0][1].set_title(keys[2]) ax[0][2].plot(plt_data.index, plt_data[keys[6]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='m') ax[0][2].xaxis.set_major_locator(MultipleLocator(5)) ax[0][2].yaxis.set_major_locator(MultipleLocator(0.0015)) ax[0][2].set_title('偏转角度') ax[1][0].plot(plt_data.index, plt_data[keys[1]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='m') ax[1][0].xaxis.set_major_locator(MultipleLocator(5)) ax[1][0].yaxis.set_major_locator(MultipleLocator(0.5)) ax[1][0].set_title(keys[1]) ax[1][1].plot(plt_data.index, plt_data[keys[3]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='g') ax[1][1].xaxis.set_major_locator(MultipleLocator(5)) ax[1][1].yaxis.set_major_locator(MultipleLocator(0.5)) ax[1][1].set_title(keys[3]) ax[1][2].plot(plt_data.index, plt_data['MCX'], linestyle = '-', linewidth = 1, color = 'steelblue', label='MCX', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='r') ax[1][2].plot(plt_data.index, plt_data['MCY'], linestyle = '-', linewidth = 1, color = 'steelblue', label='MCY', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='y') ax[1][2].xaxis.set_major_locator(MultipleLocator(5)) ax[1][2].yaxis.set_major_locator(MultipleLocator(0.5)) ax[1][2].set_title('Mark中心偏移XY') ax[1][2].legend() ax[2][0].plot(plt_data.index, plt_data[keys[-3]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='m') ax[2][0].axhline(1.6,c='orange',ls='-.',label='Length:1.6um') ax[2][0].xaxis.set_major_locator(MultipleLocator(5)) ax[2][0].yaxis.set_major_locator(MultipleLocator(0.5)) ax[2][0].set_title(keys[-3]) ax[2][0].legend() ax[2][1].plot(plt_data.index, plt_data[keys[-2]], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='m') ax[2][1].axhline(1.6,c='orange',ls='-.',label='Length:1.6um') ax[2][1].xaxis.set_major_locator(MultipleLocator(5)) ax[2][1].yaxis.set_major_locator(MultipleLocator(0.5)) ax[2][1].set_title(keys[-2]) ax[2][1].legend() ax[2][2].plot(plt_data.index, plt_data['MCL'], linestyle = '-', linewidth = 1, color = 'steelblue', marker = 'o', markersize = 5, markeredgecolor='black', markerfacecolor='m') ax[2][2].axhline(1.6,c='orange',ls='-.',label='Length:1.6um') ax[2][2].xaxis.set_major_locator(MultipleLocator(5)) ax[2][2].yaxis.set_major_locator(MultipleLocator(0.5)) ax[2][2].set_title('Mark中心偏移MCL') ax[2][2].legend() plt.suptitle(f'{name}:贴片数据') fig.tight_layout() plt.show() def wafer_data_make(data_list, gap1, new_origin): # 该函数用于设置wafer位置信息 ''' :param data_list: 如['mark1','mark2','mark3','mark4'] :param gap1: die位置间隔设置,即每个矩形的间隔设置 :param new_origin: 原点位置设定 :return: ''' df_empty = pd.DataFrame(columns=['芯片号', 'P_X', 'P_Y']) Die_count = 0 # i的最大值即为列数 for i in range(len(data_list)): # j的最大值即为该列的Die个数 for j in range(int(data_list[i][2])): x_coordinate = (int(data_list[i][0]) - float(new_origin[0])) * gap1 y_coordinate = (-int(data_list[i][1]) - j + float(new_origin[1])) * gap1 Die_count = Die_count + 1 df_empty.loc[Die_count - 1] = [Die_count, x_coordinate, y_coordinate] df_empty['芯片号'] = df_empty['芯片号'].astype(int) wafer_data = df_empty.set_index('芯片号') return wafer_data def plt_Vmap(V_data,data0,name): plt.figure() L1 = V_data["M1L"] L2 = V_data["M4L"] gap = 150 gap_rec = 400 plt.quiver(V_data['P_X'] - gap, V_data['P_Y'] + gap, V_data['M1X'], V_data['M1Y'], V_data["M1L"], cmap='coolwarm', units='xy',width = 40) # gap(自定义): 定义箭头的起始位置(4个Mark点的位置) plt.quiver(V_data["P_X"] + gap, V_data["P_Y"] - gap, V_data["M4X"], V_data["M4Y"], V_data["M4L"], cmap="coolwarm", units='xy',width = 40) for i in data0.index: color = 'k' plt.annotate(i, xy=(data0.loc[i,"P_X"],data0.loc[i,"P_Y"]), xytext=(data0.loc[i,"P_X"]-50,data0.loc[i,"P_Y"]-50), color=color) rectangle = plt.Rectangle(xy=(data0.loc[i, 'P_X'] - gap_rec/2, data0.loc[i, 'P_Y'] - gap_rec/2), width=gap_rec, height=gap_rec, fill=False, color='k') plt.gca().add_patch(rectangle) # if np.isnan(L1[i]) or np.isnan(L2[i]): # color = 'k' # elif L1[i]<1.6 and L2[i]<1.6: # color = 'b' # else: # color = 'r' # #中心点偏移 # plt.annotate(r"$C$:" + str(round(V_data["MCL"][i],2)), # xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), # xytext=(V_data.loc[i,"P_X"]-200,V_data.loc[i,"P_Y"]+100), # color=color) # #右Mark偏移 # plt.annotate(r"$R$:" + str(round(L2[i],3)), # xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), # xytext=(V_data.loc[i,"P_X"]+100,V_data.loc[i,"P_Y"]+100), # color=color) # #左Mark偏移 # plt.annotate(r"$L$:" + str(round(L1[i],3)), # xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), # xytext=(V_data.loc[i,"P_X"]-200,V_data.loc[i,"P_Y"]-100), # color=color) # plt.annotate(r"$\theta$:" + str(round(V_data.loc[i,"M_R_14"],4)), # xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), # xytext=(V_data.loc[i,"P_X"]+100,V_data.loc[i,"P_Y"]-100), # color=color) # plt.xlim(-3000,2500) # plt.ylim(-3000,3000) plt.colorbar() plt.title(f'{name}:C:中心点偏移,L(左下):Mark1偏移,R(右上):Mark2偏移,(单位:um)') plt.show() def plt_XYmap(V_data,name): plt.figure() L1 = V_data["M1L"] L2 = V_data["M4L"] plt.quiver(V_data["P_X"],V_data["P_Y"],V_data["MCX"],V_data["MCY"], V_data["MCL"], cmap="coolwarm", units='xy') def plt_annotate(V_data,i,color): #中心点偏移 plt.annotate(r"$X$:" + str(round(V_data["MCX"][i],2)), xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), xytext=(V_data.loc[i,"P_X"]-200,V_data.loc[i,"P_Y"]+50), color=color) #右Mark偏移 plt.annotate(r"$C$:" + str(round(V_data["MCL"][i],2)), xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), xytext=(V_data.loc[i,"P_X"]+50,V_data.loc[i,"P_Y"]+50), color=color) #左Mark偏移 plt.annotate(r"$Y$:" + str(round(V_data["MCY"][i],2)), xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), xytext=(V_data.loc[i,"P_X"]-200,V_data.loc[i,"P_Y"]-50), color=color) #角度偏移 plt.annotate(r"$\theta$:" + str(round(V_data.loc[i,"M_R"],4)), xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), xytext=(V_data.loc[i,"P_X"]+50,V_data.loc[i,"P_Y"]-50), color=color) for i in V_data.index: plt.annotate(i, xy=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), xytext=(V_data.loc[i,"P_X"],V_data.loc[i,"P_Y"]), color="k") if np.isnan(L1[i]) or np.isnan(L2[i]): plt_annotate(V_data,i,'k') elif L1[i]<=0.707 and L2[i]<=0.707: plt_annotate(V_data,i,'orange') elif L1[i]<=1.13 and L2[i]<=1.13: plt_annotate(V_data,i,'g') elif L1[i]<=1.6 and L2[i]<=1.6: plt_annotate(V_data,i,'b') else: plt_annotate(V_data,i,'r') # plt.xlim(-2500,2500) # plt.ylim(-3000,3000) plt.colorbar() plt.title(f'{name}:C:中心点偏移矢量,X:中心点X偏移,Y:中心点Y偏移,(单位:um)') plt.show()