@wafertools/wafermap 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +10 -2
- package/CHANGELOG.md +366 -0
- package/README.md +1 -1
- package/dist/packages/canvas-adapter/charts/binCluster.d.ts +0 -1
- package/dist/packages/canvas-adapter/charts/boxplot.d.ts +8 -1
- package/dist/packages/canvas-adapter/charts/boxplot.js +1 -1
- package/dist/packages/canvas-adapter/charts/capability.d.ts +0 -1
- package/dist/packages/canvas-adapter/charts/correlation.d.ts +0 -1
- package/dist/packages/canvas-adapter/charts/histogram.d.ts +0 -1
- package/dist/packages/canvas-adapter/charts/histogram.js +1 -1
- package/dist/packages/canvas-adapter/charts/regionYieldDiagram.d.ts +0 -1
- package/dist/packages/canvas-adapter/charts/scatter.d.ts +6 -1
- package/dist/packages/canvas-adapter/charts/scatter.js +1 -1
- package/dist/packages/canvas-adapter/charts/trend.d.ts +7 -0
- package/dist/packages/canvas-adapter/charts/trend.js +1 -1
- package/dist/packages/canvas-adapter/hitGrid.d.ts +22 -0
- package/dist/packages/canvas-adapter/hitGrid.js +1 -0
- package/dist/packages/canvas-adapter/index.d.ts +1 -0
- package/dist/packages/canvas-adapter/index.js +1 -1
- package/dist/packages/canvas-adapter/insightsTab.d.ts +24 -2
- package/dist/packages/canvas-adapter/insightsTab.js +1 -1
- package/dist/packages/canvas-adapter/maplessSummary.d.ts +8 -1
- package/dist/packages/canvas-adapter/maplessSummary.js +1 -1
- package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
- package/dist/packages/canvas-adapter/renderWaferMap.d.ts +45 -1
- package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
- package/dist/packages/canvas-adapter/summaryPanel.d.ts +15 -5
- package/dist/packages/canvas-adapter/summaryPanel.js +3 -3
- package/dist/packages/canvas-adapter/toCanvas.js +1 -1
- package/dist/packages/canvas-adapter/toolbar.d.ts +46 -11
- package/dist/packages/canvas-adapter/toolbar.js +2 -2
- package/dist/packages/canvas-adapter/userGuideHtml.d.ts +1 -1
- package/dist/packages/canvas-adapter/userGuideHtml.js +27 -16
- package/dist/packages/canvas-adapter/version.d.ts +2 -2
- package/dist/packages/canvas-adapter/version.js +1 -1
- package/dist/packages/canvas-adapter/warnings.d.ts +25 -0
- package/dist/packages/canvas-adapter/warnings.js +1 -1
- package/dist/packages/core/dies.d.ts +11 -0
- package/dist/packages/core/dies.js +1 -1
- package/dist/packages/renderer/binColors.d.ts +80 -0
- package/dist/packages/renderer/binColors.js +1 -0
- package/dist/packages/renderer/buildView.d.ts +82 -6
- package/dist/packages/renderer/buildView.js +1 -1
- package/dist/packages/renderer/buildWaferMap.d.ts +8 -2
- package/dist/packages/renderer/buildWaferMap.js +1 -1
- package/dist/packages/renderer/colorMap.d.ts +16 -15
- package/dist/packages/renderer/colorMap.js +1 -1
- package/dist/packages/renderer/colorSchemes.d.ts +57 -25
- package/dist/packages/renderer/colorSchemes.js +1 -1
- package/dist/packages/renderer/index.d.ts +3 -1
- package/dist/packages/renderer/index.js +1 -1
- package/dist/packages/stats/analyzeWaferLot.js +1 -1
- package/dist/packages/stats/analyzeWaferMap.js +1 -1
- package/dist/packages/stats/histogram.d.ts +28 -1
- package/dist/packages/stats/histogram.js +1 -1
- package/dist/packages/stats/population.d.ts +23 -0
- package/dist/packages/stats/population.js +1 -0
- package/dist/packages/stats/renderFindingsReport.js +10 -10
- package/dist/packages/stats/renderSummaryReport.js +22 -22
- package/dist/packages/stats/yield.js +1 -1
- package/package.json +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{NO_DATA_FILL as ae}from"../../renderer/colorMap.js";import{categorical as Te}from"./palette.js";import{buildScatterData as we,buildScatterDataGrouped as Me}from"../../stats/scatter.js";import{pearsonOfPairs as ve}from"../../stats/correlation.js";import{buildFacetTable as Le}from"../../stats/facets.js";import{SPACE as T,RADIUS as ke,fontPx as j,FONT as q,CLR as H}from"../toolbar.js";import{cardShell as Ce,observeResize as Ae,makeTooltip as De,attachChartTip as Oe,makeTestSelect as $e,makeWaferSelect as Be,chartFillHeight as Pe,applyCanvasFlow as He,drawAxisUnit as We,resolveChartCanvasColors as Ee,makeAxisFormat as re,makeSeriesLegendItem as Fe,prepareCanvas as Ie}from"./chartShell.js";const c=52,Ne=16,s=16,Re=44;export function renderScatterPanel(W){const{title:ce="Test scatter",items:C,testDefs:J,binColors:de,onSaveImage:me,groups:E}=W,{card:i,body:L,controlsRow:Q}=Ce(ce,me,W.ownerDocument),F=J.filter(t=>t.testNumber!==void 0),y=!!(E&&E.length>0),V=(E??[]).map(t=>t.key),fe=new Map(V.map((t,n)=>[t,n]));let p=W.xTestNumber??F[0]?.testNumber??null,x=W.yTestNumber??F[1]?.testNumber??p,A=null;const Z=()=>A!==null?C[A]?[C[A]]:[]:C;function ee(t,n,o){const l=i.ownerDocument.createElement("label");Object.assign(l.style,{display:"inline-flex",alignItems:"center",gap:T.xs,fontSize:q.body,color:H.label});const g=i.ownerDocument.createElement("span");g.textContent=t;const m=$e(F,n,o,{maxWidth:"180px",emptyText:"No tests",ownerDocument:i.ownerDocument});return l.append(g,m),{wrap:l,select:m}}const{wrap:pe,select:ue}=ee("X:",p,t=>{p=t,$()}),{wrap:xe,select:he}=ee("Y:",x,t=>{x=t,$()});Q.append(pe,xe),!y&&C.length>1&&Q.appendChild(Be(C,A,t=>{A=t,$()},{ownerDocument:i.ownerDocument}));const D=i.ownerDocument.createElement("div");Object.assign(D.style,{color:H.warnText,background:H.warnBg,border:`1px solid ${H.warnBorder}`,borderRadius:ke.control,padding:`${T.xs} ${T.md}`,fontSize:q.body,marginBottom:T.xs,display:"none"}),i.insertBefore(D,L);function te(){const t=y?[]:Le(Z(),{facetableOnly:!0}).filter(n=>n.splittable).map(n=>n.label);t.length>0?(D.textContent=`\u26A0 Mixed ${t.join(", ")} across these points \u2014 trends here may be confounded (Simpson's paradox). Use Group by, or the Wafer picker, to narrow to a like-for-like set.`,D.style.display=""):D.style.display="none"}te();const U=i.ownerDocument.createElement("div");Object.assign(U.style,{color:H.label,fontSize:q.body,marginBottom:T.xs}),i.insertBefore(U,L);function G(){const t=y?"One point per die \xB7 coloured by group \xB7 click legend to filter":"One point per die across all wafers \xB7 coloured by hard bin \xB7 click legend to filter",n=h.size===0?f:f.filter(g=>h.has(I(g))),{r:o,n:l}=ve(n);U.textContent=o===null?`${t} \xB7 n = ${l.toLocaleString()}`:`${t} \xB7 r = ${o.toFixed(3)} \xB7 n = ${l.toLocaleString()}`}const I=t=>y?t.group??"\u2014":String(t.hbin??0),ne=t=>y?Te(fe.get(t)??0):t==="0"?ae:de?.get(Number(t))??ae,oe=t=>y?t:t==="0"?"No bin data":`Bin ${t}`,h=new Set,O=i.ownerDocument.createElement("div");Object.assign(O.style,{display:"flex",flexWrap:"wrap",gap:T.sm,marginTop:T.md,marginBottom:T.xl}),L.appendChild(O);const k=i.ownerDocument.createElement("canvas");k.style.display="block",k.style.cursor="crosshair",L.appendChild(k);const ge=De(i);let f=[],w=0,N=1,M=0,R=1;function z(t){const n=J.find(o=>o.testNumber===t);return{unit:n?.unit,limitLow:n?.limitLow,limitHigh:n?.limitHigh}}function be(){const t=L.clientWidth,n=Math.max(200,Math.min(400,t*.65)),o=Pe(i,L,k,n);return{w:t,h:o,plotW:Math.max(10,t-c-Ne),plotH:Math.max(10,o-s-Re)}}const X=new Map;function ie(){for(const[t,n]of X){const o=h.has(t);n.setState({selected:o,dimmed:h.size>0&&!o})}}function le(t){O.innerHTML="",X.clear(),h.clear();for(const n of t){const o=Fe(oe(n),ne(n),i.ownerDocument),l=o.el;l.dataset.cat=n,X.set(n,o),Oe(l,i,ge,`${oe(n)} \u2014 click to filter`),l.addEventListener("click",()=>{h.has(n)?h.delete(n):h.add(n),ie(),G(),_()}),O.appendChild(l)}ie()}function _(){He(k,O);const t=Ee(i),n=N-w,o=R-M,{w:l,h:g,plotW:m,plotH:d}=be(),B=Ie(k,i,l,g);if(!B)return;const{ctx:e}=B;if(f.length===0){e.font=`${j()}px system-ui, sans-serif`,e.fillStyle=t.textMuted,e.textAlign="center",e.textBaseline="middle",e.fillText("No data \u2014 select two parametric tests with values.",l/2,g/2);return}const b=4,Y=re(Math.max(Math.abs(w),Math.abs(N)),p!==null?z(p).unit:void 0),K=re(Math.max(Math.abs(M),Math.abs(R)),x!==null?z(x).unit:void 0);e.font=`${j(-1)}px system-ui, sans-serif`,e.strokeStyle=t.border,e.lineWidth=.5,e.fillStyle=t.textMuted;for(let a=0;a<=b;a++){const S=w+n*a/b,r=c+a/b*m;e.beginPath(),e.moveTo(r,s),e.lineTo(r,s+d),e.stroke(),e.textAlign="center",e.textBaseline="top",e.fillText(Y.tick(S),r,s+d+4);const v=M+o*a/b,u=s+(1-a/b)*d;e.beginPath(),e.moveTo(c,u),e.lineTo(c+m,u),e.stroke(),e.textAlign="right",e.textBaseline="middle",e.fillText(K.tick(v),c-4,u)}Y.unitLabel&&We(e,Y.unitLabel,c+m/2,s+d+24,t.textMuted),K.unitLabel&&(e.save(),e.font=`${j(-1)}px system-ui, sans-serif`,e.fillStyle=t.textMuted,e.textAlign="center",e.textBaseline="middle",e.translate(6,s+d/2),e.rotate(-Math.PI/2),e.fillText(`(${K.unitLabel})`,0,0),e.restore());const P=h.size===0?f:f.filter(a=>h.has(I(a))),se=P.length>5e3?Math.ceil(P.length/5e3):1;e.globalAlpha=Math.max(.15,Math.min(.7,200/(P.length/se)));for(let a=0;a<P.length;a+=se){const S=P[a],r=c+(S.x-w)/n*m,v=s+(1-(S.y-M)/o)*d;e.beginPath(),e.arc(r,v,2.5,0,Math.PI*2),e.fillStyle=ne(I(S)),e.fill()}if(e.globalAlpha=1,p!==null&&x!==null){const a=z(p),S=z(x);e.strokeStyle=t.textMuted,e.fillStyle=t.textMuted,e.lineWidth=1,e.setLineDash([4,3]),e.font=`${j(-1)}px system-ui, sans-serif`,e.textBaseline="top";for(const[r,v]of[[a.limitLow,"LSL"],[a.limitHigh,"USL"]]){if(r===void 0||r<w||r>N)continue;const u=c+(r-w)/n*m;e.beginPath(),e.moveTo(u,s),e.lineTo(u,s+d),e.stroke(),e.textAlign="left",e.fillText(v,u+2,s+2)}for(const[r,v]of[[S.limitLow,"LSL"],[S.limitHigh,"USL"]]){if(r===void 0||r<M||r>R)continue;const u=s+(1-(r-M)/o)*d;e.beginPath(),e.moveTo(c,u),e.lineTo(c+m,u),e.stroke(),e.textAlign="left",e.fillText(v,c+3,u+2)}e.setLineDash([])}e.strokeStyle=t.border,e.lineWidth=1,e.beginPath(),e.moveTo(c,s),e.lineTo(c,s+d),e.moveTo(c,s+d),e.lineTo(c+m,s+d),e.stroke()}function $(){if(te(),F.length<2||p===null||x===null){f=[],le([]),G(),_();return}f=y?Me(E,p,x):we(Z(),p,x);let t;if(y){const n=new Set(f.map(I));t=V.filter(o=>n.has(o))}else t=Array.from(new Set(f.map(n=>n.hbin??0))).sort((n,o)=>n-o).map(String);if(le(t),G(),f.length>0){const n=f.map(b=>b.x),o=f.map(b=>b.y),l=Math.min(...n),g=Math.max(...n),m=Math.min(...o),d=Math.max(...o),B=(g-l)*.05||1,e=(d-m)*.05||1;w=l-B,N=g+B,M=m-e,R=d+e}_()}const ye=Ae(i,()=>_());$();function Se(t,n){p=t,x=n,ue.value=String(t),he.value=String(n),$()}return{card:i,setXY:Se,destroy:()=>ye.disconnect()}}
|
|
@@ -9,6 +9,13 @@ export interface TrendPanelOptions {
|
|
|
9
9
|
onSaveImage?: SaveImageHandler;
|
|
10
10
|
/** Click a point to open that wafer's map on this test. */
|
|
11
11
|
onOpen?: (key: number, testNumber: number) => void;
|
|
12
|
+
/**
|
|
13
|
+
* What the dashed reference line is, as a noun phrase — "lot mean" when the
|
|
14
|
+
* items are one lot, else "mean of all wafers" (see stats/population.ts).
|
|
15
|
+
* The panel sees no wafer metadata, so the host names it. Default
|
|
16
|
+
* "mean of all wafers", which is true of any set.
|
|
17
|
+
*/
|
|
18
|
+
centreLabel?: string;
|
|
12
19
|
/** Initial axis toggles, shared with the sibling distribution panels. */
|
|
13
20
|
axisPrefs?: AxisPrefs;
|
|
14
21
|
/** Fired when the user changes an axis toggle here, so siblings can follow. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildTestTrendData as
|
|
1
|
+
import{buildTestTrendData as de,trendCentre as fe}from"../../stats/trend.js";import{isParametricTest as ue}from"../../renderer/buildWaferMap.js";import{fmt as D}from"../../renderer/fmt.js";import{SPACE as ie,fontPx as he,FONT as pe,CLR as ge}from"../toolbar.js";import{QUANTITY as _}from"./palette.js";import{cardShell as xe,observeResize as be,makeTooltip as ye,positionChartTooltip as ve,makeLinkedTestSelect as Te,makeLinkedAxisPrefs as Le,renderEmptyState as z,growCardToFitContent as we,chartFillHeight as ke,PADDING as X,resolveAxisRange as Ce,shouldIncludeLimitsByDefault as Se,drawOffAxisLimits as Ae,prepareCanvas as Pe}from"./chartShell.js";const oe=220,Ne=56,De=34,Me=3.5;export function renderTrendPanel(g){const{items:j,testDefs:le,onSaveImage:se,onOpen:C,centreLabel:G="mean of all wafers"}=g,re=g.title??"Wafer-to-wafer trend",{card:l,body:f,controlsRow:U}=xe(re,se,g.ownerDocument);l.style.alignSelf="start";const M=le.filter(o=>o.testNumber!==void 0&&ue(o));let h=g.selectedTestNumber??M[0]?.testNumber??null,I=0;const Y=Te(M,h,o=>{h=o,S(),g.onTestChange?.(o)},{maxWidth:"240px",emptyText:"No parametric tests",ownerDocument:l.ownerDocument});U.appendChild(Y.el);const O=l.ownerDocument.createElement("span");Object.assign(O.style,{display:"inline-flex",gap:ie.lg,alignItems:"center"}),U.appendChild(O);const $=Le(O,g.axisPrefs,o=>{g.onAxisPrefsChange?.(o),S()},l.ownerDocument),T=l.ownerDocument.createElement("div");Object.assign(T.style,{color:ge.label,fontSize:pe.body,marginBottom:ie.sm}),l.insertBefore(T,f);const L=ye(l);let H=null,n=[];function ae(o){return M.find(B=>B.testNumber===o)}function S(){const{includeLimits:o,clipOutliers:B}=$.get();if(f.innerHTML="",H?.disconnect(),H=null,M.length===0||h===null){T.textContent="",z(f,"No parametric test data available for a trend.");return}if(j.length<2){T.textContent="",z(f,"A wafer-to-wafer trend needs at least two wafers.");return}if(n=de(j,h),!n.some(r=>r.count>0)){T.textContent="",z(f,"No values recorded for this test.");return}const s=ae(h),x=fe(n),Q=()=>{T.textContent=`Point = wafer mean, whisker = \xB11\u03C3, dashed = ${G} \xB7 wafers in slot order`+(C?" \xB7 click a point to open that wafer":"")+(I?` \xB7 axis clipped, ${I} outside`:"")};Q();const u=l.ownerDocument.createElement("canvas");u.style.display="block",f.appendChild(u);let A=null;const q=()=>{const r=Math.max(1,f.clientWidth),d=Math.max(oe,ke(l,f,u,oe)),i=Pe(u,l,r,d);if(!i)return;const{ctx:e,theme:b}=i;let P=1/0,N=-1/0;const K=[];for(const t of n)!t.count||!Number.isFinite(t.mean)||(P=Math.min(P,t.mean-t.stddev),N=Math.max(N,t.mean+t.stddev),K.push(t.mean-t.stddev,t.mean+t.stddev));if(!Number.isFinite(P)||!Number.isFinite(N))return;const V=o??Se(P,N,s?.limitLow,s?.limitHigh);$.sync(V,s?.limitLow!==void 0||s?.limitHigh!==void 0);const E=Ce({dataMin:P,dataMax:N,limitLow:s?.limitLow,limitHigh:s?.limitHigh,includeLimits:V,clipOutliers:B,values:K});I=E.clippedCount,Q();let p=E.lo,w=E.hi;const Z=(w-p)*.08;p-=Z,w+=Z;const a=X+Ne;e.font=`${he(-1)}px system-ui, sans-serif`;const ee=t=>t.length>8?`${t.slice(0,7)}\u2026`:t,ce=n.length?Math.ceil(Math.max(e.measureText(ee(n[0].label)).width,e.measureText(ee(n[n.length-1].label)).width)/2):0,y=r-X-ce,F=X,k=d-De,v=t=>k-(t-p)/(w-p)*(k-F),te=n.length>1?(y-a)/(n.length-1):0;A={left:a,step:te};const R=t=>n.length>1?a+t*te:(a+y)/2;e.strokeStyle=b.border,e.lineWidth=1,e.beginPath(),e.moveTo(a,F),e.lineTo(a,k),e.lineTo(y,k),e.stroke(),e.fillStyle=b.text,e.textAlign="right",e.textBaseline="middle";for(const t of[0,.5,1]){const c=p+(w-p)*t;e.fillText(D(c,s?.unit),a-6,v(c))}Ae(e,E.offAxis,{left:a,right:y,top:F,bottom:k},"vertical",b.limitLine,t=>D(t,s?.unit));for(const[t,c]of[[s?.limitLow,"LSL"],[s?.limitHigh,"USL"]]){if(t===void 0||t<p||t>w)continue;const m=v(t);e.save(),e.strokeStyle=b.limitLine,e.globalAlpha=.7,e.setLineDash([4,3]),e.beginPath(),e.moveTo(a,m),e.lineTo(y,m),e.stroke(),e.restore(),e.save(),e.fillStyle=b.limitLine,e.textAlign="left",e.fillText(c,a+3,m-6),e.restore()}if(x!==null&&x>=p&&x<=w){const t=v(x);e.save(),e.strokeStyle=b.text,e.globalAlpha=.5,e.setLineDash([3,3]),e.beginPath(),e.moveTo(a,t),e.lineTo(y,t),e.stroke(),e.restore()}e.strokeStyle=_,e.lineWidth=1.5,e.beginPath();let W=!1;n.forEach((t,c)=>{if(!t.count||!Number.isFinite(t.mean)){W=!1;return}const m=R(c),ne=v(t.mean);W?e.lineTo(m,ne):e.moveTo(m,ne),W=!0}),e.stroke(),n.forEach((t,c)=>{if(!t.count||!Number.isFinite(t.mean))return;const m=R(c);t.stddev>0&&(e.save(),e.strokeStyle=_,e.globalAlpha=.55,e.lineWidth=1,e.beginPath(),e.moveTo(m,v(t.mean-t.stddev)),e.lineTo(m,v(t.mean+t.stddev)),e.stroke(),e.restore()),e.fillStyle=_,e.beginPath(),e.arc(m,v(t.mean),Me,0,Math.PI*2),e.fill()}),e.fillStyle=b.text,e.textBaseline="top",e.textAlign="center";const me=Math.max(1,Math.ceil(n.length*42/Math.max(1,y-a)));n.forEach((t,c)=>{if(c%me!==0&&c!==n.length-1)return;const m=t.label.length>8?`${t.label.slice(0,7)}\u2026`:t.label;e.fillText(m,R(c),k+6)}),we(l,f,d)},J=r=>{if(!A||A.step<=0)return-1;const d=u.getBoundingClientRect(),i=Math.round((r.clientX-d.left-A.left)/A.step);return i>=0&&i<n.length&&n[i].count>0?i:-1};u.addEventListener("mousemove",r=>{const d=J(r);if(d<0){L.style.display="none",u.style.cursor="default";return}const i=n[d];u.style.cursor=C&&i.key!==void 0?"pointer":"default",L.innerHTML=`<strong>${i.label}</strong><br>mean ${D(i.mean,s?.unit)} \xB7 \u03C3 ${D(i.stddev,s?.unit)}<br>n = ${i.count.toLocaleString()}`+(x!==null?`<br>\u0394 vs ${G} ${i.mean-x>=0?"+":""}${D(i.mean-x,s?.unit)}`:"")+(C&&i.key!==void 0?"<br><em>click to open this wafer</em>":""),L.style.display="block",ve(L,l,r.clientX,r.clientY)}),u.addEventListener("mouseleave",()=>{L.style.display="none"}),u.addEventListener("click",r=>{const d=J(r);if(d<0||!C)return;const i=n[d];i.key!==void 0&&h!==null&&C(i.key,h)}),q(),H=be(f,q)}return S(),{card:l,destroy:()=>{H?.disconnect(),L.remove(),l.remove()},setTest:o=>{Y.set(o)&&(h=o,S())},setAxisPrefs:o=>{$.set(o)&&S()}}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dimensions of the uniform grid toCanvas indexes die centres into for O(1)
|
|
3
|
+
* hit-testing. Cells are nominally `cellW`×`cellH` (1.5 dies across), but the
|
|
4
|
+
* grid only accelerates hit-testing, so its size must never depend on the
|
|
5
|
+
* geometry being sane. A die size wrong by orders of magnitude — a misread
|
|
6
|
+
* WCR record gave dies ~1e-8 mm wide against a normal die-index span — once
|
|
7
|
+
* asked for more cells than an array can hold: every render threw `Invalid
|
|
8
|
+
* array length`, the map never appeared, and a host waiting for it stayed busy
|
|
9
|
+
* forever.
|
|
10
|
+
*
|
|
11
|
+
* So: a non-finite or non-positive cell size falls back to the span, and cells
|
|
12
|
+
* grow until the grid holds at most max(4096, 4 × pointCount) of them. A
|
|
13
|
+
* coarser grid only means a hit test inspects a few more dies; correctness is
|
|
14
|
+
* unaffected, because the caller clamps every die into range.
|
|
15
|
+
*/
|
|
16
|
+
export declare function hitGridDims(spanX: number, spanY: number, cellW: number, cellH: number, pointCount: number): {
|
|
17
|
+
cellW: number;
|
|
18
|
+
cellH: number;
|
|
19
|
+
nCols: number;
|
|
20
|
+
nRows: number;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=hitGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const I=4096;export function hitGridDims(h,m,n,a,u){const r=Number.isFinite(h)&&h>0?h:0,c=Number.isFinite(m)&&m>0?m:0;let e=Number.isFinite(n)&&n>0?n:Math.max(r,1),s=Number.isFinite(a)&&a>0?a:Math.max(c,1);const o=Math.max(4096,u*4),M=()=>[Math.max(1,Math.ceil(r/e)+1),Math.max(1,Math.ceil(c/s)+1)];let[t,i]=M();if(t*i>o){const x=Math.sqrt(t*i/o);for(e*=x,s*=x,[t,i]=M();t*i>o;)e*=1.1,s*=1.1,[t,i]=M()}return{cellW:e,cellH:s,nCols:t,nRows:i}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{toCanvas}from"./toCanvas.js";export{renderWaferMap}from"./renderWaferMap.js";export{renderWaferGallery}from"./renderWaferGallery.js";export{buildDieListSection}from"./dieList.js";export{collectWarnings,severityOf}from"./warnings.js";export{setDetachWindowOpener}from"./toolbar.js";export{openWaferMapGuide}from"./toolbar.js";export{ICONS}from"./icons.js";export{openReportModal}from"./toolbar.js";
|
|
1
|
+
export{WMAP_VERSION,WMAP_BUILD_TIME}from"./version.js";export{toCanvas}from"./toCanvas.js";export{renderWaferMap}from"./renderWaferMap.js";export{renderWaferGallery}from"./renderWaferGallery.js";export{buildDieListSection}from"./dieList.js";export{collectWarnings,severityOf}from"./warnings.js";export{setDetachWindowOpener}from"./toolbar.js";export{openWaferMapGuide}from"./toolbar.js";export{ICONS}from"./icons.js";export{openReportModal}from"./toolbar.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LotStatsSummary } from '../stats/types.js';
|
|
2
2
|
import type { WaferMapDisplayItem } from './renderWaferGallery.js';
|
|
3
|
+
import type { BinColors } from '../renderer/binColors.js';
|
|
3
4
|
import { type SaveImageHandler, type SaveTextHandler } from './toolbar.js';
|
|
4
5
|
export type InsightsView = 'overview' | 'distributions' | 'correlation';
|
|
5
6
|
/** Public option shape for `RenderOptions.insights`/`GalleryOptions.insights`. */
|
|
@@ -31,8 +32,12 @@ export interface InsightsTabDeps {
|
|
|
31
32
|
getItems: () => Array<WaferMapDisplayItem | null>;
|
|
32
33
|
/** Precomputed lot-level yield, when the host has one — reused directly instead of recomputing (see stats/yield.ts). Omit when there is no lot (e.g. a single wafer). */
|
|
33
34
|
getLotStats?: () => LotStatsSummary | undefined;
|
|
34
|
-
/**
|
|
35
|
-
|
|
35
|
+
/**
|
|
36
|
+
* The host map's resolved bin colours (`View.binColors`, or the gallery's
|
|
37
|
+
* gallery-wide assignment) — read fresh each render so a live palette change is
|
|
38
|
+
* picked up, and so a bin is the same colour in a chart as on the map.
|
|
39
|
+
*/
|
|
40
|
+
getBinColors: () => BinColors;
|
|
36
41
|
passBins: number[];
|
|
37
42
|
/** Read fresh each render — used by the Overview tab's ring/quadrant regional yield cards. Default 4. */
|
|
38
43
|
getRingCount?: () => number;
|
|
@@ -48,6 +53,23 @@ export interface InsightsTabDeps {
|
|
|
48
53
|
* same test instead of hard-bin mode.
|
|
49
54
|
*/
|
|
50
55
|
openWafer?: (waferIndex: number, label: string, testNumber?: number) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Shows `testNumber` on the host's own map, in test-value mode, and leaves
|
|
58
|
+
* Insights — the single-wafer counterpart to `openWafer`.
|
|
59
|
+
*
|
|
60
|
+
* A single-wafer host (`renderWaferMap`) rightly passes no `openWafer`: the
|
|
61
|
+
* only wafer there is to open is the one already on screen, and opening it
|
|
62
|
+
* again in a modal would be two maps of one wafer. But a boxplot leaf click
|
|
63
|
+
* carries a second, independent payload — the selected test — and *that*
|
|
64
|
+
* half is as useful with one wafer as with twenty; without this the click was
|
|
65
|
+
* simply inert, and the only route from "this test looks wrong" to seeing it
|
|
66
|
+
* on the map was to leave Insights and find the test again in the toolbar's
|
|
67
|
+
* plot-mode picker.
|
|
68
|
+
*
|
|
69
|
+
* Ignored when `openWafer` is set (a gallery opens the wafer, which already
|
|
70
|
+
* lands on this test), and only consulted for a leaf row of the sole item.
|
|
71
|
+
*/
|
|
72
|
+
focusTest?: (testNumber: number) => void;
|
|
51
73
|
/** Default sub-tab shown on first render. Default 'overview'. */
|
|
52
74
|
defaultView?: InsightsView;
|
|
53
75
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildFacetTable as we,facetValueOf as Te,FACET_NONE_VALUE as ve}from"../stats/facets.js";import{mergeTestDefs as ke}from"../stats/mergeTestDefs.js";import{isParametricTest as $e}from"../renderer/buildWaferMap.js";import{getColorScheme as Be}from"../renderer/colorSchemes.js";import{LEADING as De,ALPHA as Ee,SPACE as w,EDGE_GUTTER as K,FONT as H,CLR as B,RADIUS as Oe,SHADOW as Ie,controlStyle as Le,wireControlHover as ee,wireTooltip as Pe}from"./toolbar.js";import{ICONS as Re}from"./icons.js";import{renderCapabilityPanel as Ae}from"./charts/capability.js";import{renderBoxplotPanel as je}from"./charts/boxplot.js";import{renderTrendPanel as We}from"./charts/trend.js";import{renderHistogramPanel as Ge}from"./charts/histogram.js";import{renderCorrelationPanel as He}from"./charts/correlation.js";import{renderScatterPanel as Ye}from"./charts/scatter.js";import{renderBarPanel as te}from"./charts/barPanel.js";import{renderBinClusterPanel as Fe}from"./charts/binCluster.js";import{renderTestPassRatePanel as Me}from"./charts/testPassRate.js";import{QUANTITY as Ne}from"./charts/palette.js";import{cardFrameStyle as Ve,makeChartGridWrap as X,makeLabeledSelect as ze,makeLinkedGroupSelect as Ue}from"./charts/chartShell.js";import{buildYieldData as N,buildYieldDataCombined as ne}from"../stats/yield.js";import{buildBinParetoData as _e}from"../stats/binPareto.js";import{buildLotTestSection as qe,buildLotFunctionalSection as Qe,buildMetadataStripBox as Ke}from"./summaryPanel.js";import{buildRegionYieldData as ae,buildRingRegions as Xe,buildQuadrantRegions as Je}from"../stats/regions.js";import{renderRegionYieldDiagram as oe}from"./charts/regionYieldDiagram.js";const Ze=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}];export function createInsightsTab(D){const{getItems:re,getLotStats:ie,getColorSchemeName:E,passBins:T,getRingCount:se,onSaveImage:v,onSaveText:V,openWafer:Y}=D,le=D.showMetadataStrip??!0,j=D.contentInset??K,d=D.ownerDocument??document,P=d.createElement("div");Object.assign(P.style,{display:"none",flexDirection:"column",width:"100%",paddingTop:"0"});const de=K,R=d.createElement("div");Object.assign(R.style,{paddingLeft:de});const $=d.createElement("div");Object.assign($.style,{display:"flex",gap:w.xs,alignItems:"center",background:B.menuBg,border:`1px solid ${B.menuBorder}`,borderRadius:Oe.container,boxShadow:Ie.panel,padding:`0 ${w.lg}`,marginBottom:w.lg,marginLeft:j,marginRight:j}),$.setAttribute("role","tablist"),$.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const a=Array.from($.querySelectorAll('[role="tab"]')),r=a.indexOf(d.activeElement);if(r===-1)return;e.preventDefault();const c=a[(r+(e.key==="ArrowRight"?1:-1)+a.length)%a.length];c.focus(),c.click()});const W=d.createElement("div");Object.assign(W.style,{display:"flex",flexDirection:"column",gap:w.lg,marginTop:"0",paddingLeft:j,paddingRight:j}),P.appendChild(R),P.appendChild($),P.appendChild(W);let G=D.defaultView??"overview",A,I=null,O=null;const z=e=>{O!==e&&(O=e,M())};let F=[];function U(e,a,r){Y?.(e,a,r)}function ce(){return re().map((e,a)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:e.label??String(e.wafer.metadata?.waferId??""),waferIndex:a,statsSummary:e.statsSummary,testDefs:e.testDefs}).filter(e=>e!=null)}function J(e,a){Object.assign(e.style,{background:"none",border:"none",borderBottom:a?`2px solid ${B.iconActive}`:"2px solid transparent",color:a?B.iconActive:B.label,fontWeight:a?"700":"500",fontSize:H.body,padding:`${w.sm} ${K} ${w.md}`,cursor:"pointer",marginBottom:"-1px"})}function pe(e,a){const r=d.createElement("button");r.type="button",r.textContent=a;const c=e===G;return J(r,c),r.dataset.on=c?"true":"false",ee(r,"bare"),r.dataset.wmapInsightsTab=e,r.setAttribute("role","tab"),r.setAttribute("aria-selected",c?"true":"false"),r.tabIndex=c?0:-1,r.addEventListener("click",()=>{G!==e&&(G=e,M())}),r}function ue(e){const a=d.createElement("button");return a.type="button",a.textContent=`\u2039 ${e.label}`,J(a,!1),a.dataset.wmapInsightsBack="1",a.addEventListener("click",e.onBack),a}function me(e,a,r,c=!0){const s=X(d),u=Be(E());let h="label";const m=r??"group",f=T.length===1?`bin ${T[0]}`:`bins ${T.join(", ")}`,i=ie?.(),b=new Map(i?.lotYieldSeries.map(l=>[l.waferIndex,l.yieldPercent])),y=l=>({...l,label:l.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:b.get(l.waferIndex),key:l.waferIndex}),g=e.map(y),p=a?.map(l=>({key:l.key,items:l.items.map(y)})),t=()=>p?ne(p,T,h):N(g,T,h),S={title:a?`Yield by ${m} (pass: ${f})`:`Yield by wafer (pass: ${f})`,data:t(),selfControl:{current:h,options:[["yield","Sort: yield"],["label",a?`Sort: ${m}`:"Sort: wafer ID"]],onChange:l=>(h=l,{data:t()})},barColor:()=>Ne,valueLabel:l=>`${l.percent.toFixed(1)}%`,reference:l=>{if(l.length<3)return null;const k=l.map(Q=>Q.percent).sort((Q,xe)=>Q-xe),L=k.length%2?k[(k.length-1)/2]:(k[k.length/2-1]+k[k.length/2])/2;return{value:L,label:`median ${L.toFixed(1)}%`}},drill:p?{onOpenGroup:l=>{const k=p.find(L=>L.key===l.label)?.items??[];return{data:N(k,T,h),title:`Yield by wafer \u2014 ${m}: ${l.label} (pass: ${f})`}},onBack:()=>({data:t(),title:`Yield by ${m} (pass: ${f})`}),groupLabelText:m}:void 0,onOpen:Y?l=>{typeof l.key=="number"&&U(l.key,`Wafer ${l.label}`)}:void 0,ownerDocument:d};let C=null;if(c&&(C=te(S,v),C.card.style.minHeight="360px",s.appendChild(C.card)),a){const l=Fe({title:"Hard bin pareto",groups:a.map(k=>({key:k.key,items:k.items.map(L=>({dies:L.dies,hardBinCounts:L.statsSummary?.stats.hardBinCounts,softBinCounts:L.statsSummary?.stats.softBinCounts}))})),colorScheme:E(),onSaveImage:v,ownerDocument:d});return l.card.style.minHeight="360px",s.appendChild(l.card),{card:s,destroy:()=>{C?.destroy(),l.destroy()}}}let n="hbin";const o=u.forBin,x=e.map(l=>({dies:l.dies,hardBinCounts:l.statsSummary?.stats.hardBinCounts,softBinCounts:l.statsSummary?.stats.softBinCounts})),Z=()=>_e(x,n),Se={title:"Hard bin pareto",data:Z(),selfControl:{current:n,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:l=>(n=l,{data:Z(),title:`${n==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:l=>o(l.binCode??0),ownerDocument:d},q=te(Se,v);return q.card.style.minHeight="360px",s.appendChild(q.card),{card:s,destroy:()=>{C?.destroy(),q.destroy()}}}function _(){const e=d.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{...Ve(),display:"flex",flexDirection:"column",gap:w.lg,minWidth:"0"}),e}function fe(e){if(R.innerHTML="",R.style.marginBottom="0",!le)return;const a=Ke(e.map(r=>({metadata:r.metadata})),void 0,{facetableOnly:!1});a&&(a.style.marginBottom="0",R.appendChild(a),R.style.marginBottom=w.xs)}function be(e,a,r,c){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const s=e.map(o=>o.wafer),u=e.map(o=>o.dies),h=e.flatMap(o=>o.dies),m=e.map(o=>o.statsSummary),f=m.every(o=>o!==void 0)?m:void 0,i=se?.()??4,b=[],y=[],p=Me({groups:(c??[{key:"",items:e}]).map(o=>({key:o.key,items:o.items.map(x=>({dies:x.dies,testSpecYield:x.statsSummary?.stats.testSpecYield,functionalYield:x.statsSummary?.stats.functionalYield}))})),testDefs:r,onSaveImage:v,ownerDocument:d});p.card.style.minHeight="300px",b.push(p.card),y.push(p.destroy);const t=ae(u,s,i,T,Xe);if(t.length){const o=oe({title:"Ring yield",mode:"ring",rows:t,colorScheme:E(),onSaveImage:v,ownerDocument:d});b.push(o.card),y.push(o.destroy)}const S=ae(u,s,i,T,Je);if(S.length){const o=oe({title:"Quadrant yield",mode:"quadrant",rows:S,colorScheme:E(),onSaveImage:v,ownerDocument:d});b.push(o.card),y.push(o.destroy)}let C=null;if(a.length){const o=qe(h,a,void 0,f,V,u.map(x=>({dies:x})),void 0,"full");if(o){const x=_();x.appendChild(o),C=x}}let n=null;if(r.length){const o=Qe(h,r,f,V);if(o){const x=_();x.appendChild(o),n=x}}return{elements:b,testValuesCard:C,functionalCard:n,destroy:()=>{for(const o of y)o()}}}function ge(e){const a=T.length===1?`bin ${T[0]}`:`bins ${T.join(", ")}`,r=e.length===1,c=e[0],s=_();Object.assign(s.style,{flexDirection:"row",flexWrap:"wrap",gap:w.md});const u=i=>{const b=i.lastElementChild;return b&&Object.assign(b.style,{borderRight:"none",paddingRight:"0",marginRight:"0"}),i};function h(i,b,y){const g=d.createElement("div");Object.assign(g.style,{display:"flex",alignItems:"baseline",gap:w.sm,paddingRight:w.xxl,marginRight:w.md,borderRight:`1px solid ${B.menuBorder}`});const p=d.createElement("div");p.textContent=i,Object.assign(p.style,{fontSize:H.heading,fontWeight:"700",color:B.value,lineHeight:De.tight});const t=d.createElement("div");if(t.textContent=b,Object.assign(t.style,{fontSize:H.body,color:B.label}),g.append(p,t),y){const S=d.createElement("div");S.textContent=y,Object.assign(S.style,{fontSize:H.meta,color:B.label,opacity:Ee.muted}),g.appendChild(S)}return g}if(r){const i=N([{...c,key:c.waferIndex}],T)[0]?.percent;return i!==void 0&&s.appendChild(h(`${i.toFixed(1)}%`,`Yield \xB7 pass: ${a}`)),s.appendChild(h(String(c.dies.length),"Total dies")),u(s)}s.appendChild(h(String(e.length),"Wafers"));const m=N(e.map(i=>({...i,key:i.waferIndex})),T).map(i=>i.percent).filter(i=>Number.isFinite(i));if(m.length){const i=m.reduce((g,p)=>g+p,0)/m.length,b=ne([{key:"all",items:e.map(g=>({...g,key:g.waferIndex}))}],T)[0]?.percent,y=b!==void 0&&b.toFixed(1)!==i.toFixed(1);s.appendChild(h(`${i.toFixed(1)}%`,`Mean per-wafer yield \xB7 pass: ${a}`,y?`${b.toFixed(1)}% by dies`:void 0))}const f=e.map(i=>i.statsSummary);if(f.every(i=>i!==void 0)){const i=f.reduce((y,g)=>y+g.stats.analyzedDies,0),b=f.reduce((y,g)=>y+g.stats.excludedDies,0);s.appendChild(h(i.toLocaleString(),"Dies analysed",b?`${b.toLocaleString()} excluded`:void 0))}else s.appendChild(h(e.reduce((i,b)=>i+b.dies.length,0).toLocaleString(),"Total dies"));return u(s)}function he(e,a,r,c,s){const u=d.createElement("div");Object.assign(u.style,{display:"flex",flexDirection:"column",gap:w.lg});const h=e.length===1&&!c;e.length&&!c&&u.appendChild(ge(e));const m=me(e,c,s,!h);u.appendChild(m.card);const f=be(e,a,r,c);for(const i of f.elements)m.card.appendChild(i);return f.testValuesCard&&u.appendChild(f.testValuesCard),f.functionalCard&&u.appendChild(f.functionalCard),{card:u,destroy:()=>{m.destroy(),f.destroy()}}}function ye(e,a,r,c){const s=X(d);let u={includeLimits:void 0,clipOutliers:!1};const h=n=>{u=n;for(const o of[g,p,t])o!==m&&o?.setAxisPrefs(n)};let m=null;const f=n=>o=>{m=n(),h(o),m=null},i=n=>({...n,testStats:n.statsSummary?.stats.perTestStats}),b=e.map(i),y=r?.map(n=>({key:n.key,items:n.items.map(i)})),g=je({title:"Test value distribution",axisPrefs:u,onAxisPrefsChange:f(()=>g),onTestChange:n=>S(n),selectedTestNumber:I??void 0,items:b,testDefs:a,groups:y,groupLabelText:c,colorScheme:E(),onSaveImage:v,onGroupChange:n=>z(n),onOpen:Y?(n,o)=>U(n,`Wafer ${e.find(x=>x.waferIndex===n)?.label??n}`,o):void 0,ownerDocument:d}),p=Ge({title:"Value histogram",axisPrefs:u,onAxisPrefsChange:f(()=>p),onTestChange:n=>S(n),selectedTestNumber:I??void 0,items:e,testDefs:a,groups:r,onGroupChange:n=>z(n),colorScheme:E(),onSaveImage:v,ownerDocument:d}),t=We({title:"Wafer-to-wafer trend",axisPrefs:u,onAxisPrefsChange:f(()=>t),onTestChange:n=>S(n),selectedTestNumber:I??void 0,items:e.map(n=>({label:n.label,key:n.waferIndex,dies:n.dies,testStats:n.statsSummary?.stats.perTestStats})),testDefs:a,onSaveImage:v,onOpen:Y?(n,o)=>U(n,`Wafer ${e.find(x=>x.waferIndex===n)?.label??n}`,o):void 0,ownerDocument:d}),S=n=>{I=n,g.setTest(n),p.setTest(n),t.setTest(n),C.setTest(n)},C=Ae({title:"Process capability",items:e,testDefs:a,colorScheme:E(),onSaveImage:v,selectedTestNumber:I??void 0,onSelectTest:n=>S(n),ownerDocument:d});return s.append(C.card,g.card,p.card,t.card),{card:s,destroy:()=>{C.destroy(),g.destroy(),p.destroy(),t.destroy()}}}function Ce(e,a,r){const c=X(d),s=Ye({title:"Test scatter",items:e,testDefs:a,groups:r,colorScheme:E(),onSaveImage:v,ownerDocument:d}),u=He({title:"Test correlation matrix",items:e,testDefs:a,colorScheme:E(),onSaveImage:v,onSaveText:V,onSelectPair:(h,m)=>s.setXY(h,m),ownerDocument:d});return c.append(u.card,s.card),{card:c,destroy:()=>{u.destroy(),s.destroy()}}}function M(){for(const t of F)t.destroy();F=[],W.innerHTML="",$.innerHTML="",D.backTab&&$.appendChild(ue(D.backTab));for(const t of Ze)$.appendChild(pe(t.key,t.label));const e=ce();fe(e);const a=we(e,{facetableOnly:!0}).filter(t=>t.splittable),r=d.createElement("div");Object.assign(r.style,{display:"flex",gap:w.md,alignItems:"center",marginLeft:w.xxl,paddingBottom:w.xs});let c;a.length>0?(r.appendChild(ze("Group by:",[{value:"",label:"None"},...a.map(t=>({value:t.key,label:`${t.label} (${t.values.length})`}))],A??"",t=>{A=t||void 0,O=null,M()},{hook:"group-by",ownerDocument:d})),c=a.find(t=>t.key===A)?.label):A=void 0;let s;if(A){const t=new Map,S=[];for(const C of e){const n=Te(C.metadata,A)??ve;t.has(n)||(t.set(n,[]),S.push(n)),t.get(n).push(C)}s=S.map(C=>({key:C,items:t.get(C)}))}O!==null&&!s?.some(t=>t.key===O)&&(O=null),s&&s.length>0&&r.appendChild(Ue(s.map(t=>t.key),"Show:",O,t=>z(t),{ownerDocument:d}).el);let u=null;if(D.onOpenGuide){const t=d.createElement("button");t.type="button",t.innerHTML=Re.help,t.setAttribute("aria-label","User guide"),Object.assign(t.style,{...Le("bare"),display:"inline-flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",flexShrink:"0"}),ee(t,"bare"),Pe(t,"User guide"),t.addEventListener("click",()=>D.onOpenGuide()),Object.assign(t.style,{marginLeft:"auto"}),u=t}$.appendChild(r),u&&$.appendChild(u);const h=O!==null?s?.find(t=>t.key===O):void 0,m=h?.items??e,f=h?void 0:s,i=ke(m),b=i.defs,y=b.filter($e);I!==null&&!y.some(t=>t.testNumber===I)&&(I=null);const g=G==="overview"?he(m,y,b,f,c):G==="distributions"?ye(m,y,f,c):Ce(m,y,f),p=i.conflicts.filter(t=>t.excluded);if(p.length>0){const t=d.createElement("div");Object.assign(t.style,{color:B.label,fontSize:H.body,padding:`0 ${j} ${w.sm}`});const S=p.slice(0,6).map(o=>o.testNumber).join(", "),C=p.length>6?`, and ${p.length-6} more`:"",n=p.length===1?"it":"them";t.textContent=`${p.length} test ${p.length===1?"number is":"numbers are"} hidden (${S}${C}) \u2014 the wafers in view describe ${n} differently, so their values cannot be pooled. `+(s&&s.length>0?`Pick one ${c??"group"} under "Show:" to analyse ${n}.`:"Load one test program at a time to analyse them."),t.dataset.wmapWithheldTests=String(p.length),W.appendChild(t)}F.push(g),W.appendChild(g.card)}return{el:P,render:M,destroy:()=>{for(const e of F)e.destroy();P.remove()}}}
|
|
1
|
+
import{buildFacetTable as $e,facetValueOf as Be,FACET_NONE_VALUE as De}from"../stats/facets.js";import{mergeTestDefs as Le}from"../stats/mergeTestDefs.js";import{isParametricTest as Ie}from"../renderer/buildWaferMap.js";import{NO_DATA_FILL as ne}from"../renderer/colorMap.js";import{describeWaferPopulation as Oe,populationStat as Ee}from"../stats/population.js";import{LEADING as Pe,ALPHA as Ae,SPACE as w,EDGE_GUTTER as K,FONT as G,CLR as B,RADIUS as Re,SHADOW as je,controlStyle as We,wireControlHover as ae,wireTooltip as Ge}from"./toolbar.js";import{ICONS as He}from"./icons.js";import{renderCapabilityPanel as Ye}from"./charts/capability.js";import{renderBoxplotPanel as Fe}from"./charts/boxplot.js";import{renderTrendPanel as Me}from"./charts/trend.js";import{renderHistogramPanel as Ne}from"./charts/histogram.js";import{renderCorrelationPanel as Ve}from"./charts/correlation.js";import{renderScatterPanel as _e}from"./charts/scatter.js";import{renderBarPanel as oe}from"./charts/barPanel.js";import{renderBinClusterPanel as ze}from"./charts/binCluster.js";import{renderTestPassRatePanel as Ue}from"./charts/testPassRate.js";import{QUANTITY as qe}from"./charts/palette.js";import{cardFrameStyle as Qe,makeChartGridWrap as X,makeLabeledSelect as Ke,makeLinkedGroupSelect as Xe}from"./charts/chartShell.js";import{buildYieldData as N,buildYieldDataCombined as re}from"../stats/yield.js";import{buildBinParetoData as Je}from"../stats/binPareto.js";import{buildLotTestSection as Ze,buildLotFunctionalSection as et,buildMetadataStripBox as tt}from"./summaryPanel.js";import{buildRegionYieldData as ie,buildRingRegions as nt,buildQuadrantRegions as at}from"../stats/regions.js";import{renderRegionYieldDiagram as se}from"./charts/regionYieldDiagram.js";const ot=[{key:"overview",label:"Overview"},{key:"distributions",label:"Distributions"},{key:"correlation",label:"Correlation"}];export function createInsightsTab(D){const{getItems:le,getLotStats:de,getBinColors:J,passBins:T,getRingCount:ce,onSaveImage:v,onSaveText:V,openWafer:H,focusTest:Z}=D,pe=D.showMetadataStrip??!0,R=D.contentInset??K,d=D.ownerDocument??document,E=d.createElement("div");Object.assign(E.style,{display:"none",flexDirection:"column",width:"100%",paddingTop:"0"});const ue=K,P=d.createElement("div");Object.assign(P.style,{paddingLeft:ue});const $=d.createElement("div");Object.assign($.style,{display:"flex",gap:w.xs,alignItems:"center",background:B.menuBg,border:`1px solid ${B.menuBorder}`,borderRadius:Re.container,boxShadow:je.panel,padding:`0 ${w.lg}`,marginBottom:w.lg,marginLeft:R,marginRight:R}),$.setAttribute("role","tablist"),$.addEventListener("keydown",e=>{if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;const n=Array.from($.querySelectorAll('[role="tab"]')),o=n.indexOf(d.activeElement);if(o===-1)return;e.preventDefault();const c=n[(o+(e.key==="ArrowRight"?1:-1)+n.length)%n.length];c.focus(),c.click()});const j=d.createElement("div");Object.assign(j.style,{display:"flex",flexDirection:"column",gap:w.lg,marginTop:"0",paddingLeft:R,paddingRight:R}),E.appendChild(P),E.appendChild($),E.appendChild(j);let W=D.defaultView??"overview",A,I=null,L=null,Y={includeLimits:void 0,clipOutliers:!1};const _=e=>{L!==e&&(L=e,M())};let F=[];function z(e,n,o){H?.(e,n,o)}function fe(e){return H?{open:(n,o)=>z(n,`Wafer ${e.find(c=>c.waferIndex===n)?.label??n}`,o)}:Z&&e.length===1?{open:(n,o)=>Z(o),label:"show this test on the map"}:null}function me(){return le().map((e,n)=>e==null?null:{metadata:e.wafer.metadata??void 0,dies:e.dies,wafer:e.wafer,label:e.label??String(e.wafer.metadata?.waferId??""),waferIndex:n,statsSummary:e.statsSummary,testDefs:e.testDefs}).filter(e=>e!=null)}function ee(e,n){Object.assign(e.style,{background:"none",border:"none",borderBottom:n?`2px solid ${B.iconActive}`:"2px solid transparent",color:n?B.iconActive:B.label,fontWeight:n?"700":"500",fontSize:G.body,padding:`${w.sm} ${K} ${w.md}`,cursor:"pointer",marginBottom:"-1px"})}function be(e,n){const o=d.createElement("button");o.type="button",o.textContent=n;const c=e===W;return ee(o,c),o.dataset.on=c?"true":"false",ae(o,"bare"),o.dataset.wmapInsightsTab=e,o.setAttribute("role","tab"),o.setAttribute("aria-selected",c?"true":"false"),o.tabIndex=c?0:-1,o.addEventListener("click",()=>{W!==e&&(W=e,M())}),o}function ge(e){const n=d.createElement("button");return n.type="button",n.textContent=`\u2039 ${e.label}`,ee(n,!1),n.dataset.wmapInsightsBack="1",n.addEventListener("click",e.onBack),n}function ye(e,n,o,c=!0){const s=X(d),f=J();let y="label";const u=o??"group",m=T.length===1?`bin ${T[0]}`:`bins ${T.join(", ")}`,i=de?.(),b=new Map(i?.lotYieldSeries.map(r=>[r.waferIndex,r.yieldPercent])),h=r=>({...r,label:r.label.replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPercent:b.get(r.waferIndex),key:r.waferIndex}),g=e.map(h),p=n?.map(r=>({key:r.key,items:r.items.map(h)})),t=()=>p?re(p,T,y):N(g,T,y),x={title:n?`Yield by ${u} (pass: ${m})`:`Yield by wafer (pass: ${m})`,data:t(),selfControl:{current:y,options:[["yield","Sort: yield"],["label",n?`Sort: ${u}`:"Sort: wafer ID"]],onChange:r=>(y=r,{data:t()})},barColor:()=>qe,valueLabel:r=>`${r.percent.toFixed(1)}%`,reference:r=>{if(r.length<3)return null;const k=r.map(Q=>Q.percent).sort((Q,ke)=>Q-ke),O=k.length%2?k[(k.length-1)/2]:(k[k.length/2-1]+k[k.length/2])/2;return{value:O,label:`median ${O.toFixed(1)}%`}},drill:p?{onOpenGroup:r=>{const k=p.find(O=>O.key===r.label)?.items??[];return{data:N(k,T,y),title:`Yield by wafer \u2014 ${u}: ${r.label} (pass: ${m})`}},onBack:()=>({data:t(),title:`Yield by ${u} (pass: ${m})`}),groupLabelText:u}:void 0,onOpen:H?r=>{typeof r.key=="number"&&z(r.key,`Wafer ${r.label}`)}:void 0,ownerDocument:d};let C=null;if(c&&(C=oe(x,v),C.card.style.minHeight="360px",s.appendChild(C.card)),n){const r=ze({title:"Hard bin pareto",groups:n.map(k=>({key:k.key,items:k.items.map(O=>({dies:O.dies,hardBinCounts:O.statsSummary?.stats.hardBinCounts,softBinCounts:O.statsSummary?.stats.softBinCounts}))})),onSaveImage:v,ownerDocument:d});return r.card.style.minHeight="360px",s.appendChild(r.card),{card:s,destroy:()=>{C?.destroy(),r.destroy()}}}let a="hbin";const l=r=>r===void 0?ne:(a==="hbin"?f.hard:f.soft).get(r)??ne,S=e.map(r=>({dies:r.dies,hardBinCounts:r.statsSummary?.stats.hardBinCounts,softBinCounts:r.statsSummary?.stats.softBinCounts})),te=()=>Je(S,a),ve={title:"Hard bin pareto",data:te(),selfControl:{current:a,options:[["hbin","Hard bins"],["sbin","Soft bins"]],onChange:r=>(a=r,{data:te(),title:`${a==="hbin"?"Hard":"Soft"} bin pareto`})},barColor:r=>l(r.binCode),ownerDocument:d},q=oe(ve,v);return q.card.style.minHeight="360px",s.appendChild(q.card),{card:s,destroy:()=>{C?.destroy(),q.destroy()}}}function U(){const e=d.createElement("div");return e.dataset.wmapChartCard="1",Object.assign(e.style,{...Qe(),display:"flex",flexDirection:"column",gap:w.lg,minWidth:"0"}),e}function he(e){if(P.innerHTML="",P.style.marginBottom="0",!pe)return;const n=tt(e.map(o=>({metadata:o.metadata})),void 0,{facetableOnly:!1});n&&(n.style.marginBottom="0",P.appendChild(n),P.style.marginBottom=w.xs)}function Ce(e,n,o,c){if(!e.length)return{elements:[],testValuesCard:null,functionalCard:null,destroy:()=>{}};const s=e.map(l=>l.wafer),f=e.map(l=>l.dies),y=e.flatMap(l=>l.dies),u=e.map(l=>l.statsSummary),m=u.every(l=>l!==void 0)?u:void 0,i=ce?.()??4,b=[],h=[],p=Ue({groups:(c??[{key:"",items:e}]).map(l=>({key:l.key,items:l.items.map(S=>({dies:S.dies,testSpecYield:S.statsSummary?.stats.testSpecYield,functionalYield:S.statsSummary?.stats.functionalYield}))})),testDefs:o,onSaveImage:v,ownerDocument:d});p.card.style.minHeight="300px",b.push(p.card),h.push(p.destroy);const t=ie(f,s,i,T,nt);if(t.length){const l=se({title:"Ring yield",mode:"ring",rows:t,onSaveImage:v,ownerDocument:d});b.push(l.card),h.push(l.destroy)}const x=ie(f,s,i,T,at);if(x.length){const l=se({title:"Quadrant yield",mode:"quadrant",rows:x,onSaveImage:v,ownerDocument:d});b.push(l.card),h.push(l.destroy)}let C=null;if(n.length){const l=Ze(y,n,void 0,m,V,f.map(S=>({dies:S})),void 0,"full");if(l){const S=U();S.appendChild(l),C=S}}let a=null;if(o.length){const l=et(y,o,m,V);if(l){const S=U();S.appendChild(l),a=S}}return{elements:b,testValuesCard:C,functionalCard:a,destroy:()=>{for(const l of h)l()}}}function xe(e){const n=T.length===1?`bin ${T[0]}`:`bins ${T.join(", ")}`,o=e.length===1,c=e[0],s=U();Object.assign(s.style,{flexDirection:"row",flexWrap:"wrap",gap:w.md});const f=i=>{const b=i.lastElementChild;return b&&Object.assign(b.style,{borderRight:"none",paddingRight:"0",marginRight:"0"}),i};function y(i,b,h){const g=d.createElement("div");Object.assign(g.style,{display:"flex",alignItems:"baseline",gap:w.sm,paddingRight:w.xxl,marginRight:w.md,borderRight:`1px solid ${B.menuBorder}`});const p=d.createElement("div");p.textContent=i,Object.assign(p.style,{fontSize:G.heading,fontWeight:"700",color:B.value,lineHeight:Pe.tight});const t=d.createElement("div");if(t.textContent=b,Object.assign(t.style,{fontSize:G.body,color:B.label}),g.append(p,t),h){const x=d.createElement("div");x.textContent=h,Object.assign(x.style,{fontSize:G.meta,color:B.label,opacity:Ae.muted}),g.appendChild(x)}return g}if(o){const i=N([{...c,key:c.waferIndex}],T)[0]?.percent;return i!==void 0&&s.appendChild(y(`${i.toFixed(1)}%`,`Yield \xB7 pass: ${n}`)),s.appendChild(y(String(c.dies.length),"Total dies")),f(s)}s.appendChild(y(String(e.length),"Wafers"));const u=N(e.map(i=>({...i,key:i.waferIndex})),T).map(i=>i.percent).filter(i=>Number.isFinite(i));if(u.length){const i=u.reduce((g,p)=>g+p,0)/u.length,b=re([{key:"all",items:e.map(g=>({...g,key:g.waferIndex}))}],T)[0]?.percent,h=b!==void 0&&b.toFixed(1)!==i.toFixed(1);s.appendChild(y(`${i.toFixed(1)}%`,`Mean per-wafer yield \xB7 pass: ${n}`,h?`${b.toFixed(1)}% by dies`:void 0))}const m=e.map(i=>i.statsSummary);if(m.every(i=>i!==void 0)){const i=m.reduce((h,g)=>h+g.stats.analyzedDies,0),b=m.reduce((h,g)=>h+g.stats.excludedDies,0);s.appendChild(y(i.toLocaleString(),"Dies analysed",b?`${b.toLocaleString()} excluded`:void 0))}else s.appendChild(y(e.reduce((i,b)=>i+b.dies.length,0).toLocaleString(),"Total dies"));return f(s)}function we(e,n,o,c,s){const f=d.createElement("div");Object.assign(f.style,{display:"flex",flexDirection:"column",gap:w.lg});const y=e.length===1&&!c;e.length&&!c&&f.appendChild(xe(e));const u=ye(e,c,s,!y);f.appendChild(u.card);const m=Ce(e,n,o,c);for(const i of m.elements)u.card.appendChild(i);return m.testValuesCard&&f.appendChild(m.testValuesCard),m.functionalCard&&f.appendChild(m.functionalCard),{card:f,destroy:()=>{u.destroy(),m.destroy()}}}function Se(e,n,o,c){const s=X(d),f=fe(e),y=a=>{Y=a;for(const l of[g,p,t])l!==u&&l?.setAxisPrefs(a)};let u=null;const m=a=>l=>{u=a(),y(l),u=null},i=a=>({...a,testStats:a.statsSummary?.stats.perTestStats}),b=e.map(i),h=o?.map(a=>({key:a.key,items:a.items.map(i)})),g=Fe({title:"Test value distribution",axisPrefs:Y,onAxisPrefsChange:m(()=>g),onTestChange:a=>x(a),selectedTestNumber:I??void 0,items:b,testDefs:n,groups:h,groupLabelText:c,onSaveImage:v,onGroupChange:a=>_(a),onOpen:f?.open,openActionLabel:f?.label,ownerDocument:d}),p=Ne({title:"Value histogram",axisPrefs:Y,onAxisPrefsChange:m(()=>p),onTestChange:a=>x(a),selectedTestNumber:I??void 0,items:e,testDefs:n,groups:o,onGroupChange:a=>_(a),onSaveImage:v,ownerDocument:d}),t=Me({title:"Wafer-to-wafer trend",axisPrefs:Y,onAxisPrefsChange:m(()=>t),onTestChange:a=>x(a),selectedTestNumber:I??void 0,items:e.map(a=>({label:a.label,key:a.waferIndex,dies:a.dies,testStats:a.statsSummary?.stats.perTestStats})),testDefs:n,onSaveImage:v,centreLabel:Ee(Oe(e.map(a=>a.wafer.metadata)),"mean"),onOpen:H?(a,l)=>z(a,`Wafer ${e.find(S=>S.waferIndex===a)?.label??a}`,l):void 0,ownerDocument:d}),x=a=>{I=a,g.setTest(a),p.setTest(a),t.setTest(a),C.setTest(a)},C=Ye({title:"Process capability",items:e,testDefs:n,onSaveImage:v,selectedTestNumber:I??void 0,onSelectTest:a=>x(a),ownerDocument:d});return s.append(C.card,g.card,p.card,t.card),{card:s,destroy:()=>{C.destroy(),g.destroy(),p.destroy(),t.destroy()}}}function Te(e,n,o){const c=X(d),s=_e({title:"Test scatter",items:e,testDefs:n,groups:o,binColors:J().hard,onSaveImage:v,ownerDocument:d}),f=Ve({title:"Test correlation matrix",items:e,testDefs:n,onSaveImage:v,onSaveText:V,onSelectPair:(y,u)=>s.setXY(y,u),ownerDocument:d});return c.append(f.card,s.card),{card:c,destroy:()=>{f.destroy(),s.destroy()}}}function M(){for(const t of F)t.destroy();F=[],j.innerHTML="",$.innerHTML="",D.backTab&&$.appendChild(ge(D.backTab));for(const t of ot)$.appendChild(be(t.key,t.label));const e=me();he(e);const n=$e(e,{facetableOnly:!0}).filter(t=>t.splittable),o=d.createElement("div");Object.assign(o.style,{display:"flex",gap:w.md,alignItems:"center",marginLeft:w.xxl,paddingBottom:w.xs});let c;n.length>0?(o.appendChild(Ke("Group by:",[{value:"",label:"None"},...n.map(t=>({value:t.key,label:`${t.label} (${t.values.length})`}))],A??"",t=>{A=t||void 0,L=null,M()},{hook:"group-by",ownerDocument:d})),c=n.find(t=>t.key===A)?.label):A=void 0;let s;if(A){const t=new Map,x=[];for(const C of e){const a=Be(C.metadata,A)??De;t.has(a)||(t.set(a,[]),x.push(a)),t.get(a).push(C)}s=x.map(C=>({key:C,items:t.get(C)}))}L!==null&&!s?.some(t=>t.key===L)&&(L=null),s&&s.length>0&&o.appendChild(Xe(s.map(t=>t.key),"Show:",L,t=>_(t),{ownerDocument:d}).el);let f=null;if(D.onOpenGuide){const t=d.createElement("button");t.type="button",t.innerHTML=He.help,t.setAttribute("aria-label","User guide"),Object.assign(t.style,{...We("bare"),display:"inline-flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",flexShrink:"0"}),ae(t,"bare"),Ge(t,"User guide"),t.addEventListener("click",()=>D.onOpenGuide()),Object.assign(t.style,{marginLeft:"auto"}),f=t}$.appendChild(o),f&&$.appendChild(f);const y=L!==null?s?.find(t=>t.key===L):void 0,u=y?.items??e,m=y?void 0:s,i=Le(u),b=i.defs,h=b.filter(Ie);I!==null&&!h.some(t=>t.testNumber===I)&&(I=null);const g=W==="overview"?we(u,h,b,m,c):W==="distributions"?Se(u,h,m,c):Te(u,h,m),p=i.conflicts.filter(t=>t.excluded);if(p.length>0){const t=d.createElement("div");Object.assign(t.style,{color:B.label,fontSize:G.body,padding:`0 ${R} ${w.sm}`});const x=p.slice(0,6).map(l=>l.testNumber).join(", "),C=p.length>6?`, and ${p.length-6} more`:"",a=p.length===1?"it":"them";t.textContent=`${p.length} test ${p.length===1?"number is":"numbers are"} hidden (${x}${C}) \u2014 the wafers in view describe ${a} differently, so their values cannot be pooled. `+(s&&s.length>0?`Pick one ${c??"group"} under "Show:" to analyse ${a}.`:"Load one test program at a time to analyse them."),t.dataset.wmapWithheldTests=String(p.length),j.appendChild(t)}F.push(g),j.appendChild(g.card)}return{el:E,render:M,destroy:()=>{for(const e of F)e.destroy();E.remove()}}}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { Die } from '../core/dies.js';
|
|
2
2
|
import type { TestDef, BinDef } from '../renderer/buildWaferMap.js';
|
|
3
3
|
import type { PlotMode } from '../renderer/buildView.js';
|
|
4
|
+
import type { BinColors } from '../renderer/binColors.js';
|
|
4
5
|
export interface MaplessSummaryOptions {
|
|
5
6
|
plotMode: PlotMode;
|
|
6
7
|
activeTest?: number;
|
|
7
8
|
hbinDefs?: BinDef[];
|
|
8
9
|
sbinDefs?: BinDef[];
|
|
9
|
-
|
|
10
|
+
/** The map's resolved bin colours (`View.binColors`), so bars match its legend. */
|
|
11
|
+
binColors?: BinColors;
|
|
12
|
+
/** The map's value gradient name, so histogram bars match its colorbar. */
|
|
13
|
+
valueColorScheme?: string;
|
|
14
|
+
/** The map's `View.reverseValueScheme` — must travel with the name, or the
|
|
15
|
+
* bars read opposite to the colorbar they are meant to match. */
|
|
16
|
+
reverseValueScheme?: boolean;
|
|
10
17
|
/** Effective log-scale setting for the active test — same resolution the
|
|
11
18
|
* map itself uses (explicit viewOpts.logScale, falling back to the
|
|
12
19
|
* TestDef's own default). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getDieTestValue as
|
|
1
|
+
import{getDieTestValue as $}from"../renderer/buildWaferMap.js";import{resolveTestNumber as T,findTestDef as B}from"../renderer/buildView.js";import{buildBinSection as V}from"./summaryPanel.js";import{buildTestHistogramData as z}from"../stats/histogram.js";import{resolveValueColorFn as F}from"../renderer/colorSchemes.js";import{TRACKING as N,SPACE as y,RADIUS as I,FONT as S,CLR as f,wireTooltip as A}from"./toolbar.js";import{fmt as w}from"../renderer/fmt.js";function d(o,n,e){const a=document.createElement(o);return n&&Object.assign(a.style,n),e!==void 0&&(a.textContent=e),a}function W(o,n,e,a,b){let p=1/0,m=-1/0;for(const r of o){const s=$(r,n);s!==void 0&&(s<p&&(p=s),s>m&&(m=s))}const v=a==="spec"&&e&&(e.limitLow!==void 0||e.limitHigh!==void 0);let t,l;v?(t=e.limitLow!==void 0?e.limitLow:isFinite(p)?p:0,l=e.limitHigh!==void 0?e.limitHigh:isFinite(m)?m:1):(t=isFinite(p)?p:0,l=isFinite(m)?m:1),t===l&&(l=t+1);const h=r=>Math.min(1,Math.max(0,r));if(b&&t>0&&l>0){const r=Math.log10(t),s=Math.log10(l)-r;return c=>c<=0?0:h((Math.log10(c)-r)/s)}return r=>h((r-t)/(l-t))}function E(o,n,e,a,b,p,m,v){const t=d("div",{display:"flex",flexDirection:"column",gap:y.xxs,minWidth:"0",flex:"1",minHeight:"0"});t.appendChild(d("div",{fontSize:S.meta,fontWeight:"700",letterSpacing:N,textTransform:"uppercase",color:f.label},n?.name?`${n.name} distribution`:"Value distribution"));const l=o[0].rangeLow,h=o[o.length-1].rangeHigh,r=h-l||1,s=i=>Math.min(1,Math.max(0,(i-l)/r)),c=F(a,b),u=W(p,e,n,m,v),g=Math.max(1,...o.map(i=>i.count)),L=d("div",{position:"relative",display:"flex",alignItems:"flex-end",gap:y.xxs,flex:"1",minHeight:"48px"});for(const i of o){const x=d("div",{flex:"1",minWidth:"2px",background:c(u((i.rangeLow+i.rangeHigh)/2)),height:`${i.count/g*100}%`,borderRadius:"1px 1px 0 0"});x.dataset.wmapBar="1",A(x,`${w(i.rangeLow,n?.unit)} \u2013 ${w(i.rangeHigh,n?.unit)}: ${i.count}`,{asDataPoint:!0}),L.appendChild(x)}const H=[];for(const[i,x]of[[n?.limitLow,"LSL"],[n?.limitHigh,"USL"]]){if(i===void 0||i<l||i>h)continue;const C=s(i)*100,M=d("div",{position:"absolute",top:"0",bottom:"0",left:`${C}%`,width:"2px",marginLeft:"-1px",background:f.value,boxShadow:`0 0 0 1px ${f.panelBg}`,pointerEvents:"none"});M.dataset.wmapLimitMarker="1",L.appendChild(M),H.push({pct:C,text:`${x} ${w(i,n?.unit)}`})}if(t.appendChild(L),H.length){const i=d("div",{position:"relative",height:"14px"});for(const{pct:x,text:C}of H){const M=Math.min(96,Math.max(4,x));i.appendChild(d("span",{position:"absolute",left:`${M}%`,top:"0",transform:"translateX(-50%)",whiteSpace:"nowrap",fontSize:S.body,fontWeight:"600",color:f.text,background:f.panelBg,border:`1px solid ${f.value}`,borderRadius:I.control,padding:"0 3px",lineHeight:"12px"},C))}t.appendChild(i)}const R=d("div",{display:"flex",justifyContent:"space-between",fontSize:S.body,color:f.label});return R.appendChild(d("span",{},w(o[0].rangeLow,n?.unit))),R.appendChild(d("span",{},w(o[o.length-1].rangeHigh,n?.unit))),t.appendChild(R),t}export function buildMaplessSummary(o,n,e){const{plotMode:a,activeTest:b,hbinDefs:p,sbinDefs:m,binColors:v,valueColorScheme:t,reverseValueScheme:l,logScale:h=!1,colorbarRangeMode:r="spec",valueRangeDies:s}=e;if(a==="hardBin"||a==="softBin"){const c=a==="hardBin"?p:m,u=a==="hardBin"?v?.hard:v?.soft,g=V(o,c,a==="hardBin"?"hard":"soft",u);if(g)return g}else if(a==="value"){const{testNumber:c}=T(b??0,n),u=B(n,b??0),g=z([{dies:o}],c,12,u?.limitLow,u?.limitHigh);if(g.length)return E(g,u,c,t,l,s??o,r,h)}return d("div",{padding:y.xl,fontSize:S.body,color:f.label,textAlign:"center"},"No summary available for this view.")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getUniqueTestNumbers as oo,resolveTestNumber as io,findTestDef as lo}from"../renderer/buildView.js";import{getColorScheme as ao}from"../renderer/colorSchemes.js";import{metadataValueColor as so}from"../renderer/colorMap.js";import{resolveCanvasTheme as ro}from"./canvasTheme.js";import{ICONS as Te}from"./icons.js";import{SHADOW as Le,LEADING as Xe,TRACKING as co,controlStyle as uo,wireControlHover as pt,SPACE as w,EDGE_GUTTER as ne,MAP_CHROME_INSET as fo,RADIUS as z,FONT as T,CLR as g,sevColor as tn,MODE_LABELS as po,BIN_LEGEND_MODES as nn,STACKED_MODES as he,Z_ABOVE as on,applyOverlayZ as go,getTooltip as mo,hideTooltip as ln,createToolbarHelpers as ho,buildModeMenuEl as bo,openDetachWindow as yo,openFloatingWindow as wo,openModal as xo,openReportModal as vo,copyWmapThemeTokens as So,syncWmapPopupTheme as Co,openUserGuideWindow as Mo,makePaletteBtn as Do,makeLogScaleBtn as ko,makeLegendStyleBtn as Eo,makeOverlaysBtn as Bo,makeOrientationBtn as Oo,menuLayerFor as an,saveImageBlob as To,markMenuTrigger as $e,wireMenuA11y as sn,wireExpandToggle as rn,wireTooltip as dn,requestedPassFailDisplay as cn,overlayMenuRows as Lo,anyOverlayActive as $o,logWmapVersionOnce as Wo,buildDataModeEntries as Ro,metadataKeyHasData as Io,metadataModeEntry as Ao}from"./toolbar.js";import{aggregateValues as Po,aggregateBinCounts as un}from"../core/aggregates.js";import{renderWaferMap as gt}from"./renderWaferMap.js";import{classifyChanged as Fo}from"./renderWaferMap.js";import{buildWaferMap as Ho,getTestPassStatus as fn,isParametricTest as mt,getDieTestValue as jo}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Ze}from"../stats/analyzeWaferMap.js";import{collectWarnings as zo,buildWarningsMenuEl as No,severityOf as Vo}from"./warnings.js";import{compareNatural as _o}from"../core/utils.js";import{createSummaryPanelEl as ht,buildMetadataStripRow as Go,buildCompactMetadataRows as pn,metadataEntries as gn,renderLotSummaryContent as Ko}from"./summaryPanel.js";import{renderLotSummaryReportHtml as qo}from"../stats/renderSummaryReport.js";import{prettyKey as Uo}from"../stats/facets.js";import{mergeTestDefs as Xo}from"../stats/mergeTestDefs.js";import{getDieKey as Zo,hasPosition as Yo}from"../core/dies.js";function be(u){const S=new Set;return u.filter(f=>S.has(f.bin)?!1:(S.add(f.bin),!0))}const bt=12;function Qo(u,S,f){let P=S;if(S.length>bt){const v=S.slice(0,bt-1),L=S.slice(bt-1),oe=L.reduce((Qe,se)=>Qe+se.count,0);P=[...v,{color:g.label,count:oe,label:`Other (${L.length} bins)`}]}const F=u.createElement("div");Object.assign(F.style,{display:"flex",width:"100%",height:"8px",borderRadius:z.control,overflow:"hidden",border:`1px solid ${g.menuBorder}`,boxSizing:"border-box",marginTop:w.xs,flexShrink:"0"}),F.setAttribute("role","img"),F.setAttribute("aria-label",`Population split: ${P.map(v=>`${v.label} ${Ye(v.count/f*100)}`).join(", ")}`);for(const v of P){const L=v.count/f*100,oe=u.createElement("div");Object.assign(oe.style,{flex:`${L} 1 0`,minWidth:L>0?"2px":"0",background:v.color}),dn(oe,`${v.label} \xB7 ${v.count.toLocaleString()} dies \xB7 ${Ye(L)}`),F.appendChild(oe)}return F}function Ye(u){return u>0&&u<.1?"<0.1%":`${u.toFixed(1)}%`}function mn(u,S){const f=new Map;let P=0;for(const F of u)for(const v of F.dies){if(v.partial||v.edgeExcluded)continue;const L=S(v);L!==void 0&&(f.set(L,(f.get(L)??0)+1),P++)}return{counts:f,total:P}}function hn(u,S){const f=u.ownerDocument.createElement("div");Object.assign(f.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:`${w.xxs} ${w.xs}`,borderRadius:z.control});const P=u.ownerDocument.createElement("span");Object.assign(P.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:S.color,border:S.isActive?`2px solid ${g.iconActive}`:`1px solid ${g.menuBorder}`,borderRadius:z.control,boxSizing:"border-box"});const F=u.ownerDocument.createElement("span");if(F.textContent=S.label,Object.assign(F.style,{fontWeight:S.isActive?"700":"400",color:S.isActive?g.iconActive:g.text,whiteSpace:"nowrap"}),f.appendChild(P),f.appendChild(F),S.count!==void 0){const v=u.ownerDocument.createElement("span");if(v.textContent=S.count.toLocaleString(),Object.assign(v.style,{color:S.isActive?g.iconActive:g.text,fontWeight:S.isActive?"700":"400",whiteSpace:"nowrap"}),f.appendChild(v),S.percent!==void 0){const L=u.ownerDocument.createElement("span");L.textContent=Ye(S.percent),Object.assign(L.style,{color:g.label,whiteSpace:"nowrap"}),f.appendChild(L)}}f.setAttribute("role","button"),f.setAttribute("aria-pressed",S.isActive?"true":"false"),f.tabIndex=0,f.addEventListener("mouseenter",()=>{f.style.background=g.bgHover}),f.addEventListener("mouseleave",()=>{f.style.background="transparent"}),f.addEventListener("focus",()=>{f.style.background=g.bgHover}),f.addEventListener("blur",()=>{f.style.background="transparent"}),f.addEventListener("click",S.onClick),f.addEventListener("keydown",v=>{(v.key==="Enter"||v.key===" ")&&(v.preventDefault(),S.onClick())}),u.appendChild(f)}export function renderWaferGallery(u,S,f={}){Wo();const P=f.cardPadding??6,F=f.downloadFilename??"wafer-gallery";let v=f.columns;const L=f.showPlotModeSelector??!0,oe=f.showHelpButton??!1,Qe=f.userGuideExtension,se=f.insights?.enabled??!1,bn=go(f.zIndex),re=f.summaryPanel,We=f.passBins??[1];let Re=f.fallbackFormat,H=f.lotStatsSummary,ye=f.legendPosition??"default",Ie=f.perCardLegend??!1;function we(){const e=c.plotMode??"hardBin";return nn.has(e)?null:c.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"This lot has no shared colour bar for value mode, so each map keeps its own"}function yt(){const e=Ie||we()!==null;for(const t of C)t&&t.setOptions({showLegend:e})}let c={plotMode:"hardBin",colorScheme:"default",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...f.viewOptions},C=[],ie=[],de=[],O=[],x=S.map(e=>typeof e=="function"?null:e);function wt(){return Xo(x)}function ce(){if(x.some(e=>e?.testDefs?.length))return wt().defs}let Je=0,Ae=0;const N=new Map;let yn=0,R=null,xe=null,xt=new Set,h=null,wn={};function vt(e){return x[e]?.statsSummary??H?.perWafer.find(t=>t.waferIndex===e)?.summary}function et(){return!!(x.some(e=>e?.statsSummary?.findings.length)||H?.perWafer.some(e=>e.summary.findings.length))}const xn=mo(),ue=ho(xn),{makeBtn:Z,setActive:ve,makeSep:V,makeMenuRow:vn,makeMenuSection:Sn,makeDropdown:St,closeOpenMenu:Pe,getOpenMenu:Se,setOpenMenu:Ce}=ue;u.ownerDocument.addEventListener("click",Pe,!0);const Ct=()=>ln();window.addEventListener("blur",Ct);let Mt=f.findingsNotice;function Dt(e){xt=new Set(e);const t=[...W.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,r)=>{const d=xt.has(r);o.style.outline=d?`3px solid ${g.findingHighlight}`:"",o.style.outlineOffset=d?"-3px":"",d&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function kt(){Dt([])}function Et(){for(const e of C)e&&e.clearSelection()}function tt(e,t){const n=new Set(e),o=t??C.map((r,d)=>d);for(const r of o){const d=O[r],i=C[r];if(!d||!i)continue;const s=d.dies.filter(a=>n.has(Zo(a)));i.setSelection(s)}}function Cn(){const e=[];for(let t=0;t<x.length;t++){const n=x[t];if(!n)continue;const o=vt(t)?.findings??[];o.length&&e.push({index:t,item:n,unusualCount:o.filter(r=>r.severity==="unusual").length,notableCount:o.filter(r=>r.severity==="notable").length,totalCount:o.length})}return e}function Mn(e){const t=O[e]??x[e];t&&Oe(e,t)}function Dn(e){const t=vt(e)?.findings??[];if(t.length)return{total:t.length,unusual:t.filter(n=>n.severity==="unusual").length,notable:t.filter(n=>n.severity==="notable").length}}function kn(){const e=be(x.flatMap(n=>n?.hbinDefs??[])),t=be(x.flatMap(n=>n?.sbinDefs??[]));vo(qo({items:x.map((n,o)=>({label:n?.label??`W${o+1}`,wafer:n?.wafer,dies:n?.dies,statsSummary:n?.statsSummary})),hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:ce(),passBins:We,ringCount:c.ringCount}),{anchor:u})}function En(){if(!h)return;h.innerHTML="";const e=Cn();if(x.length>0){const n=u.ownerDocument.createElement("div"),o=e.length,r=x.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${r} wafers`:`${o} of ${r} wafer${r===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:T.body,color:g.label,marginBottom:w.md}),h.appendChild(n)}if(e.length>0){const n=u.ownerDocument.createElement("button");n.type="button",n.textContent="Summary report",Object.assign(n.style,{...uo("outlined"),marginBottom:w.lg,display:"block",width:"100%",textAlign:"left"}),pt(n),n.addEventListener("click",kn),h.appendChild(n)}if(e.length===0){const n=u.ownerDocument.createElement("div");Object.assign(n.style,{color:g.icon,fontSize:T.body,padding:"4px 0"}),n.textContent="No findings on any wafer.",h.appendChild(n)}else for(const{index:n,item:o,unusualCount:r,notableCount:d,totalCount:i}of e){const s=r?"unusual":d?"notable":"info",a=r+d||i,l=u.ownerDocument.createElement("button");l.type="button",Object.assign(l.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:w.xs,border:"none",borderLeft:`3px solid ${tn(s)}`,borderRadius:z.control,background:g.bgHover,cursor:"pointer",fontSize:T.body,textAlign:"left",boxSizing:"border-box"}),l.addEventListener("mouseover",()=>{l.style.background=g.bgActive}),l.addEventListener("mouseout",()=>{l.style.background=g.bgHover});const p=u.ownerDocument.createElement("span");p.textContent=o.label??`W${n+1}`,Object.assign(p.style,{color:g.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const y=u.ownerDocument.createElement("span");y.textContent=String(a),l.setAttribute("aria-label",`${o.label??`W${n+1}`} \u2014 ${a} finding${a===1?"":"s"}${r?`, ${r} unusual`:""} \u2014 view wafer`),Object.assign(y.style,{marginLeft:w.sm,flexShrink:"0",background:tn(s),color:"#fff",borderRadius:z.container,padding:"1px 5px",fontSize:T.body,fontWeight:"600"}),l.appendChild(p),l.appendChild(y),l.addEventListener("click",()=>Oe(n,o)),h.appendChild(l)}const t=u.ownerDocument.createElement("div");t.style.height="12px",h.appendChild(t)}function j(){if(h)if(H){const e=be(x.flatMap(n=>n?.hbinDefs??[])),t=be(x.flatMap(n=>n?.sbinDefs??[]));Ko(h,{lotSummary:H,items:x,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:ce(),passBins:We,ringCount:c.ringCount,colorScheme:c.colorScheme,plotMode:c.plotMode??"hardBin",fallbackFormat:Re,activeFindingId:xe,warnings:f.warnings?.display??!0?Y:[],findingsFilter:wn,findingsNotice:Mt,onFindingsFilterChange:j,onSaveText:f.onSaveText,onFindingClick:(n,o)=>{xe===n.id?nt():On(n,o),j()},onWaferClick:Mn,findingsFor:Dn,dieListOptions:f.dieList})}else En()}function Bn(e){const t=e.highlight;return t?.kind==="wafer"&&t.waferIndices?.length?t.waferIndices:null}function Bt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}let Fe=[];function Ot(){if(Fe.length!==0){for(const e of Fe)C[e]?.setOptions({plotMode:c.plotMode,activeTest:c.activeTest});Fe=[]}}function nt(){xe=null,kt(),Et(),Ot(),B({highlightBin:void 0},{fireCallback:!1})}function On(e,t){if(xe===e.id){nt();return}xe=e.id,t.style.background=g.bgActive,t.style.fontWeight="600",Ot();const{kind:n,index:o}=e.variable;if(n==="test"){const d=o??0,i=ce();if(i===void 0||i.some(a=>a.testNumber===d))B({plotMode:"value",activeTest:d,highlightBin:void 0},{fireCallback:!1});else{B({highlightBin:void 0},{fireCallback:!1});const l=he.has(c.plotMode??"hardBin")?null:Bn(e);if(l){for(const p of l)C[p]?.setOptions({plotMode:"value",activeTest:d});Fe=[...l]}}}else n==="softBin"?B({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):B({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1});kt(),Et();const r=e.highlight;if(r.kind==="wafer"){Dt(r.waferIndices);const d=Bt(e);for(const i of r.waferIndices){const l=O[i]?.statsSummary?.findings.find(p=>Bt(p)===d)?.highlight?.dieKeys;l?.length&&tt(l,[i])}}else r.kind==="bin"?r.dieKeys?.length&&tt(r.dieKeys):(r.kind==="region"||r.kind==="dies")&&r.dieKeys?.length&&tt(r.dieKeys)}function le(){if(!R)return;const e=!!h;R.style.display=(H||et())&&e&&!ke?"flex":"none";const t=h?h.style.display!=="none":!1;(H?.hasNotableFindings||x.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?R.style.color=g.findingIndicator:R.dataset.active||(R.style.color=g.icon)}const $=u.ownerDocument.createElement("div");$.dataset.wmapToolbar="gallery",Object.assign($.style,{flexShrink:"0",marginLeft:"auto",display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:z.control,padding:"0",boxShadow:Le.panel,flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const Tt=()=>{const e=Se();e&&(e.remove(),Ce(null)),$e(K,!1)},K=Z("mode","Plot mode",()=>{if(Se()){Tt();return}const e=x.flatMap(b=>b?.dies??[]),t=ce(),{testEntries:n,binEntries:o,stackedEntries:r}=Ro(e,t,{includeStacked:!0}),d=x.filter(Boolean).length,i=b=>{if(b===void 0)return d;let A=0;for(const X of x)X?.dies?.some(J=>fn(J,b)!==void 0||J.testValues?.[b]!==void 0)&&A++;return A},s=d<2?n:n.map(b=>{const A=i(b.activeTest);return A===d?b:{...b,label:`${b.label} \u2014 ${A} of ${d} wafers`}}),a=c.plotMode??"hardBin",l=c.activeTest??0;function p(b){return b.plotMode!==a?!1:b.plotMode==="value"?l===(b.activeTest??0):b.plotMode==="metadata"?c.activeMetadataKey===b.activeMetadataKey:!0}function y(b,A){b.activeTest!==void 0?B({plotMode:"value",activeTest:b.activeTest,activeMetadataKey:void 0,logScale:b.logScale}):b.activeMetadataKey!==void 0?B({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:b.activeMetadataKey,passFailDisplay:"off"}):B({plotMode:b.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),A.remove(),Ce(null),$e(K,!1)}const M=new Set,k=x.flatMap(b=>b?.metadataFields??[]).filter(b=>!M.has(b.key)&&M.add(b.key)).filter(b=>Io(e,b.key)).map(Ao),I=bo(K.getBoundingClientRect(),s,o,r,p,y,{makeMenuRow:vn,makeMenuSection:Sn},a,K.ownerDocument.defaultView??window,k);an(K).appendChild(I),Ce(I),$e(K,!0),sn(I,K,Tt)});$e(K,!1);const Tn=()=>O.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:Ln,sync:Lt}=Do(ue,()=>c.plotMode??"hardBin",()=>c.colorScheme??"default",Tn,e=>B({colorScheme:e}),{get:()=>c.markFailingDies??!1,set:e=>B({markFailingDies:e})});Lt();const $n=S.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function He(){const e=ce(),{testNumber:t}=io(c.activeTest??0,e);return{testNumber:t,td:lo(e,t)}}function $t(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function Me(){if((c.plotMode??"hardBin")!=="value")return!1;const{td:e}=He();return e!==void 0&&!mt(e)}function Wn(){if((c.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=He();return x.some(n=>n?.dies?.some(o=>fn(o,e,t)!==void 0))}function Rn(e,t){if(!t||!mt(t))return;const n=t.limitLow!==void 0||t.limitHigh!==void 0;if((cn(c)==="spec"&&n?"spec":c.colorbarRangeMode??"spec")==="spec"&&n)return;let d=1/0,i=-1/0;for(const s of x)if(s)for(const a of s.dies){const l=jo(a,e);l!==void 0&&(l<d&&(d=l),l>i&&(i=l))}if(isFinite(d))return d===i?[d,d+1]:[d,i]}function ot(){if((c.plotMode??"hardBin")!=="value")return;const{testNumber:e,td:t}=He(),n=Rn(e,t),o=n?{test:e,range:n}:void 0;c={...c,valueRange:o};for(const r of C)r&&r.setOptions({valueRange:o})}let it=!1;function In(){if(it)return;it=!0,(u.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{it=!1,ot()})}const An=Bo(ue,()=>Lo(c,$n,{functionalActive:Me(),hasLimits:$t()&&!Me(),hasRecorded:Wn()&&!Me()},e=>B(e)),()=>$o(c)),{btn:Pn,sync:Wt}=Eo(ue,()=>({plotMode:c.plotMode,legendPosition:ye}),e=>{ye=e;for(const t of C)t&&t.setOptions({legendPosition:ye})},{get:()=>Ie,set:e=>{Ie=e,yt()},blockedReason:we});Wt();const Fn=[{value:"mean",label:"Mean"},{value:"median",label:"Median"},{value:"stddev",label:"Std Dev"},{value:"min",label:"Min"},{value:"max",label:"Max"},{value:"count",label:"Count"}],Rt=St("aggr","Aggregation method",()=>Fn,()=>c.aggregationMethod??"mean",e=>B({aggregationMethod:e}));function It(){const e=c.plotMode==="stackedValues";Rt.style.display=e?"":"none"}It();const{btn:Hn,sync:At}=ko(ue,()=>({...c,functionalActive:Me()}),e=>B(e));At();const je=Z("specRange","Colorbar range: spec limits",()=>{const e=c.colorbarRangeMode==="data"?"spec":"data";B({colorbarRangeMode:e})});function Pt(){const e=(c.plotMode??"hardBin")==="value"&&$t()&&cn(c)==="off"&&!Me();je.style.display=e?"":"none";const t=(c.colorbarRangeMode??"spec")==="spec";ve(je,t),je.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}Pt();const jn=Oo(ue,()=>c,e=>B(e)),zn=Z("downloadAll","Download gallery PNG",no),Nn=St("columns","Columns",()=>[{value:"auto",label:"Auto"},{value:"1",label:"1 column"},{value:"2",label:"2 columns"},{value:"3",label:"3 columns"},{value:"4",label:"4 columns"},{value:"5",label:"5 columns"}],()=>v!=null?String(v):"auto",e=>Ut(e==="auto"?void 0:Number(e))),E=u.ownerDocument.createElement("div");Object.assign(E.style,{display:"inline-flex",alignItems:"center",gap:"0"}),$.appendChild(E),L&&E.appendChild(K),E.appendChild(Ln),E.appendChild(Rt),E.appendChild(Hn),E.appendChild(je),E.appendChild(V()),E.appendChild(An),E.appendChild(V()),E.appendChild(Pn),E.appendChild(V()),E.appendChild(jn),E.appendChild(V()),E.appendChild(Nn),E.appendChild(V()),E.appendChild(zn),(H||et())&&(R=Z("findings","Summary panel",()=>{if(!h)return;const e=h.style.display!=="none";e||j(),h.style.display=e?"none":"flex",ve(R,!e),le()}),$.appendChild(V()),$.appendChild(R));let _=null,ze=null,Y=[],Ft=!1;function Ht(){const e=zo({lotStatsSummary:H,result:{warnings:[...x.flatMap(n=>n?.warnings??[]),...wt().warnings]}}),t=e.length!==Y.length||e.some((n,o)=>n.code!==Y[o]?.code||n.message!==Y[o]?.message);Y=e,(t||!Ft)&&(Ft=!0,f.warnings?.onWarning?.(e)),Vn()}function Vn(){if(!_||!ze)return;const e=Y.length,t=e>0;if(_.style.display=t?"flex":"none",ze.style.display=t?"":"none",!t)return;const n=Vo(Y[0]),o=`${e} data ${e===1?"warning":"warnings"}`;_.style.color=n==="error"?g.errText:g.warnText,_.ariaLabel=n==="error"?`${o} \u2014 wafers in this lot may be positionally wrong`:o}(f.warnings?.display??!0)&&(ze=V(),_=Z("warning","Data warnings",()=>{const e=Se();if(Pe(new MouseEvent("click")),e)return;const t=No(_.getBoundingClientRect(),Y,_.ownerDocument.defaultView??window);an(u).appendChild(t),Ce(t),sn(t,_,()=>Pe(new MouseEvent("click")))}),$e(_,!1),$.appendChild(ze),$.appendChild(_)),Ht();let ae=null;se&&(ae=Z("analysis","Insights",()=>{Nt(!ke)}),ae.dataset.wmapInsightsBtn="1",$.appendChild(V()),$.appendChild(ae));function jt(){import("./userGuideHtml.js").then(e=>Mo({buildWaferMap:Ho,renderWaferMap:gt,renderWaferGallery,analyzeWaferMap:Ze},e.USER_GUIDE_HTML,Qe,u))}oe&&($.appendChild(V()),$.appendChild(Z("help","User guide",()=>jt())));const fe=u.ownerDocument.createElement("div");fe.dataset.wmapGalleryMeta="1",Object.assign(fe.style,{flex:"1",minWidth:"0",overflow:"hidden",display:"flex",alignItems:"center",padding:`${w.sm} ${w.lg}`,fontSize:T.sub,lineHeight:Xe.none,boxSizing:"border-box"});const Ne=u.ownerDocument.createElement("div");Object.assign(Ne.style,{background:g.canvasBg,display:"flex",alignItems:"stretch",gap:w.lg,paddingBottom:w.lg,minWidth:"0"});const Q=u.ownerDocument.createElement("div");Q.dataset.wmapGalleryLegend="1",Object.assign(Q.style,{display:"flex",flexDirection:"column",gap:w.sm,background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:z.container,padding:`${w.sm} ${w.lg}`,marginBottom:w.lg,boxShadow:Le.panel,fontSize:T.body,lineHeight:Xe.none,boxSizing:"border-box",width:"100%",minWidth:"0"});const G=u.ownerDocument.createElement("div");Object.assign(G.style,{display:"flex",flexDirection:"row",alignItems:"flex-start"});let pe=null,De=null,zt=null;function _n(){return se?pe?Promise.resolve(pe):(zt??=import("./insightsTab.js").then(({createInsightsTab:e})=>(pe=e({getItems:()=>x,getLotStats:()=>H,getColorSchemeName:()=>c.colorScheme??"default",passBins:We,getRingCount:()=>c.ringCount??4,defaultView:f.insights?.defaultView,onOpenGuide:void 0,showMetadataStrip:!1,onSaveImage:f.onSaveImage,onSaveText:f.onSaveText,ownerDocument:u.ownerDocument,openWafer:(t,n,o)=>{const r=x[t];if(!r)return;let d=null;const i=xo({title:n,onClose:()=>d?.destroy(),anchor:u});Yt(i,n,r.wafer.metadata??void 0),d=dt(i.contentWrap,r,o)}}),De=pe.el,De.style.display="none",u.appendChild(De),pe)),zt):Promise.resolve(null)}let ke=!1;function Nt(e){se&&(ke=e,De&&(De.style.display=e?"flex":"none"),G.style.display=e?"none":"flex",E.style.display=e?"none":"inline-flex",$.style.display="inline-flex",ae&&(ve(ae,e),ae.innerHTML=e?Te.wafer:Te.analysis,ae.ariaLabel=e?"Back to gallery view":"Insights"),le(),Ge(),e&&_n().then(t=>{!t||!ke||(t.el.style.display="flex",t.render())}))}se&&f.insights?.defaultOpen&&queueMicrotask(()=>Nt(!0));const Gn=4,lt=240,Vt=480,Kn=720,qn=1.25,_t=f.maxSize;let q=_t??Vt;function Gt(e){const t=P*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const r=o.dies[0].width;if(!(r>0))continue;const d=o.wafer.radius*2*(Gn/r),i=Math.ceil(d+t);(n==null||i>n)&&(n=i)}return n}function Un(e){const t=Gt(e);return t==null?lt:Math.min(q,Math.max(lt,t))}function Xn(e){if(_t!=null)return!1;const t=Gt(e);if(t==null)return!1;const n=Math.min(Kn,Math.max(Vt,t));return n<=q?!1:(q=n,!0)}function Zn(){for(const e of Array.from(W.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${q}px`,e.style.maxHeight=`${q}px`)}let Ve=lt,Kt=0;function qt(e){const t=Xn(e);if(t&&Zn(),v!=null){t&&_e();return}const n=Un(e);n>Ve&&(Ve=n),_e()}function Ut(e){v=e,_e()}function at(e){return`repeat(${e}, minmax(0, ${q}px))`}function Xt(e){W.style.gridTemplateColumns!==e&&(W.style.gridTemplateColumns=e)}function _e(){if(v!=null){Xt(at(v));return}const e=Math.max(1,Kt),t=12,n=W.clientWidth||0,o=d=>(n-t*(d-1))/d;let r=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const d=Math.min(q,Ve*qn),i=s=>{let a=0;for(;a<e&&o(a+1)>=s;)a++;return a};r=i(d)||i(Ve)||1}Xt(at(r))}const W=u.ownerDocument.createElement("div");if(Object.assign(W.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:at(1),gap:w.xl,paddingLeft:ne,paddingRight:ne,justifyContent:"start",alignContent:"start",isolation:"isolate"}),re?.placement){const e=re.placement;h=ht(e,ne,u.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.display="flex",h.style.flexDirection="column"}else if(H||et()){const e=!!re?.defaultOpen;h=ht("right",ne,u.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.flexDirection="column",h.style.display=e?"flex":"none",j()}le(),h?.style.display!=="none"&&R&&ve(R,!0),(re?.placement??"right")==="left"?(h&&G.appendChild(h),G.appendChild(W)):(G.appendChild(W),h&&G.appendChild(h));const Ee=u.ownerDocument.createElement("div");Object.assign(Ee.style,{position:"sticky",top:"0",display:"flex",flexDirection:"column",paddingLeft:ne,paddingRight:ne,paddingTop:ne,zIndex:"1",background:g.menuBg}),Ne.appendChild(fe),Ne.appendChild($),Ee.appendChild(Ne),Ee.appendChild(Q),u.appendChild(Ee),u.appendChild(G);function Ge(){Q.innerHTML="";const e=c.plotMode??"hardBin",t=!ke&&nn.has(e),n=O.filter(m=>m!=null),o=n.find(m=>m.isLotStack),r=Go(n.map(m=>({metadata:m.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),d=e==="metadata",i=c.activeMetadataKey,s=t&&!d?mn(n,m=>(e==="softBin"?m.sbin:m.hbin)??void 0):{counts:new Map,total:0},a=[...s.counts.keys()].sort((m,D)=>m-D),l=t&&d&&i?mn(n,m=>{const D=m.metadata?.[i];return D!=null&&(typeof D=="string"||typeof D=="number"||typeof D=="boolean")?String(D):void 0}):{counts:new Map,total:0},p=new Set(l.counts.keys()),y=t&&d?[...p].sort(_o):[];if(fe.innerHTML="",r&&fe.appendChild(r),fe.style.display=r?"flex":"none",!a.length&&!y.length){Q.style.display="none";return}Q.style.display="flex";const M=u.ownerDocument.createElement("div");Object.assign(M.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:`${w.sm} ${w.xl}`,maxHeight:"86px",overflowY:"auto",overflowX:"hidden"}),Q.appendChild(M);const k=ao(c.colorScheme),I=c.highlightBin,b=O.flatMap(m=>m?.metadataFields??[]).find(m=>m.key===i),A=d?b?.label??(i?Uo(i):"Metadata"):po[e],X=u.ownerDocument.createElement("span");if(X.textContent=A,Object.assign(X.style,{fontSize:T.body,fontWeight:"700",letterSpacing:co,textTransform:"uppercase",color:g.label,flexShrink:"0"}),M.appendChild(X),!d&&s.total>0){const m=We.reduce((me,ut)=>me+(s.counts.get(ut)??0),0),D=m/s.total*100,ee=u.ownerDocument.createElement("span");ee.textContent=`Yield ${Ye(D)}`,Object.assign(ee.style,{fontSize:T.body,fontWeight:"700",color:g.value,whiteSpace:"nowrap",flexShrink:"0"});const te=u.ownerDocument.createElement("span");te.textContent=`${m.toLocaleString()} / ${s.total.toLocaleString()} dies`,Object.assign(te.style,{fontSize:T.body,color:g.label,whiteSpace:"nowrap",flexShrink:"0"}),M.appendChild(ee),M.appendChild(te)}if(d){const m=c.highlightMetadataValue;y.forEach((D,ee)=>{const te=m===D,me=b?.values?.find(ft=>ft.value===D),ut=me?.color??so(ee),en=l.counts.get(D)??0;hn(M,{color:ut,isActive:te,label:me?.label??D,count:en,percent:l.total>0?en/l.total*100:void 0,onClick:()=>{const ft=c.highlightMetadataValue===D?void 0:D;B({highlightMetadataValue:ft})}})});return}const J=e==="softBin"?O.flatMap(m=>m?.sbinDefs??[]):O.flatMap(m=>m?.hbinDefs??[]),qe=new Set,ct=[];for(const m of J)qe.has(m.bin)||(qe.add(m.bin),ct.push(m));const Ue=ct.length>0?new Map(ct.map(m=>[m.bin,m])):null,Jt=m=>{const D=Ue?.get(m);return(c.colorScheme==="custom"?D?.color:void 0)??k.forBin(m)};for(const m of a){const D=I===m,ee=Ue?.get(m),te=s.counts.get(m)??0;hn(M,{color:Jt(m),isActive:D,label:ee?.name?`${m} \xB7 ${ee.name}`:`Bin ${m}`,count:te,percent:s.total>0?te/s.total*100:void 0,onClick:()=>{const me=c.highlightBin===m?void 0:m;B({highlightBin:me})}})}s.total>0&&a.length>1&&Q.appendChild(Qo(u.ownerDocument,[...s.counts.entries()].sort(([,m],[,D])=>D-m).map(([m,D])=>({color:Jt(m),count:D,label:Ue?.get(m)?.name?`${m} \xB7 ${Ue.get(m).name}`:`Bin ${m}`})),s.total))}function Be(e){const t=x.filter(s=>s!==null);if(!t.length)return[];const n=t.map(s=>s.dies.filter(Yo)),o=t[0].wafer,r=t.length,d=o.metadata?{...o,metadata:(({wafer:s,waferId:a,...l})=>l)(o.metadata)}:o;function i(s,a){return{...s,stats:{...s.stats,isLotStack:!0,aggregationMethod:a,lotSize:r}}}if(e==="stackedValues"){const s=ce();let a=s?.filter(mt);if(s!==void 0&&a?.length===0)return[];if(s?.length||(a=oo(t.flatMap(y=>y.dies)).map(y=>({testNumber:y,name:`Test ${y}`}))),!a?.length)return[];const l=c.aggregationMethod??"mean";return a.map(p=>{const y=Po(n,l,p.testNumber),M={testNumber:0,name:p.name,unit:p.unit};return{wafer:d,dies:y,testDefs:[M],label:`${p.name} \xB7 ${l}`,isLotStack:!0,aggrMethod:l,lotSize:r,statsSummary:i(Ze({wafer:d,dies:y,testDefs:[M]},{testNumbers:[0]}),l)}})}if(e==="stackedBins"){let s=be(t.flatMap(a=>a.hbinDefs??[]));return(!s||s.length===0)&&(s=[...new Set(t.flatMap(l=>l.dies.map(p=>p.hbin).filter(p=>p!=null)))].sort((l,p)=>l-p).map(l=>({bin:l,name:`Bin ${l}`}))),s.map(a=>{const l=un(n,a.bin,"hard"),p=[{bin:a.bin,name:a.name}];return{wafer:d,dies:l,hbinDefs:p,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:r,statsSummary:i(Ze({wafer:d,dies:l,hbinDefs:p}),"countBin")}})}if(e==="stackedSoftBins"){let s=be(t.flatMap(a=>a.sbinDefs??[]));return(!s||s.length===0)&&(s=[...new Set(t.flatMap(l=>l.dies.map(p=>p.sbin).filter(p=>p!=null)))].sort((l,p)=>l-p).map(l=>({bin:l,name:`Bin ${l}`}))),s.map(a=>{const l=un(n,a.bin,"soft"),p=[{bin:a.bin,name:a.name}];return{wafer:d,dies:l,sbinDefs:p,label:`${a.bin} \xB7 ${a.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:r,statsSummary:i(Ze({wafer:d,dies:l,sbinDefs:p}),"countBin")}})}return t}function st(e){const t=x.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:c.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}const Yn=new Set(["default","accessible","custom"]);function B(e,{fireCallback:t=!0}={}){const n=c.plotMode,o=we()!==null;c={...c,...e};const r=c.plotMode,d=he.has(r),i=n!==void 0&&he.has(n),s=Ae>0;if(e.plotMode!==void 0&&e.plotMode!==n&&(r==="hardBin"||r==="softBin")&&!Yn.has(c.colorScheme??"")&&(c={...c,colorScheme:"default"}),e.plotMode!==void 0)if(d){const l=st(r);if(c={...c,...l},s)for(const p of C)p&&p.setOptions(e);else U(Be(r))}else if(i){const{valueRange:l,lotSize:p,aggregationMethod:y,...M}=c;if(c=M,s)for(const k of C)k&&k.setOptions(e);else U(x.filter(k=>k!==null))}else for(const l of C)l&&l.setOptions(e);else if(e.aggregationMethod!==void 0&&r==="stackedValues")if(s)for(const l of C)l&&l.setOptions(e);else U(Be("stackedValues"));else for(const l of C)l&&l.setOptions(e);we()!==null!==o&&yt(),Ge(),It(),Wt(),Lt();const a=e.plotMode!==void 0&&e.plotMode!==n;if((e.colorScheme!==void 0||a)&&j(),At(),Pt(),ot(),t){const l=Object.keys(e);f.onViewOptionsChange?.(c,l,Fo(l))}}function Zt(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0"});const r=e.createElement("span");r.textContent=t,Object.assign(r.style,{fontWeight:"700",fontSize:T.sub,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(r);const d=gn(n??{});let i=null;if(d.length>0){const s=e.createElement("span");Object.assign(s.style,{fontSize:T.body,lineHeight:Xe.none,color:g.label,flexShrink:"0"}),s.textContent="\u25BE",o.appendChild(s),Object.assign(o.style,{cursor:"pointer",borderRadius:z.control}),o.addEventListener("mouseenter",()=>{o.style.background=g.bgHover}),o.addEventListener("mouseleave",()=>{o.style.background="none"}),i=e.createElement("div"),i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:on,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:Le.menu,padding:`${w.md} ${w.lg}`,fontSize:T.body,display:"none"});const a=pn(n??{});a&&i.appendChild(a),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),rn(o,l=>{s.textContent=l?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(l)),i&&(i.style.display=l?"block":"none")})}return{wrap:o,metaPanel:i}}function Yt(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),r=gn(n??{});if(!o||r.length===0)return;const d=o.parentElement,i=u.ownerDocument.createElement("div");Object.assign(i.style,{display:"flex",alignItems:"center",gap:w.xs,flex:"1",minWidth:"0",cursor:"pointer"}),pt(i,"bare"),d?.insertBefore(i,o),i.appendChild(o);const s=u.ownerDocument.createElement("span");Object.assign(s.style,{fontSize:T.body,lineHeight:Xe.none,color:g.label,flexShrink:"0"}),s.textContent="\u25BE",i.appendChild(s);const a=u.ownerDocument.createElement("div");a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:on,background:g.menuBg,borderBottom:`1px solid ${g.menuBorder}`,boxShadow:Le.menu,padding:`${w.md} ${w.lg}`,fontSize:T.body,display:"none"});const l=pn(n??{});l&&a.appendChild(l),e.contentWrap.style.position="relative",e.contentWrap.appendChild(a),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),rn(i,p=>{s.textContent=p?"\u25B4":"\u25BE",i.setAttribute("aria-expanded",String(p)),a.style.display=p?"block":"none"})}function rt(e,t,n){const o=u.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:z.container,boxShadow:Le.panel,overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${q}px`,maxHeight:`${q}px`});const r=u.ownerDocument.createElement("div");Object.assign(r.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:w.sm});const{wrap:d,metaPanel:i}=Zt(document,e.label??"",e.wafer.metadata??void 0);r.appendChild(d);const s=u.ownerDocument.createElement("button");s.dataset.wmapExpandBtn="1",s.setAttribute("aria-label","Open full view"),dn(s),s.innerHTML=Te.expand,Object.assign(s.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${g.menuBorder}`,borderRadius:z.control,background:g.panelBg,color:g.label,padding:w.xxs,cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),pt(s),r.appendChild(s),o.appendChild(r);const a=u.ownerDocument.createElement("div");Object.assign(a.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(a),i&&a.appendChild(i),W.appendChild(o);const l=Ie||we()!==null,p=e.viewOptions?{...c,...e.viewOptions}:c,y=gt(a,e,{viewOptions:{...p,showLegend:l},toolbarControls:"full",showTooltip:!0,padding:P,legendPosition:ye,fallbackFormat:Re,statsSummary:e.statsSummary,onSaveImage:f.onSaveImage,onSaveText:f.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>Oe(t,e),showIdentity:!1,chromeInset:fo});return y.setViewControlsVisible(!1),y.setSummaryVisible(!1),s.onclick=()=>Oe(t,e),{card:o,ctrl:y,canvasWrapper:a,expandBtn:s}}function Qn(e){const t=de[e];if(!t)return;const n=[...N.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=Te.minimize,t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>eo(n.id)):(t.innerHTML=Te.expand,t.setAttribute("aria-label","Open full view"),t.onclick=()=>Oe(e,O[e]))}function U(e){to(),Se()?.remove(),Ce(null),nt(),O=[];for(const i of C)i&&i.destroy();C=[],ie=[],de=[],Ae=0,W.innerHTML="",Kt=e.length,qt(e.map(i=>typeof i=="function"?null:i));const t=[];for(let i=0;i<e.length;i++){const s=e[i];if(typeof s=="function"){const a=u.ownerDocument.createElement("div");a.className="wmap-gallery-card",Object.assign(a.style,{background:g.menuBg,border:`1px solid ${g.menuBorder}`,borderRadius:z.container,aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const l=u.ownerDocument.createElement("span");l.textContent="\u2026",Object.assign(l.style,{color:g.label,fontSize:"18px"}),a.appendChild(l),W.appendChild(a),O.push(null),C.push(null),ie.push(null),de.push(null),t.push({index:i,factory:s,placeholder:a}),Ae++}else{const{ctrl:a,canvasWrapper:l,expandBtn:p}=rt(s,i,e.length);O.push(s),C.push(a),ie.push(l),de.push(p)}}O.flatMap(i=>i?[...i.hbinDefs??[],...i.sbinDefs??[]]:[]).some(i=>i.color)&&!f.viewOptions?.colorScheme&&(c={...c,colorScheme:"custom"}),Ge(),ot();const o=++Je;let r=0;function d(){if(o!==Je)return;if(r>=t.length){if(he.has(c.plotMode)){const I=c.plotMode;U(Be(I))}return}const{index:i,factory:s,placeholder:a}=t[r++],l=s();O[i]=l,x[i]=l,qt([l]);const{card:p,ctrl:y,canvasWrapper:M,expandBtn:k}=rt(l,i,e.length);C[i]=y,ie[i]=M,de[i]=k,Ae--,a.replaceWith(p),Ge(),In(),!h&&!re?.placement&&l.statsSummary?.findings.length?(h=ht("right",ne,u.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.flexDirection="column",h.style.display="none",(re?.placement??"right")==="left"?G.insertBefore(h,W):G.appendChild(h),j(),R||(R=Z("findings","Summary panel",()=>{if(!h)return;const b=h.style.display!=="none";b||j(),h.style.display=b?"none":"flex",ve(R,!b),le()}),$.appendChild(V()),$.appendChild(R)),le()):h&&h.style.display!=="none"&&j(),le(),setTimeout(d,0)}t.length>0&&setTimeout(d,0)}if(he.has(c.plotMode)&&x.length>0){const e=st(c.plotMode);c={...c,...e},U(Be(c.plotMode))}else U(S);let ge=0;const Qt=new(u.ownerDocument.defaultView??window).ResizeObserver(()=>{if(ge)return;ge=(u.ownerDocument.defaultView??window).requestAnimationFrame(()=>{ge=0,v==null&&_e()})});Qt.observe(W),h&&j();function Jn(e,t){const n=ie[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=u.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:g.label,fontSize:T.body,textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Oe(e,t){for(const i of N.values())if(i.cardIndex===e)return;const n=t.label??"Wafer map",o=yn++,r=C[e]?.getOptions(),d=yo(n);if(d){const i=d.document;i.title=n,Object.assign(i.documentElement.style,{height:"100%"}),Object.assign(i.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:T.family}),So(u,i.documentElement);const s=Co(u,i.documentElement,()=>I.setOptions({})),a=i.createElement("div");a.dataset.wmapWindowBanner="1",a.textContent=n,Object.assign(a.style,{display:"none",padding:`${w.sm} ${w.xl}`,fontSize:T.body,fontWeight:"700",background:g.warnBg,color:g.warnText,borderBottom:`1px solid ${g.warnBorder}`,flexShrink:"0"}),i.body.appendChild(a);const l=i.createElement("div");Object.assign(l.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),i.body.appendChild(l);const{wrap:p,metaPanel:y}=Zt(i,n,t.wafer.metadata??void 0),M=i.createElement("div");Object.assign(M.style,{display:"flex",alignItems:"center",padding:`${w.md} ${w.lg} ${w.sm}`,borderBottom:`1px solid ${g.menuBorder}`,flexShrink:"0",gap:w.sm}),M.appendChild(p),l.appendChild(M);const k=i.createElement("div");Object.assign(k.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),y&&k.appendChild(y),l.appendChild(k);const I=dt(k,t,void 0,r),b=setInterval(()=>{d.closed&&Ke(o)},400);d.addEventListener("pagehide",()=>Ke(o)),N.set(o,{id:o,ctrl:I,cardIndex:e,label:n,closePollId:b,stopThemeSync:s,close:()=>{d.closed||d.close()},setTitle:A=>{i.title=A,a.textContent=A,a.style.display="block"}})}else{const i=wo({title:n,onClose:()=>Ke(o),anchor:u});i.contentWrap.style.flexDirection="column",Yt(i,n,t.wafer.metadata??void 0);const s=dt(i.contentWrap,t,void 0,r);N.set(o,{id:o,ctrl:s,cardIndex:e,label:n,closePollId:null,close:()=>i.close(),setTitle:a=>{const l=i.box.querySelector("[data-wmap-window-title]");l&&(l.textContent=a,l.title=a)}})}C[e]?.destroy(),C[e]=null,Jn(e,d!==null),Qn(e)}function dt(e,t,n,o){const r=t.viewOptions?{...c,...t.viewOptions}:c,d=o?{...r,...o}:r,s={...n!==void 0?{...d,plotMode:"value",activeTest:n}:d,showLegend:!0},a=gt(e,t,{viewOptions:s,toolbarControls:"full",showTooltip:!0,padding:P,legendPosition:ye,fallbackFormat:Re,statsSummary:t.statsSummary,onSaveImage:f.onSaveImage,onSaveText:f.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showIdentity:!1});return a.setViewControlsVisible(!0),a.setSummaryVisible(!0),a.setExpandVisible(!1),a}function Ke(e){const t=N.get(e);if(!t)return;N.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const o=t.cardIndex,r=O[o];if(!r)return;const d={...r,viewOptions:n};O[o]=d;const{card:i,ctrl:s,canvasWrapper:a,expandBtn:l}=rt(d,o,O.length);ie[o]?.parentElement?.replaceWith(i),C[o]=s,ie[o]=a,de[o]=l}function eo(e){const t=N.get(e);t&&(t.close(),Ke(e))}function to(){for(const e of N.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function no(){const e=[...W.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),r=e[0].width,d=e[0].height,i=8,s=(u.ownerDocument.defaultView??window).devicePixelRatio||1,a=Math.round(26*s),l=Math.round(12*s),p=u.ownerDocument.createElement("canvas");p.width=n*r+(n-1)*i,p.height=o*(d+a)+(o-1)*i;const y=p.getContext("2d"),M=ro(W);y.fillStyle=M.background,y.fillRect(0,0,p.width,p.height),e.forEach((k,I)=>{const b=I%n,A=Math.floor(I/n),X=b*(r+i),J=A*(d+a+i),qe=k.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";y.fillStyle=M.surface,y.fillRect(X,J,r,a),y.fillStyle=M.text,y.font=`700 ${l}px system-ui, sans-serif`,y.textAlign="left",y.textBaseline="middle",y.fillText(qe,X+Math.round(10*s),J+a/2,r-Math.round(20*s)),y.drawImage(k,X,J+a)}),p.toBlob(k=>{k&&To(k,F,f.onSaveImage)})}return{setItems(e){x=e.map(n=>typeof n=="function"?null:n);const t=c.plotMode;if(he.has(t))if(e.some(o=>typeof o=="function"))U(e);else{const o=st(t);c={...c,...o},U(Be(t))}else U(e)},setOptions(e){B(e,{fireCallback:!1})},getOptions(){return{...c}},setFallbackFormat(e){Re=e;for(const t of C)t&&t.setFallbackFormat(e)},setFindingsNotice(e){Mt=e,j()},setLotStatsSummary(e){H=e,Ht(),h&&j(),le()},setColumns(e){Ut(e)},openUserGuide:jt,destroy(){Je++;for(const e of[...N.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();N.clear();for(const e of C)e&&e.destroy();C=[],Se()?.remove(),Qt.disconnect(),ge&&((u.ownerDocument.defaultView??window).cancelAnimationFrame(ge),ge=0),u.ownerDocument.removeEventListener("click",Pe,!0),window.removeEventListener("blur",Ct),bn(),ln(),Ee.remove(),G.remove(),h?.remove(),pe?.destroy()}}}
|
|
1
|
+
import{getUniqueTestNumbers as ro,resolveTestNumber as co,findTestDef as fo,collectMetadataValues as uo}from"../renderer/buildView.js";import{metadataCategoricalValue as po}from"../core/metadata.js";import{resolveBinColors as go,binColorWarning as mo}from"../renderer/binColors.js";import{NO_DATA_FILL as ho}from"../renderer/colorMap.js";import{metadataValueColor as bo}from"../renderer/colorMap.js";import{resolveCanvasTheme as yo}from"./canvasTheme.js";import{ICONS as $e}from"./icons.js";import{SHADOW as We,LEADING as Ze,TRACKING as wo,controlStyle as xo,wireControlHover as mt,SPACE as x,EDGE_GUTTER as te,MAP_CHROME_INSET as vo,RADIUS as V,FONT as O,CLR as m,sevColor as an,MODE_LABELS as Co,BIN_LEGEND_MODES as sn,STACKED_MODES as be,Z_ABOVE as rn,applyOverlayZ as So,getTooltip as Mo,hideTooltip as dn,createToolbarHelpers as Do,buildModeMenuEl as ko,openDetachWindow as Eo,openFloatingWindow as Bo,openModal as Oo,openReportModal as To,copyWmapThemeTokens as Lo,syncWmapPopupTheme as $o,openUserGuideWindow as Wo,makePaletteBtn as Ro,makeLogScaleBtn as Io,makeLegendStyleBtn as Ao,makeOverlaysBtn as Po,makeOrientationBtn as Fo,menuLayerFor as cn,saveImageBlob as Ho,markMenuTrigger as Re,wireMenuA11y as fn,wireExpandToggle as un,wireTooltip as pn,requestedPassFailDisplay as gn,overlayMenuRows as jo,anyOverlayActive as Vo,logWmapVersionOnce as zo,buildDataModeEntries as No,metadataKeyHasData as _o,metadataModeEntry as Go}from"./toolbar.js";import{aggregateValues as Ko,aggregateBinCounts as mn}from"../core/aggregates.js";import{renderWaferMap as ht}from"./renderWaferMap.js";import{classifyChanged as qo,COLOR_KEYS as Uo}from"./renderWaferMap.js";import{buildWaferMap as Xo,getTestPassStatus as hn,isParametricTest as bt,getDieTestValue as Zo}from"../renderer/buildWaferMap.js";import{analyzeWaferMap as Ye}from"../stats/analyzeWaferMap.js";import{collectWarnings as Yo,buildWarningsMenuEl as Qo,severityOf as Jo}from"./warnings.js";import{compareNatural as bn}from"../core/utils.js";import{createSummaryPanelEl as yt,buildMetadataStripRow as ei,buildCompactMetadataRows as yn,metadataEntries as wn,renderLotSummaryContent as ti}from"./summaryPanel.js";import{renderLotSummaryReportHtml as ni}from"../stats/renderSummaryReport.js";import{prettyKey as oi}from"../stats/facets.js";import{mergeTestDefs as ii}from"../stats/mergeTestDefs.js";import{getDieKey as li,hasPosition as ai}from"../core/dies.js";function ne(f){const C=new Set;return f.filter(p=>C.has(p.bin)?!1:(C.add(p.bin),!0))}const wt=12;function si(f,C,p){let P=C;if(C.length>wt){const v=C.slice(0,wt-1),T=C.slice(wt-1),oe=T.reduce((Je,re)=>Je+re.count,0);P=[...v,{color:m.label,count:oe,label:`Other (${T.length} bins)`}]}const F=f.createElement("div");Object.assign(F.style,{display:"flex",width:"100%",height:"8px",borderRadius:V.control,overflow:"hidden",border:`1px solid ${m.menuBorder}`,boxSizing:"border-box",marginTop:x.xs,flexShrink:"0"}),F.setAttribute("role","img"),F.setAttribute("aria-label",`Population split: ${P.map(v=>`${v.label} ${Qe(v.count/p*100)}`).join(", ")}`);for(const v of P){const T=v.count/p*100,oe=f.createElement("div");Object.assign(oe.style,{flex:`${T} 1 0`,minWidth:T>0?"2px":"0",background:v.color}),pn(oe,`${v.label} \xB7 ${v.count.toLocaleString()} dies \xB7 ${Qe(T)}`),F.appendChild(oe)}return F}function Qe(f){return f>0&&f<.1?"<0.1%":`${f.toFixed(1)}%`}function xn(f,C){const p=new Map;let P=0;for(const F of f)for(const v of F.dies){if(v.partial||v.edgeExcluded)continue;const T=C(v);T!==void 0&&(p.set(T,(p.get(T)??0)+1),P++)}return{counts:p,total:P}}function vn(f,C){const p=f.ownerDocument.createElement("div");Object.assign(p.style,{display:"flex",alignItems:"center",gap:"5px",cursor:"pointer",userSelect:"none",padding:`${x.xxs} ${x.xs}`,borderRadius:V.control});const P=f.ownerDocument.createElement("span");Object.assign(P.style,{display:"inline-block",width:"13px",height:"13px",flexShrink:"0",background:C.color,border:C.isActive?`2px solid ${m.iconActive}`:`1px solid ${m.menuBorder}`,borderRadius:V.control,boxSizing:"border-box"});const F=f.ownerDocument.createElement("span");if(F.textContent=C.label,Object.assign(F.style,{fontWeight:C.isActive?"700":"400",color:C.isActive?m.iconActive:m.text,whiteSpace:"nowrap"}),p.appendChild(P),p.appendChild(F),C.count!==void 0){const v=f.ownerDocument.createElement("span");if(v.textContent=C.count.toLocaleString(),Object.assign(v.style,{color:C.isActive?m.iconActive:m.text,fontWeight:C.isActive?"700":"400",whiteSpace:"nowrap"}),p.appendChild(v),C.percent!==void 0){const T=f.ownerDocument.createElement("span");T.textContent=Qe(C.percent),Object.assign(T.style,{color:m.label,whiteSpace:"nowrap"}),p.appendChild(T)}}p.setAttribute("role","button"),p.setAttribute("aria-pressed",C.isActive?"true":"false"),p.tabIndex=0,p.addEventListener("mouseenter",()=>{p.style.background=m.bgHover}),p.addEventListener("mouseleave",()=>{p.style.background="transparent"}),p.addEventListener("focus",()=>{p.style.background=m.bgHover}),p.addEventListener("blur",()=>{p.style.background="transparent"}),p.addEventListener("click",C.onClick),p.addEventListener("keydown",v=>{(v.key==="Enter"||v.key===" ")&&(v.preventDefault(),C.onClick())}),f.appendChild(p)}export function renderWaferGallery(f,C,p={}){zo();const P=p.cardPadding??6,F=p.downloadFilename??"wafer-gallery";let v=p.columns;const T=p.showPlotModeSelector??!0,oe=p.showHelpButton??!1,Je=p.userGuideExtension,re=p.insights?.enabled??!1,Cn=So(p.zIndex),de=p.summaryPanel,ye=p.passBins??[1];let Ie=p.fallbackFormat,H=p.lotStatsSummary,we=p.legendPosition??"default",Ae=p.perCardLegend??!1;function xe(){const e=d.plotMode??"hardBin";return sn.has(e)?null:d.colorbarRangeMode==="data"?"Each map has its own value range, so it keeps its own colour bar":"These wafers have no shared colour bar for value mode, so each map keeps its own"}function xt(){const e=Ae||xe()!==null;for(const t of S)t&&t.setOptions({showLegend:e})}let d={plotMode:"hardBin",showDieLabels:!1,showRingBoundaries:!1,showQuadrantBoundaries:!1,ringCount:4,rotation:0,flipX:!1,flipY:!1,...p.viewOptions},S=[],ie=[],ce=[],L=[],w=C.map(e=>typeof e=="function"?null:e);function vt(){return ii(w)}function fe(){if(w.some(e=>e?.testDefs?.length))return vt().defs}let et=0,Pe=0;const z=new Map;let Sn=0,A=null,ve=null,Ct=new Set,h=null,Mn={};function St(e){return w[e]?.statsSummary??H?.perWafer.find(t=>t.waferIndex===e)?.summary}function tt(){return!!(w.some(e=>e?.statsSummary?.findings.length)||H?.perWafer.some(e=>e.summary.findings.length))}const Dn=Mo(),ue=Do(Dn),{makeBtn:Z,setActive:Ce,makeSep:N,makeMenuRow:kn,makeMenuSection:En,makeDropdown:Mt,closeOpenMenu:Fe,getOpenMenu:Se,setOpenMenu:Me}=ue;f.ownerDocument.addEventListener("click",Fe,!0);const Dt=()=>dn();window.addEventListener("blur",Dt);let kt=p.findingsNotice;function Et(e){Ct=new Set(e);const t=[...I.querySelectorAll(".wmap-gallery-card")];let n;t.forEach((o,c)=>{const l=Ct.has(c);o.style.outline=l?`3px solid ${m.findingHighlight}`:"",o.style.outlineOffset=l?"-3px":"",l&&n===void 0&&(n=o)}),n?.scrollIntoView?.({behavior:"smooth",block:"nearest"})}function Bt(){Et([])}function Ot(){for(const e of S)e&&e.clearSelection()}function nt(e,t){const n=new Set(e),o=t??S.map((c,l)=>l);for(const c of o){const l=L[c],a=S[c];if(!l||!a)continue;const s=l.dies.filter(i=>n.has(li(i)));a.setSelection(s)}}function Bn(){const e=[];for(let t=0;t<w.length;t++){const n=w[t];if(!n)continue;const o=St(t)?.findings??[];o.length&&e.push({index:t,item:n,unusualCount:o.filter(c=>c.severity==="unusual").length,notableCount:o.filter(c=>c.severity==="notable").length,totalCount:o.length})}return e}function On(e){const t=L[e]??w[e];t&&Te(e,t)}function Tn(e){const t=St(e)?.findings??[];if(t.length)return{total:t.length,unusual:t.filter(n=>n.severity==="unusual").length,notable:t.filter(n=>n.severity==="notable").length}}function Ln(){const e=ne(w.flatMap(n=>n?.hbinDefs??[])),t=ne(w.flatMap(n=>n?.sbinDefs??[]));To(ni({items:w.map((n,o)=>({label:n?.label??`W${o+1}`,wafer:n?.wafer,dies:n?.dies,statsSummary:n?.statsSummary})),hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:fe(),passBins:ye,ringCount:d.ringCount}),{anchor:f})}function $n(){if(!h)return;h.innerHTML="";const e=Bn();if(w.length>0){const n=f.ownerDocument.createElement("div"),o=e.length,c=w.filter(Boolean).length;n.textContent=o===0?`No findings on any of the ${c} wafers`:`${o} of ${c} wafer${c===1?"":"s"} with findings`,Object.assign(n.style,{fontSize:O.body,color:m.label,marginBottom:x.md}),h.appendChild(n)}if(e.length>0){const n=f.ownerDocument.createElement("button");n.type="button",n.textContent="Summary report",Object.assign(n.style,{...xo("outlined"),marginBottom:x.lg,display:"block",width:"100%",textAlign:"left"}),mt(n),n.addEventListener("click",Ln),h.appendChild(n)}if(e.length===0){const n=f.ownerDocument.createElement("div");Object.assign(n.style,{color:m.icon,fontSize:O.body,padding:"4px 0"}),n.textContent="No findings on any wafer.",h.appendChild(n)}else for(const{index:n,item:o,unusualCount:c,notableCount:l,totalCount:a}of e){const s=c?"unusual":l?"notable":"info",i=c+l||a,r=f.ownerDocument.createElement("button");r.type="button",Object.assign(r.style,{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"5px 8px",marginBottom:x.xs,border:"none",borderLeft:`3px solid ${an(s)}`,borderRadius:V.control,background:m.bgHover,cursor:"pointer",fontSize:O.body,textAlign:"left",boxSizing:"border-box"}),r.addEventListener("mouseover",()=>{r.style.background=m.bgActive}),r.addEventListener("mouseout",()=>{r.style.background=m.bgHover});const u=f.ownerDocument.createElement("span");u.textContent=o.label??`W${n+1}`,Object.assign(u.style,{color:m.iconHover,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"});const b=f.ownerDocument.createElement("span");b.textContent=String(i),r.setAttribute("aria-label",`${o.label??`W${n+1}`} \u2014 ${i} finding${i===1?"":"s"}${c?`, ${c} unusual`:""} \u2014 view wafer`),Object.assign(b.style,{marginLeft:x.sm,flexShrink:"0",background:an(s),color:"#fff",borderRadius:V.container,padding:"1px 5px",fontSize:O.body,fontWeight:"600"}),r.appendChild(u),r.appendChild(b),r.addEventListener("click",()=>Te(n,o)),h.appendChild(r)}const t=f.ownerDocument.createElement("div");t.style.height="12px",h.appendChild(t)}function j(){if(h)if(H){const e=ne(w.flatMap(n=>n?.hbinDefs??[])),t=ne(w.flatMap(n=>n?.sbinDefs??[]));ti(h,{lotSummary:H,items:w,hbinDefs:e.length?e:void 0,sbinDefs:t.length?t:void 0,testDefs:fe(),passBins:ye,ringCount:d.ringCount,binColors:d.binColors,plotMode:d.plotMode??"hardBin",fallbackFormat:Ie,activeFindingId:ve,warnings:p.warnings?.display??!0?Y:[],findingsFilter:Mn,findingsNotice:kt,onFindingsFilterChange:j,onSaveText:p.onSaveText,onFindingClick:(n,o)=>{ve===n.id?ot():Rn(n,o),j()},onWaferClick:On,findingsFor:Tn,dieListOptions:p.dieList})}else $n()}function Wn(e){const t=e.highlight;return t?.kind==="wafer"&&t.waferIndices?.length?t.waferIndices:null}function Tt(e){return[e.variable.kind,e.variable.index??"",e.variable.bin??"",e.comparison.family,e.comparison.left,e.effect.direction].join("|")}let He=[];function Lt(){if(He.length!==0){for(const e of He)S[e]?.setOptions({plotMode:d.plotMode,activeTest:d.activeTest});He=[]}}function ot(){ve=null,Bt(),Ot(),Lt(),B({highlightBin:void 0},{fireCallback:!1})}function Rn(e,t){if(ve===e.id){ot();return}ve=e.id,t.style.background=m.bgActive,t.style.fontWeight="600",Lt();const{kind:n,index:o}=e.variable;if(n==="test"){const l=o??0,a=fe();if(a===void 0||a.some(i=>i.testNumber===l))B({plotMode:"value",activeTest:l,highlightBin:void 0},{fireCallback:!1});else{B({highlightBin:void 0},{fireCallback:!1});const r=be.has(d.plotMode??"hardBin")?null:Wn(e);if(r){for(const u of r)S[u]?.setOptions({plotMode:"value",activeTest:l});He=[...r]}}}else n==="softBin"?B({plotMode:"softBin",highlightBin:void 0},{fireCallback:!1}):B({plotMode:"hardBin",highlightBin:void 0},{fireCallback:!1});Bt(),Ot();const c=e.highlight;if(c.kind==="wafer"){Et(c.waferIndices);const l=Tt(e);for(const a of c.waferIndices){const r=L[a]?.statsSummary?.findings.find(u=>Tt(u)===l)?.highlight?.dieKeys;r?.length&&nt(r,[a])}}else c.kind==="bin"?c.dieKeys?.length&&nt(c.dieKeys):(c.kind==="region"||c.kind==="dies")&&c.dieKeys?.length&&nt(c.dieKeys)}function le(){if(!A)return;const e=!!h;A.style.display=(H||tt())&&e&&!Ee?"flex":"none";const t=h?h.style.display!=="none":!1;(H?.hasNotableFindings||w.some(o=>o?.statsSummary?.hasNotableFindings))&&!t?A.style.color=m.findingIndicator:A.dataset.active||(A.style.color=m.icon)}const R=f.ownerDocument.createElement("div");R.dataset.wmapToolbar="gallery",Object.assign(R.style,{flexShrink:"0",marginLeft:"auto",display:"inline-flex",flexDirection:"row",alignItems:"center",gap:"0",background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:V.control,padding:"0",boxShadow:We.panel,flexWrap:"wrap",minWidth:"0",overflowX:"auto"});const $t=()=>{const e=Se();e&&(e.remove(),Me(null)),Re(K,!1)},K=Z("mode","Plot mode",()=>{if(Se()){$t();return}const e=w.flatMap(y=>y?.dies??[]),t=fe(),{testEntries:n,binEntries:o,stackedEntries:c}=No(e,t,{includeStacked:!0}),l=w.filter(Boolean).length,a=y=>{if(y===void 0)return l;let $=0;for(const se of w)se?.dies?.some(X=>hn(X,y)!==void 0||X.testValues?.[y]!==void 0)&&$++;return $},s=l<2?n:n.map(y=>{const $=a(y.activeTest);return $===l?y:{...y,label:`${y.label} \u2014 ${$} of ${l} wafers`}}),i=d.plotMode??"hardBin",r=d.activeTest??0;function u(y){return y.plotMode!==i?!1:y.plotMode==="value"?r===(y.activeTest??0):y.plotMode==="metadata"?d.activeMetadataKey===y.activeMetadataKey:!0}function b(y,$){y.activeTest!==void 0?B({plotMode:"value",activeTest:y.activeTest,activeMetadataKey:void 0,logScale:y.logScale}):y.activeMetadataKey!==void 0?B({plotMode:y.plotMode,activeTest:void 0,activeMetadataKey:y.activeMetadataKey,passFailDisplay:"off"}):B({plotMode:y.plotMode,activeTest:void 0,activeMetadataKey:void 0,passFailDisplay:"off"}),$.remove(),Me(null),Re(K,!1)}const M=new Set,k=w.flatMap(y=>y?.metadataFields??[]).filter(y=>!M.has(y.key)&&M.add(y.key)).filter(y=>_o(e,y.key)).map(Go),D=ko(K.getBoundingClientRect(),s,o,c,u,b,{makeMenuRow:kn,makeMenuSection:En},i,K.ownerDocument.defaultView??window,k);cn(K).appendChild(D),Me(D),Re(K,!0),fn(D,K,$t)});Re(K,!1);const In=()=>L.flatMap(e=>e?[...e.hbinDefs??[],...e.sbinDefs??[]]:[]).some(e=>e.color),{btn:An,sync:Wt}=Ro(ue,()=>({...d,plotMode:d.plotMode??"hardBin"}),In,e=>B(e));Wt();const Pn=C.some(e=>typeof e!="function"&&(e.reticles?.length??0)>0);function je(){const e=fe(),{testNumber:t}=co(d.activeTest??0,e);return{testNumber:t,td:fo(e,t)}}function Rt(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=je();return e!==void 0&&(e.limitLow!==void 0||e.limitHigh!==void 0)}function De(){if((d.plotMode??"hardBin")!=="value")return!1;const{td:e}=je();return e!==void 0&&!bt(e)}function Fn(){if((d.plotMode??"hardBin")!=="value")return!1;const{testNumber:e,td:t}=je();return w.some(n=>n?.dies?.some(o=>hn(o,e,t)!==void 0))}function Hn(e,t){if(!t||!bt(t))return;const n=t.limitLow!==void 0||t.limitHigh!==void 0;if((gn(d)==="spec"&&n?"spec":d.colorbarRangeMode??"spec")==="spec"&&n)return;let l=1/0,a=-1/0;for(const s of w)if(s)for(const i of s.dies){const r=Zo(i,e);r!==void 0&&(r<l&&(l=r),r>a&&(a=r))}if(isFinite(l))return l===a?[l,l+1]:[l,a]}function It(){if((d.plotMode??"hardBin")!=="metadata")return;const e=d.activeMetadataKey;if(!e)return;const t=new Set;for(const n of w)if(n)for(const o of uo(n.dies,e))t.add(o);return{key:e,values:[...t].sort(bn)}}function it(){const e=It();if(!(e===void 0&&d.metadataValueOrder===void 0)){d={...d,metadataValueOrder:e};for(const t of S)t&&t.setOptions({metadataValueOrder:e})}}function lt(){if((d.plotMode??"hardBin")!=="value")return;const{testNumber:e,td:t}=je(),n=Hn(e,t),o=n?{test:e,range:n}:void 0;d={...d,valueRange:o};for(const c of S)c&&c.setOptions({valueRange:o})}let at=!1;function jn(){if(at)return;at=!0,(f.ownerDocument.defaultView?.requestAnimationFrame??(t=>setTimeout(()=>t(0),0)))(()=>{at=!1,lt(),it(),At()})}function Ve(){const e=ne(w.flatMap(o=>o?.hbinDefs??[])),t=ne(w.flatMap(o=>o?.sbinDefs??[]));function*n(){for(const o of w)o&&(yield*o.dies)}return go(n(),{passBins:ye,binColorScheme:d.binColorScheme,useDefinedBinColors:d.useDefinedBinColors,hbinDefs:e,sbinDefs:t})}function At(){const e=Ve();d={...d,binColors:e};for(const t of S)t&&t.setOptions({binColors:e})}const Vn=Po(ue,()=>jo(d,Pn,{functionalActive:De(),hasLimits:Rt()&&!De(),hasRecorded:Fn()&&!De(),binMode:(d.plotMode??"hardBin")==="hardBin"||(d.plotMode??"hardBin")==="softBin"},e=>B(e)),()=>Vo(d)),{btn:zn,sync:Pt}=Ao(ue,()=>({plotMode:d.plotMode,legendPosition:we}),e=>{we=e;for(const t of S)t&&t.setOptions({legendPosition:we})},{get:()=>Ae,set:e=>{Ae=e,xt()},blockedReason:xe});Pt();const Nn=[{value:"mean",label:"Mean"},{value:"median",label:"Median"},{value:"stddev",label:"Std Dev"},{value:"min",label:"Min"},{value:"max",label:"Max"},{value:"count",label:"Count"}],Ft=Mt("aggr","Aggregation method",()=>Nn,()=>d.aggregationMethod??"mean",e=>B({aggregationMethod:e}));function Ht(){const e=d.plotMode==="stackedValues";Ft.style.display=e?"":"none"}Ht();const{btn:_n,sync:jt}=Io(ue,()=>({...d,functionalActive:De()}),e=>B(e));jt();const ze=Z("specRange","Colorbar range: spec limits",()=>{const e=d.colorbarRangeMode==="data"?"spec":"data";B({colorbarRangeMode:e})});function Vt(){const e=(d.plotMode??"hardBin")==="value"&&Rt()&&gn(d)==="off"&&!De();ze.style.display=e?"":"none";const t=(d.colorbarRangeMode??"spec")==="spec";Ce(ze,t),ze.ariaLabel=t?"Colorbar range: spec limits (click for data range)":"Colorbar range: data range (click for spec limits)"}Vt();const Gn=Fo(ue,()=>d,e=>B(e)),Kn=Z("downloadAll","Download gallery PNG",ao),qn=Mt("columns","Columns",()=>[{value:"auto",label:"Auto"},{value:"1",label:"1 column"},{value:"2",label:"2 columns"},{value:"3",label:"3 columns"},{value:"4",label:"4 columns"},{value:"5",label:"5 columns"}],()=>v!=null?String(v):"auto",e=>Yt(e==="auto"?void 0:Number(e))),E=f.ownerDocument.createElement("div");Object.assign(E.style,{display:"inline-flex",alignItems:"center",gap:"0"}),R.appendChild(E),T&&E.appendChild(K),E.appendChild(An),E.appendChild(Ft),E.appendChild(_n),E.appendChild(ze),E.appendChild(N()),E.appendChild(Vn),E.appendChild(N()),E.appendChild(zn),E.appendChild(N()),E.appendChild(Gn),E.appendChild(N()),E.appendChild(qn),E.appendChild(N()),E.appendChild(Kn),(H||tt())&&(A=Z("findings","Summary panel",()=>{if(!h)return;const e=h.style.display!=="none";e||j(),h.style.display=e?"none":"flex",Ce(A,!e),le()}),R.appendChild(N()),R.appendChild(A));let _=null,Ne=null,Y=[],zt=!1;function _e(){const e=Yo({lotStatsSummary:H,result:{warnings:[...w.flatMap(n=>n?.warnings??[]),...vt().warnings]},extra:[d.binColors&&mo(d.binColors,d.plotMode)].filter(n=>!!n)}),t=e.length!==Y.length||e.some((n,o)=>n.code!==Y[o]?.code||n.message!==Y[o]?.message);Y=e,(t||!zt)&&(zt=!0,p.warnings?.onWarning?.(e)),Un()}function Un(){if(!_||!Ne)return;const e=Y.length,t=e>0;if(_.style.display=t?"flex":"none",Ne.style.display=t?"":"none",!t)return;const n=Jo(Y[0]),o=`${e} data ${e===1?"warning":"warnings"}`;_.style.color=n==="error"?m.errText:m.warnText,_.ariaLabel=n==="error"?`${o} \u2014 some wafers may be positionally wrong`:o}(p.warnings?.display??!0)&&(Ne=N(),_=Z("warning","Data warnings",()=>{const e=Se();if(Fe(new MouseEvent("click")),e)return;const t=Qo(_.getBoundingClientRect(),Y,_.ownerDocument.defaultView??window);cn(f).appendChild(t),Me(t),fn(t,_,()=>Fe(new MouseEvent("click")))}),Re(_,!1),R.appendChild(Ne),R.appendChild(_)),_e();let ae=null;re&&(ae=Z("analysis","Insights",()=>{Gt(!Ee)}),ae.dataset.wmapInsightsBtn="1",R.appendChild(N()),R.appendChild(ae));function Nt(){import("./userGuideHtml.js").then(e=>Wo({buildWaferMap:Xo,renderWaferMap:ht,renderWaferGallery,analyzeWaferMap:Ye},e.USER_GUIDE_HTML,Je,f))}oe&&(R.appendChild(N()),R.appendChild(Z("help","User guide",()=>Nt())));const pe=f.ownerDocument.createElement("div");pe.dataset.wmapGalleryMeta="1",Object.assign(pe.style,{flex:"1",minWidth:"0",overflow:"hidden",display:"flex",alignItems:"center",padding:`${x.sm} ${x.lg}`,fontSize:O.sub,lineHeight:Ze.none,boxSizing:"border-box"});const Ge=f.ownerDocument.createElement("div");Object.assign(Ge.style,{background:m.canvasBg,display:"flex",alignItems:"stretch",gap:x.lg,paddingBottom:x.lg,minWidth:"0"});const Q=f.ownerDocument.createElement("div");Q.dataset.wmapGalleryLegend="1",Object.assign(Q.style,{display:"flex",flexDirection:"column",gap:x.sm,background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:V.container,padding:`${x.sm} ${x.lg}`,marginBottom:x.lg,boxShadow:We.panel,fontSize:O.body,lineHeight:Ze.none,boxSizing:"border-box",width:"100%",minWidth:"0"});const G=f.ownerDocument.createElement("div");Object.assign(G.style,{display:"flex",flexDirection:"row",alignItems:"flex-start"});let ge=null,ke=null,_t=null;function Xn(){return re?ge?Promise.resolve(ge):(_t??=import("./insightsTab.js").then(({createInsightsTab:e})=>(ge=e({getItems:()=>w,getLotStats:()=>H,getBinColors:()=>d.binColors??Ve(),passBins:ye,getRingCount:()=>d.ringCount??4,defaultView:p.insights?.defaultView,onOpenGuide:void 0,showMetadataStrip:!1,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,ownerDocument:f.ownerDocument,openWafer:(t,n,o)=>{const c=w[t];if(!c)return;let l=null;const a=Oo({title:n,onClose:()=>l?.destroy(),anchor:f});en(a,n,c.wafer.metadata??void 0),l=ft(a.contentWrap,c,o)}}),ke=ge.el,ke.style.display="none",f.appendChild(ke),ge)),_t):Promise.resolve(null)}let Ee=!1;function Gt(e){re&&(Ee=e,ke&&(ke.style.display=e?"flex":"none"),G.style.display=e?"none":"flex",E.style.display=e?"none":"inline-flex",R.style.display="inline-flex",ae&&(Ce(ae,e),ae.innerHTML=e?$e.wafer:$e.analysis,ae.ariaLabel=e?"Back to gallery view":"Insights"),le(),Ue(),e&&Xn().then(t=>{!t||!Ee||(t.el.style.display="flex",t.render())}))}re&&p.insights?.defaultOpen&&queueMicrotask(()=>Gt(!0));const Zn=4,st=240,Kt=480,Yn=720,Qn=1.25,qt=p.maxSize;let q=qt??Kt;function Ut(e){const t=P*2+110+2;let n=null;for(const o of e){if(o==null||!o.dies?.length)continue;const c=o.dies[0].width;if(!(c>0))continue;const l=o.wafer.radius*2*(Zn/c),a=Math.ceil(l+t);(n==null||a>n)&&(n=a)}return n}function Jn(e){const t=Ut(e);return t==null?st:Math.min(q,Math.max(st,t))}function eo(e){if(qt!=null)return!1;const t=Ut(e);if(t==null)return!1;const n=Math.min(Yn,Math.max(Kt,t));return n<=q?!1:(q=n,!0)}function to(){for(const e of Array.from(I.children))e.classList.contains("wmap-gallery-card")&&(e.style.maxWidth=`${q}px`,e.style.maxHeight=`${q}px`)}let Ke=st,Xt=0;function Zt(e){const t=eo(e);if(t&&to(),v!=null){t&&qe();return}const n=Jn(e);n>Ke&&(Ke=n),qe()}function Yt(e){v=e,qe()}function rt(e){return`repeat(${e}, minmax(0, ${q}px))`}function Qt(e){I.style.gridTemplateColumns!==e&&(I.style.gridTemplateColumns=e)}function qe(){if(v!=null){Qt(rt(v));return}const e=Math.max(1,Xt),t=12,n=I.clientWidth||0,o=l=>(n-t*(l-1))/l;let c=Math.max(1,Math.ceil(Math.sqrt(e)));if(n>0){const l=Math.min(q,Ke*Qn),a=s=>{let i=0;for(;i<e&&o(i+1)>=s;)i++;return i};c=a(l)||a(Ke)||1}Qt(rt(c))}const I=f.ownerDocument.createElement("div");if(Object.assign(I.style,{flex:"1 1 0",minWidth:"0",display:"grid",gridTemplateColumns:rt(1),gap:x.xl,paddingLeft:te,paddingRight:te,justifyContent:"start",alignContent:"start",isolation:"isolate"}),de?.placement){const e=de.placement;h=yt(e,te,f.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.display="flex",h.style.flexDirection="column"}else if(H||tt()){const e=!!de?.defaultOpen;h=yt("right",te,f.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.flexDirection="column",h.style.display=e?"flex":"none",j()}le(),h?.style.display!=="none"&&A&&Ce(A,!0),(de?.placement??"right")==="left"?(h&&G.appendChild(h),G.appendChild(I)):(G.appendChild(I),h&&G.appendChild(h));const Be=f.ownerDocument.createElement("div");Object.assign(Be.style,{position:"sticky",top:"0",display:"flex",flexDirection:"column",paddingLeft:te,paddingRight:te,paddingTop:te,zIndex:"1",background:m.menuBg}),Ge.appendChild(pe),Ge.appendChild(R),Be.appendChild(Ge),Be.appendChild(Q),f.appendChild(Be),f.appendChild(G);function Ue(){Q.innerHTML="";const e=d.plotMode??"hardBin",t=!Ee&&sn.has(e),n=L.filter(g=>g!=null),o=n.find(g=>g.isLotStack),c=ei(n.map(g=>({metadata:g.wafer.metadata??void 0})),o?{lotSize:o.lotSize??n.length,aggrMethod:o.aggrMethod}:void 0),l=e==="metadata",a=d.activeMetadataKey,s=t&&!l?xn(n,g=>(e==="softBin"?g.sbin:g.hbin)??void 0):{counts:new Map,total:0},i=[...s.counts.keys()].sort((g,W)=>g-W),r=t&&l&&a?xn(n,g=>po(g.metadata?.[a])):{counts:new Map,total:0},u=l?It()?.values:void 0,b=t&&l?(u??[...r.counts.keys()].sort(bn)).filter(g=>r.counts.has(g)):[];if(pe.innerHTML="",c&&pe.appendChild(c),pe.style.display=c?"flex":"none",!i.length&&!b.length){Q.style.display="none";return}Q.style.display="flex";const M=f.ownerDocument.createElement("div");Object.assign(M.style,{display:"flex",flexWrap:"wrap",alignItems:"center",gap:`${x.sm} ${x.xl}`,maxHeight:"86px",overflowY:"auto",overflowX:"hidden"}),Q.appendChild(M);const k=d.highlightBin,D=L.flatMap(g=>g?.metadataFields??[]).find(g=>g.key===a),y=l?D?.label??(a?oi(a):"Metadata"):Co[e],$=f.ownerDocument.createElement("span");if($.textContent=y,Object.assign($.style,{fontSize:O.body,fontWeight:"700",letterSpacing:wo,textTransform:"uppercase",color:m.label,flexShrink:"0"}),M.appendChild($),!l&&s.total>0){const g=ye.reduce((he,pt)=>he+(s.counts.get(pt)??0),0),W=g/s.total*100,J=f.ownerDocument.createElement("span");J.textContent=`Yield ${Qe(W)}`,Object.assign(J.style,{fontSize:O.body,fontWeight:"700",color:m.value,whiteSpace:"nowrap",flexShrink:"0"});const ee=f.ownerDocument.createElement("span");ee.textContent=`${g.toLocaleString()} / ${s.total.toLocaleString()} dies`,Object.assign(ee.style,{fontSize:O.body,color:m.label,whiteSpace:"nowrap",flexShrink:"0"}),M.appendChild(J),M.appendChild(ee)}if(l){const g=d.highlightMetadataValue;b.forEach((W,J)=>{const ee=g===W,he=D?.values?.find(gt=>gt.value===W),pt=he?.color??bo(J),ln=r.counts.get(W)??0;vn(M,{color:pt,isActive:ee,label:he?.label??W,count:ln,percent:r.total>0?ln/r.total*100:void 0,onClick:()=>{const gt=d.highlightMetadataValue===W?void 0:W;B({highlightMetadataValue:gt})}})});return}const se=e==="softBin"?L.flatMap(g=>g?.sbinDefs??[]):L.flatMap(g=>g?.hbinDefs??[]),X=new Set,Le=[];for(const g of se)X.has(g.bin)||(X.add(g.bin),Le.push(g));const ut=Le.length>0?new Map(Le.map(g=>[g.bin,g])):null,nn=d.binColors??Ve(),so=e==="softBin"?nn.soft:nn.hard,on=g=>so.get(g)??ho;for(const g of i){const W=k===g,J=ut?.get(g),ee=s.counts.get(g)??0;vn(M,{color:on(g),isActive:W,label:J?.name?`${g} \xB7 ${J.name}`:`Bin ${g}`,count:ee,percent:s.total>0?ee/s.total*100:void 0,onClick:()=>{const he=d.highlightBin===g?void 0:g;B({highlightBin:he})}})}s.total>0&&i.length>1&&Q.appendChild(si(f.ownerDocument,[...s.counts.entries()].sort(([,g],[,W])=>W-g).map(([g,W])=>({color:on(g),count:W,label:ut?.get(g)?.name?`${g} \xB7 ${ut.get(g).name}`:`Bin ${g}`})),s.total))}function Oe(e){const t=w.filter(s=>s!==null);if(!t.length)return[];const n=t.map(s=>s.dies.filter(ai)),o=t[0].wafer,c=t.length,l=o.metadata?{...o,metadata:(({wafer:s,waferId:i,...r})=>r)(o.metadata)}:o;function a(s,i){return{...s,stats:{...s.stats,isLotStack:!0,aggregationMethod:i,lotSize:c}}}if(e==="stackedValues"){const s=fe();let i=s?.filter(bt);if(s!==void 0&&i?.length===0)return[];if(s?.length||(i=ro(t.flatMap(b=>b.dies)).map(b=>({testNumber:b,name:`Test ${b}`}))),!i?.length)return[];const r=d.aggregationMethod??"mean";return i.map(u=>{const b=Ko(n,r,u.testNumber),M={testNumber:0,name:u.name,unit:u.unit};return{wafer:l,dies:b,testDefs:[M],label:`${u.name} \xB7 ${r}`,isLotStack:!0,aggrMethod:r,lotSize:c,statsSummary:a(Ye({wafer:l,dies:b,testDefs:[M]},{testNumbers:[0]}),r)}})}if(e==="stackedBins"){let s=ne(t.flatMap(i=>i.hbinDefs??[]));return(!s||s.length===0)&&(s=[...new Set(t.flatMap(r=>r.dies.map(u=>u.hbin).filter(u=>u!=null)))].sort((r,u)=>r-u).map(r=>({bin:r,name:`Bin ${r}`}))),s.map(i=>{const r=mn(n,i.bin,"hard"),u=[{bin:i.bin,name:i.name}];return{wafer:l,dies:r,hbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:c,statsSummary:a(Ye({wafer:l,dies:r,hbinDefs:u}),"countBin")}})}if(e==="stackedSoftBins"){let s=ne(t.flatMap(i=>i.sbinDefs??[]));return(!s||s.length===0)&&(s=[...new Set(t.flatMap(r=>r.dies.map(u=>u.sbin).filter(u=>u!=null)))].sort((r,u)=>r-u).map(r=>({bin:r,name:`Bin ${r}`}))),s.map(i=>{const r=mn(n,i.bin,"soft"),u=[{bin:i.bin,name:i.name}];return{wafer:l,dies:r,sbinDefs:u,label:`${i.bin} \xB7 ${i.name}`,isLotStack:!0,aggrMethod:"countBin",lotSize:c,statsSummary:a(Ye({wafer:l,dies:r,sbinDefs:u}),"countBin")}})}return t}function dt(e){const t=w.length;return e==="stackedBins"||e==="stackedSoftBins"?{valueRange:[0,t],lotSize:t}:e==="stackedValues"?{aggregationMethod:d.aggregationMethod??"mean",valueRange:void 0,lotSize:void 0}:{}}function B(e,{fireCallback:t=!0}={}){const n=Object.keys(e),o=d.plotMode,c=xe()!==null;d={...d,...e};const l=d.plotMode,a=be.has(l),s=o!==void 0&&be.has(o),i=Pe>0;if("binColorScheme"in e||"useDefinedBinColors"in e){const u=Ve();d={...d,binColors:u},e={...e,binColors:u}}if(e.plotMode!==void 0)if(a){const u=dt(l);if(d={...d,...u},i)for(const b of S)b&&b.setOptions(e);else U(Oe(l))}else if(s){const{valueRange:u,lotSize:b,aggregationMethod:M,...k}=d;if(d=k,i)for(const D of S)D&&D.setOptions(e);else U(w.filter(D=>D!==null))}else for(const u of S)u&&u.setOptions(e);else if(e.aggregationMethod!==void 0&&l==="stackedValues")if(i)for(const u of S)u&&u.setOptions(e);else U(Oe("stackedValues"));else for(const u of S)u&&u.setOptions(e);xe()!==null!==c&&xt(),Ue(),Ht(),Pt(),Wt();const r=e.plotMode!==void 0&&e.plotMode!==o;(Uo.some(u=>u in e)||r)&&j(),_e(),jt(),Vt(),lt(),it(),t&&p.onViewOptionsChange?.(d,n,qo(n))}function Jt(e,t,n){const o=e.createElement("div");Object.assign(o.style,{display:"flex",alignItems:"center",gap:x.xs,flex:"1",minWidth:"0"});const c=e.createElement("span");c.textContent=t,Object.assign(c.style,{fontWeight:"700",fontSize:O.sub,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}),o.appendChild(c);const l=wn(n??{});let a=null;if(l.length>0){const s=e.createElement("span");Object.assign(s.style,{fontSize:O.body,lineHeight:Ze.none,color:m.label,flexShrink:"0"}),s.textContent="\u25BE",o.appendChild(s),Object.assign(o.style,{cursor:"pointer",borderRadius:V.control}),o.addEventListener("mouseenter",()=>{o.style.background=m.bgHover}),o.addEventListener("mouseleave",()=>{o.style.background="none"}),a=e.createElement("div"),a.dataset.wmapCardMetaPanel="1",Object.assign(a.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:rn,background:m.menuBg,borderBottom:`1px solid ${m.menuBorder}`,boxShadow:We.menu,padding:`${x.md} ${x.lg}`,fontSize:O.body,display:"none"});const i=yn(n??{});i&&a.appendChild(i),o.setAttribute("aria-expanded","false"),o.setAttribute("aria-label",`Wafer info for ${t||"this card"}. Click to expand.`),un(o,r=>{s.textContent=r?"\u25B4":"\u25BE",o.setAttribute("aria-expanded",String(r)),a&&(a.style.display=r?"block":"none")})}return{wrap:o,metaPanel:a}}function en(e,t,n){const o=e.box.querySelector("[data-wmap-window-title]"),c=wn(n??{});if(!o||c.length===0)return;const l=o.parentElement,a=f.ownerDocument.createElement("div");Object.assign(a.style,{display:"flex",alignItems:"center",gap:x.xs,flex:"1",minWidth:"0",cursor:"pointer"}),mt(a,"bare"),l?.insertBefore(a,o),a.appendChild(o);const s=f.ownerDocument.createElement("span");Object.assign(s.style,{fontSize:O.body,lineHeight:Ze.none,color:m.label,flexShrink:"0"}),s.textContent="\u25BE",a.appendChild(s);const i=f.ownerDocument.createElement("div");i.dataset.wmapCardMetaPanel="1",Object.assign(i.style,{position:"absolute",top:"0",left:"0",right:"0",zIndex:rn,background:m.menuBg,borderBottom:`1px solid ${m.menuBorder}`,boxShadow:We.menu,padding:`${x.md} ${x.lg}`,fontSize:O.body,display:"none"});const r=yn(n??{});r&&i.appendChild(r),e.contentWrap.style.position="relative",e.contentWrap.appendChild(i),a.setAttribute("aria-expanded","false"),a.setAttribute("aria-label",`Wafer info for ${t}. Click to expand.`),un(a,u=>{s.textContent=u?"\u25B4":"\u25BE",a.setAttribute("aria-expanded",String(u)),i.style.display=u?"block":"none"})}function ct(e,t,n){const o=f.ownerDocument.createElement("div");o.className="wmap-gallery-card",Object.assign(o.style,{background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:V.container,boxShadow:We.panel,overflow:"hidden",display:"flex",flexDirection:"column",position:"relative",aspectRatio:"1",maxWidth:`${q}px`,maxHeight:`${q}px`});const c=f.ownerDocument.createElement("div");Object.assign(c.style,{display:"flex",alignItems:"center",padding:`${x.md} ${x.lg} ${x.sm}`,borderBottom:`1px solid ${m.menuBorder}`,flexShrink:"0",gap:x.sm});const{wrap:l,metaPanel:a}=Jt(document,e.label??"",e.wafer.metadata??void 0);c.appendChild(l);const s=f.ownerDocument.createElement("button");s.dataset.wmapExpandBtn="1",s.setAttribute("aria-label","Open full view"),pn(s),s.innerHTML=$e.expand,Object.assign(s.style,{display:"flex",alignItems:"center",justifyContent:"center",border:`1px solid ${m.menuBorder}`,borderRadius:V.control,background:m.panelBg,color:m.label,padding:x.xxs,cursor:"pointer",flexShrink:"0",width:"22px",height:"22px"}),mt(s),c.appendChild(s),o.appendChild(c);const i=f.ownerDocument.createElement("div");Object.assign(i.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),o.appendChild(i),a&&i.appendChild(a),I.appendChild(o);const r=Ae||xe()!==null,u=e.viewOptions?{...d,...e.viewOptions}:d,b=ht(i,e,{viewOptions:{...u,showLegend:r},toolbarControls:"full",showTooltip:!0,padding:P,legendPosition:we,fallbackFormat:Ie,statsSummary:e.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:e.onClick,onSelect:e.onSelect,onExpand:()=>Te(t,e),showIdentity:!1,chromeInset:vo});return b.setViewControlsVisible(!1),b.setSummaryVisible(!1),s.onclick=()=>Te(t,e),{card:o,ctrl:b,canvasWrapper:i,expandBtn:s}}function no(e){const t=ce[e];if(!t)return;const n=[...z.values()].find(o=>o.cardIndex===e);n?(t.innerHTML=$e.minimize,t.setAttribute("aria-label","Reattach to gallery"),t.onclick=()=>io(n.id)):(t.innerHTML=$e.expand,t.setAttribute("aria-label","Open full view"),t.onclick=()=>Te(e,L[e]))}function U(e){lo(),Se()?.remove(),Me(null),ot(),L=[];for(const l of S)l&&l.destroy();S=[],ie=[],ce=[],Pe=0,I.innerHTML="",Xt=e.length,Zt(e.map(l=>typeof l=="function"?null:l));const t=[];for(let l=0;l<e.length;l++){const a=e[l];if(typeof a=="function"){const s=f.ownerDocument.createElement("div");s.className="wmap-gallery-card",Object.assign(s.style,{background:m.menuBg,border:`1px solid ${m.menuBorder}`,borderRadius:V.container,aspectRatio:"1",display:"flex",alignItems:"center",justifyContent:"center"});const i=f.ownerDocument.createElement("span");i.textContent="\u2026",Object.assign(i.style,{color:m.label,fontSize:"18px"}),s.appendChild(i),I.appendChild(s),L.push(null),S.push(null),ie.push(null),ce.push(null),t.push({index:l,factory:a,placeholder:s}),Pe++}else{const{ctrl:s,canvasWrapper:i,expandBtn:r}=ct(a,l,e.length);L.push(a),S.push(s),ie.push(i),ce.push(r)}}At(),Ue(),lt(),it();const n=++et;let o=0;function c(){if(n!==et)return;if(o>=t.length){if(be.has(d.plotMode)){const k=d.plotMode;U(Oe(k))}return}const{index:l,factory:a,placeholder:s}=t[o++],i=a();L[l]=i,w[l]=i,Zt([i]);const{card:r,ctrl:u,canvasWrapper:b,expandBtn:M}=ct(i,l,e.length);S[l]=u,ie[l]=b,ce[l]=M,Pe--,s.replaceWith(r),Ue(),jn(),!h&&!de?.placement&&i.statsSummary?.findings.length?(h=yt("right",te,f.ownerDocument),h.style.maxHeight="calc(100vh - 80px)",h.style.position="sticky",h.style.top="8px",h.style.flexDirection="column",h.style.display="none",(de?.placement??"right")==="left"?G.insertBefore(h,I):G.appendChild(h),j(),A||(A=Z("findings","Summary panel",()=>{if(!h)return;const D=h.style.display!=="none";D||j(),h.style.display=D?"none":"flex",Ce(A,!D),le()}),R.appendChild(N()),R.appendChild(A)),le()):h&&h.style.display!=="none"&&j(),le(),setTimeout(c,0)}t.length>0&&setTimeout(c,0)}if(be.has(d.plotMode)&&w.length>0){const e=dt(d.plotMode);d={...d,...e},U(Oe(d.plotMode))}else U(C);_e();let me=0;const tn=new(f.ownerDocument.defaultView??window).ResizeObserver(()=>{if(me)return;me=(f.ownerDocument.defaultView??window).requestAnimationFrame(()=>{me=0,v==null&&qe()})});tn.observe(I),h&&j();function oo(e,t){const n=ie[e];if(!n)return;n.innerHTML="",Object.assign(n.style,{alignItems:"center",justifyContent:"center"});const o=f.ownerDocument.createElement("span");o.textContent=t?"Opened in its own window":"Opened in the wafer viewer",Object.assign(o.style,{color:m.label,fontSize:O.body,textAlign:"center",padding:"0 12px"}),n.appendChild(o)}function Te(e,t){for(const a of z.values())if(a.cardIndex===e)return;const n=t.label??"Wafer map",o=Sn++,c=S[e]?.getOptions(),l=Eo(n);if(l){const a=l.document;a.title=n,Object.assign(a.documentElement.style,{height:"100%"}),Object.assign(a.body.style,{margin:"0",height:"100vh",overflow:"hidden",display:"flex",flexDirection:"column",fontFamily:O.family}),Lo(f,a.documentElement);const s=$o(f,a.documentElement,()=>D.setOptions({})),i=a.createElement("div");i.dataset.wmapWindowBanner="1",i.textContent=n,Object.assign(i.style,{display:"none",padding:`${x.sm} ${x.xl}`,fontSize:O.body,fontWeight:"700",background:m.warnBg,color:m.warnText,borderBottom:`1px solid ${m.warnBorder}`,flexShrink:"0"}),a.body.appendChild(i);const r=a.createElement("div");Object.assign(r.style,{flex:"1",minHeight:"0",display:"flex",flexDirection:"column"}),a.body.appendChild(r);const{wrap:u,metaPanel:b}=Jt(a,n,t.wafer.metadata??void 0),M=a.createElement("div");Object.assign(M.style,{display:"flex",alignItems:"center",padding:`${x.md} ${x.lg} ${x.sm}`,borderBottom:`1px solid ${m.menuBorder}`,flexShrink:"0",gap:x.sm}),M.appendChild(u),r.appendChild(M);const k=a.createElement("div");Object.assign(k.style,{position:"relative",flex:"1",minHeight:"0",overflow:"hidden",display:"flex",flexDirection:"column"}),b&&k.appendChild(b),r.appendChild(k);const D=ft(k,t,void 0,c),y=setInterval(()=>{l.closed&&Xe(o)},400);l.addEventListener("pagehide",()=>Xe(o)),z.set(o,{id:o,ctrl:D,cardIndex:e,label:n,closePollId:y,stopThemeSync:s,close:()=>{l.closed||l.close()},setTitle:$=>{a.title=$,i.textContent=$,i.style.display="block"}})}else{const a=Bo({title:n,onClose:()=>Xe(o),anchor:f});a.contentWrap.style.flexDirection="column",en(a,n,t.wafer.metadata??void 0);const s=ft(a.contentWrap,t,void 0,c);z.set(o,{id:o,ctrl:s,cardIndex:e,label:n,closePollId:null,close:()=>a.close(),setTitle:i=>{const r=a.box.querySelector("[data-wmap-window-title]");r&&(r.textContent=i,r.title=i)}})}S[e]?.destroy(),S[e]=null,oo(e,l!==null),no(e)}function ft(e,t,n,o){const c=t.viewOptions?{...d,...t.viewOptions}:d,l=o?{...c,...o}:c,s={...n!==void 0?{...l,plotMode:"value",activeTest:n}:l,showLegend:!0},i=ht(e,t,{viewOptions:s,toolbarControls:"full",showTooltip:!0,padding:P,legendPosition:we,fallbackFormat:Ie,statsSummary:t.statsSummary,onSaveImage:p.onSaveImage,onSaveText:p.onSaveText,onClick:t.onClick,onSelect:t.onSelect,showExpandButton:!1,showIdentity:!1});return i.setViewControlsVisible(!0),i.setSummaryVisible(!0),i.setExpandVisible(!1),i}function Xe(e){const t=z.get(e);if(!t)return;z.delete(e),t.closePollId!=null&&clearInterval(t.closePollId),t.stopThemeSync?.();const n=t.ctrl.getOptions();if(t.ctrl.destroy(),t.cardIndex===null)return;const o=t.cardIndex,c=L[o];if(!c)return;const l={...c,viewOptions:n};L[o]=l;const{card:a,ctrl:s,canvasWrapper:i,expandBtn:r}=ct(l,o,L.length);ie[o]?.parentElement?.replaceWith(a),S[o]=s,ie[o]=i,ce[o]=r}function io(e){const t=z.get(e);t&&(t.close(),Xe(e))}function lo(){for(const e of z.values())e.cardIndex!==null&&(e.cardIndex=null,e.setTitle(`${e.label} \u2014 unlinked from gallery`))}function ao(){const e=[...I.querySelectorAll("canvas")];if(!e.length)return;const t=e.length,n=Math.ceil(Math.sqrt(t)),o=Math.ceil(t/n),c=e[0].width,l=e[0].height,a=8,s=(f.ownerDocument.defaultView??window).devicePixelRatio||1,i=Math.round(26*s),r=Math.round(12*s),u=f.ownerDocument.createElement("canvas");u.width=n*c+(n-1)*a,u.height=o*(l+i)+(o-1)*a;const b=u.getContext("2d"),M=yo(I);b.fillStyle=M.background,b.fillRect(0,0,u.width,u.height),e.forEach((k,D)=>{const y=D%n,$=Math.floor(D/n),se=y*(c+a),X=$*(l+i+a),Le=k.closest(".wmap-gallery-card")?.querySelector("span")?.textContent??"";b.fillStyle=M.surface,b.fillRect(se,X,c,i),b.fillStyle=M.text,b.font=`700 ${r}px system-ui, sans-serif`,b.textAlign="left",b.textBaseline="middle",b.fillText(Le,se+Math.round(10*s),X+i/2,c-Math.round(20*s)),b.drawImage(k,se,X+i)}),u.toBlob(k=>{k&&Ho(k,F,p.onSaveImage)})}return{setItems(e){w=e.map(n=>typeof n=="function"?null:n);const t=d.plotMode;if(be.has(t))if(e.some(o=>typeof o=="function"))U(e);else{const o=dt(t);d={...d,...o},U(Oe(t))}else U(e)},setOptions(e){B(e,{fireCallback:!1})},getOptions(){return{...d}},setFallbackFormat(e){Ie=e;for(const t of S)t&&t.setFallbackFormat(e)},setFindingsNotice(e){kt=e,j()},setLotStatsSummary(e){H=e,_e(),h&&j(),le()},setColumns(e){Yt(e)},openUserGuide:Nt,destroy(){et++;for(const e of[...z.values()])e.closePollId!=null&&clearInterval(e.closePollId),e.close(),e.ctrl.destroy();z.clear();for(const e of S)e&&e.destroy();S=[],Se()?.remove(),tn.disconnect(),me&&((f.ownerDocument.defaultView??window).cancelAnimationFrame(me),me=0),f.ownerDocument.removeEventListener("click",Fe,!0),window.removeEventListener("blur",Dt),Cn(),dn(),Be.remove(),G.remove(),h?.remove(),ge?.destroy()}}}
|