Wafer parametric contour
Semiconductor — oxide thickness, computed
Example from the compendium of canonical charts
Python Code
"""Semiconductor — Wafer parametric contour (oxide thickness, computed)."""
from pathlib import Path
# ── Palette + theme (matching the Plotly Studio gallery these charts ship in) ──
VIOLET, TEAL, GREEN, PINK, ORANGE = "#845EEE", "#52B3D0", "#55B685", "#DA5597", "#E9A23B"
PRIMARY, SECONDARY = VIOLET, TEAL
COLORWAY = [VIOLET, TEAL, GREEN, PINK, ORANGE]
BG, TEXT, GRID, MUTED = "#ffffff", "#1c2024", "#d9d9e0", "#60646c"
FONT = "Inter, -apple-system, BlinkMacSystemFont, sans-serif"
COLORSCALE = [[0, "rgba(132, 94, 238, 0.05)"], [1, "rgba(132, 94, 238, 0.9)"]]
def apply_theme(fig):
"""Light gallery theme: white background, Inter font, soft gridlines."""
fig.update_layout(
paper_bgcolor=BG, plot_bgcolor=BG, colorway=COLORWAY,
font=dict(family=FONT, color=TEXT, size=12),
legend=dict(font=dict(color=TEXT)),
hoverlabel=dict(bgcolor="#f0f0f3", font=dict(color=TEXT, family=FONT), bordercolor=GRID),
)
fig.update_xaxes(gridcolor=GRID, linecolor=GRID, zerolinecolor=GRID)
fig.update_yaxes(gridcolor=GRID, linecolor=GRID, zerolinecolor=GRID)
def fetch_csv(url, **kwargs):
import io
import pandas as pd
import requests
r = requests.get(url, timeout=60)
r.raise_for_status()
return pd.read_csv(io.StringIO(r.text), **kwargs)
def fetch_json(url):
import requests
r = requests.get(url, timeout=60)
r.raise_for_status()
return r.json()
import numpy as np
import plotly.graph_objects as go
def generate():
rng = np.random.default_rng(0)
# Wafer at normalized coords: x,y ∈ [-1,1], circular mask r ≤ 1
N = 50
x = np.linspace(-1, 1, N)
y = np.linspace(-1, 1, N)
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
# Oxide thickness model: P(x,y) = 100 - 8r² + 2x - y + noise (Angstroms)
noise = rng.normal(0, 0.5, X.shape)
P = 100 + (-8) * R**2 + 2 * X + (-1) * Y + noise
# Apply circular mask
P[R > 1] = np.nan
print(f" P range (excl NaN): {np.nanmin(P):.1f} – {np.nanmax(P):.1f} Å")
fig = go.Figure()
# Contour fill
fig.add_trace(go.Contour(
x=x,
y=y,
z=P,
colorscale="RdYlGn",
zmid=100,
contours=dict(
start=float(np.nanmin(P)),
end=float(np.nanmax(P)),
size=2,
showlabels=True,
labelfont=dict(size=9, color="black"),
),
colorbar=dict(
title="Thickness (Å)",
thickness=16,
),
hovertemplate="x: %{x:.2f}<br>y: %{y:.2f}<br>Thickness: %{z:.1f} Å<extra></extra>",
))
# Draw wafer edge circle
theta = np.linspace(0, 2 * np.pi, 300)
fig.add_trace(go.Scatter(
x=np.cos(theta),
y=np.sin(theta),
mode="lines",
line=dict(color="black", width=2),
showlegend=False,
hoverinfo="skip",
))
# Notch mark at bottom (270°)
fig.add_trace(go.Scatter(
x=[0],
y=[-1.0],
mode="markers",
marker=dict(symbol="triangle-down", size=10, color="black"),
showlegend=False,
hoverinfo="skip",
))
fig.update_layout(
xaxis=dict(
title="Wafer X (norm.)",
range=[-1.1, 1.1],
scaleanchor="y",
constrain="domain",
zeroline=True,
zerolinewidth=1,
showgrid=False,
),
yaxis=dict(
title="Wafer Y (norm.)",
range=[-1.15, 1.1],
constrain="domain",
zeroline=True,
zerolinewidth=1,
showgrid=False,
),
margin=dict(t=20, b=60, l=60, r=80),
annotations=[
dict(
text="Oxide thickness (Å) — Level-1 model: 100−8r²+2x−y+noise",
x=0.5, y=1.04,
xref="paper", yref="paper",
showarrow=False,
font=dict(size=10),
)
],
)
apply_theme(fig)
return fig
fig = generate()
fig.show()
Made with Plotly