Specific Process Knowledge/Lithography/EBeamLithography/thopesplaystuff
<!doctype html> <html lang="en"> <head>
<meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>EBL Dose Simulator — Hello Kitty Theme</title> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> <style> :root{ --pink:#ffb6d5; --hotpink:#ff69b4; --accent:#fff0f6; --text:#333; --card:#fff; } body{ margin:0; font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial; background: linear-gradient(180deg,var(--accent),#fff); color:var(--text); } header{ display:flex;align-items:center;gap:16px;padding:18px 24px;background:var(--pink);box-shadow:0 6px 18px rgba(255,105,180,0.12); } .logo{ width:64px;height:64px;border-radius:12px;background:linear-gradient(180deg,var(--hotpink),#ffd1ea);display:flex;align-items:center;justify-content:center;box-shadow:0 6px 10px rgba(0,0,0,0.06); } .logo svg{width:46px;height:46px} h1{font-size:20px;margin:0} .container{max-width:1100px;margin:20px auto;padding:18px} .grid{display:grid;grid-template-columns:320px 1fr;gap:18px} .card{background:var(--card);border-radius:12px;padding:14px;box-shadow:0 8px 22px rgba(0,0,0,0.06)} label{font-size:13px;display:block;margin-bottom:6px} .small{font-size:12px;color:#666} input[type=range]{width:100%} .row{display:flex;gap:12px;align-items:center} button{background:var(--hotpink);border:none;color:white;padding:8px 12px;border-radius:10px;cursor:pointer} footer{margin-top:18px;text-align:center;color:#777;font-size:13px} .muted{color:#666;font-size:13px} canvas{background:transparent} </style>
</head> <body>
<header>
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"> <g fill="none" stroke="#ffffff" stroke-width="1.6"> <ellipse cx="32" cy="36" rx="18" ry="14" fill="#fff" stroke="none"/> <path d="M18 18c-6 0-8-6-8-6s6 0 8 2c2 2 6 4 10 4s8-2 10-4c2-2 8-2 8-2s-2 6-8 6" fill="#fff" stroke="none"/> </g> <circle cx="24" cy="34" r="2.5" fill="#ff69b4"/> <circle cx="40" cy="34" r="2.5" fill="#ff69b4"/> <rect x="28" y="38" width="8" height="6" rx="3" fill="#ff69b4"/> </svg>
EBL Dose Simulator — Hello Kitty Theme
</header>
<main class="container">
<label for="widthSlider">Line width: 100 nm</label>
<input id="widthSlider" type="range" min="10" max="400" value="100" step="1">
<label for="doseInput">Incident dose (a.u.):</label>
<input id="doseInput" type="number" value="1" step="0.1" style="width:100%" />
<label>Proximity function parameters</label>
<label>Forward sigma (σf, nm): 5</label>
<input id="sfSlider" type="range" min="1" max="30" value="5">
<label>Backscatter sigma (σb, nm): 200</label>
<input id="sbSlider" type="range" min="50" max="2000" value="200">
<label>Backscatter weight (η): 0.4</label>
<input id="etaSlider" type="range" min="0" max="0.9" step="0.01" value="0.4">
<button id="resetBtn">Reset</button>
<canvas id="doseChart" height="220"></canvas>
<label style="display:flex;gap:6px;align-items:center"><input id="showPattern" type="checkbox" checked> Show pattern</label>
<label style="display:flex;gap:6px;align-items:center"><input id="showForward" type="checkbox" checked> Forward component</label>
<label style="display:flex;gap:6px;align-items:center"><input id="showBack" type="checkbox" checked> Backscatter component</label>
<footer>
</footer> </main>
<script> // --- Configuration & utilities --- const LENGTH = 2000; // nm length of simulation window const DX = 1; // nm resolution const N = Math.floor(LENGTH/DX); const x = new Array(N).fill(0).map((_,i)=>i*DX);
function gaussian1d(sigma){
const twiceVar = 2*sigma*sigma;
const radius = Math.ceil(6*sigma/DX);
const kernel = new Float64Array(radius*2+1);
let sum = 0;
for(let i=-radius;i<=radius;i++){
const v = Math.exp(-(i*DX)*(i*DX)/twiceVar);
kernel[i+radius]=v; sum+=v;
}
for(let i=0;i<kernel.length;i++) kernel[i]/=sum;
return {kernel, radius};
}
function convolve(signal, kernel, radius){
const out = new Float64Array(signal.length);
for(let i=0;i<signal.length;i++){
let s=0;
for(let k=-radius;k<=radius;k++){
const j=i+k;
if(j<0||j>=signal.length) continue;
s += signal[j]*kernel[k+radius];
}
out[i]=s;
}
return out;
}
function makePattern(lineWidth){
// three parallel lines centered at 600, 1000, 1400 nm
const centers = [600,1000,1400];
const pat = new Float64Array(N);
const half = lineWidth/2;
for(let i=0;i<N;i++){
const xi = x[i];
for(const c of centers){
if(Math.abs(xi-c) <= half) { pat[i]=1; break; }
}
}
return pat;
}
// --- UI elements --- const widthSlider = document.getElementById('widthSlider'); const widthLabel = document.getElementById('widthLabel'); const doseInput = document.getElementById('doseInput'); const sfSlider = document.getElementById('sfSlider'); const sbSlider = document.getElementById('sbSlider'); const etaSlider = document.getElementById('etaSlider'); const sfLabel = document.getElementById('sfLabel'); const sbLabel = document.getElementById('sbLabel'); const etaLabel = document.getElementById('etaLabel'); const resetBtn = document.getElementById('resetBtn'); const showPattern = document.getElementById('showPattern'); const showForward = document.getElementById('showForward'); const showBack = document.getElementById('showBack');
// --- Chart --- const ctx = document.getElementById('doseChart').getContext('2d'); const chart = new Chart(ctx, {
type: 'line',
data: {
labels: x,
datasets: [
{label:'Total dose', data: new Array(N).fill(0), tension:0.2, borderWidth:2, pointRadius:0, spanGaps:true},
{label:'Pattern (direct)', data: new Array(N).fill(0), tension:0.2, borderWidth:1, pointRadius:0, borderDash:[4,4], hidden:!showPattern.checked},
{label:'Forward scatter', data: new Array(N).fill(0), tension:0.2, borderWidth:1, pointRadius:0, hidden:!showForward.checked},
{label:'Backscatter', data: new Array(N).fill(0), tension:0.2, borderWidth:1, pointRadius:0, hidden:!showBack.checked},
]
},
options: {
animation:false,
plugins:{legend:{position:'top'}},
scales: {
x:{display:true,title:{display:true,text:'x (nm)'}},
y:{display:true,title:{display:true,text:'Relative dose (a.u.)'}}
}
}
});
function updateChart(total, pattern, forwardComp, backComp){
chart.data.datasets[0].data = Array.from(total);
chart.data.datasets[1].data = Array.from(pattern);
chart.data.datasets[2].data = Array.from(forwardComp);
chart.data.datasets[3].data = Array.from(backComp);
chart.data.datasets[1].hidden = !showPattern.checked;
chart.data.datasets[2].hidden = !showForward.checked;
chart.data.datasets[3].hidden = !showBack.checked;
chart.update('none');
}
function computeAndRender(){
const w = Number(widthSlider.value);
widthLabel.textContent = `${w} nm`;
const doseScale = Number(doseInput.value) || 1;
const sf = Number(sfSlider.value); sfLabel.textContent = sf;
const sb = Number(sbSlider.value); sbLabel.textContent = sb;
const eta = Number(etaSlider.value); etaLabel.textContent = eta;
const pattern = makePattern(w);
// forward kernel
const {kernel: kf, radius: rf} = gaussian1d(sf);
const {kernel: kb, radius: rb} = gaussian1d(sb);
const forwardComp = convolve(pattern, kf, rf).map(v=>v*(1-eta)*doseScale); const backComp = convolve(pattern, kb, rb).map(v=>v*eta*doseScale);
const total = new Float64Array(N); for(let i=0;i<N;i++) total[i]=forwardComp[i]+backComp[i];
updateChart(total, pattern.map(v=>v*doseScale), forwardComp, backComp);
}
// --- events --- [widthSlider, doseInput, sfSlider, sbSlider, etaSlider].forEach(el=>el.addEventListener('input',computeAndRender)); [showPattern, showForward, showBack].forEach(el=>el.addEventListener('change',computeAndRender)); resetBtn.addEventListener('click',()=>{
widthSlider.value=100; doseInput.value=1; sfSlider.value=5; sbSlider.value=200; etaSlider.value=0.4; computeAndRender();
});
// initial render computeAndRender(); </script> </body> </html>