Jump to content

Specific Process Knowledge/Lithography/EBeamLithography/thopesplaystuff: Difference between revisions

From LabAdviser
Thope (talk | contribs)
Created page with "<!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,..."
 
Thope (talk | contribs)
Blanked the page
Tags: Blanking Manual revert
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
<!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>
    <div class="logo" aria-hidden>
      <!-- Cute Hello-Kitty-like SVG (original, stylized cat) -->
      <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>
    </div>
    <div>
      <h1>EBL Dose Simulator — Hello Kitty Theme</h1>
      <div class="small">Simulate exposure dose including forward- and backscattered electrons (proximity effect)</div>
    </div>
  </header>


  <main class="container">
    <div class="grid">
      <div class="card">
        <div style="margin-bottom:10px">
          <label for="widthSlider">Line width: <strong id="widthLabel">100 nm</strong></label>
          <input id="widthSlider" type="range" min="10" max="400" value="100" step="1">
          <div class="small muted">Change the width of the three parallel lines. Dose profile updates live.</div>
        </div>
        <div style="margin-top:12px">
          <label for="doseInput">Incident dose (a.u.):</label>
          <input id="doseInput" type="number" value="1" step="0.1" style="width:100%" />
          <div class="small muted">This is a scale factor — relative units (a.u.).</div>
        </div>
        <hr style="margin:12px 0;border:none;border-top:1px solid #f1d7e3">
        <div>
          <label>Proximity function parameters</label>
          <div class="small">A two-Gaussian point-spread function is used: narrow forward-scatter (σ<sub>f</sub>) and broad backscatter (σ<sub>b</sub>) with weight η.</div>
          <div style="margin-top:8px">
            <label>Forward sigma (σ<sub>f</sub>, nm): <strong id="sfLabel">5</strong></label>
            <input id="sfSlider" type="range" min="1" max="30" value="5">
          </div>
          <div style="margin-top:8px">
            <label>Backscatter sigma (σ<sub>b</sub>, nm): <strong id="sbLabel">200</strong></label>
            <input id="sbSlider" type="range" min="50" max="2000" value="200">
          </div>
          <div style="margin-top:8px">
            <label>Backscatter weight (η): <strong id="etaLabel">0.4</strong></label>
            <input id="etaSlider" type="range" min="0" max="0.9" step="0.01" value="0.4">
          </div>
        </div>
        <hr style="margin:12px 0;border:none;border-top:1px solid #f1d7e3">
        <div style="display:flex;gap:8px;justify-content:space-between">
          <button id="resetBtn">Reset</button>
          <div class="small muted">Tip: drag the line-width slider to see how proximity effects blur and add dose between lines.</div>
        </div>
      </div>
      <div class="card">
        <canvas id="doseChart" height="220"></canvas>
        <div style="display:flex;gap:14px;margin-top:10px;align-items:center">
          <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>
        </div>
      </div>
    </div>
    <footer>
      <div class="muted">Model: 1D cross-section of three parallel lines. Uses a two-Gaussian proximity function: PSF(r) = (1-η)*G(σf) + η*G(σb). Units are arbitrary — this is a relative-dose visualizer, useful for intuition and teaching.</div>
    </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>

Latest revision as of 17:34, 2 September 2025