Last active
December 30, 2015 18:20
-
-
Save jbcrail/4f8fd19b6c0c285a4d3c to your computer and use it in GitHub Desktop.
Yield Analysis for Silicon Wafer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import pandas as pd | |
from collections import OrderedDict | |
from bokeh.models import ColumnDataSource, GridPlot, HoverTool | |
from bokeh.palettes import RdYlGn9 | |
from bokeh.plotting import Figure, hplot, vplot, output_file, show | |
def generate_dataset(name, size): | |
""" | |
Create a square dataset of values between [0, 1.0) drawn from a distribution | |
based on the given name. | |
""" | |
if name == "cluster": | |
# Cluster of error values | |
a = np.rint(np.random.multivariate_normal([size/4, 3*size/4], [[1.2, 0], [0.4, 0.8]], size=10000)) | |
df = pd.DataFrame(np.vstack(a), columns=['x', 'y']) | |
df['yield'] = np.random.random_sample((10000,)) | |
cluster = df.groupby(['x', 'y']).mean().reset_index() | |
# Sample of good values to be merged into | |
b = np.ones((size, size)) | |
df = pd.DataFrame(b).unstack().reset_index() | |
df.columns = ['x', 'y', 'yield'] | |
df = pd.merge(df, cluster, how='left', on=['x', 'y']) | |
df['yield'] = np.where(df.yield_y.isnull(), df.yield_x, df.yield_y) | |
df = df.drop('yield_x', axis=1) | |
df = df.drop('yield_y', axis=1) | |
else: | |
# Uniformly random sample of error values | |
grid = pd.DataFrame(np.random.random_sample((size, size))) | |
df = grid.unstack().reset_index() | |
df.columns = ['x', 'y', 'yield'] | |
return df | |
def apply_palette(df, palette): | |
# Create a color mapping | |
edges = np.linspace(0.0, 1.0, num=len(palette)+1)[1:] | |
color_map = dict(zip(edges, list(reversed(palette)))) | |
def categorize_bins(n): | |
for upper in sorted(color_map.keys()): | |
if n <= upper: | |
return color_map[upper] | |
return "NaN" | |
df['color'] = df['yield'].map(categorize_bins) | |
return df | |
def minimum_grid(n, default): | |
return default if n < default else n | |
def contains_point(center, radius, x, y): | |
return (x-center[0])**2 + (y-center[1])**2 < radius**2 | |
def make_plot(name, title, size): | |
def contains_square(row): | |
center = ((size-1)/2.0, (size-1)/2.0) | |
radius = size / 2.0 | |
corners = [(row.x+0.5, row.y+0.5), (row.x+0.5, row.y-0.5), (row.x-0.5, row.y-0.5), (row.x-0.5, row.y+0.5)] | |
return all([contains_point(center, radius, p[0], p[1]) for p in corners]) | |
df = generate_dataset(name, size) | |
df = apply_palette(df, RdYlGn9) | |
df['percentage'] = df['yield'].map(lambda n: n * 100) | |
df['contains'] = df.apply(contains_square, axis=1) | |
df = df[df.contains] | |
source = ColumnDataSource(df) | |
min_grid_size = minimum_grid(size * 10, 600) | |
p = Figure( | |
plot_width=min_grid_size, | |
plot_height=min_grid_size, | |
x_range=(-1, size), | |
y_range=(-1, size), | |
tools="hover,save", | |
toolbar_location=None) | |
p.circle(x=(size-1)/2.0, y=(size-1)/2.0, radius=size/2.0, line_color='#bbbbbb', fill_color='#bbbbbb') | |
p.rect('x', 'y', name='dies', source=source, color='color', width=0.9, height=0.9) | |
p.title = title | |
p.axis.visible = None | |
p.xgrid.grid_line_color = None | |
p.ygrid.grid_line_color = None | |
p.outline_line_color = None | |
hover = p.select(dict(type=HoverTool)) | |
hover.names = ["dies"] | |
hover.tooltips = OrderedDict([ | |
("Yield", "@percentage%"), | |
]) | |
return p | |
if __name__ == '__main__': | |
# Approximate size chart for wafers: | |
# - 6" (150mm) => 12 | |
# - 8" (200mm) => 16 | |
# - 12" (300mm) => 25 | |
plot_6_random = make_plot("random", "6\" wafer w/ random errors", 12) | |
plot_6_cluster = make_plot("cluster", "6\" wafer w/ clustered errors", 12) | |
plot_8_random = make_plot("random", "8\" wafer w/ random errors", 16) | |
plot_8_cluster = make_plot("cluster", "8\" wafer w/ clustered errors", 16) | |
plot_12_random = make_plot("random", "12\" wafer w/ random errors", 25) | |
plot_12_cluster = make_plot("cluster", "12\" wafer w/ clustered errors", 25) | |
layout = vplot( | |
hplot(plot_6_random, plot_6_cluster), | |
hplot(plot_8_random, plot_8_cluster), | |
hplot(plot_12_random, plot_12_cluster) | |
) | |
output_file("wafer_yield.html", title="Wafer Yield Example") | |
show(layout) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment