Files
ZKFC_ACC/QX8800SP_DA.py
2025-11-23 21:23:21 +08:00

658 lines
26 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
# 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 = ['TXnm','TYnm','thetaμrad','Rppm']
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()