Skip to content

Commit eb65316

Browse files
Update __init__.py
1 parent 61162d0 commit eb65316

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

klarfkit/__init__.py

+112-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,116 @@
11
#!/usr/bin/env python
22
# coding: utf-8
33

4-
import klarfkit
4+
import pandas as pd
5+
import matplotlib.pyplot as plt
6+
import seaborn as sns
7+
import numpy as np
8+
import warnings
59

10+
class WaferMap:
11+
12+
def __init__(self):
13+
self.sample_size = None
14+
self.die_pitch = None
15+
self.die_origin = None
16+
self.center_location = None
17+
self.defect_list = pd.DataFrame()
18+
19+
def load_klarf(self, file, name=None):
20+
21+
with open(file) as f:
22+
data = [i.strip() for i in f.readlines()]
23+
cols = []
24+
defects = []
25+
defect_collect = False
26+
for i in data:
27+
28+
if "SampleSize" in i:
29+
if self.sample_size and self.sample_size != (float(i[:-1].split()[-1]) * 1000):
30+
warnings.warn(f"Warning: Files contain inconsistant sample sizes! {self.sample_size/1000}mm vs {(float(i[:-1].split()[-1]))}mm!")
31+
self.sample_size = float(i[:-1].split()[-1]) * 1000
32+
33+
elif "DiePitch" in i:
34+
if self.die_pitch and self.die_pitch != [float(j) for j in i[:-1].split(" ")[1:]]:
35+
warnings.warn("Warning: Files contain inconsistent die sizes. Recommend setting die_line_alpha to 0 for plotting")
36+
self.die_pitch = [float(j) for j in i[:-1].split(" ")[1:]]
37+
38+
elif "DieOrigin" in i:
39+
self.die_origin = [float(j) for j in i[:-1].split(" ")[1:]]
40+
41+
elif "CenterLocation" in i:
42+
self.center_location = [float(j) for j in i[:-1].split(" ")[1:]]
43+
44+
elif "DefectRecordSpec" in i:
45+
for j in i[:-1].split()[2::]:
46+
cols.append(j)
47+
48+
elif "DefectList" in i:
49+
defect_collect = True
50+
51+
elif "SummarySpec" in i:
52+
defect_collect = False
53+
54+
elif defect_collect:
55+
defects.append(i.replace(";", "").split())
56+
57+
df = pd.DataFrame(defects, columns=cols).astype(float)
58+
df['_XACTUAL'] = (df['XINDEX'] * self.die_pitch[0]) + df['XREL'] - self.center_location[0]
59+
df['_YACTUAL'] = (df['YINDEX'] * self.die_pitch[1]) + df['YREL'] - self.center_location[1]
60+
61+
if name:
62+
df['_KLARFNAME'] = name
63+
else:
64+
df['_KLARFNAME'] = file
65+
66+
self.defect_list = pd.concat([self.defect_list, df]).reset_index(drop=True)
67+
68+
def plot_wafer_map(self, color='_KLARFNAME', die_line_alpha=0.2, die_line_color='gray', *args, **kwargs):
69+
wafer_sin = (np.sin(np.arange(0, 2 * np.pi, 1 / 1000))) * self.sample_size / 2
70+
wafer_cos = (np.cos(np.arange(0, 2 * np.pi, 1 / 1000))) * self.sample_size / 2
71+
# Plot the wafer circle
72+
plt.plot(wafer_sin, wafer_cos, color='k', linewidth=0.3)
73+
74+
for i in range(-int(self.sample_size // self.die_pitch[0]) - 10,
75+
int(self.sample_size // self.die_pitch[0]) + 10):
76+
77+
die_x_lines = -self.center_location[0] + (i * self.die_pitch[0])
78+
height_squared = (self.sample_size / 2) ** 2 - die_x_lines ** 2
79+
if height_squared > 0:
80+
height = np.sqrt(height_squared)
81+
82+
plt.vlines(die_x_lines,
83+
-height,
84+
height,
85+
color=die_line_color,
86+
alpha=die_line_alpha)
87+
88+
for i in range(-int(self.sample_size // self.die_pitch[1]) - 10,
89+
int(self.sample_size // self.die_pitch[1]) + 10):
90+
91+
die_y_lines = -self.center_location[1] + (i * self.die_pitch[1])
92+
width_squared = (self.sample_size / 2) ** 2 - die_y_lines ** 2
93+
if width_squared > 0:
94+
width = np.sqrt(width_squared)
95+
96+
plt.hlines(die_y_lines,
97+
-width,
98+
width,
99+
color=die_line_color,
100+
alpha=die_line_alpha)
101+
102+
if color in self.defect_list.columns:
103+
sns.scatterplot(x=self.defect_list['_XACTUAL'],
104+
y=self.defect_list['_YACTUAL'],
105+
hue=self.defect_list[color],
106+
*args, **kwargs)
107+
108+
plt.legend(loc='lower left')
109+
else:
110+
sns.scatterplot(x=self.defect_list['_XACTUAL'],
111+
y=self.defect_list['_YACTUAL'],
112+
color=color,
113+
*args, **kwargs)
114+
115+
plt.xlim(-self.sample_size / 2 - 2000, self.sample_size / 2 + 2000)
116+
plt.ylim(-self.sample_size / 2 - 2000, self.sample_size / 2 + 2000)

0 commit comments

Comments
 (0)