@wafertools/wafermap 0.32.0 → 0.33.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 +1 -1
- package/CHANGELOG.md +162 -1
- package/README.md +2 -2
- package/dist/packages/canvas-adapter/charts/chartShell.d.ts +2 -12
- package/dist/packages/canvas-adapter/charts/chartShell.js +1 -1
- package/dist/packages/canvas-adapter/insightsTab.js +1 -1
- package/dist/packages/canvas-adapter/renderWaferGallery.js +1 -1
- package/dist/packages/canvas-adapter/renderWaferMap.d.ts +30 -0
- package/dist/packages/canvas-adapter/renderWaferMap.js +1 -1
- package/dist/packages/canvas-adapter/summaryPanel.d.ts +22 -3
- package/dist/packages/canvas-adapter/summaryPanel.js +4 -3
- package/dist/packages/canvas-adapter/toCanvas.js +1 -1
- package/dist/packages/canvas-adapter/toolbar.d.ts +54 -1
- 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 +76 -13
- package/dist/packages/canvas-adapter/version.d.ts +2 -2
- package/dist/packages/canvas-adapter/version.js +1 -1
- package/dist/packages/core/aggregates.d.ts +6 -0
- package/dist/packages/core/aggregates.js +1 -1
- package/dist/packages/core/compact.d.ts +205 -0
- package/dist/packages/core/compact.js +3 -0
- package/dist/packages/core/passBins.d.ts +6 -0
- package/dist/packages/core/passBins.js +1 -1
- package/dist/packages/renderer/axisTicks.d.ts +14 -0
- package/dist/packages/renderer/axisTicks.js +1 -1
- package/dist/packages/renderer/buildView.d.ts +26 -1
- package/dist/packages/renderer/buildView.js +1 -1
- package/dist/packages/renderer/buildWaferMap.js +1 -1
- package/dist/packages/renderer/compactView.d.ts +22 -0
- package/dist/packages/renderer/compactView.js +1 -0
- package/dist/packages/renderer/xyIndicator.d.ts +27 -0
- package/dist/packages/renderer/xyIndicator.js +1 -0
- package/dist/packages/stats/analyzeWaferLot.d.ts +28 -0
- package/dist/packages/stats/analyzeWaferLot.js +1 -1
- package/dist/packages/stats/analyzeWaferMap.d.ts +36 -1
- package/dist/packages/stats/analyzeWaferMap.js +1 -1
- package/dist/packages/stats/binRows.d.ts +38 -0
- package/dist/packages/stats/binRows.js +1 -0
- package/dist/packages/stats/filterFindings.d.ts +25 -0
- package/dist/packages/stats/filterFindings.js +1 -1
- package/dist/packages/stats/findingText.d.ts +9 -0
- package/dist/packages/stats/findingText.js +2 -0
- package/dist/packages/stats/lotDrift.d.ts +16 -0
- package/dist/packages/stats/lotDrift.js +1 -0
- package/dist/packages/stats/lotPattern.d.ts +33 -0
- package/dist/packages/stats/lotPattern.js +1 -0
- package/dist/packages/stats/math.d.ts +51 -0
- package/dist/packages/stats/math.js +1 -1
- package/dist/packages/stats/patternClassification.d.ts +31 -0
- package/dist/packages/stats/patternClassification.js +1 -1
- package/dist/packages/stats/presentation.d.ts +42 -0
- package/dist/packages/stats/presentation.js +1 -0
- package/dist/packages/stats/regions.d.ts +9 -0
- package/dist/packages/stats/regions.js +1 -1
- package/dist/packages/stats/renderSummaryReport.d.ts +15 -2
- package/dist/packages/stats/renderSummaryReport.js +32 -27
- package/dist/packages/stats/reportHtml.d.ts +54 -9
- package/dist/packages/stats/reportHtml.js +130 -47
- package/dist/packages/stats/synthesis.d.ts +66 -0
- package/dist/packages/stats/synthesis.js +2 -0
- package/dist/packages/stats/types.d.ts +1 -1
- package/dist/packages/stats/yieldRows.d.ts +31 -0
- package/dist/packages/stats/yieldRows.js +1 -0
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/dist/packages/stats/findingsNarrative.d.ts +0 -3
- package/dist/packages/stats/findingsNarrative.js +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import{testValue as Ne}from"../core/dieTable.js";import{waferDisplayLabel as ve}from"../core/waferLabel.js";import{itemPassBins as Se,passBinsLabel as dt}from"../core/passBins.js";import{isParametricTest as ct}from"../renderer/buildWaferMap.js";import{testLabel as pt,markedTestLabel as ut,unmarkedLabel as ft,derivedFields as we,derivedKeyText as mt,derivedCsvCell as Fe,isDerivedTest as Te,DERIVED_CSV_HEADER as De}from"../renderer/testLabel.js";import{buildRingRegions as gt,buildQuadrantRegions as ht,buildRegionYieldData as bt}from"../stats/regions.js";import{computeFunctionalYield as xt}from"../stats/analyzeWaferMap.js";import{renderWaferReportHtml as yt,renderLotReportHtml as Ct}from"../stats/renderSummaryReport.js";import{buildFindingsNarrative as vt}from"../stats/findingsNarrative.js";import{formatFindingTooltip as St}from"../stats/reportHtml.js";import{filterFindings as wt}from"../stats/filterFindings.js";import{buildFacetTable as $t,prettyKey as Ee}from"../stats/facets.js";import{commonMetadata as Re}from"../stats/facets.js";import{resolveMetadataColumns as kt}from"../stats/metadataColumns.js";import{resolveBinColors as Me,resolveBinColorsByWafer as Lt}from"../renderer/binColors.js";import{NO_DATA_FILL as Bt}from"../renderer/colorMap.js";import{classifySpec as Nt,isOutOfSpec as Ft}from"../renderer/spec.js";import{describeWaferPopulation as Ie,populationLabel as Tt}from"../stats/population.js";import{buildWarningsBanner as $e,collectWarnings as Ae}from"./warnings.js";export{$e as buildWarningsBanner};import{fmt as We,fmtAggregationMethod as Dt,plainBinTerms as de}from"../renderer/fmt.js";import{getUniqueTestNumbers as Et}from"../renderer/buildView.js";import{describeValues as Rt,quantile as Pe}from"../stats/math.js";import{pooledTestStatsSteps as Mt}from"../stats/capability.js";import{sortBinsForDisplay as It}from"../stats/binPareto.js";import{poolFunctionalYield as At}from"../stats/testPassRate.js";import{makeLabeledSelect as ze,makeSegmented as ke}from"./charts/chartShell.js";import{SHADOW as He,MOTION as Oe,LEADING as te,TRACKING as fe,wireControlHover as G,controlStyle as me,SPACE as x,RADIUS as q,FONT as F,CLR as $,sevColor as ge,openModal as Ye,openReportModal as _e,saveTextFile as je,wireTooltip as ce}from"./toolbar.js";import{buildDieListSection as Wt}from"./dieList.js";export{csvField}from"../core/utils.js";import{csvField as he,drain as be,maxOf as Pt,medianOfSorted as zt,minOf as Ht}from"../core/utils.js";import{metadataDisplayValue as Ot}from"../core/metadata.js";const Yt=$.panelBg,Ke=`1px solid ${$.menuBorder}`,_t="12px",Y=$.label,ne=$.value,Ve="10px";function l(e,t,i,n=document){const o=n.createElement(e);return t&&Object.assign(o.style,t),i!==void 0&&(o.textContent=i),o}function se(e){return l("div",{fontSize:Ve,fontWeight:"700",letterSpacing:fe,textTransform:"uppercase",color:Y,marginBottom:x.sm},e)}const qe=new WeakMap,Ge=["regionYield","testValues","functionalTests"];function xe(e){if(!e)return{collapsed:new Set(Ge),regionMode:"ring",waferSort:"slot"};let t=qe.get(e);return t||(t={collapsed:new Set(Ge),regionMode:"ring",waferSort:"slot"},qe.set(e,t)),t}function oe(e,t=!0,i,n){const o=l("div"),u=xe(n?.panel);n?.stateKey&&n.panel&&(t=!u.collapsed.has(n.stateKey));const s=document.createElement("button");s.type="button",Object.assign(s.style,{display:"flex",alignItems:"center",gap:x.xs,width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const m=l("span",{fontSize:F.meta,color:Y,transition:`transform ${Oe.base}`,transform:t?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:te.none,marginRight:"1px"},"\u25B6"),p=l("span",{fontSize:Ve,fontWeight:"700",letterSpacing:fe,textTransform:"uppercase",color:Y,flex:"1"},e);if(G(s,"bare"),s.setAttribute("aria-expanded",t?"true":"false"),s.appendChild(m),s.appendChild(p),i){const b=l("span",{fontSize:F.meta,fontWeight:"700",background:$.warnBg,color:$.warnText,borderRadius:q.pill,padding:"1px 5px"},i);s.appendChild(b)}const r=l("div");r.style.display=t?"block":"none";let a=t;if(s.addEventListener("click",()=>{a=!a,r.style.display=a?"block":"none",m.style.transform=a?"rotate(90deg)":"rotate(0deg)",s.setAttribute("aria-expanded",a?"true":"false"),n?.stateKey&&n.panel&&(a?u.collapsed.delete(n.stateKey):u.collapsed.add(n.stateKey))}),n?.control){const b=l("div",{display:"flex",alignItems:"center",gap:x.sm});s.style.width="auto",s.style.flex="1",b.appendChild(s);const f=()=>{r.innerHTML="",n.render?.(r)},w=n.control(f);w&&(w.style.marginBottom="6px",w.addEventListener("click",k=>k.stopPropagation()),b.appendChild(w)),o.appendChild(b)}else o.appendChild(s);return o.appendChild(r),n?.render?.(r),{outer:o,content:r}}function Ue(){return l("div",{height:"1px",background:$.separator,margin:`${_t} 0`,flexShrink:"0"})}function Le(e,t,i=$.barFill,n,o){const u=l("div",{marginBottom:"5px"}),s=l("div",{display:"flex",justifyContent:"space-between",fontSize:F.body,color:ne,marginBottom:x.xxs}),m=l("span",{color:Y},e),p=l("span",{fontWeight:"600"},`${t.toFixed(1)}%`);s.appendChild(m),s.appendChild(p);const r=n!==void 0?n:Math.min(100,Math.max(0,t)),a=i,b=l("div",{position:"relative",height:"9px",background:$.bgActive,borderRadius:q.control,overflow:"hidden"}),f=l("div",{height:"100%",width:`${r}%`,background:a,borderRadius:q.control,transition:`width ${Oe.base}`});if(b.appendChild(f),o!==void 0){const w=l("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"2px",marginLeft:"-1px",background:$.value,opacity:"0.8"});b.appendChild(w)}return u.appendChild(s),u.appendChild(b),u}function Qe(){const e=l("div",{display:"flex",gap:x.sm,marginBottom:x.md});return e.finish=()=>{const t=e.lastElementChild;t&&Object.assign(t.style,{borderRight:"none",paddingRight:"0"})},e}function pe(e,t,i){const n=l("div",{padding:`${x.xxs} ${x.md} ${x.xxs} 0`,borderRight:Ke,textAlign:"center",flex:"1"}),o=l("div",{fontSize:F.heading,fontWeight:"700",color:ne,lineHeight:te.tight},e),u=l("div",{fontSize:F.body,color:Y,marginTop:x.xxs},t);return n.appendChild(o),n.appendChild(u),i&&n.appendChild(l("div",{fontSize:F.body,color:Y,opacity:"0.85"},i)),n}function Xe(e,t){const i=l("div",{display:"flex",justifyContent:"space-between",fontSize:F.body,gap:x.md,marginBottom:"3px"}),n=l("span",{color:Y,flexShrink:"0"},e),o=l("span",{color:ne,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},t);return i.appendChild(n),i.appendChild(o),i}function jt(e,t){const i=l("div",{display:"flex",fontSize:F.body,gap:x.sm,marginBottom:"3px"}),n=l("span",{color:Y,flexShrink:"0"},`${e}:`),o=l("span",{color:ne,fontWeight:"500",wordBreak:"break-all"},t);return i.appendChild(n),i.appendChild(o),i}export function metadataEntries(e){const t=[];for(const[i,n]of Object.entries(e)){const o=Ot(n);o!==void 0&&t.push([i,o])}return t}const Kt=["lot","product","testprogram","split"],ye=e=>{const t=Kt.indexOf(e.toLowerCase().replace(/[^a-z]/g,""));return t===-1?Number.MAX_SAFE_INTEGER:t};export function buildFacetSummaryChips(e,t=3){if(!e.length)return null;const i=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:`${x.xs} ${x.lg}`}),n=[...e].sort((m,p)=>ye(m.key)-ye(p.key)),o=n.filter(m=>ye(m.key)!==Number.MAX_SAFE_INTEGER),u=n.filter(m=>ye(m.key)===Number.MAX_SAFE_INTEGER),s=m=>{const p=l("span",{whiteSpace:"nowrap"}),r=l("span",{color:Y},`${Ee(m.key)}: `);p.appendChild(r);const a=m.values.slice(0,t),b=m.values.length-a.length;let f=a.map(w=>w.value).join(", ");return b>0&&(f+=` +${b} more`),p.appendChild(document.createTextNode(f)),p};for(const m of o)i.appendChild(s(m));if(u.length){const m=l("span",{display:"none",flexWrap:"wrap",alignItems:"baseline",gap:`${x.xs} ${x.lg}`});for(const a of u)m.appendChild(s(a));const p=l("button",{background:"none",border:"none",padding:"0",cursor:"pointer",color:$.iconActive,fontSize:F.body,whiteSpace:"nowrap"});p.type="button",G(p,"bare");const r=a=>{m.style.display=a?"contents":"none",p.textContent=a?"less":`+${u.length} more`,p.setAttribute("aria-expanded",String(a))};r(!1),p.addEventListener("click",()=>r(p.getAttribute("aria-expanded")!=="true")),i.appendChild(m),i.appendChild(p)}return i}export function buildMetadataStripRow(e,t,i){const n=$t(e,i),o=buildFacetSummaryChips(n);if(!o&&!t)return null;const u=l("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(t){const s=l("span",{fontWeight:"500",whiteSpace:"nowrap"},t.aggrMethod?`${t.lotSize} wafers stacked \xB7 ${t.aggrMethod}`:`${t.lotSize} wafers stacked`);u.appendChild(s)}return o&&u.appendChild(o),u}const Vt={display:"flex",flexDirection:"column",gap:x.sm,background:$.menuBg,border:`1px solid ${$.menuBorder}`,borderRadius:q.container,padding:`${x.sm} ${x.lg}`,boxShadow:He.panel,fontSize:F.body,lineHeight:te.none,boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(e,t,i){const n=buildMetadataStripRow(e,t,i);if(!n)return null;const o=l("div",Vt);return o.appendChild(n),o}export function buildCompactMetadataRows(e){const t=metadataEntries(e);if(!t.length)return null;const i=l("div");for(const[n,o]of t)i.appendChild(jt(Ee(n),o));return i}export function buildMetadataInfoSection(e,t){const i=buildMetadataStripRow(e,t,{facetableOnly:e.length>1});if(!i)return null;const n=l("div");return n.appendChild(se("Wafer Info")),n.appendChild(i),n}export function buildYieldSection(e,t,i=[1]){const n=l("div");n.appendChild(se("Summary"));const o=Qe();if(o.appendChild(pe(String(e.totalDies),"Total dies")),e.partialDies>0&&o.appendChild(pe(String(e.partialDies),"Partial")),e.yieldPercent!==null){const u=dt([i]);o.appendChild(pe(`${e.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${u}`))}return o.finish(),n.appendChild(o),e.edgeExcludedDies>0&&n.appendChild(Xe("Edge excluded (outer zone)",String(e.edgeExcludedDies))),n}export function buildBinSection(e,t,i,n,o,u){const s=new Map;if(o)for(const[r,a]of Object.entries(o))s.set(Number(r),a);else for(const r of e){if(r.partial||r.edgeExcluded)continue;const a=i==="hard"?r.hbin:r.sbin;a!=null&&s.set(a,(s.get(a)??0)+1)}if(!s.size)return null;const m=n??Me(e,{passBins:u,...i==="hard"?{hbinDefs:t}:{sbinDefs:t}}),p=l("div");p.appendChild(se(Ze(i,[...s.values()].reduce((r,a)=>r+a,0))));for(const r of Je(s,t,m[i],m.pass[i]))p.appendChild(r);return p}function Ze(e,t){return`${e==="hard"?"Hard":"Soft"} Bin Breakdown \u2014 % of dies (N=${t})`}function Je(e,t,i,n){const o=[...e.values()].reduce((m,p)=>m+p,0),u=t?new Map(t.map(m=>[m.bin,m])):null;return It(e.entries(),n).map(([m,p])=>{const r=u?.get(m),a=r?.name?`Bin ${m} \xB7 ${r.name}`:`Bin ${m}`,b=p/o*100,f=i.get(m)??Bt;return Le(`${a} (${p})`,b,f)})}export function buildBinBreakdownSection(e){const{dies:t,hbinDefs:i,sbinDefs:n,hardCounts:o,softCounts:u,plotMode:s,passBins:m=[1],panel:p}=e,r=e.binColors??Me(t,{passBins:m,hbinDefs:i,sbinDefs:n}),a=v=>{const g=v==="hard"?o:u,h=new Map;if(g){for(const[y,S]of Object.entries(g))h.set(Number(y),S);return h}for(const y of t){if(y.partial||y.edgeExcluded)continue;const S=v==="hard"?y.hbin:y.sbin;S!=null&&h.set(S,(h.get(S)??0)+1)}return h},b=a("hard"),f=a("soft"),w=b.size>0,k=f.size>0;if(!w&&!k)return null;const E=xe(p),H=s==="softBin"||s==="stackedSoftBins"?"soft":s==="hardBin"||s==="stackedBins"?"hard":void 0;let I=E.binMode??H??(w?"hard":"soft");I==="hard"&&!w&&(I="soft"),I==="soft"&&!k&&(I="hard");const O=I==="hard"?b:f,z=I==="hard"?i:n,C=[...O.values()].reduce((v,g)=>v+g,0),{outer:d}=oe(Ze(I,C),!0,void 0,{stateKey:"bins",panel:p,render:v=>{const g=I==="hard"?r.hard:r.soft;for(const h of Je(O,z,g,r.pass[I]))v.appendChild(h)},control:w&&k&&p?()=>ke([["hard","Hard"],["soft","Soft"]],I,v=>{E.binMode=v;const g=buildBinBreakdownSection(e);g&&d.replaceWith(g)},p.ownerDocument,!0):void 0});return d}export function buildLotBinSection(e,t,i,n){return buildBinSection(e,t,i,n)}export function buildRegionYieldPanelSection(e){const{diesByWafer:t,allWafers:i,ringCount:n,passBins:o,panel:u}=e,s=xe(u),m=a=>bt(t,i,n,o,a==="ring"?gt:ht);if(!m("ring").length&&!m("quadrant").length)return null;const p=s.regionMode,{outer:r}=oe(p==="ring"?"Ring Yield":"Quadrant Yield",!0,void 0,{stateKey:"regionYield",panel:u,render:a=>{const b=m(p);if(!b.length){a.appendChild(l("div",{fontSize:F.body,color:Y},"No positioned dies for this breakdown."));return}for(const{label:f,n:w,yieldPercent:k}of b)a.appendChild(Le(`${f} (N=${w})`,k))},control:u?()=>ke([["ring","Ring"],["quadrant","Quadrant"]],p,a=>{s.regionMode=a;const b=buildRegionYieldPanelSection(e);b&&r.replaceWith(b)},u.ownerDocument,!0):void 0});return r}export function buildLotOverviewSection(e,t=[]){const i=l("div"),n=Ie(e.perWafer.map(s=>s.summary.wafer));i.appendChild(se(n.lotId!==void 0?"Lot Summary":"Summary"));const o=Qe();o.appendChild(pe(String(e.stats.waferCount),"Wafers"));const u=e.perWafer.map(s=>s.summary.stats.yieldPercent).filter(s=>s!==null);if(u.length){const s=u.reduce((m,p)=>m+p,0)/u.length;o.appendChild(pe(`${s.toFixed(1)}%`,"Mean per-wafer yield"))}if(o.finish(),i.appendChild(o),t.length){const s=t.reduce((p,r)=>p+r.stats.analyzedDies,0),m=t.reduce((p,r)=>p+r.stats.excludedDies,0);(s||m)&&i.appendChild(Xe("Dies analysed",m?`${s.toLocaleString()} (${m.toLocaleString()} excluded)`:s.toLocaleString()))}return i}export function buildPerWaferYieldSection(e,t,i,n,o){const u=e.perWafer.map(C=>({waferIndex:C.waferIndex,label:ve(t[C.waferIndex],C.waferIndex).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:C.summary.stats.yieldPercent})).filter(C=>C.yieldPct!==null);if(!u.length)return null;const s=Ht(u.map(C=>C.yieldPct)),m=Pt(u.map(C=>C.yieldPct)),p=s===m?"":` (${s.toFixed(1)}\u2013${m.toFixed(1)}%)`,r=[...u.map(C=>C.yieldPct)].sort((C,d)=>C-d),a=zt(r),b=Pe(r,.25),f=Pe(r,.75),w=u.length>=5?b-1.5*(f-b):-1/0,k=xe(n),E=C=>{const d=k.waferSort==="yield"?[...u].sort((v,g)=>v.yieldPct-g.yieldPct):u;for(const{waferIndex:v,label:g,yieldPct:h}of d){const S=h<w?`${g} \xB7 low outlier`:g,L=Le(S,h,void 0,void 0,a),A=o?.(v);A?.total&&O(L,A),z(L,v,g,h,A),C.appendChild(L)}},H=` \xB7 median ${a.toFixed(1)}%`,{outer:I}=oe("Wafer Yield"+p+H,!0,void 0,{stateKey:"waferYield",panel:n,render:E,control:n?C=>ke([["slot","Slot"],["yield","Yield"]],k.waferSort,d=>{k.waferSort=d,C()},n.ownerDocument,!0):void 0});return I;function O(C,d){const v=d.unusual?"unusual":d.notable?"notable":"info",g=l("span",{marginLeft:x.sm,flexShrink:"0",background:ge(v),color:"#fff",borderRadius:q.container,padding:"0 5px",fontSize:F.body,fontWeight:"600"},`${d.total}`);g.setAttribute("aria-hidden","true"),ce(g,`${d.total} finding${d.total===1?"":"s"}`+(d.unusual?`, ${d.unusual} unusual`:"")+(d.notable?`, ${d.notable} notable`:"")),C.firstElementChild?.firstElementChild?.appendChild(g)}function z(C,d,v,g,h){i&&(C.style.cursor="pointer",C.style.borderRadius="4px",C.style.padding="2px 3px",C.style.marginLeft="-3px",C.style.marginRight="-3px",C.setAttribute("role","button"),C.setAttribute("aria-label",`${v}, ${g.toFixed(1)}% yield`+(h?.total?`, ${h.total} finding${h.total===1?"":"s"}${h.unusual?`, ${h.unusual} unusual`:""}`:"")+" \u2014 open wafer"),C.tabIndex=0,C.addEventListener("mouseenter",()=>{C.style.background=$.bgHover}),C.addEventListener("mouseleave",()=>{C.style.background=""}),C.addEventListener("focus",()=>{C.style.background=$.bgHover}),C.addEventListener("blur",()=>{C.style.background=""}),C.addEventListener("click",()=>i(d)),C.addEventListener("keydown",y=>{(y.key==="Enter"||y.key===" ")&&(y.preventDefault(),i(d))}))}}function qt(e){return Rt(Float64Array.from(e))}function et(e,t){if(!e)return[];const i=e.waferMetadata??(e.perWaferMetadata?Re(e.perWaferMetadata.map(n=>({metadata:n}))):void 0);return!i||!Object.keys(i).length?[]:kt({waferMetadata:i,waferKeys:"identity",waferPlacement:"csv",reservedLabels:t}).columns}function tt(e){return e?.populationLabel?[{key:"population",label:"Population",scope:"wafer",constant:e.populationLabel,get:()=>e.populationLabel,csvOnly:!0}]:[]}export function buildTestSection(...e){return be(buildTestSectionSteps(...e))}export function*buildTestSectionSteps(e,t,i,n,o,u,s,m,p="full"){const r=e.filter(c=>!c.partial&&!c.edgeExcluded),a=new Map((n?.perTestStats??[]).map(c=>[c.testNumber,c])),b=new Map((n?.testSpecYield??[]).map(c=>[c.testNumber,c]));let f;if(t?.length?f=t.filter(ct).map(c=>({testNumber:c.testNumber,name:c.name,unit:c.unit,limitLow:c.limitLow,limitHigh:c.limitHigh,limitLowInclusive:c.limitLowInclusive,limitHighInclusive:c.limitHighInclusive,...we(c)})):f=Et(r).map(W=>({testNumber:W,name:pt(void 0,W)})),!f.length)return null;const w=f.filter(c=>r.some(W=>{const j=Ne(W,c.testNumber);return j!==void 0&&isFinite(j)}));if(!w.length)return null;const k=w.some(c=>c.limitLow!==void 0||c.limitHigh!==void 0),E=[],H=c=>!!c&&c.stddev!==void 0&&c.median!==void 0&&c.q1!==void 0&&c.q3!==void 0,I=c=>c.limitLow!==void 0||c.limitHigh!==void 0,O=!!(s?.length&&t?.length),C=(O||w.some(c=>!H(a.get(c.testNumber))||I(c)&&!b.has(c.testNumber)))&&t?.length?yield*Mt(s??[{dies:e}],t):void 0;for(const c of w){yield;const W=a.get(c.testNumber),j=C?.specTally.get(c.testNumber),ee=C?.stats.get(c.testNumber),K=()=>r.map(D=>Ne(D,c.testNumber)).filter(D=>D!==void 0&&isFinite(D));let Q;if(H(W)){const D=W;Q={testNumber:c.testNumber,min:D.min,max:D.max,mean:D.mean,count:D.count,stddev:D.stddev,median:D.median,q1:D.q1,q3:D.q3}}else if(ee)Q={testNumber:c.testNumber,...ee};else{const D=K();if(!D.length)continue;Q={testNumber:c.testNumber,...qt(D)}}let M=null,B=0;if(I(c)){const D=b.get(c.testNumber);if(D)({yieldPercent:M,totalDies:B}=D);else if(j)B=j.n,M=B>0?(B-j.fail)/B*100:null;else{const X=K();let ue=0;for(const ie of X)Ft(Nt(ie,c))&&ue++;B=X.length,M=X.length>0?(X.length-ue)/X.length*100:null}}E.push({entry:c,stats:Q,specYieldPct:M,specN:B})}if(!E.length)return null;const d=new Map;for(const c of(O?C?.capability:void 0)??[])c.hasSpec&&d.set(c.testNumber,c.ppk);const v=d.size>0,h=new Set(E.map(c=>c.stats.count)).size===1?E[0].stats.count:null,y=l("div"),S=l("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:x.sm}),L=h!==null?` \xB7 N=${h.toLocaleString()}`:"",A=u?.populationLabel?`Test Values (${E.length}) \u2014 ${u.populationLabel}${L}`:`Test Values (${E.length})${L}`,T=se(A);T.style.marginBottom="0",S.appendChild(T);const R=document.createElement("button");R.type="button",R.textContent="Test values CSV",Object.assign(R.style,{...me("outlined")}),G(R),R.addEventListener("click",()=>{const c=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];v&&c.push("Ppk");const W=E.some(B=>B.specYieldPct!==null&&B.specN!==B.stats.count);k&&(c.push("Lo limit","Hi limit","Limit Yield %"),W&&c.push("Limit Yield N"));const j=E.some(B=>Te(B.entry));j&&c.push(De);const ee=[...et(u,c),...tt(u)],Q=[[...ee.map(B=>B.label),...c].map(he).join(",")],M=B=>We(B,void 0,"engineering");for(const{entry:B,stats:D,specYieldPct:X,specN:ue}of E){const ie=[...ee.map(le=>le.constant??""),B.name,B.unit??"",String(D.count),M(D.min),M(D.q1),M(D.median),M(D.mean),M(D.q3),M(D.max),M(D.stddev)];if(v){const le=d.get(B.testNumber);ie.push(le==null?"":le.toFixed(3))}k&&(ie.push(B.limitLow!==void 0?M(B.limitLow):"",B.limitHigh!==void 0?M(B.limitHigh):"",X!==null?X.toFixed(1):""),W&&ie.push(B.limitLow!==void 0||B.limitHigh!==void 0?String(ue):"")),j&&ie.push(Fe(B)),Q.push(ie.map(he).join(","))}je(Q.join(`
|
|
2
|
-
`),"test-values.csv","text/csv",o)}),
|
|
3
|
-
`),"functional-tests.csv","text/csv",n)}),b.appendChild(k),a.appendChild(b);const E=l("table",{width:"100%",borderCollapse:"collapse",fontSize:F.body}),H=document.createElement("thead"),I=document.createElement("tr"),O=p===null?["Test","N","Pass","Fail","Pass rate"]:["Test","Pass","Fail","Pass rate"];for(const g of O)I.appendChild(l("th",{textAlign:g==="Test"?"left":"right",fontWeight:"700",fontSize:F.body,letterSpacing:fe,textTransform:"uppercase",color:Y,padding:"3px 8px 5px",borderBottom:`1px solid ${$.menuBorder}`,whiteSpace:"nowrap"},g));H.appendChild(I),E.appendChild(H);const z=document.createElement("tbody");for(const g of s){const h=document.createElement("tr"),y=(S,L="right")=>{h.appendChild(l("td",{textAlign:L,padding:`${x.xs} ${x.md}`,borderBottom:`1px solid ${$.menuBorder}`,color:ne,whiteSpace:"nowrap"},S))};y(g.label,"left"),p===null&&y(String(g.totalDies)),y(String(g.passDies)),y(String(g.failDies)),y(g.passRatePercent!==null?`${g.passRatePercent.toFixed(1)}%`:"\u2014"),z.appendChild(h)}E.appendChild(z);const C=l("div",{overflowX:"auto"});C.appendChild(E);const d=st(C,s);if(!u)return a.appendChild(d),a;b.remove();const{outer:v}=oe(f,!0,void 0,{stateKey:"functionalTests",panel:u,render:g=>g.appendChild(d),control:()=>k});return v}export function buildLotFunctionalSection(e,t,i,n,o){const u=i?.length?{perWaferMetadata:i.map(m=>m.wafer??{}),populationLabel:`${i.length} wafer${i.length===1?"":"s"} pooled`}:void 0,s=At(i);return s?buildFunctionalTestSection(e,t,s,n,u,o):buildFunctionalTestSection(e,t,void 0,n,u,o)}const ae={unusual:0,notable:1,info:2};function Be(e){return l("span",{display:"inline-block",width:"7px",height:"7px",borderRadius:q.pill,background:ge(e),flexShrink:"0"})}function nt(e,t){let i=e.summary;if(t){const n=[" has "," have "].find(o=>i.startsWith(`${t}${o}`));n?i=i.slice(t.length+n.length):i.startsWith(`${t} `)&&(i=i.slice(t.length+1))}return i=de(i),i.length?i[0].toUpperCase()+i.slice(1):i}function it(e){return ot(e.map(t=>({label:t.variable.label,...we(t.variable)})))}function ot(e){const t=mt(e);return t?l("div",{fontSize:F.body,color:Y,marginTop:x.sm,lineHeight:te.base},t):null}function st(e,t){const i=ot(t);if(!i)return e;const n=l("div",{});return n.append(e,i),n}export function buildFindingsSection(e,t,i,n,o=!1){if(!e.length)return null;const u=e.some(d=>d.severity==="unusual"||d.severity==="notable"),s=u?e.filter(d=>d.severity!=="info").length.toString():void 0,{outer:m,content:p}=o?(()=>{const d=l("div");return{outer:d,content:d}})():oe(`Findings (${e.length})`,u,s);function r(d){return d.reduce((v,g)=>ae[g.severity]<ae[v]?g.severity:v,"info")}function a(d){const v=new Map;for(const h of d){const y=`${h.comparison.family}\0${h.comparison.left}`,S=v.get(y)??[];S.push(h),v.set(y,S)}const g=[...v.entries()].map(([h,y])=>{const S=[...y].sort((L,A)=>ae[L.severity]-ae[A.severity]);return{key:h,findings:S,worst:r(S)}});return g.sort((h,y)=>ae[h.worst]-ae[y.worst]),g}function b(d,v){const h={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[d]??d;return v.toLowerCase().startsWith(h.toLowerCase())?v:`${h}: ${v}`}const f=e.filter(d=>d.comparison.family==="spatial-pattern"),w=new Set([...f.flatMap(d=>d.relatedIds??[]),...e.flatMap(d=>d.absorbedIds??[])]),k=e.filter(d=>d.comparison.family!=="spatial-pattern"&&!w.has(d.id)),E=a(k),H=()=>[...E.flatMap(d=>d.findings),...f.flatMap(d=>e.filter(v=>d.relatedIds?.includes(v.id)))];function I(d,v=!1,g){const h=n===d.id,y=document.createElement("button");return y.type="button",y.dataset.wmapFinding=d.id,y.textContent=nt(d,g),ce(y,St(d)),y.setAttribute("aria-current",h?"true":"false"),Object.assign(y.style,{border:`1px solid ${$.menuBorder}`,borderLeft:`3px solid ${ge(d.severity)}`,background:h?$.bgActive:$.menuBg,borderRadius:q.container,padding:v?"6px 10px":"8px 10px",textAlign:"left",fontSize:v?"10px":"11px",fontWeight:h?"600":"400",color:$.text,cursor:"pointer",width:"100%",marginBottom:x.xs}),G(y,"bare"),y.addEventListener("click",()=>i(d,y)),y}const O=de(vt(e)??"");if(O){const d=l("div",{background:$.bgActive,borderRadius:q.container,padding:`${x.md} ${x.lg}`,marginBottom:x.md,display:"flex",gap:x.md,alignItems:"flex-start"}),v=l("span",{flex:"1",fontSize:F.body,lineHeight:te.base,color:$.text},O);d.appendChild(v);const g=l("button",{flexShrink:"0",border:"none",background:"none",fontSize:F.body,color:$.icon,cursor:"pointer",padding:"0",lineHeight:te.base,whiteSpace:"nowrap"},"Detail \u25B8");g.type="button",G(g,"bare"),g.addEventListener("click",()=>{const h=Ye({title:"Findings Summary",onClose:()=>{},anchor:g}),y=l("p",{fontSize:"16px",lineHeight:te.base,color:$.text,padding:`${x.xxl} ${x.xxxl} ${x.xxl}`,margin:"0",borderBottom:`1px solid ${$.menuBorder}`,flexShrink:"0"},O);h.contentWrap.appendChild(y);const S=l("div",{overflowY:"auto",padding:`${x.xxl} ${x.xxxl}`,flex:"1"}),L=(T,R)=>{const P=l("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:F.sub,fontWeight:"600",color:ne,marginTop:x.lg,marginBottom:x.xs});return P.appendChild(Be(T)),P.appendChild(l("span",{},R)),P};for(const T of f){S.appendChild(L(T.severity,T.comparison.left)),S.appendChild(l("div",{fontSize:F.body,color:$.text,padding:"4px 0 4px 15px",marginBottom:x.xxs},de(T.summary)));const R=e.filter(P=>T.relatedIds?.includes(P.id));for(const P of R)S.appendChild(l("div",{fontSize:F.body,color:Y,padding:"2px 0 2px 23px",marginBottom:x.xxs},de(P.summary)))}for(const T of E){const[R,P]=T.key.split("\0");S.appendChild(L(T.worst,b(R,P)));for(const Z of T.findings)S.appendChild(l("div",{fontSize:F.body,color:$.text,padding:"4px 0 4px 15px",marginBottom:x.xxs},nt(Z,P)))}const A=it(H());A&&S.appendChild(A),h.contentWrap.appendChild(S),Object.assign(h.contentWrap.style,{flexDirection:"column",overflow:"hidden"})}),d.appendChild(g),p.appendChild(d)}let z=!0;for(const d of f){z||p.appendChild(l("div",{height:"1px",background:$.separator,margin:"4px 0"})),z=!1;const v=e.filter(L=>d.relatedIds?.includes(L.id)),g=v.length>0,h=l("div",{position:"relative",marginBottom:g?"2px":"4px"}),y=n===d.id,S=document.createElement("button");if(S.type="button",S.dataset.wmapFinding=d.id,Object.assign(S.style,{border:`1px solid ${$.menuBorder}`,borderLeft:`3px solid ${ge(d.severity)}`,background:y?$.bgActive:$.menuBg,borderRadius:q.container,padding:"8px 32px 8px 10px",textAlign:"left",fontSize:F.body,fontWeight:y?"600":"500",color:$.text,cursor:"pointer",width:"100%"}),S.textContent=de(d.summary),ce(S,d.summary),S.setAttribute("aria-current",y?"true":"false"),G(S,"bare"),S.addEventListener("click",()=>i(d,S)),h.appendChild(S),g){const L=l("div",{display:"none",paddingLeft:"12px",marginBottom:x.xs});for(const R of v)L.appendChild(I(R,!0));h.appendChild(L);let A=!1;const T=l("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:F.body,color:$.icon,cursor:"pointer",padding:`${x.xxs} ${x.xs}`,lineHeight:te.none},"\u25B8");G(T,"bare"),T.type="button",ce(T),T.setAttribute("aria-label","Show supporting findings"),T.setAttribute("aria-expanded","false"),T.addEventListener("click",R=>{R.stopPropagation(),A=!A,L.style.display=A?"block":"none",T.textContent=A?"\u25BE":"\u25B8";const P=A?"Hide supporting findings":"Show supporting findings";T.setAttribute("aria-label",P),T.setAttribute("aria-expanded",String(A))}),h.appendChild(T)}p.appendChild(h)}for(const d of E){z||p.appendChild(l("div",{height:"1px",background:$.separator,margin:"4px 0"})),z=!1;const[v,g]=d.key.split("\0"),h=l("div",{display:"flex",alignItems:"center",gap:x.sm,fontSize:F.body,fontWeight:"600",color:ne,margin:"2px 0 4px"});h.appendChild(Be(d.worst)),h.appendChild(l("span",{},b(v,g))),p.appendChild(h);for(const y of d.findings)p.appendChild(I(y,!1,g))}const C=it(H());return C&&p.appendChild(C),m}const Gt=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],Ut=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],Qt=["unusual","notable","info"],Xt={unusual:"Unusual",notable:"Notable",info:"Info"};function Zt(e,t,i){const n=l("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:x.lg,marginBottom:x.lg,paddingBottom:"10px",borderBottom:`1px solid ${$.separator}`}),o={unusual:0,notable:0,info:0};for(const r of e)o[r.severity]++;const u=Qt.filter(r=>o[r]>0),s=new Set(t.severity===void 0?u:Array.isArray(t.severity)?t.severity:[t.severity]),m=l("div",{display:"flex",gap:x.xs,flexWrap:"wrap"});for(const r of u){const a=document.createElement("button");a.type="button";const b=()=>{const f=s.has(r);a.setAttribute("aria-pressed",f?"true":"false"),Object.assign(a.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${$.menuBorder}`,borderRadius:q.pill,background:f?$.bgActive:"none",opacity:f?"1":"0.5",color:$.text,fontSize:F.body,padding:`${x.xxs} ${x.md}`,cursor:"pointer"}),a.dataset.on=f?"true":"false"};a.appendChild(Be(r)),a.appendChild(l("span",{},`${Xt[r]} ${o[r]}`)),ce(a,()=>s.has(r)?"Click to hide these findings":"Click to show these findings"),b(),G(a,"bare"),a.addEventListener("click",()=>{s.has(r)?s.delete(r):s.add(r),t.severity=s.size===u.length?void 0:[...s],i()}),m.appendChild(a)}n.appendChild(m);const p=t.kind!==void 0||t.family!==void 0;return(e.length>=Jt||p)&&(n.appendChild(ze("Kind:",Gt,t.kind??"",r=>{t.kind=r||void 0,i()},{maxWidth:"130px"})),n.appendChild(ze("Region:",Ut,t.family??"",r=>{t.family=r||void 0,i()},{maxWidth:"150px"}))),n}const Jt=8;function en(e,t){const i=l("div",{display:"flex",flexDirection:"column",gap:x.xs,padding:x.md,marginBottom:x.md,background:$.bgHover,borderRadius:q.control},void 0,t);if(i.appendChild(l("div",{fontSize:F.body,color:$.value},e.message,t)),e.detail&&i.appendChild(l("div",{fontSize:F.meta,color:Y},e.detail,t)),e.actionLabel&&e.onAction){const n=l("button",me("outlined"),e.actionLabel,t);n.type="button",n.style.alignSelf="flex-start",n.style.marginTop=x.xs,G(n),n.addEventListener("click",e.onAction),i.appendChild(n)}return i}export function buildFindingsSectionWithFilter(e,t,i,n,o,u,s){if(!e.findings.length&&!s)return null;const m=e.findings.some(k=>k.severity==="unusual"||k.severity==="notable"),p=m?e.findings.filter(k=>k.severity!=="info").length.toString():void 0,r=u?.ownerDocument??document,{outer:a,content:b}=oe(`Findings (${e.findings.length})`,m||!!s,p,{stateKey:"findings",panel:u});if(s&&b.appendChild(en(s,r)),!e.findings.length)return a;b.appendChild(Zt(e.findings,n,o));const f=wt(e,n);if(!f.length)return b.appendChild(l("div",{color:Y,fontSize:F.body,textAlign:"center",padding:`${x.xxl} ${x.md}`},"No findings match the current filter.")),a;const w=buildFindingsSection(f,e,t,i,!0);return w&&b.appendChild(w),a}export function buildLotTestSection(...e){return be(buildLotTestSectionSteps(...e))}export function*buildLotTestSectionSteps(e,t,i,n,o,u,s,m="full"){const p=n?.length?{perWaferMetadata:n.map(a=>a.wafer??{}),populationLabel:`${n.length} wafer${n.length===1?"":"s"} pooled`}:void 0;let r;if(n?.length&&n.every(a=>a.stats.perTestStats!==void 0)){const a=new Map;for(const b of n)for(const f of b.stats.perTestStats??[]){const w=a.get(f.testNumber);w?(w.n+=f.count,w.sum+=f.mean*f.count,w.min=Math.min(w.min,f.min),w.max=Math.max(w.max,f.max)):a.set(f.testNumber,{n:f.count,sum:f.mean*f.count,min:f.min,max:f.max})}r={perTestStats:[...a.entries()].map(([b,f])=>({testNumber:b,count:f.n,min:f.min,max:f.max,mean:f.sum/f.n}))}}if(n?.length&&n.every(a=>a.stats.testSpecYield!==void 0)){const a=new Map;for(const b of n)for(const f of b.stats.testSpecYield??[]){const w=a.get(f.testNumber);w?(w.passDies+=f.passDies,w.totalDies+=f.totalDies):a.set(f.testNumber,{passDies:f.passDies,totalDies:f.totalDies})}r={...r,testSpecYield:[...a.entries()].map(([b,f])=>({testNumber:b,totalDies:f.totalDies,yieldPercent:f.totalDies>0?f.passDies/f.totalDies*100:null}))}}return yield*buildTestSectionSteps(e,t,i,r,o,p,u,s,m)}export function createSummaryPanelEl(e,t,i=document){const n=e==="top"||e==="bottom",o=l("div",{background:Yt,color:$.text,fontVariantNumeric:"tabular-nums",border:Ke,borderRadius:q.container,padding:x.xl,overflowY:"auto",overflowX:n?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:F.family,fontSize:F.sub,boxShadow:He.panel},void 0,i);return e==="right"&&(o.style.marginRight=t),e==="left"&&(o.style.marginLeft=t),e==="bottom"&&(o.style.marginBottom=t),n?(o.style.height="180px",o.style.width="100%"):(o.style.width="300px",o.style.maxHeight="100%"),o}export function wrapWithSummaryPanel(e,t,i){const n=i==="top"||i==="bottom",o=l("div",{display:"flex",flexDirection:n?"column":"row",gap:x.md,width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:n?"flex-start":"stretch"});return e.style.flex="1 1 0",e.style.minWidth="0",e.style.minHeight="0",i==="right"||i==="bottom"?(o.appendChild(e),o.appendChild(t)):(o.appendChild(t),o.appendChild(e)),o}function at(e){return l("div",{fontSize:F.heading,fontWeight:"600",color:ne,marginBottom:x.lg},e)}function Ce(e,t){const i=l("button",me("outlined"),e);return i.type="button",G(i),i.addEventListener("click",t),i}function rt(...e){const t=e.filter(n=>!!n);if(!t.length)return null;const i=l("div",{display:"flex",flexWrap:"wrap",gap:x.sm,marginBottom:x.lg});for(const n of t)i.appendChild(n);return i}function lt(e,t,i,n,o,u,s,m,p,r,a){const b=e.ownerDocument,f=Ye({title:"Die list",onClose:()=>{},anchor:e,ownerDocument:b});f.contentWrap.style.padding="14px 16px";const w=Wt(t,i,{...s,title:n,onSaveText:m,waferMetadata:o,metadataFields:u,extraColumn:p,getWafer:r,ringCount:a,ownerDocument:b});w&&f.contentWrap.appendChild(w)}export function renderWaferSummaryContent(...e){be(renderWaferSummaryContentSteps(...e))}export function*renderWaferSummaryContentSteps(e,t){const i=e.scrollTop;e.innerHTML="";const{wafer:n,dies:o,yieldSummary:u,dataCoverage:s,hbinDefs:m,sbinDefs:p,testDefs:r,statsSummary:a,passBins:b=[1],ringCount:f=4,binColors:w,plotMode:k,fallbackFormat:E,onFindingClick:H,activeFindingId:I=null,findingsFilter:O,onFindingsFilterChange:z,findingsNotice:C,onSaveText:d,metadataFields:v,dieListOptions:g,metadataShownElsewhere:h}=t;e.appendChild(at("Wafer Summary"));const y=t.warnings??Ae({statsSummary:a});y.length&&e.appendChild($e(y,e.ownerDocument));const S=u&&s?Ce("Summary report",()=>{_e(yt({wafer:n,dies:o,yield:u,dataCoverage:s,hbinDefs:m,sbinDefs:p,testDefs:r,passBins:b,ringCount:f},a),{anchor:e})}):null,L=(g?.enabled??!0)&&o.length?Ce("View die list",()=>{lt(e,o,r,`Die list \u2014 ${o.length} dies`,n.metadata,v,g,d,void 0,()=>n,f)}):null,A=rt(S,L);A&&e.appendChild(A);let T=!0;const R=_=>{_&&(T||e.appendChild(Ue()),T=!1,e.appendChild(_))},P=a?.stats.isLotStack?a.stats:void 0,Z=P?.lotSize!==void 0?{lotSize:P.lotSize,aggrMethod:Dt(P.aggregationMethod)}:void 0;h||R(buildMetadataInfoSection([{metadata:n.metadata??void 0}],Z)),u&&s&&R(buildYieldSection(u,s,b)),yield,a&&H&&O&&z&&(R(buildFindingsSectionWithFilter(a,H,I,O,z,e,C)),yield),R(buildBinBreakdownSection({dies:o,hbinDefs:m,sbinDefs:p,binColors:w,hardCounts:a?.stats.hardBinCounts,softCounts:a?.stats.softBinCounts,plotMode:k,passBins:b,panel:e})),yield,R(buildRegionYieldPanelSection({diesByWafer:[o],allWafers:[n],ringCount:f,passBins:b,panel:e})),yield;const J=n.metadata?{waferMetadata:n.metadata}:void 0;R(yield*buildTestSectionSteps(o,r,E,a?.stats,d,J,[{dies:o}],e,"compact")),yield,R(buildFunctionalTestSection(o,r,a?.stats.functionalYield,d,J,e)),e.appendChild(l("div",{height:"12px",flexShrink:"0"})),e.scrollTop=i}export function reportMapsFromItems(e,t,i){const n=[];return e.forEach((o,u)=>{!o?.wafer||!o.dies||n.push({...o,wafer:o.wafer,dies:o.dies,label:ve(o,u),passBins:[...Se(o,t)],ringCount:o.ringCount??i})}),n}export function renderLotSummaryContent(...e){be(renderLotSummaryContentSteps(...e))}export function*renderLotSummaryContentSteps(e,t){const i=e.scrollTop;e.innerHTML="";const{lotSummary:n,items:o,hbinDefs:u,sbinDefs:s,testDefs:m,passBins:p=[1],ringCount:r=4,binColors:a,plotMode:b,fallbackFormat:f,onFindingClick:w,activeFindingId:k=null,onWaferClick:E,findingsFilter:H,onFindingsFilterChange:I,findingsNotice:O,onSaveText:z,dieListOptions:C,findingsFor:d}=t;e.appendChild(at(`Summary \u2014 ${Tt(Ie(n.perWafer.map(N=>N.summary.wafer)))}`));const v=t.warnings??Ae({lotStatsSummary:n});v.length&&e.appendChild($e(v,e.ownerDocument));const g=Ce("Summary report",()=>{_e(Ct(reportMapsFromItems(o,p,r)),{anchor:e})}),h=[],y=[],S=[],L=[],A=[],T=new WeakMap,R=new WeakMap;for(let N=0;N<o.length;N++){yield;const V=o[N];if(!V){y.push([]);continue}V.wafer&&(h.push(V.wafer),L.push(V.dies??[]),A.push(Se(V,p)));const re=V.dies??[],c=ve(V,N);for(const W of re)T.set(W,c),V.wafer&&R.set(W,V.wafer);y.push(re);for(const W of re)S.push(W)}const P=C?.enabled??!0?Ce("View die list",()=>{S.length&<(e,S,m,`Die list \u2014 ${S.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,Re(o.filter(N=>!!N).map(N=>({metadata:N.wafer?.metadata}))),o.find(N=>N?.metadataFields?.length)?.metadataFields,C,z,{label:"Wafer",get:N=>T.get(N)},N=>R.get(N),r)}):null,Z=rt(g,P);Z&&e.appendChild(Z);const J=o.map(N=>N?.statsSummary).filter(N=>!!N);let _=!0;const U=N=>{N&&(_||e.appendChild(Ue()),_=!1,e.appendChild(N))};U(buildLotOverviewSection(n,J)),yield,w&&H&&I&&(U(buildFindingsSectionWithFilter(n,w,k,H,I,e,O)),yield),U(buildPerWaferYieldSection(n,o,E,e,d)),yield,U(buildBinBreakdownSection({dies:S,hbinDefs:u,sbinDefs:s,plotMode:b,passBins:p,panel:e,binColors:a??Lt(o.flatMap(N=>N?[{dies:N.dies??[],passBins:Se(N,p)}]:[]),{hbinDefs:u,sbinDefs:s}).colors})),yield,U(buildRegionYieldPanelSection({diesByWafer:L,allWafers:h,ringCount:r,passBins:N=>A[N],panel:e})),yield,m?.length&&(U(yield*buildLotTestSectionSteps(S,m,f,J,z,y.map(N=>({dies:N})),e,"compact")),yield,U(buildLotFunctionalSection(S,m,J,z,e))),e.appendChild(l("div",{height:"12px",flexShrink:"0"})),e.scrollTop=i}
|
|
1
|
+
import{testValue as Be}from"../core/dieTable.js";import{waferDisplayLabel as ve}from"../core/waferLabel.js";import{commonPassBins as gt,itemPassBins as me,passBinsLabel as ht}from"../core/passBins.js";import{isParametricTest as bt}from"../renderer/buildWaferMap.js";import{testLabel as xt,markedTestLabel as yt,unmarkedLabel as Ct,derivedFields as we,derivedKeyText as vt,derivedCsvCell as Ee,isDerivedTest as Te,DERIVED_CSV_HEADER as De}from"../renderer/testLabel.js";import{buildRingRegions as wt,buildQuadrantRegions as St,buildRegionYieldData as Lt}from"../stats/regions.js";import{computeFunctionalYield as $t}from"../stats/analyzeWaferMap.js";import{buildSynthesis as Re,synthesisText as kt}from"../stats/synthesis.js";import{MEAN_WAFER_YIELD_LABEL as Bt,METER_DOTS as Ne,SEVERITY_MARK as Et,filledDots as Fe,impactWord as Tt,formatPoints as Dt,shortfallColor as Rt}from"../stats/presentation.js";import{regionYieldRows as Nt,waferYieldRows as Ft}from"../stats/yieldRows.js";import{formatFindingTooltip as Ae}from"../stats/findingText.js";import{arrangeFindings as At,filterFindings as Mt}from"../stats/filterFindings.js";import{buildFacetTable as Wt,prettyKey as Me}from"../stats/facets.js";import{commonMetadata as We}from"../stats/facets.js";import{resolveMetadataColumns as It}from"../stats/metadataColumns.js";import{resolveBinColors as Ie,resolveBinColorsByWafer as Pt}from"../renderer/binColors.js";import{NO_DATA_FILL as zt}from"../renderer/colorMap.js";import{classifySpec as Ht,isOutOfSpec as Yt}from"../renderer/spec.js";import{describeWaferPopulation as Pe,populationLabel as Ot}from"../stats/population.js";import{buildWarningsBanner as Se,collectWarnings as ze}from"./warnings.js";export{Se as buildWarningsBanner};import{fmt as He,fmtAggregationMethod as _t,plainBinTerms as ae}from"../renderer/fmt.js";import{getUniqueTestNumbers as jt}from"../renderer/buildView.js";import{describeValues as Vt}from"../stats/math.js";import{pooledTestStatsSteps as Kt}from"../stats/capability.js";import{binBreakdownRows as qt,binBreakdownTitle as Ye,binCountsFrom as Oe,totalOf as _e}from"../stats/binRows.js";import{poolFunctionalYield as Gt}from"../stats/testPassRate.js";import{makeLabeledSelect as je,makeSegmented as Le}from"./charts/chartShell.js";import{SHADOW as Ve,MOTION as Ke,LEADING as Q,TRACKING as le,wireControlHover as U,controlStyle as ge,SPACE as g,RADIUS as G,FONT as T,CLR as C,sevColor as de,openModal as qe,openReportModal as Ge,saveTextFile as Ue,wireTooltip as re}from"./toolbar.js";import{buildDieListSection as Ut}from"./dieList.js";export{csvField}from"../core/utils.js";import{csvField as he,drain as be,maxOf as Qt,minOf as Xt}from"../core/utils.js";import{metadataDisplayValue as Zt}from"../core/metadata.js";const Jt=C.panelBg,Qe=`1px solid ${C.menuBorder}`,en="12px",z=C.label,X=C.value,Xe="10px";function a(e,n,i,t=document){const o=t.createElement(e);return n&&Object.assign(o.style,n),i!==void 0&&(o.textContent=i),o}function pe(e){return a("div",{fontSize:Xe,fontWeight:"700",letterSpacing:le,textTransform:"uppercase",color:z,marginBottom:g.sm},e)}const Ze=new WeakMap,Je=["regionYield","testValues","functionalTests"];function xe(e){if(!e)return{collapsed:new Set(Je),regionMode:"ring",waferSort:"slot"};let n=Ze.get(e);return n||(n={collapsed:new Set(Je),regionMode:"ring",waferSort:"slot"},Ze.set(e,n)),n}function ne(e,n=!0,i,t){const o=a("div"),c=xe(t?.panel);t?.stateKey&&t.panel&&(n=!c.collapsed.has(t.stateKey));const s=document.createElement("button");s.type="button",Object.assign(s.style,{display:"flex",alignItems:"center",gap:g.xs,width:"100%",background:"none",border:"none",cursor:"pointer",padding:"0 0 6px",textAlign:"left"});const h=a("span",{fontSize:T.meta,color:z,transition:`transform ${Ke.base}`,transform:n?"rotate(90deg)":"rotate(0deg)",display:"inline-block",lineHeight:Q.none,marginRight:"1px"},"\u25B6"),f=a("span",{fontSize:Xe,fontWeight:"700",letterSpacing:le,textTransform:"uppercase",color:z,flex:"1"},e);if(U(s,"bare"),s.setAttribute("aria-expanded",n?"true":"false"),s.appendChild(h),s.appendChild(f),i){const x=a("span",{fontSize:T.meta,fontWeight:"700",background:C.warnBg,color:C.warnText,borderRadius:G.pill,padding:"1px 5px"},i);s.appendChild(x)}const l=a("div");l.style.display=n?"block":"none";let p=n;if(s.addEventListener("click",()=>{p=!p,l.style.display=p?"block":"none",h.style.transform=p?"rotate(90deg)":"rotate(0deg)",s.setAttribute("aria-expanded",p?"true":"false"),t?.stateKey&&t.panel&&(p?c.collapsed.delete(t.stateKey):c.collapsed.add(t.stateKey))}),t?.control){const x=a("div",{display:"flex",alignItems:"center",gap:g.sm});s.style.width="auto",s.style.flex="1",x.appendChild(s);const r=()=>{l.innerHTML="",t.render?.(l)},m=t.control(r);m&&(m.style.marginBottom="6px",m.addEventListener("click",v=>v.stopPropagation()),x.appendChild(m)),o.appendChild(x)}else o.appendChild(s);return o.appendChild(l),t?.render?.(l),{outer:o,content:l}}function et(){return a("div",{height:"1px",background:C.separator,margin:`${en} 0`,flexShrink:"0"})}function $e(e,n,i=C.barFill,t,o,c){const s=a("div",{marginBottom:"5px"});c&&c.step>0&&Object.assign(s.style,{background:Rt(c.step),borderRadius:G.container,padding:"2px 4px",marginLeft:"-4px",marginRight:"-4px"});const h=a("div",{display:"flex",justifyContent:"space-between",fontSize:T.body,color:X,marginBottom:g.xxs}),f=a("span",{color:z},e),l=a("span",{fontWeight:"600",fontVariantNumeric:"tabular-nums"},`${n.toFixed(1)}%`);c&&(l.appendChild(a("span",{fontWeight:"400",marginLeft:g.sm,color:c.step>0?X:z},Dt(c.delta))),c.step>0&&(f.style.color=X)),h.appendChild(f),h.appendChild(l);const p=t!==void 0?t:Math.min(100,Math.max(0,n)),x=i,r=a("div",{position:"relative",height:"9px",background:C.bgActive,borderRadius:G.control,overflow:"hidden"}),m=a("div",{height:"100%",width:`${p}%`,background:x,borderRadius:G.control,transition:`width ${Ke.base}`});if(r.appendChild(m),o!==void 0){const v=a("div",{position:"absolute",top:"0",bottom:"0",left:`${o}%`,width:"2px",marginLeft:"-1px",background:C.value,opacity:"0.8"});r.appendChild(v)}return s.appendChild(h),s.appendChild(r),s}function tt(){const e=a("div",{display:"flex",gap:g.sm,marginBottom:g.md});return e.finish=()=>{const n=e.lastElementChild;n&&Object.assign(n.style,{borderRight:"none",paddingRight:"0"})},e}function ue(e,n,i){const t=a("div",{padding:`${g.xxs} ${g.md} ${g.xxs} 0`,borderRight:Qe,textAlign:"center",flex:"1"}),o=a("div",{fontSize:T.heading,fontWeight:"700",color:X,lineHeight:Q.tight},e),c=a("div",{fontSize:T.body,color:z,marginTop:g.xxs},n);return t.appendChild(o),t.appendChild(c),i&&t.appendChild(a("div",{fontSize:T.body,color:z,opacity:"0.85"},i)),t}function nt(e,n){const i=a("div",{display:"flex",justifyContent:"space-between",fontSize:T.body,gap:g.md,marginBottom:"3px"}),t=a("span",{color:z,flexShrink:"0"},e),o=a("span",{color:X,textAlign:"right",fontWeight:"500",wordBreak:"break-all"},n);return i.appendChild(t),i.appendChild(o),i}function tn(e,n){const i=a("div",{display:"flex",fontSize:T.body,gap:g.sm,marginBottom:"3px"}),t=a("span",{color:z,flexShrink:"0"},`${e}:`),o=a("span",{color:X,fontWeight:"500",wordBreak:"break-all"},n);return i.appendChild(t),i.appendChild(o),i}export function metadataEntries(e){const n=[];for(const[i,t]of Object.entries(e)){const o=Zt(t);o!==void 0&&n.push([i,o])}return n}const nn=["lot","product","testprogram","split"],ye=e=>{const n=nn.indexOf(e.toLowerCase().replace(/[^a-z]/g,""));return n===-1?Number.MAX_SAFE_INTEGER:n};export function buildFacetSummaryChips(e,n=3){if(!e.length)return null;const i=a("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:`${g.xs} ${g.lg}`}),t=[...e].sort((h,f)=>ye(h.key)-ye(f.key)),o=t.filter(h=>ye(h.key)!==Number.MAX_SAFE_INTEGER),c=t.filter(h=>ye(h.key)===Number.MAX_SAFE_INTEGER),s=h=>{const f=a("span",{whiteSpace:"nowrap"}),l=a("span",{color:z},`${Me(h.key)}: `);f.appendChild(l);const p=h.values.slice(0,n),x=h.values.length-p.length;let r=p.map(m=>m.value).join(", ");return x>0&&(r+=` +${x} more`),f.appendChild(document.createTextNode(r)),f};for(const h of o)i.appendChild(s(h));if(c.length){const h=a("span",{display:"none",flexWrap:"wrap",alignItems:"baseline",gap:`${g.xs} ${g.lg}`});for(const p of c)h.appendChild(s(p));const f=a("button",{background:"none",border:"none",padding:"0",cursor:"pointer",color:C.iconActive,fontSize:T.body,whiteSpace:"nowrap"});f.type="button",U(f,"bare");const l=p=>{h.style.display=p?"contents":"none",f.textContent=p?"less":`+${c.length} more`,f.setAttribute("aria-expanded",String(p))};l(!1),f.addEventListener("click",()=>l(f.getAttribute("aria-expanded")!=="true")),i.appendChild(h),i.appendChild(f)}return i}export function buildMetadataStripRow(e,n,i){const t=Wt(e,i),o=buildFacetSummaryChips(t);if(!o&&!n)return null;const c=a("div",{display:"flex",flexWrap:"wrap",alignItems:"baseline",gap:"4px 14px"});if(n){const s=a("span",{fontWeight:"500",whiteSpace:"nowrap"},n.aggrMethod?`${n.lotSize} wafers stacked \xB7 ${n.aggrMethod}`:`${n.lotSize} wafers stacked`);c.appendChild(s)}return o&&c.appendChild(o),c}const on={display:"flex",flexDirection:"column",gap:g.sm,background:C.menuBg,border:`1px solid ${C.menuBorder}`,borderRadius:G.container,padding:`${g.sm} ${g.lg}`,boxShadow:Ve.panel,fontSize:T.body,lineHeight:Q.none,boxSizing:"border-box",width:"100%",minWidth:"0"};export function buildMetadataStripBox(e,n,i){const t=buildMetadataStripRow(e,n,i);if(!t)return null;const o=a("div",on);return o.appendChild(t),o}export function buildCompactMetadataRows(e){const n=metadataEntries(e);if(!n.length)return null;const i=a("div");for(const[t,o]of n)i.appendChild(tn(Me(t),o));return i}export function buildMetadataInfoSection(e,n){const i=buildMetadataStripRow(e,n,{facetableOnly:e.length>1});if(!i)return null;const t=a("div");return t.appendChild(pe("Wafer Info")),t.appendChild(i),t}export function buildYieldSection(e,n,i=[1]){const t=a("div");t.appendChild(pe("Summary"));const o=tt();if(o.appendChild(ue(String(e.totalDies),"Total dies")),e.partialDies>0&&o.appendChild(ue(String(e.partialDies),"Partial")),e.yieldPercent!==null){const c=ht([i]);o.appendChild(ue(`${e.yieldPercent.toFixed(1)}%`,"Yield",`pass: ${c}`))}return o.finish(),t.appendChild(o),e.edgeExcludedDies>0&&t.appendChild(nt("Edge excluded (outer zone)",String(e.edgeExcludedDies))),t}export function buildBinSection(e,n,i,t,o,c){const s=Oe(e,i,o);if(!s.size)return null;const h=t??Ie(e,{passBins:c,...i==="hard"?{hbinDefs:n}:{sbinDefs:n}}),f=a("div");f.appendChild(pe(Ye(i,_e(s))));for(const l of it(s,n,h[i],h.pass[i]))f.appendChild(l);return f}function it(e,n,i,t){return qt(e,n,t).map(o=>$e(`${o.label} (${o.count})`,o.percent,i.get(o.bin)??zt))}export function buildBinBreakdownSection(e){const{dies:n,hbinDefs:i,sbinDefs:t,hardCounts:o,softCounts:c,plotMode:s,passBins:h=[1],panel:f}=e,l=e.binColors??Ie(n,{passBins:h,hbinDefs:i,sbinDefs:t}),p=D=>Oe(n,D,D==="hard"?o:c),x=p("hard"),r=p("soft"),m=x.size>0,v=r.size>0;if(!m&&!v)return null;const L=xe(f),A=s==="softBin"||s==="stackedSoftBins"?"soft":s==="hardBin"||s==="stackedBins"?"hard":void 0;let u=L.binMode??A??(m?"hard":"soft");u==="hard"&&!m&&(u="soft"),u==="soft"&&!v&&(u="hard");const E=u==="hard"?x:r,W=u==="hard"?i:t,b=_e(E),{outer:S}=ne(Ye(u,b),!0,void 0,{stateKey:"bins",panel:f,render:D=>{const y=u==="hard"?l.hard:l.soft;for(const $ of it(E,W,y,l.pass[u]))D.appendChild($)},control:m&&v&&f?()=>Le([["hard","Hard"],["soft","Soft"]],u,D=>{L.binMode=D;const y=buildBinBreakdownSection(e);y&&S.replaceWith(y)},f.ownerDocument,!0):void 0});return S}export function buildLotBinSection(e,n,i,t){return buildBinSection(e,n,i,t)}export function buildRegionYieldPanelSection(e){const{diesByWafer:n,allWafers:i,ringCount:t,passBins:o,panel:c}=e,s=xe(c),h=p=>Lt(n,i,t,o,p==="ring"?wt:St);if(!h("ring").length&&!h("quadrant").length)return null;const f=s.regionMode,{outer:l}=ne(f==="ring"?"Ring Yield":"Quadrant Yield",!0,void 0,{stateKey:"regionYield",panel:c,render:p=>{const x=h(f);if(!x.length){p.appendChild(a("div",{fontSize:T.body,color:z},"No positioned dies for this breakdown."));return}for(const{label:r,n:m,yieldPercent:v,delta:L,step:A}of Nt(x).rows)p.appendChild($e(`${r} (N=${m})`,v,void 0,void 0,void 0,{delta:L,step:A}))},control:c?()=>Le([["ring","Ring"],["quadrant","Quadrant"]],f,p=>{s.regionMode=p;const x=buildRegionYieldPanelSection(e);x&&l.replaceWith(x)},c.ownerDocument,!0):void 0});return l}export function buildLotOverviewSection(e,n=[]){const i=a("div"),t=Pe(e.perWafer.map(s=>s.summary.wafer));i.appendChild(pe(t.lotId!==void 0?"Lot Summary":"Summary"));const o=tt();o.appendChild(ue(String(e.stats.waferCount),"Wafers"));const c=e.perWafer.map(s=>s.summary.stats.yieldPercent).filter(s=>s!==null);if(c.length){const s=c.reduce((h,f)=>h+f,0)/c.length;o.appendChild(ue(`${s.toFixed(1)}%`,Bt))}if(o.finish(),i.appendChild(o),n.length){const s=n.reduce((f,l)=>f+l.stats.analyzedDies,0),h=n.reduce((f,l)=>f+l.stats.excludedDies,0);(s||h)&&i.appendChild(nt("Dies analysed",h?`${s.toLocaleString()} (${h.toLocaleString()} excluded)`:s.toLocaleString()))}return i}export function buildPerWaferYieldSection(e,n,i,t,o){const c=e.perWafer.map(u=>({waferIndex:u.waferIndex,label:ve(n[u.waferIndex],u.waferIndex).replace(/\s*·\s*\d+(\.\d+)?%$/,""),yieldPct:u.summary.stats.yieldPercent})).filter(u=>u.yieldPct!==null);if(!c.length)return null;const s=Xt(c.map(u=>u.yieldPct)),h=Qt(c.map(u=>u.yieldPct)),f=s===h?"":` (${s.toFixed(1)}\u2013${h.toFixed(1)}%)`,{rows:l,median:p}=Ft(c.map(u=>({...u,yieldPercent:u.yieldPct}))),x=xe(t),r=u=>{const E=x.waferSort==="yield"?[...l].sort((W,b)=>W.yieldPct-b.yieldPct):l;for(const W of E){const{waferIndex:b,label:S,yieldPct:D,delta:y,step:$}=W,N=W.outlier?`${S} \xB7 ${W.outlier} outlier`:S,k=$e(N,D,void 0,void 0,p,{delta:y,step:$}),w=o?.(b);w?.total&&L(k,w),A(k,b,S,D,w),u.appendChild(k)}},m=` \xB7 median ${p.toFixed(1)}%`,{outer:v}=ne("Wafer Yield"+f+m,!0,void 0,{stateKey:"waferYield",panel:t,render:r,control:t?u=>Le([["slot","Slot"],["yield","Yield"]],x.waferSort,E=>{x.waferSort=E,u()},t.ownerDocument,!0):void 0});return v;function L(u,E){const W=E.unusual?"unusual":E.notable?"notable":"info",b=a("span",{marginLeft:g.sm,flexShrink:"0",background:de(W),color:"#fff",borderRadius:G.container,padding:"0 5px",fontSize:T.body,fontWeight:"600"},`${E.total}`);b.setAttribute("aria-hidden","true"),re(b,`${E.total} finding${E.total===1?"":"s"}`+(E.unusual?`, ${E.unusual} unusual`:"")+(E.notable?`, ${E.notable} notable`:"")),u.firstElementChild?.firstElementChild?.appendChild(b)}function A(u,E,W,b,S){i&&(u.style.cursor="pointer",u.style.borderRadius="4px",u.style.padding="2px 3px",u.style.marginLeft="-3px",u.style.marginRight="-3px",u.setAttribute("role","button"),u.setAttribute("aria-label",`${W}, ${b.toFixed(1)}% yield`+(S?.total?`, ${S.total} finding${S.total===1?"":"s"}${S.unusual?`, ${S.unusual} unusual`:""}`:"")+" \u2014 open wafer"),u.tabIndex=0,u.addEventListener("mouseenter",()=>{u.style.background=C.bgHover}),u.addEventListener("mouseleave",()=>{u.style.background=""}),u.addEventListener("focus",()=>{u.style.background=C.bgHover}),u.addEventListener("blur",()=>{u.style.background=""}),u.addEventListener("click",()=>i(E)),u.addEventListener("keydown",D=>{(D.key==="Enter"||D.key===" ")&&(D.preventDefault(),i(E))}))}}function sn(e){return Vt(Float64Array.from(e))}function ot(e,n){if(!e)return[];const i=e.waferMetadata??(e.perWaferMetadata?We(e.perWaferMetadata.map(t=>({metadata:t}))):void 0);return!i||!Object.keys(i).length?[]:It({waferMetadata:i,waferKeys:"identity",waferPlacement:"csv",reservedLabels:n}).columns}function st(e){return e?.populationLabel?[{key:"population",label:"Population",scope:"wafer",constant:e.populationLabel,get:()=>e.populationLabel,csvOnly:!0}]:[]}export function buildTestSection(...e){return be(buildTestSectionSteps(...e))}export function*buildTestSectionSteps(e,n,i,t,o,c,s,h,f="full"){const l=e.filter(d=>!d.partial&&!d.edgeExcluded),p=new Map((t?.perTestStats??[]).map(d=>[d.testNumber,d])),x=new Map((t?.testSpecYield??[]).map(d=>[d.testNumber,d]));let r;if(n?.length?r=n.filter(bt).map(d=>({testNumber:d.testNumber,name:d.name,unit:d.unit,limitLow:d.limitLow,limitHigh:d.limitHigh,limitLowInclusive:d.limitLowInclusive,limitHighInclusive:d.limitHighInclusive,...we(d)})):r=jt(l).map(P=>({testNumber:P,name:xt(void 0,P)})),!r.length)return null;const m=r.filter(d=>l.some(P=>{const _=Be(P,d.testNumber);return _!==void 0&&isFinite(_)}));if(!m.length)return null;const v=m.some(d=>d.limitLow!==void 0||d.limitHigh!==void 0),L=[],A=d=>!!d&&d.stddev!==void 0&&d.median!==void 0&&d.q1!==void 0&&d.q3!==void 0,u=d=>d.limitLow!==void 0||d.limitHigh!==void 0,E=!!(s?.length&&n?.length),b=(E||m.some(d=>!A(p.get(d.testNumber))||u(d)&&!x.has(d.testNumber)))&&n?.length?yield*Kt(s??[{dies:e}],n):void 0;for(const d of m){yield;const P=p.get(d.testNumber),_=b?.specTally.get(d.testNumber),K=b?.stats.get(d.testNumber),q=()=>l.map(M=>Be(M,d.testNumber)).filter(M=>M!==void 0&&isFinite(M));let J;if(A(P)){const M=P;J={testNumber:d.testNumber,min:M.min,max:M.max,mean:M.mean,count:M.count,stddev:M.stddev,median:M.median,q1:M.q1,q3:M.q3}}else if(K)J={testNumber:d.testNumber,...K};else{const M=q();if(!M.length)continue;J={testNumber:d.testNumber,...sn(M)}}let I=null,R=0;if(u(d)){const M=x.get(d.testNumber);if(M)({yieldPercent:I,totalDies:R}=M);else if(_)R=_.n,I=R>0?(R-_.fail)/R*100:null;else{const ee=q();let fe=0;for(const se of ee)Yt(Ht(se,d))&&fe++;R=ee.length,I=ee.length>0?(ee.length-fe)/ee.length*100:null}}L.push({entry:d,stats:J,specYieldPct:I,specN:R})}if(!L.length)return null;const S=new Map;for(const d of(E?b?.capability:void 0)??[])d.hasSpec&&S.set(d.testNumber,d.ppk);const D=S.size>0,$=new Set(L.map(d=>d.stats.count)).size===1?L[0].stats.count:null,N=a("div"),k=a("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:g.sm}),w=$!==null?` \xB7 N=${$.toLocaleString()}`:"",F=c?.populationLabel?`Test Values (${L.length}) \u2014 ${c.populationLabel}${w}`:`Test Values (${L.length})${w}`,j=pe(F);j.style.marginBottom="0",k.appendChild(j);const H=document.createElement("button");H.type="button",H.textContent="Test values CSV",Object.assign(H.style,{...ge("outlined")}),U(H),H.addEventListener("click",()=>{const d=["Test","Unit","N","Min","Q1","Median","Mean","Q3","Max","StdDev"];D&&d.push("Ppk");const P=L.some(R=>R.specYieldPct!==null&&R.specN!==R.stats.count);v&&(d.push("Lo limit","Hi limit","Limit Yield %"),P&&d.push("Limit Yield N"));const _=L.some(R=>Te(R.entry));_&&d.push(De);const K=[...ot(c,d),...st(c)],J=[[...K.map(R=>R.label),...d].map(he).join(",")],I=R=>He(R,void 0,"engineering");for(const{entry:R,stats:M,specYieldPct:ee,specN:fe}of L){const se=[...K.map(ce=>ce.constant??""),R.name,R.unit??"",String(M.count),I(M.min),I(M.q1),I(M.median),I(M.mean),I(M.q3),I(M.max),I(M.stddev)];if(D){const ce=S.get(R.testNumber);se.push(ce==null?"":ce.toFixed(3))}v&&(se.push(R.limitLow!==void 0?I(R.limitLow):"",R.limitHigh!==void 0?I(R.limitHigh):"",ee!==null?ee.toFixed(1):""),P&&se.push(R.limitLow!==void 0||R.limitHigh!==void 0?String(fe):"")),_&&se.push(Ee(R)),J.push(se.map(he).join(","))}Ue(J.join(`
|
|
2
|
+
`),"test-values.csv","text/csv",o)}),k.appendChild(H),N.appendChild(k);const Y=a("table",{width:"100%",borderCollapse:"collapse",fontSize:T.body}),te=document.createElement("thead"),ie=document.createElement("tr"),O=["Test"];$===null&&O.push("N"),f==="full"&&O.push("Min","Q1","Median"),O.push("Mean"),f==="full"&&O.push("Q3","Max","StdDev"),D&&O.push("Ppk"),f==="full"&&v&&O.push("Lo limit","Hi limit"),v&&O.push("Limit yield");for(const d of O){const P=a("th",{textAlign:d==="Test"?"left":"right",fontWeight:"600",fontSize:T.meta,letterSpacing:le,textTransform:"uppercase",color:z,padding:"3px 8px 5px",borderBottom:`1px solid ${C.menuBorder}`,whiteSpace:"nowrap"},d);ie.appendChild(P)}te.appendChild(ie),Y.appendChild(te);const Z=document.createElement("tbody");for(const{entry:d,stats:P,specYieldPct:_,specN:K}of L){const q=R=>He(R,d.unit,i),J=document.createElement("tr"),I=(R,M="right")=>{const ee=a("td",{textAlign:M,padding:`${g.xs} ${g.md}`,borderBottom:`1px solid ${C.menuBorder}`,color:C.text,whiteSpace:"nowrap"},R);J.appendChild(ee)};if(I(yt(d,d.testNumber),"left"),$===null&&I(`${P.count}`),f==="full"&&(I(q(P.min)),I(q(P.q1)),I(q(P.median))),I(q(P.mean)),f==="full"&&(I(q(P.q3)),I(q(P.max)),I(q(P.stddev))),D){const R=S.get(d.testNumber);I(R==null?"\u2014":R.toFixed(2))}f==="full"&&v&&(I(d.limitLow!==void 0?q(d.limitLow):"\u2014"),I(d.limitHigh!==void 0?q(d.limitHigh):"\u2014")),v&&I(_!==null?$!==null&&K===$?`${_.toFixed(1)}%`:`${_.toFixed(1)}% (N=${K})`:"\u2014"),Z.appendChild(J)}Y.appendChild(Z);const V=a("div",{overflowX:"auto"});V.appendChild(Y);const oe=dt(V,L.map(d=>({label:d.entry.name,...we(d.entry)})));if(!h)return N.appendChild(oe),N;k.remove();const{outer:B}=ne(F,!0,void 0,{stateKey:"testValues",panel:h,render:d=>d.appendChild(oe),control:()=>H});return B}export function buildFunctionalTestSection(e,n,i,t,o,c){const s=i??$t(e,n);if(!s?.length)return null;const f=new Set(s.map(y=>y.totalDies)).size===1?s[0].totalDies:null,l=f!==null?` \xB7 N=${f.toLocaleString()}`:"",p=a("div"),x=a("div",{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:g.sm}),r=o?.populationLabel?`Functional Tests (${s.length}) \u2014 ${o.populationLabel}${l}`:`Functional Tests (${s.length})${l}`,m=pe(r);m.style.marginBottom="0",x.appendChild(m);const v=document.createElement("button");v.type="button",v.textContent="Functional CSV",Object.assign(v.style,{...ge("outlined")}),U(v),v.addEventListener("click",()=>{const y=["Test","N","Pass","Fail","Pass Rate %"],$=s.some(w=>Te(w));$&&y.push(De);const N=[...ot(o,y),...st(o)],k=[[...N.map(w=>w.label),...y].map(he).join(",")];for(const w of s)k.push([...N.map(F=>F.constant??""),Ct(w.label),String(w.totalDies),String(w.passDies),String(w.failDies),w.passRatePercent!==null?w.passRatePercent.toFixed(1):"",...$?[Ee(w)]:[]].map(he).join(","));Ue(k.join(`
|
|
3
|
+
`),"functional-tests.csv","text/csv",t)}),x.appendChild(v),p.appendChild(x);const L=a("table",{width:"100%",borderCollapse:"collapse",fontSize:T.body}),A=document.createElement("thead"),u=document.createElement("tr"),E=f===null?["Test","N","Pass","Fail","Pass rate"]:["Test","Pass","Fail","Pass rate"];for(const y of E)u.appendChild(a("th",{textAlign:y==="Test"?"left":"right",fontWeight:"700",fontSize:T.body,letterSpacing:le,textTransform:"uppercase",color:z,padding:"3px 8px 5px",borderBottom:`1px solid ${C.menuBorder}`,whiteSpace:"nowrap"},y));A.appendChild(u),L.appendChild(A);const W=document.createElement("tbody");for(const y of s){const $=document.createElement("tr"),N=(k,w="right")=>{$.appendChild(a("td",{textAlign:w,padding:`${g.xs} ${g.md}`,borderBottom:`1px solid ${C.menuBorder}`,color:X,whiteSpace:"nowrap"},k))};N(y.label,"left"),f===null&&N(String(y.totalDies)),N(String(y.passDies)),N(String(y.failDies)),N(y.passRatePercent!==null?`${y.passRatePercent.toFixed(1)}%`:"\u2014"),W.appendChild($)}L.appendChild(W);const b=a("div",{overflowX:"auto"});b.appendChild(L);const S=dt(b,s);if(!c)return p.appendChild(S),p;x.remove();const{outer:D}=ne(r,!0,void 0,{stateKey:"functionalTests",panel:c,render:y=>y.appendChild(S),control:()=>v});return D}export function buildLotFunctionalSection(e,n,i,t,o){const c=i?.length?{perWaferMetadata:i.map(h=>h.wafer??{}),populationLabel:`${i.length} wafer${i.length===1?"":"s"} pooled`}:void 0,s=Gt(i);return s?buildFunctionalTestSection(e,n,s,t,c,o):buildFunctionalTestSection(e,n,void 0,t,c,o)}function ke(e){const{tier:n,word:i}=Et[e],t=Fe(n),o=a("span",{flexShrink:"0",letterSpacing:"1px",lineHeight:Q.none,color:de(e)},"\u25CF".repeat(t)+"\u25CB".repeat(Ne-t));return o.setAttribute("role","img"),o.setAttribute("aria-label",i),re(o,i),o}function at(e,n){let i=e.summary;if(n){const t=[" has "," have "].find(o=>i.startsWith(`${n}${o}`));t?i=i.slice(n.length+t.length):i.startsWith(`${n} `)&&(i=i.slice(n.length+1))}return i=ae(i),i.length?i[0].toUpperCase()+i.slice(1):i}function rt(e){return lt(e.map(n=>({label:n.variable.label,...we(n.variable)})))}function lt(e){const n=vt(e);return n?a("div",{fontSize:T.body,color:z,marginTop:g.sm,lineHeight:Q.base},n):null}function dt(e,n){const i=lt(n);if(!i)return e;const t=a("div",{});return t.append(e,i),t}export function buildFindingsSection(e,n,i,t,o=!1,c){if(!e.length)return null;const s=e.some(b=>b.severity==="unusual"||b.severity==="notable"),h=s?e.filter(b=>b.severity!=="info").length.toString():void 0,{outer:f,content:l}=o?(()=>{const b=a("div");return{outer:b,content:b}})():ne(`Findings (${e.length})`,s,h);function p(b,S){const y={ring:"Ring",quadrant:"Quadrant",sector:"Sector","reticle-position":"Reticle","test-site":"Test site",cluster:"Cluster","edge-arc":"Edge arc",wafer:"Wafer"}[b]??b;return S.toLowerCase().startsWith(y.toLowerCase())?S:`${y}: ${S}`}const x=At(e),r=x.patterns.map(b=>b.finding),m=x.groups.map(b=>({...b,key:`${b.family}\0${b.left}`})),v=()=>[...m.flatMap(b=>b.findings),...r.flatMap(b=>e.filter(S=>b.relatedIds?.includes(S.id)))];function L(b,S=!1,D){const y=t===b.id,$=document.createElement("button");return $.type="button",$.dataset.wmapFinding=b.id,$.textContent=at(b,D),re($,Ae(b)),$.setAttribute("aria-current",y?"true":"false"),Object.assign($.style,{border:`1px solid ${C.menuBorder}`,borderLeft:`3px solid ${de(b.severity)}`,background:y?C.bgActive:C.menuBg,borderRadius:G.container,padding:S?"6px 10px":"8px 10px",textAlign:"left",fontSize:S?"10px":"11px",fontWeight:y?"600":"400",color:C.text,cursor:"pointer",width:"100%",marginBottom:g.xs}),U($,"bare"),$.addEventListener("click",()=>i(b,$)),$}const A=a("button",{flexShrink:"0",border:"none",background:"none",fontSize:T.body,color:C.icon,cursor:"pointer",padding:"0",lineHeight:Q.base,whiteSpace:"nowrap"},"Detail \u25B8");A.type="button",U(A,"bare"),A.addEventListener("click",()=>{const b=qe({title:"Findings Summary",onClose:()=>{},anchor:A}),S=Re(n,{passBins:c}),D=a("div",{fontSize:"16px",lineHeight:Q.base,color:C.text,padding:`${g.xxl} ${g.xxxl} ${g.xxl}`,margin:"0",borderBottom:`1px solid ${C.menuBorder}`,flexShrink:"0",display:"flex",flexDirection:"column",gap:g.md});for(const k of kt(S).split(`
|
|
4
|
+
`))D.appendChild(a("p",{margin:"0"},ae(k)));b.contentWrap.appendChild(D);const y=a("div",{overflowY:"auto",padding:`${g.xxl} ${g.xxxl}`,flex:"1"}),$=(k,w)=>{const F=a("div",{display:"flex",alignItems:"center",gap:"7px",fontSize:T.sub,fontWeight:"600",color:X,marginTop:g.lg,marginBottom:g.xs});return F.appendChild(ke(k)),F.appendChild(a("span",{},w)),F};for(const k of r){y.appendChild($(k.severity,k.comparison.left)),y.appendChild(a("div",{fontSize:T.body,color:C.text,padding:"4px 0 4px 15px",marginBottom:g.xxs},ae(k.summary)));const w=e.filter(F=>k.relatedIds?.includes(F.id));for(const F of w)y.appendChild(a("div",{fontSize:T.body,color:z,padding:"2px 0 2px 23px",marginBottom:g.xxs},ae(F.summary)))}for(const k of m){const[w,F]=k.key.split("\0");y.appendChild($(k.worst,p(w,F)));for(const j of k.findings)y.appendChild(a("div",{fontSize:T.body,color:C.text,padding:"4px 0 4px 15px",marginBottom:g.xxs},at(j,F)))}const N=rt(v());N&&y.appendChild(N),b.contentWrap.appendChild(y),Object.assign(b.contentWrap.style,{flexDirection:"column",overflow:"hidden"})});const u=a("div",{display:"flex",justifyContent:"flex-end",marginBottom:g.xs});u.appendChild(A),l.appendChild(u);let E=!0;for(const b of r){E||l.appendChild(a("div",{height:"1px",background:C.separator,margin:"4px 0"})),E=!1;const S=e.filter(k=>b.relatedIds?.includes(k.id)),D=S.length>0,y=a("div",{position:"relative",marginBottom:D?"2px":"4px"}),$=t===b.id,N=document.createElement("button");if(N.type="button",N.dataset.wmapFinding=b.id,Object.assign(N.style,{border:`1px solid ${C.menuBorder}`,borderLeft:`3px solid ${de(b.severity)}`,background:$?C.bgActive:C.menuBg,borderRadius:G.container,padding:"8px 32px 8px 10px",textAlign:"left",fontSize:T.body,fontWeight:$?"600":"500",color:C.text,cursor:"pointer",width:"100%"}),N.textContent=ae(b.summary),re(N,b.summary),N.setAttribute("aria-current",$?"true":"false"),U(N,"bare"),N.addEventListener("click",()=>i(b,N)),y.appendChild(N),D){const k=a("div",{display:"none",paddingLeft:"12px",marginBottom:g.xs});for(const j of S)k.appendChild(L(j,!0));y.appendChild(k);let w=!1;const F=a("button",{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",border:"none",background:"none",fontSize:T.body,color:C.icon,cursor:"pointer",padding:`${g.xxs} ${g.xs}`,lineHeight:Q.none},"\u25B8");U(F,"bare"),F.type="button",re(F),F.setAttribute("aria-label","Show supporting findings"),F.setAttribute("aria-expanded","false"),F.addEventListener("click",j=>{j.stopPropagation(),w=!w,k.style.display=w?"block":"none",F.textContent=w?"\u25BE":"\u25B8";const H=w?"Hide supporting findings":"Show supporting findings";F.setAttribute("aria-label",H),F.setAttribute("aria-expanded",String(w))}),y.appendChild(F)}l.appendChild(y)}for(const b of m){E||l.appendChild(a("div",{height:"1px",background:C.separator,margin:"4px 0"})),E=!1;const[S,D]=b.key.split("\0"),y=a("div",{display:"flex",alignItems:"center",gap:g.sm,fontSize:T.body,fontWeight:"600",color:X,margin:"2px 0 4px"});y.appendChild(ke(b.worst)),y.appendChild(a("span",{},p(S,D))),l.appendChild(y);for(const $ of b.findings)l.appendChild(L($,!1,D))}const W=rt(v());return W&&l.appendChild(W),f}const an={high:"rgba(168, 65, 18, 0.10)",medium:"rgba(138, 101, 0, 0.10)",low:""},pt={high:"unusual",medium:"notable",low:"info"};function rn(e,n){const i=Fe(e),t=a("span",{display:"inline-flex",alignItems:"baseline",gap:g.xs,whiteSpace:"nowrap"}),o=a("span",{letterSpacing:"1px",color:de(pt[e])},"\u25CF".repeat(i)+"\u25CB".repeat(Ne-i));return o.setAttribute("aria-hidden","true"),t.appendChild(o),t.appendChild(a("span",{fontSize:T.meta,fontWeight:"600",letterSpacing:le,textTransform:"uppercase",color:X},n)),t}export function buildSynthesisSection(e,n,i,t,o,c){const s=Re(e,{passBins:n}),h=new Map(e.findings.map(r=>[r.id,r])),{outer:f,content:l}=ne("What stands out",!0,void 0,{stateKey:"synthesis",panel:o}),p=(r,m)=>{for(const v of m){const L=v.target?h.get(v.target.id):void 0,A=ae(v.text);if(!L||!i||!A){r.appendChild(document.createTextNode(A));continue}const u=document.createElement("button");u.type="button",u.textContent=A,u.dataset.wmapFinding=L.id,u.setAttribute("aria-current",t===L.id?"true":"false"),Object.assign(u.style,{border:"none",background:"none",padding:"0",margin:"0",font:"inherit",color:"inherit",textDecoration:"underline dotted",textUnderlineOffset:"2px",cursor:"pointer",textAlign:"inherit",fontWeight:t===L.id?"600":"inherit"}),re(u,Ae(L));const E=W=>{u.style.textDecoration=W?"underline solid":"underline dotted",u.style.color=W?C.iconActive:"inherit"};u.addEventListener("mouseenter",()=>E(!0)),u.addEventListener("mouseleave",()=>E(!1)),u.addEventListener("focus",()=>E(!0)),u.addEventListener("blur",()=>E(!1)),u.addEventListener("click",()=>i(L,u)),r.appendChild(u)}},x=(r,m)=>{const v=a("div",{fontSize:T.body,lineHeight:Q.base,color:C.text,...m});return p(v,r),v};l.appendChild(x(s.headline,{fontWeight:"600",marginBottom:g.sm})),s.nothing&&l.appendChild(a("div",{fontSize:T.body,lineHeight:Q.base,color:C.text,marginBottom:g.sm},s.nothing));for(const r of s.items){const m=a("div",{borderLeft:`3px solid ${de(pt[r.impact])}`,background:an[r.impact]||C.bgActive,borderRadius:`0 ${G.container} ${G.container} 0`,padding:`${g.sm} ${g.md}`,marginBottom:g.sm});m.appendChild(rn(r.impact,Tt(r.impact))),m.appendChild(x(r.parts,{marginTop:g.xxs})),l.appendChild(m)}s.also&&l.appendChild(x(s.also,{marginBottom:g.sm}));for(const r of s.watch??[]){const m=x(r.parts,{marginBottom:g.xs});m.insertBefore(a("span",{fontSize:T.meta,fontWeight:"600",letterSpacing:le,textTransform:"uppercase",color:z,marginRight:g.sm},"Watch"),m.firstChild),l.appendChild(m)}if(l.appendChild(a("div",{fontSize:T.body,lineHeight:Q.base,color:z},ae(s.checked))),c){const r=a("button",{border:"none",background:"none",padding:"0",marginTop:g.sm,fontSize:T.body,color:C.icon,cursor:"pointer",textDecoration:"underline",textUnderlineOffset:"2px"},"Full report \u25B8");r.type="button",U(r,"bare"),r.addEventListener("click",c),l.appendChild(r)}return f}const ln=[{value:"",label:"All kinds"},{value:"yield",label:"Yield"},{value:"hardBin",label:"Hard bin"},{value:"softBin",label:"Soft bin"},{value:"test",label:"Test value"},{value:"functionalTest",label:"Functional test"},{value:"spatialPattern",label:"Spatial pattern"}],dn=[{value:"",label:"All regions"},{value:"ring",label:"Ring"},{value:"quadrant",label:"Quadrant"},{value:"reticle-position",label:"Reticle position"},{value:"test-site",label:"Test site"},{value:"wafer",label:"Wafer"},{value:"sector",label:"Sector"},{value:"cluster",label:"Cluster"},{value:"edge-arc",label:"Edge arc"},{value:"spatial-pattern",label:"Spatial pattern"}],pn=["unusual","notable","info"],cn={unusual:"Unusual",notable:"Notable",info:"Minor"};function un(e,n,i){const t=a("div",{display:"flex",flexWrap:"wrap",alignItems:"center",gap:g.lg,marginBottom:g.lg,paddingBottom:"10px",borderBottom:`1px solid ${C.separator}`}),o={unusual:0,notable:0,info:0};for(const l of e)o[l.severity]++;const c=pn.filter(l=>o[l]>0),s=new Set(n.severity===void 0?c:Array.isArray(n.severity)?n.severity:[n.severity]),h=a("div",{display:"flex",gap:g.xs,flexWrap:"wrap"});for(const l of c){const p=document.createElement("button");p.type="button";const x=()=>{const m=s.has(l);p.setAttribute("aria-pressed",m?"true":"false"),Object.assign(p.style,{display:"inline-flex",alignItems:"center",gap:"5px",border:`1px solid ${C.menuBorder}`,borderRadius:G.pill,background:m?C.bgActive:"none",opacity:m?"1":"0.5",color:C.text,fontSize:T.body,padding:`${g.xxs} ${g.md}`,cursor:"pointer"}),p.dataset.on=m?"true":"false"},r=ke(l);r.removeAttribute("role"),r.removeAttribute("aria-label"),r.setAttribute("aria-hidden","true"),p.appendChild(r),p.appendChild(a("span",{},`${cn[l]} ${o[l]}`)),re(p,()=>s.has(l)?"Click to hide these findings":"Click to show these findings"),x(),U(p,"bare"),p.addEventListener("click",()=>{s.has(l)?s.delete(l):s.add(l),n.severity=s.size===c.length?void 0:[...s],i()}),h.appendChild(p)}t.appendChild(h);const f=n.kind!==void 0||n.family!==void 0;return(e.length>=fn||f)&&(t.appendChild(je("Kind:",ln,n.kind??"",l=>{n.kind=l||void 0,i()},{maxWidth:"130px"})),t.appendChild(je("Region:",dn,n.family??"",l=>{n.family=l||void 0,i()},{maxWidth:"150px"}))),t}const fn=8;function mn(e,n){const i=a("div",{display:"flex",flexDirection:"column",gap:g.xs,padding:g.md,marginBottom:g.md,background:C.bgHover,borderRadius:G.control},void 0,n);if(i.appendChild(a("div",{fontSize:T.body,color:C.value},e.message,n)),e.detail&&i.appendChild(a("div",{fontSize:T.meta,color:z},e.detail,n)),e.actionLabel&&e.onAction){const t=a("button",ge("outlined"),e.actionLabel,n);t.type="button",t.style.alignSelf="flex-start",t.style.marginTop=g.xs,U(t),t.addEventListener("click",e.onAction),i.appendChild(t)}return i}export function buildFindingsSectionWithFilter(e,n,i,t,o,c,s,h){if(!e.findings.length&&!s)return null;const f=e.findings.some(L=>L.severity==="unusual"||L.severity==="notable"),l=f?e.findings.filter(L=>L.severity!=="info").length.toString():void 0,p=c?.ownerDocument??document,{outer:x,content:r}=ne(`Findings (${e.findings.length})`,f||!!s,l,{stateKey:"findings",panel:c});if(s&&r.appendChild(mn(s,p)),!e.findings.length)return x;r.appendChild(un(e.findings,t,o));const m=Mt(e,t);if(!m.length)return r.appendChild(a("div",{color:z,fontSize:T.body,textAlign:"center",padding:`${g.xxl} ${g.md}`},"No findings match the current filter.")),x;const v=buildFindingsSection(m,e,n,i,!0,h);return v&&r.appendChild(v),x}export function buildLotTestSection(...e){return be(buildLotTestSectionSteps(...e))}export function*buildLotTestSectionSteps(e,n,i,t,o,c,s,h="full"){const f=t?.length?{perWaferMetadata:t.map(p=>p.wafer??{}),populationLabel:`${t.length} wafer${t.length===1?"":"s"} pooled`}:void 0;let l;if(t?.length&&t.every(p=>p.stats.perTestStats!==void 0)){const p=new Map;for(const x of t)for(const r of x.stats.perTestStats??[]){const m=p.get(r.testNumber);m?(m.n+=r.count,m.sum+=r.mean*r.count,m.min=Math.min(m.min,r.min),m.max=Math.max(m.max,r.max)):p.set(r.testNumber,{n:r.count,sum:r.mean*r.count,min:r.min,max:r.max})}l={perTestStats:[...p.entries()].map(([x,r])=>({testNumber:x,count:r.n,min:r.min,max:r.max,mean:r.sum/r.n}))}}if(t?.length&&t.every(p=>p.stats.testSpecYield!==void 0)){const p=new Map;for(const x of t)for(const r of x.stats.testSpecYield??[]){const m=p.get(r.testNumber);m?(m.passDies+=r.passDies,m.totalDies+=r.totalDies):p.set(r.testNumber,{passDies:r.passDies,totalDies:r.totalDies})}l={...l,testSpecYield:[...p.entries()].map(([x,r])=>({testNumber:x,totalDies:r.totalDies,yieldPercent:r.totalDies>0?r.passDies/r.totalDies*100:null}))}}return yield*buildTestSectionSteps(e,n,i,l,o,f,c,s,h)}export function createSummaryPanelEl(e,n,i=document){const t=e==="top"||e==="bottom",o=a("div",{background:Jt,color:C.text,fontVariantNumeric:"tabular-nums",border:Qe,borderRadius:G.container,padding:g.xl,overflowY:"auto",overflowX:t?"auto":"hidden",flexShrink:"0",boxSizing:"border-box",fontFamily:T.family,fontSize:T.sub,boxShadow:Ve.panel},void 0,i);return e==="right"&&(o.style.marginRight=n),e==="left"&&(o.style.marginLeft=n),e==="bottom"&&(o.style.marginBottom=n),t?(o.style.height="180px",o.style.width="100%"):(o.style.width="300px",o.style.maxHeight="100%"),o}export function wrapWithSummaryPanel(e,n,i){const t=i==="top"||i==="bottom",o=a("div",{display:"flex",flexDirection:t?"column":"row",gap:g.md,width:"100%",height:"100%",flex:"1 1 0",minHeight:"0",boxSizing:"border-box",alignItems:t?"flex-start":"stretch"});return e.style.flex="1 1 0",e.style.minWidth="0",e.style.minHeight="0",i==="right"||i==="bottom"?(o.appendChild(e),o.appendChild(n)):(o.appendChild(n),o.appendChild(e)),o}function ct(e,n,i,t,o){const c=n.find(h=>h.id===i);if(!c||!o)return;t.close();const s=[...e.querySelectorAll("button[data-wmap-finding]")].find(h=>h.dataset.wmapFinding===i)??e.ownerDocument.createElement("button");o(c,s)}function ut(e){return a("div",{fontSize:T.heading,fontWeight:"600",color:X,marginBottom:g.lg},e)}function Ce(e,n){const i=a("button",ge("outlined"),e);return i.type="button",U(i),i.addEventListener("click",n),i}function ft(...e){const n=e.filter(t=>!!t);if(!n.length)return null;const i=a("div",{display:"flex",flexWrap:"wrap",gap:g.sm,marginBottom:g.lg});for(const t of n)i.appendChild(t);return i}function mt(e,n,i,t,o,c,s,h,f,l,p){const x=e.ownerDocument,r=qe({title:"Die list",onClose:()=>{},anchor:e,ownerDocument:x});r.contentWrap.style.padding="14px 16px";const m=Ut(n,i,{...s,title:t,onSaveText:h,waferMetadata:o,metadataFields:c,extraColumn:f,getWafer:l,ringCount:p,ownerDocument:x});m&&r.contentWrap.appendChild(m)}export function renderWaferSummaryContent(...e){be(renderWaferSummaryContentSteps(...e))}export function*renderWaferSummaryContentSteps(e,n){const i=e.scrollTop;e.innerHTML="";const{wafer:t,dies:o,yieldSummary:c,dataCoverage:s,hbinDefs:h,sbinDefs:f,testDefs:l,statsSummary:p,passBins:x=[1],ringCount:r=4,binColors:m,plotMode:v,fallbackFormat:L,onFindingClick:A,activeFindingId:u=null,findingsFilter:E,onFindingsFilterChange:W,findingsNotice:b,onSaveText:S,metadataFields:D,dieListOptions:y,metadataShownElsewhere:$}=n;e.appendChild(ut("Wafer Summary"));const N=n.warnings??ze({statsSummary:p});N.length&&e.appendChild(Se(N,e.ownerDocument));const k=c&&s?()=>{import("../stats/renderSummaryReport.js").then(({renderWaferReportHtml:Z})=>{Ge(Z({wafer:t,dies:o,yield:c,dataCoverage:s,hbinDefs:h,sbinDefs:f,testDefs:l,passBins:x,ringCount:r},p,{binColors:m,live:!!A}),{anchor:e,onFinding:(V,oe)=>ct(e,p?.findings??[],V,oe,A)})})}:null,w=k?Ce("Summary report",k):null,F=(y?.enabled??!0)&&o.length?Ce("View die list",()=>{mt(e,o,l,`Die list \u2014 ${o.length} dies`,t.metadata,D,y,S,void 0,()=>t,r)}):null,j=ft(w,F);j&&e.appendChild(j);let H=!0;const Y=Z=>{Z&&(H||e.appendChild(et()),H=!1,e.appendChild(Z))},te=p?.stats.isLotStack?p.stats:void 0,ie=te?.lotSize!==void 0?{lotSize:te.lotSize,aggrMethod:_t(te.aggregationMethod)}:void 0;$||Y(buildMetadataInfoSection([{metadata:t.metadata??void 0}],ie)),c&&s&&Y(buildYieldSection(c,s,x)),yield,p&&(Y(buildSynthesisSection(p,x,A,u,e,k??void 0)),yield),p&&A&&E&&W&&(Y(buildFindingsSectionWithFilter(p,A,u,E,W,e,b,x)),yield),Y(buildBinBreakdownSection({dies:o,hbinDefs:h,sbinDefs:f,binColors:m,hardCounts:p?.stats.hardBinCounts,softCounts:p?.stats.softBinCounts,plotMode:v,passBins:x,panel:e})),yield,Y(buildRegionYieldPanelSection({diesByWafer:[o],allWafers:[t],ringCount:r,passBins:x,panel:e})),yield;const O=t.metadata?{waferMetadata:t.metadata}:void 0;Y(yield*buildTestSectionSteps(o,l,L,p?.stats,S,O,[{dies:o}],e,"compact")),yield,Y(buildFunctionalTestSection(o,l,p?.stats.functionalYield,S,O,e)),e.appendChild(a("div",{height:"12px",flexShrink:"0"})),e.scrollTop=i}export function reportMapsFromItems(e,n,i){const t=[];return e.forEach((o,c)=>{!o?.wafer||!o.dies||t.push({...o,wafer:o.wafer,dies:o.dies,label:ve(o,c),passBins:[...me(o,n)],ringCount:o.ringCount??i})}),t}export function renderLotSummaryContent(...e){be(renderLotSummaryContentSteps(...e))}export function*renderLotSummaryContentSteps(e,n){const i=e.scrollTop;e.innerHTML="";const{lotSummary:t,items:o,hbinDefs:c,sbinDefs:s,testDefs:h,passBins:f=[1],ringCount:l=4,binColors:p,plotMode:x,fallbackFormat:r,onFindingClick:m,activeFindingId:v=null,onWaferClick:L,findingsFilter:A,onFindingsFilterChange:u,findingsNotice:E,onSaveText:W,dieListOptions:b,findingsFor:S}=n;e.appendChild(ut(`Summary \u2014 ${Ot(Pe(t.perWafer.map(B=>B.summary.wafer)))}`));const D=n.warnings??ze({lotStatsSummary:t});D.length&&e.appendChild(Se(D,e.ownerDocument));const y=()=>{import("../stats/renderSummaryReport.js").then(({renderLotReportHtml:B})=>{Ge(B(reportMapsFromItems(o,f,l),{binColors:p,live:!!m}),{anchor:e,onFinding:(d,P)=>ct(e,t.findings,d,P,m)})})},$=Ce("Summary report",y),N=[],k=[],w=[],F=[],j=[],H=new WeakMap,Y=new WeakMap;for(let B=0;B<o.length;B++){yield;const d=o[B];if(!d){k.push([]);continue}d.wafer&&(N.push(d.wafer),F.push(d.dies??[]),j.push(me(d,f)));const P=d.dies??[],_=ve(d,B);for(const K of P)H.set(K,_),d.wafer&&Y.set(K,d.wafer);k.push(P);for(const K of P)w.push(K)}const te=b?.enabled??!0?Ce("View die list",()=>{w.length&&mt(e,w,h,`Die list \u2014 ${w.length} dies across ${o.length} wafer${o.length===1?"":"s"}`,We(o.filter(B=>!!B).map(B=>({metadata:B.wafer?.metadata}))),o.find(B=>B?.metadataFields?.length)?.metadataFields,b,W,{label:"Wafer",get:B=>H.get(B)},B=>Y.get(B),l)}):null,ie=ft($,te);ie&&e.appendChild(ie);const O=o.map(B=>B?.statsSummary).filter(B=>!!B);let Z=!0;const V=B=>{B&&(Z||e.appendChild(et()),Z=!1,e.appendChild(B))};V(buildLotOverviewSection(t,O)),yield;const oe=gt(o.map(B=>B?me(B,f):void 0).filter(B=>B!==void 0));V(buildSynthesisSection(t,oe,m,v,e,y)),yield,m&&A&&u&&(V(buildFindingsSectionWithFilter(t,m,v,A,u,e,E,oe)),yield),V(buildPerWaferYieldSection(t,o,L,e,S)),yield,V(buildBinBreakdownSection({dies:w,hbinDefs:c,sbinDefs:s,plotMode:x,passBins:f,panel:e,binColors:p??Pt(o.flatMap(B=>B?[{dies:B.dies??[],passBins:me(B,f)}]:[]),{hbinDefs:c,sbinDefs:s}).colors})),yield,V(buildRegionYieldPanelSection({diesByWafer:F,allWafers:N,ringCount:l,passBins:B=>j[B],panel:e})),yield,h?.length&&(V(yield*buildLotTestSectionSteps(w,h,r,O,W,k.map(B=>({dies:B})),e,"compact")),yield,V(buildLotFunctionalSection(w,h,O,W,e))),e.appendChild(a("div",{height:"12px",flexShrink:"0"})),e.scrollTop=i}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fontPx as Ft}from"./toolbar.js";import{findTestDef as Oe,buildMapTitle as Ne}from"../renderer/buildView.js";import{niceStep as Ot}from"../renderer/axisTicks.js";import{sortBinsForDisplay as co}from"../stats/binPareto.js";import{affineInvert as ro,affineVector as Ee}from"../core/transforms.js";import{asList as fo,compareNatural as ho,maxOf as Ut,minOf as He}from"../core/utils.js";import{resolveValueColorFn as go}from"../renderer/colorSchemes.js";import{NO_DATA_FILL as mo}from"../renderer/colorMap.js";import{SPEC_PASS_FILL as Ye,SPEC_FAIL_LOW as uo,SPEC_FAIL_HIGH as Xe,contrastTextColor as Ge}from"../renderer/colorMap.js";import{fmt as $e,fmtColorbarAxis as we}from"../renderer/fmt.js";import{resolveCanvasTheme as po}from"./canvasTheme.js";import{hitGridDims as xo}from"./hitGrid.js";function Ve(d,e,H,p,l){d.moveTo(e,H+l*p),d.lineTo(e-p*.9,H-l*p*.6),d.lineTo(e+p*.9,H-l*p*.6),d.closePath()}const bo=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),Mo=new Set(["hardBin","softBin","metadata"]),nt=()=>`${Ft(-2)}px system-ui, sans-serif`,Ke=3,Jt=2,yo=6,To=20,So=()=>`600 ${Ft()}px system-ui, sans-serif`,qe=36,pe=()=>`${Ft(-1)}px system-ui, sans-serif`,Lo=()=>`600 ${Ft(-1)}px system-ui, sans-serif`,jt=128,ko=()=>`${Ft(-2)}px system-ui, sans-serif`,ze=4,$=17,j=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const Zt=28,Tt=5,gt=8,Ue=15,Je=12,je=6;export function toCanvas(d,e,H={}){return drawMapCanvas(d,e,H)}export function drawMapCanvas(d,e,H={}){const p=po(d.parentElement??d),{padding:l=16,showColorbar:w=!0,markFailingDies:K=!1,colorbarWidth:g=16,background:Y=p.background,legendPosition:B="default",legendOffset:q,showAxes:z=!1,diePitchMm:C,viewport:U,activeBin:F,hoverBin:Q,afterDies:Qt,fallbackFormat:St,minRightReserve:mt,hbinDefs:Lt,sbinDefs:ft,metadataFields:kt,showTitle:st=!0}=H,Nt=fo(F),O=Math.floor(d.clientWidth||d.width),J=Math.floor(d.clientHeight||d.height),Rt=O>=BIN_LEGEND_MIN_CANVAS_W&&J>=BIN_LEGEND_MIN_CANVAS_H,ut=w&&Rt&&bo.has(e.plotMode)&&e.passFailDisplay==="off",pt=w&&Rt&&Mo.has(e.plotMode),xt=w&&Rt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),bt=pt||xt,Et=pt&&e.plotMode!=="metadata"&&e.binCounts?co(e.binCounts.entries(),e.plotMode==="softBin"?e.binColors.pass.soft:e.binColors.pass.hard):[],Ht=pt&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(ho)].map(o=>[o,e.metadataCounts.get(o)??0]):[],b=[];if(xt&&e.passFailDisplay==="test"){const o=e.passFailCounts;b.push({key:-1,color:Ye,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),b.push({key:-2,color:Xe,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(xt){const o=e.specCounts,a=Oe(e.testDefs,e.activeTest);b.push({key:-1,color:Ye,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),a?.limitHigh!==void 0&&b.push({key:-2,color:Xe,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),a?.limitLow!==void 0&&b.push({key:-3,color:uo,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const Z=xt?b.length:e.plotMode==="metadata"?Ht.length:Et.length,tt=(d.ownerDocument.defaultView??window).devicePixelRatio??1;if(O<=0||J<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const lt=B!=="default"?B:O<BIN_LEGEND_ADAPT_FLOATING?"floating":O<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",xe=lt==="default"||lt==="compact",be=lt==="left",vt=lt==="bottom",_t=lt==="top",Bt=lt==="floating",Yt=lt==="compact"||lt==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,Me=Math.floor((J-2*l)/$),ye=Z>Me?Me-1:Z,Te=bt&&vt?ye*$:0,te=bt&&_t?ye*$:0,ee=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",oe=Oe(e.testDefs,e.activeTest),Se=ee?"Count":oe?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),Le=ee?void 0:oe?.unit,[Pt,Dt]=e.valueRange,ne=o=>String(Math.round(o)),Qe=e.logScale||e.allIntegerValues?void 0:Ot(Math.max(0,Dt-Pt)*qe/Math.max(1,J))||void 0,se=e.allIntegerValues?ne:we(Dt,Se,Le,St,Qe).edgeFmt;let le=0;if(ut){const o=d.getContext("2d");o.font=nt();const a=[se(Pt),se(Dt)];Pt<0&&a.push(se(-Math.max(Math.abs(Pt),Math.abs(Dt))));for(const u of a)le=Math.max(le,o.measureText(u).width)}const ke=Math.max(To,Math.ceil(le)+Ke+Jt+yo-l),ie=ut?g+ke+8:bt&&xe?Yt:0,ae=bt&&be?Yt:0,ce=z?32:0,Xt=z?36:0,ve=mt!=null?Math.max(ie,mt):ie,to=O-2*l-ve-Xt-ae,Ae=J-2*l-ce-Te-te;d.width=Math.round(O*tt),d.height=Math.round(J*tt);const t=d.getContext("2d");t.scale(tt,tt),t.fillStyle=Y,t.fillRect(0,0,O,J);const v=e.hoverPoints;if(!v.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Gt=e.rectangles[0],re=Gt?Gt.width/2:0,fe=Gt?Gt.height/2:0,$t=e.dieBounds,Ce=($t?.minX??0)-re,eo=($t?.maxX??0)+re,oo=($t?.minY??0)-fe,Re=($t?.maxY??0)+fe,_e=eo-Ce,Be=Re-oo;let it,at,R;if(U)({originX:it,originY:at,ppm:R}=U);else{const a=e.notchDir,u=a&&a.y>.1?13:0,m=a&&a.y<-.1?13:0,h=a&&a.x<-.1?13:0,c=a&&a.x>.1?13:0,f=to-h-c,s=Ae-u-m;R=Math.min(f/_e,s/Be),it=l+Xt+ae+h+(f-_e*R)/2-Ce*R,at=l+te+u+(s-Be*R)/2+Re*R}const wt=U?.snapDist??Math.max(re,fe,1)*1.5,Vt=it+e.waferCenter.x*R,no=at-e.waferCenter.y*R,he=e.waferRadius*R,ht=o=>{const a=Math.abs(o-no);return a>=he?0:Math.sqrt(he*he-a*a)},Mt=(o,a,u,m,h,c,f=So(),s=p.text)=>{if(!o)return;t.save(),t.fillStyle=s,t.font=f,t.textAlign=m,t.textBaseline=h;const i=m==="right"?a-c:c-a;let n=o;if(i>8&&t.measureText(n).width>i){for(;n.length>1&&t.measureText(n+"\u2026").width>i;)n=n.slice(0,-1);n=n+"\u2026"}i>8&&t.fillText(n,a,u),t.restore()};t.save(),t.setTransform(R*tt,0,0,-R*tt,it*tt,at*tt);const yt=1/R,so=1/(R*tt);if(e.rectangles.length>0){const o=new Map;for(const h of e.rectangles){const c=String(h.fill);let f=o.get(c);f||(f=[],o.set(c,f)),f.push(h)}for(const[h,c]of o){t.fillStyle=h;for(let f=0;f<c.length;f+=PATH_SHAPES){t.beginPath();const s=Math.min(c.length,f+PATH_SHAPES);for(let i=f;i<s;i++){const n=c[i];t.rect(n.x-n.width/2,n.y-n.height/2,n.width,n.height)}t.fill()}}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5*so,t.lineCap="square";const a=Ze.get(e.rectangles)??outlineSegments(e.rectangles);Ze.set(e.rectangles,a);const u=PATH_SHAPES*4;for(let h=0;h<a.length;h+=u){t.beginPath();const c=Math.min(a.length,h+u);for(let f=h;f<c;f+=4)t.moveTo(a[f],a[f+1]),t.lineTo(a[f+2],a[f+3]);t.stroke()}if(t.lineCap="butt",K){const h=e.rectangles.filter(c=>c.binFail);if(h.length>0){const c=new Map;for(const f of h){const s=Ge(String(f.fill));let i=c.get(s);i||(i=[],c.set(s,i)),i.push(f)}t.save(),t.lineCap="butt";for(const[f,s]of c){t.strokeStyle=f,t.globalAlpha=.55,t.lineWidth=Math.max(.6*yt,Math.min(s[0].width,s[0].height)*.1);for(const i of s){const n=i.width/2,M=i.height/2,N=Math.max(1.6*yt,Math.min(i.width,i.height)/3);t.save(),t.beginPath(),t.rect(i.x-n,i.y-M,i.width,i.height),t.clip(),t.beginPath();for(let A=-(n+M);A<=n+M;A+=N)t.moveTo(i.x-n+A,i.y-M),t.lineTo(i.x-n+A+i.height,i.y+M);t.stroke(),t.restore()}}t.restore()}}const m=e.rectangles.filter(h=>h.specMark);if(m.length>0){const h=new Map;for(const f of m){const s=Ge(String(f.fill)),i=`${f.specMark}|${s}`;let n=h.get(i);n||(n=[],h.set(i,n)),n.push(f)}const c=2.5*yt;t.lineJoin="round";for(const[f,s]of h){const[i,n]=f.split("|"),M=n==="#000000"?"#ffffff":"#000000",N=i==="failHigh"?1:-1,A=Math.min(s[0].width,s[0].height),L=Math.max(2.5*yt,A*.3);t.beginPath();for(const V of s)Ve(t,V.x,V.y,L,N);t.strokeStyle=M,t.lineWidth=c,t.stroke(),t.fillStyle=n,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const a of o.points){for(let u=0;u<a.length;u++)u===0?t.moveTo(a[u].x,a[u].y):t.lineTo(a[u].x,a[u].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3*yt,t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1*yt,t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth*yt,t.stroke())}if(t.restore(),e.notchDir){const o=it+e.waferCenter.x*R,a=at-e.waferCenter.y*R,u=e.notchDir.x,m=-e.notchDir.y,h=e.waferRadius*R,c=4,f=9,s=5,i=o+u*(h+c),n=a+m*(h+c),M=i+u*f,N=n+m*f,A={x:-m,y:u},L=l+Xt+ae,V=O-l-ie,et=l+te,rt=J-l-Te-ce;t.save(),t.beginPath(),t.rect(L,et,V-L,rt-et),t.clip(),t.beginPath(),t.moveTo(i,n),t.lineTo(M+A.x*s,N+A.y*s),t.lineTo(M-A.x*s,N-A.y*s),t.closePath(),t.fillStyle=p.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let Pe=0;if(e.rectangles.length>0){let o=1;for(const c of e.texts)c.role!=="indicator"&&c.text.length>o&&(o=c.text.length);const a=e.rectangles[0].width*R,u=e.rectangles[0].height*R,m=Math.min(a,u),h=a/o;Pe=Math.max(8,Math.min(64,Math.round(Math.min(m*.55,h*1.8))))}for(const o of e.texts){const a=it+o.x*R,u=at-o.y*R;t.font=`${o.role==="indicator"?o.fontSize:Pe}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,a,u)}if(t.restore(),Qt?.(t,{originX:it,originY:at,ppm:R},{background:Y,text:p.text}),z&&Ao(t,O,J,it,at,R,l,ce,Xt,C,e.gridToScreen,e.rotation,p),ut){const o=go(e.valueColorScheme,e.reverseValueScheme),a=ke,u=Ae,m=Math.round(u*.75),h=l+Math.round((u-m)/2),c=O-l-g-a,f=Pt,s=Dt,i=s-f,n=e.plotMode==="stackedSoftBins"?ft:Lt,{primary:M,secondary:N,note:A}=st?Ne(e,St,n):{primary:"",secondary:"",note:void 0};if(st){const r=Math.max(h-6,l+11),W=Vt+Math.max(ht(r),ht(r-12))+8;Mt(M,O-l,r,"right","bottom",W)}let L=h+m+4;const V=r=>Vt+Math.max(ht(r),ht(r+12))+8,et=e.logScale&&f>0?Math.log10(f):0,rt=e.logScale&&s>0?Math.log10(s)-et:1,P=r=>e.logScale?(1-(Math.log10(r)-et)/rt)*m:(1-(r-f)/i)*m;for(let r=0;r<jt;r++){const W=1-r/(jt-1),E=h+r/jt*m,x=m/jt+1;t.fillStyle=o(W),t.fillRect(c,E,g,x)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(c,h,g,m),t.fillStyle=p.text,t.font=nt(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const D=Ke,Wt=qe,ct=14;let X;const I=e.logScale&&rt>0?Co(f,s,m,Wt,ct,et,rt):e.allIntegerValues?(()=>{const r=Math.max(1,Ot(i*Wt/m)),W=[],E=Math.ceil(f/r)*r;for(let x=E;x<=s+r*1e-6;x+=r){const _=(1-(x-f)/i)*m;_>ct&&_<m-ct&&W.push(Math.round(x))}return W})():(()=>{const r=i>0?Ot(i*Wt/m):0,W=[];if(r>0){X=r;const E=Math.ceil(f/r)*r;for(let x=E;x<=s+r*1e-6;x+=r){const _=(1-(x-f)/i)*m;_>ct&&_<m-ct&&W.push(x)}}return W})(),y=oe,k=ee,T=we(s,Se,Le,St,X),G=e.allIntegerValues?ne:T.tickFmt,S=e.allIntegerValues?ne:T.edgeFmt;t.textBaseline="middle";for(const r of I){const W=h+P(r);t.beginPath(),t.moveTo(c+g,W),t.lineTo(c+g+D,W),t.stroke(),t.fillText(G(r),c+g+D+Jt,W)}if(t.beginPath(),t.moveTo(c+g,h),t.lineTo(c+g+D,h),t.stroke(),t.textBaseline="top",t.fillText(S(s),c+g+D+Jt,h),t.beginPath(),t.moveTo(c+g,h+m),t.lineTo(c+g+D,h+m),t.stroke(),t.textBaseline="bottom",t.fillText(S(f),c+g+D+Jt,h+m),!k&&y&&(y.limitLow!==void 0||y.limitHigh!==void 0)){const r=[],W=e.colorbarRangeMode==="spec";for(const[E,x]of[[y.limitLow,"Lo limit"],[y.limitHigh,"Hi limit"]]){if(E===void 0||e.logScale&&E<=0)continue;const _=P(E);!W&&(_<-ct||_>m+ct)||r.push({value:E,label:x,py:Math.max(0,Math.min(m,_))})}if(r.length>0){t.save(),t.font=nt(),t.textAlign="right",t.textBaseline="middle";for(const{py:E,label:x}of r){const _=h+E;W||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(c,_),t.lineTo(c+g,_),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(c,_),t.lineTo(c+g,_),t.stroke()),t.fillStyle=p.text,t.fillText(x,c-3,_);const At=x==="Hi limit"?-1:1,Ct=4,zt=c-3-t.measureText(x).width-Ct-4;t.beginPath(),Ve(t,zt,_,Ct,At),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=p.text,t.fill()}t.restore()}}if(!k){const r=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;r&&(t.save(),t.fillStyle=p.text,t.font=Lo(),t.textAlign="right",t.textBaseline="top",t.fillText(r,O-l,L),t.restore(),L+=15)}st&&N&&(Mt(N,O-l,L,"right","top",V(L),pe(),p.text),L+=15),st&&A&&Mt(A,O-l,L,"right","top",V(L),pe(),p.text)}const de=[];let ot;if(bt){const o=lt==="compact",a=e.plotMode==="softBin"?ft:Lt,u=a?new Map(a.map(n=>[n.bin,n])):null,m=e.plotMode==="softBin"?e.binColors.soft:e.binColors.hard,h=n=>m.get(n)??mo,c=(n,M)=>{const N=t.measureText(n).width,A=o?0:t.measureText(String(M)).width,L=j+Tt+N+(A?Zt:0);return{labelWidth:N,countWidth:A,totalWidth:L}},f=kt?.find(n=>n.key===e.activeMetadataKey),s=xt?b.map(n=>{const M=o?n.compactLabel:n.label;return{key:n.key,color:n.color,count:n.count,label:M,tooltipLabel:n.tooltip,...c(M,n.count)}}):e.plotMode==="metadata"?Ht.map(([n,M])=>{const A=f?.values?.find(et=>et.value===n)?.label??n,L=o?n:A,V=e.metadataColorMap?.get(n)??"#d6d9dd";return{key:n,color:V,count:M,label:L,tooltipLabel:`${A} \xB7 ${M} dies`,...c(L,M)}}):Et.map(([n,M])=>{const N=u?.get(n),A=N?.name?`${n} \xB7 ${N.name}`:`Bin ${n}`,L=o?String(n):A;return{key:n,color:h(n),count:M,label:L,tooltipLabel:`${A} \xB7 ${M} dies`,...c(L,M)}}),i=O-l*2;if(s.length>0){const n=Bt?gt*2+(st?Ue:0):st&&!_t?Je+je:0,M=Math.max(1,Math.floor((J-2*l-n)/$));let N=s.length,A=1,L=N*$,V=[],et=0;const rt=vt||_t;if(rt){const X=Ut(s.map(y=>y.totalWidth)),I=Math.max(1,Math.min(s.length,Math.floor((i+8)/(X+8))));for(let y=I;y>=1;y--){const k=Math.ceil(s.length/y);if(k>M)continue;const T=new Array(y).fill(0);for(let S=0;S<s.length;S++){const r=S%y;T[r]=Math.max(T[r],s[S].totalWidth)}if(T.reduce((S,r)=>S+r,0)+(y-1)*8<=i||y===1){A=y,V=T,N=k,L=k*$;break}}}else N=Math.min(s.length,M),L=N*$,s.length>M&&(et=s.length-(M-1)),V=[Yt];let P,D;if(Bt){const X=Ut(s.map(r=>j+Tt+t.measureText(r.label).width+Zt)),I=Math.ceil(X);V=[I];const y=st?Ue:0,k=I+gt*2,T=L+y+gt*2,G=q?.x??0,S=q?.y??0;P=Math.min(Math.max(O-l-k+G,l),O-l-k),D=Math.min(Math.max(J-l-T+S,l),J-l-T),ot={x:P,y:D,w:k,h:T},t.save(),t.globalAlpha=.92,t.fillStyle=p.surface,t.fillRect(P,D,k,T),t.globalAlpha=1,t.strokeStyle=p.axisLine,t.lineWidth=1,t.strokeRect(P,D,k,T),t.restore(),P+=gt,D+=gt+y}else vt?(P=l,D=J-l-L):_t?(P=l,D=l):be?(P=l+4,D=Math.max(l+Math.round((J-2*l-L)/2),l+n)):(P=O-l-Yt+4,D=Math.max(l+Math.round((J-2*l-L)/2),l+n));if(st){const X=e.plotMode==="softBin"?ft:Lt,{primary:I,secondary:y,note:k}=Ne(e,St,X),T=je,G=[y,k].filter(x=>!!x),S=(x,_,At)=>G.forEach((Ct,zt)=>Mt(Ct,x,_+zt*16,"left","top",At(_+zt*16),pe(),p.text)),r=x=>Vt-Math.max(ht(x),ht(x-12))-8,W=x=>xe?O-l:r(x),E=Bt?ot.y+ot.h:D+L;if(_t){const x=E+T;Mt(I,P,x,"left","top",Vt-Math.max(ht(x),ht(x+12))-8),S(P,x+16,r)}else if(Bt)Mt(I,ot.x+gt,ot.y+gt,"left","top",ot.x+ot.w-gt),S(ot.x,E+T,()=>ot.x+ot.w);else{const x=Math.max(D-T,l+Je);Mt(I,P,x,"left","bottom",W(x)),S(P,E+T,W)}}t.save(),t.font=nt();const Wt=rt?8:0,ct=(X,I)=>{if(t.measureText(X).width<=I)return X;let y=0,k=X.length;const T="\u2026",G=t.measureText(T).width;for(;y<k;){const S=y+k+1>>1;t.measureText(X.slice(0,S)).width+G<=I?y=S:k=S-1}return y===0?T:X.slice(0,y)+T};if(rt){let X=0;for(let I=0;I<N;I++){let y=P;for(let k=0;k<A;k++){const T=s[X++];if(!T)break;const G=Nt.includes(T.key),S=!G&&T.key===Q,r=y,W=y+j+Tt,E=D+I*$+$/2,x=D+I*$+Math.round(($-j)/2),_=V[k]-j-Tt-Zt;S&&(t.fillStyle=p.hoverRow,t.fillRect(y,D+I*$,V[k],$)),t.fillStyle=T.color,t.fillRect(r,x,j,j),t.strokeStyle=G?p.accent:"rgba(0,0,0,0.25)",t.lineWidth=G?2:.75,t.strokeRect(r,x,j,j),t.fillStyle=G?p.accent:p.text,t.font=G?`bold ${nt()}`:nt(),t.textAlign="left",t.textBaseline="middle",t.fillText(ct(T.label,_),W,E),t.fillStyle=p.textMuted,t.font=nt(),t.textAlign="right",t.fillText(String(T.count),y+V[k]-2,E),de.push({bin:T.key,x:y,y:D+I*$,w:V[k],h:$,label:T.tooltipLabel}),y+=V[k]+Wt}}}else{const X=V[0],I=lt!=="compact",y=X-j-Tt-(I?Zt:0),k=P+X-2;let T=s;et>0&&(T=s.slice(0,M-1));let G=D;for(const S of T){const r=Nt.includes(S.key),W=!r&&S.key===Q,E=P,x=P+j+Tt,_=G+$/2,At=G+Math.round(($-j)/2),Ct=S.label;W&&(t.fillStyle=p.hoverRow,t.fillRect(P-3,G,X+3,$)),t.fillStyle=S.color,t.fillRect(E,At,j,j),t.strokeStyle=r?p.accent:"rgba(0,0,0,0.25)",t.lineWidth=r?2:.75,t.strokeRect(E,At,j,j),t.fillStyle=r?p.accent:p.text,t.font=r?`bold ${nt()}`:nt(),t.textAlign="left",t.textBaseline="middle",t.fillText(ct(Ct,y),x,_),(I||Bt)&&(t.fillStyle=p.textMuted,t.font=nt(),t.textAlign="right",t.fillText(String(S.count),k,_)),de.push({bin:S.key,x:P,y:G,w:X,h:$,label:S.tooltipLabel}),G+=$}et>0&&(t.fillStyle=p.textMuted,t.font=nt(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${et} more`,P+j+Tt,G+$/2))}}s.length>0&&t.restore()}const lo={originX:it,originY:at,ppm:R,snapDist:wt},De=e.rectangles[0]?.width??1,Ie=e.rectangles[0]?.height??1,dt=e.dieBounds,Kt=dt?dt.minX:v.length?He(v.map(o=>o.x)):0,qt=dt?dt.minY:v.length?He(v.map(o=>o.y)):0,io=dt?dt.maxX:v.length?Ut(v.map(o=>o.x)):1,ao=dt?dt.maxY:v.length?Ut(v.map(o=>o.y)):1,{cellW:ge,cellH:me,nCols:It,nRows:ue}=xo(io-Kt,ao-qt,De*1.5,Ie*1.5,v.length),We=Array.from({length:It*ue},()=>[]);for(let o=0;o<v.length;o++){const a=Math.floor((v[o].x-Kt)/ge),u=Math.floor((v[o].y-qt)/me),m=Number.isFinite(a)?Math.max(0,Math.min(It-1,a)):0,h=Number.isFinite(u)?Math.max(0,Math.min(ue-1,u)):0;We[h*It+m].push(o)}function Fe(o,a,u){const m=Math.max(0,Math.floor((o-u-Kt)/ge)),h=Math.min(It-1,Math.floor((o+u-Kt)/ge)),c=Math.max(0,Math.floor((a-u-qt)/me)),f=Math.min(ue-1,Math.floor((a+u-qt)/me)),s=[];for(let i=c;i<=f;i++)for(let n=m;n<=h;n++)for(const M of We[i*It+n])s.push(M);return s}return{hitTarget:{getDieAtPoint(o,a){const u=(o-it)/R,m=(at-a)/R,h=Math.max(De,Ie);for(const s of Fe(u,m,h)){const i=e.rectangles[s];if(i&&Math.abs(u-i.x)<=i.width/2&&Math.abs(m-i.y)<=i.height/2)return e.dies[s]??null}let c=null,f=wt*wt;for(const s of Fe(u,m,wt)){const i=v[s].x-u,n=v[s].y-m,M=i*i+n*n;M<f&&(f=M,c=e.dies[s]??null)}return c}},viewport:lo,binLegendRows:de,legendBox:ot}}function Ao(d,e,H,p,l,w,K,g,Y,B,q,z,C){d.save(),d.font=ko(),d.fillStyle=C.text,d.strokeStyle=C.axisLine,d.lineWidth=.5;const U=H-g+4,F=K+Y-4,Q=ro(q),Qt=Ee(Q,1,0),St=Ee(Q,0,1),mt=1e-9;function Lt(b){return B?Math.abs(b.y)<mt&&Math.abs(b.x)>mt?{pitch:B.x,sign:Math.sign(b.x)}:Math.abs(b.x)<mt&&Math.abs(b.y)>mt?{pitch:B.y,sign:Math.sign(b.y)}:null:null}const ft=Lt(Qt),kt=Lt(St);function st(b){return ft?Math.round(b*ft.sign/ft.pitch):b}function Nt(b){return kt?Math.round(b*kt.sign/kt.pitch):b}function O(b){if(!b)return Ot(50/w);const Z=50/(b*w);return Math.max(1,Math.round(Z))*b}const J=ft?.pitch,Rt=kt?.pitch,ut=O(J),pt=O(Rt);d.textAlign="center",d.textBaseline="top";const xt=Math.ceil((K-p)/w/ut)*ut,bt=(e-K-p)/w;for(let b=xt;b<=bt;b+=ut){const Z=p+b*w;if(Z<K||Z>e-K)continue;d.beginPath(),d.moveTo(Z,U-ze),d.lineTo(Z,U),d.stroke();const tt=B?String(st(b)):$e(b);d.fillText(tt,Z,U+2)}d.textAlign="right",d.textBaseline="middle";const Et=Math.ceil((l-(H-K))/w/pt)*pt,Ht=(l-K)/w;for(let b=Et;b<=Ht;b+=pt){const Z=l-b*w;if(Z<K||Z>H-K)continue;d.beginPath(),d.moveTo(F,Z),d.lineTo(F+ze,Z),d.stroke();const tt=B?String(Nt(b)):$e(b);d.fillText(tt,F-2,Z)}d.restore()}function Co(d,e,H,p,l,w,K){const g=[],Y=K;if(Y<1){const C=Ot((e-d)*p/H);if(C>0){const U=Math.ceil(d/C)*C;for(let F=U;F<=e+C*1e-6;F+=C){if(F<=d||F>=e)continue;const Q=(1-(Math.log10(F)-w)/K)*H;Q>l&&Q<H-l&&g.push(F)}}return g}const B=Y<3?[1,2,5]:[1],q=Math.floor(Math.log10(d)),z=Math.ceil(Math.log10(e));for(let C=q;C<=z;C++)for(const U of B){const F=U*Math.pow(10,C);if(F<=d||F>=e)continue;const Q=(1-(Math.log10(F)-w)/K)*H;Q>l&&Q<H-l&&g.push(F)}return g}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";export const PATH_SHAPES=256;const Ze=new WeakMap;export function outlineSegments(d){const e=g=>Math.round(g*1e6),H=new Map,p=new Map,l=(g,Y,B,q)=>{const z=e(Y);let C=g.get(z);C||g.set(z,C={at:Y,spans:[]}),C.spans.push([B,q])};for(const g of d){const Y=g.x-g.width/2,B=g.x+g.width/2,q=g.y-g.height/2,z=g.y+g.height/2;l(H,q,Y,B),l(H,z,Y,B),l(p,Y,q,z),l(p,B,q,z)}const w=[],K=(g,Y)=>{for(const{at:B,spans:q}of g.values()){q.sort((U,F)=>U[0]-F[0]);let[z,C]=q[0];for(let U=1;U<q.length;U++){const[F,Q]=q[U];e(F)<=e(C)?Q>C&&(C=Q):(Y(B,z,C),z=F,C=Q)}Y(B,z,C)}};return K(H,(g,Y,B)=>w.push(Y,g,B,g)),K(p,(g,Y,B)=>w.push(g,Y,g,B)),Float64Array.from(w)}
|
|
1
|
+
import{fontPx as Nt}from"./toolbar.js";import{findTestDef as Oe,buildMapTitle as Ne}from"../renderer/buildView.js";import{niceStep as Et,compactTickIndices as ro}from"../renderer/axisTicks.js";import{sortBinsForDisplay as fo}from"../stats/binPareto.js";import{affineInvert as ho,affineVector as Ee}from"../core/transforms.js";import{asList as go,compareNatural as mo,maxOf as Qt,minOf as He}from"../core/utils.js";import{resolveValueColorFn as uo}from"../renderer/colorSchemes.js";import{NO_DATA_FILL as po}from"../renderer/colorMap.js";import{SPEC_PASS_FILL as Ye,SPEC_FAIL_LOW as xo,SPEC_FAIL_HIGH as Xe,contrastTextColor as Ge}from"../renderer/colorMap.js";import{fmt as $e,fmtColorbarAxis as we}from"../renderer/fmt.js";import{resolveCanvasTheme as bo}from"./canvasTheme.js";import{hitGridDims as Mo}from"./hitGrid.js";function Ve(h,e,P,u,s){h.moveTo(e,P+s*u),h.lineTo(e-u*.9,P-s*u*.6),h.lineTo(e+u*.9,P-s*u*.6),h.closePath()}const yo=new Set(["value","stackedValues","stackedBins","stackedSoftBins"]),To=new Set(["hardBin","softBin","metadata"]),lt=()=>`${Nt(-2)}px system-ui, sans-serif`,Ke=3,vt=2,So=6,ko=20,Lo=()=>`600 ${Nt()}px system-ui, sans-serif`,qe=36,be=()=>`${Nt(-1)}px system-ui, sans-serif`,Ao=()=>`600 ${Nt(-1)}px system-ui, sans-serif`,te=128,Co=()=>`${Nt(-2)}px system-ui, sans-serif`,ze=4,V=17,Z=11;export const BIN_LEGEND_W=110,BIN_LEGEND_W_COMPACT=64,BIN_LEGEND_ADAPT_COMPACT=280,BIN_LEGEND_ADAPT_FLOATING=180,BIN_LEGEND_MIN_CANVAS_W=150,BIN_LEGEND_MIN_CANVAS_H=120;const ee=28,Lt=5,bt=8,Ue=15,Je=12,je=6;export function toCanvas(h,e,P={}){return drawMapCanvas(h,e,P)}export function drawMapCanvas(h,e,P={}){const u=bo(h.parentElement??h),{padding:s=16,showColorbar:C=!0,markFailingDies:z=!1,colorbarWidth:g=16,background:Y=u.background,legendPosition:D="default",legendOffset:U,showAxes:J=!1,diePitchMm:R,viewport:X,activeBin:N,hoverBin:Q,afterDies:Ht,fallbackFormat:At,minRightReserve:Yt,hbinDefs:mt,sbinDefs:Ct,metadataFields:Xt,showTitle:tt=!0}=P,ut=go(N),G=Math.floor(h.clientWidth||h.width),j=Math.floor(h.clientHeight||h.height),Rt=G>=BIN_LEGEND_MIN_CANVAS_W&&j>=BIN_LEGEND_MIN_CANVAS_H,Pt=C&&Rt&&yo.has(e.plotMode)&&e.passFailDisplay==="off",Dt=C&&Rt&&To.has(e.plotMode),ft=C&&Rt&&e.plotMode==="value"&&(e.passFailDisplay==="spec"&&e.specCounts!==void 0||e.passFailDisplay==="test"&&e.passFailCounts!==void 0),ht=Dt||ft,Gt=Dt&&e.plotMode!=="metadata"&&e.binCounts?fo(e.binCounts.entries(),e.plotMode==="softBin"?e.binColors.pass.soft:e.binColors.pass.hard):[],$t=Dt&&e.plotMode==="metadata"&&e.metadataCounts?[...e.metadataColorMap?.keys()??[...e.metadataCounts.keys()].sort(mo)].map(o=>[o,e.metadataCounts.get(o)??0]):[],dt=[];if(ft&&e.passFailDisplay==="test"){const o=e.passFailCounts;dt.push({key:-1,color:Ye,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),dt.push({key:-2,color:Xe,label:"Fail",compactLabel:"Fail",count:o.fail,tooltip:`Fail \xB7 ${o.fail} dies`})}else if(ft){const o=e.specCounts,a=Oe(e.testDefs,e.activeTest);dt.push({key:-1,color:Ye,label:"Pass",compactLabel:"Pass",count:o.pass,tooltip:`Pass \xB7 ${o.pass} dies`}),a?.limitHigh!==void 0&&dt.push({key:-2,color:Xe,label:"Fail high",compactLabel:"Fail hi",count:o.failHigh,tooltip:`Fail high \xB7 ${o.failHigh} dies`}),a?.limitLow!==void 0&&dt.push({key:-3,color:xo,label:"Fail low",compactLabel:"Fail lo",count:o.failLow,tooltip:`Fail low \xB7 ${o.failLow} dies`})}const wt=ft?dt.length:e.plotMode==="metadata"?$t.length:Gt.length,nt=(h.ownerDocument.defaultView??window).devicePixelRatio??1;if(G<=0||j<=0)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const ot=D!=="default"?D:G<BIN_LEGEND_ADAPT_FLOATING?"floating":G<BIN_LEGEND_ADAPT_COMPACT?"compact":"default",b=ot==="default"||ot==="compact",it=ot==="left",K=ot==="bottom",Mt=ot==="top",yt=ot==="floating",Tt=ot==="compact"||ot==="floating"?BIN_LEGEND_W_COMPACT:BIN_LEGEND_W,Me=Math.floor((j-2*s)/V),ye=wt>Me?Me-1:wt,Te=ht&&K?ye*V:0,oe=ht&&Mt?ye*V:0,ne=e.plotMode==="stackedBins"||e.plotMode==="stackedSoftBins",se=Oe(e.testDefs,e.activeTest),Se=ne?"Count":se?.name??(e.activeTest!=null?`Test ${e.activeTest}`:void 0),ke=ne?void 0:se?.unit,[It,Wt]=e.valueRange,le=o=>String(Math.round(o)),ve=e.logScale||e.allIntegerValues?void 0:Et(Math.max(0,Wt-It)*qe/Math.max(1,j))||void 0,ie=e.allIntegerValues?le:we(Wt,Se,ke,At,ve).edgeFmt;let ae=0;if(Pt){const o=h.getContext("2d");o.font=lt();const a=[ie(It),ie(Wt)];It<0&&a.push(ie(-Math.max(Math.abs(It),Math.abs(Wt))));for(const p of a)ae=Math.max(ae,o.measureText(p).width)}const Le=Math.max(ko,Math.ceil(ae)+Ke+vt+So-s),ce=Pt?g+Le+8:ht&&b?Tt:0,re=ht&&it?Tt:0,fe=J?32:0,Vt=J?36:0,to=Yt!=null?Math.max(ce,Yt):ce,eo=G-2*s-to-Vt-re,Ae=j-2*s-fe-Te-oe;h.width=Math.round(G*nt),h.height=Math.round(j*nt);const t=h.getContext("2d");t.scale(nt,nt),t.fillStyle=Y,t.fillRect(0,0,G,j);const v=e.hoverPoints;if(!v.length)return{hitTarget:{getDieAtPoint:()=>null},viewport:{originX:0,originY:0,ppm:1,snapDist:1},binLegendRows:[]};const Kt=e.rectangles[0],he=Kt?Kt.width/2:0,de=Kt?Kt.height/2:0,qt=e.dieBounds,Ce=(qt?.minX??0)-he,oo=(qt?.maxX??0)+he,no=(qt?.minY??0)-de,Re=(qt?.maxY??0)+de,_e=oo-Ce,Be=Re-no;let at,ct,_;if(X)({originX:at,originY:ct,ppm:_}=X);else{const a=e.notchDir,p=a&&a.y>.1?13:0,m=a&&a.y<-.1?13:0,d=a&&a.x<-.1?13:0,c=a&&a.x>.1?13:0,f=eo-d-c,l=Ae-p-m;_=Math.min(f/_e,l/Be),at=s+Vt+re+d+(f-_e*_)/2-Ce*_,ct=s+oe+p+(l-Be*_)/2+Re*_}const zt=X?.snapDist??Math.max(he,de,1)*1.5,Ut=at+e.waferCenter.x*_,so=ct-e.waferCenter.y*_,ge=e.waferRadius*_,pt=o=>{const a=Math.abs(o-so);return a>=ge?0:Math.sqrt(ge*ge-a*a)},St=(o,a,p,m,d,c,f=Lo(),l=u.text)=>{if(!o)return;t.save(),t.fillStyle=l,t.font=f,t.textAlign=m,t.textBaseline=d;const i=m==="right"?a-c:c-a;let n=o;if(i>8&&t.measureText(n).width>i){for(;n.length>1&&t.measureText(n+"\u2026").width>i;)n=n.slice(0,-1);n=n+"\u2026"}i>8&&t.fillText(n,a,p),t.restore()};t.save(),t.setTransform(_*nt,0,0,-_*nt,at*nt,ct*nt);const kt=1/_,lo=1/(_*nt);if(e.rectangles.length>0){const o=new Map;for(const d of e.rectangles){const c=String(d.fill);let f=o.get(c);f||(f=[],o.set(c,f)),f.push(d)}for(const[d,c]of o){t.fillStyle=d;for(let f=0;f<c.length;f+=PATH_SHAPES){t.beginPath();const l=Math.min(c.length,f+PATH_SHAPES);for(let i=f;i<l;i++){const n=c[i];t.rect(n.x-n.width/2,n.y-n.height/2,n.width,n.height)}t.fill()}}t.strokeStyle="rgba(0,0,0,0.18)",t.lineWidth=.5*lo,t.lineCap="square";const a=Qe.get(e.rectangles)??outlineSegments(e.rectangles);Qe.set(e.rectangles,a);const p=PATH_SHAPES*4;for(let d=0;d<a.length;d+=p){t.beginPath();const c=Math.min(a.length,d+p);for(let f=d;f<c;f+=4)t.moveTo(a[f],a[f+1]),t.lineTo(a[f+2],a[f+3]);t.stroke()}if(t.lineCap="butt",z){const d=e.rectangles.filter(c=>c.binFail);if(d.length>0){const c=new Map;for(const f of d){const l=Ge(String(f.fill));let i=c.get(l);i||(i=[],c.set(l,i)),i.push(f)}t.save(),t.lineCap="butt";for(const[f,l]of c){t.strokeStyle=f,t.globalAlpha=.55,t.lineWidth=Math.max(.6*kt,Math.min(l[0].width,l[0].height)*.1);for(const i of l){const n=i.width/2,M=i.height/2,E=Math.max(1.6*kt,Math.min(i.width,i.height)/3);t.save(),t.beginPath(),t.rect(i.x-n,i.y-M,i.width,i.height),t.clip(),t.beginPath();for(let A=-(n+M);A<=n+M;A+=E)t.moveTo(i.x-n+A,i.y-M),t.lineTo(i.x-n+A+i.height,i.y+M);t.stroke(),t.restore()}}t.restore()}}const m=e.rectangles.filter(d=>d.specMark);if(m.length>0){const d=new Map;for(const f of m){const l=Ge(String(f.fill)),i=`${f.specMark}|${l}`;let n=d.get(i);n||(n=[],d.set(i,n)),n.push(f)}const c=2.5*kt;t.lineJoin="round";for(const[f,l]of d){const[i,n]=f.split("|"),M=n==="#000000"?"#ffffff":"#000000",E=i==="failHigh"?1:-1,A=Math.min(l[0].width,l[0].height),k=Math.max(2.5*kt,A*.3);t.beginPath();for(const q of l)Ve(t,q.x,q.y,k,E);t.strokeStyle=M,t.lineWidth=c,t.stroke(),t.fillStyle=n,t.fill()}}}for(const o of e.overlays){t.beginPath();for(const a of o.points){for(let p=0;p<a.length;p++)p===0?t.moveTo(a[p].x,a[p].y):t.lineTo(a[p].x,a[p].y);o.closed&&t.closePath()}o.fill&&!o.fill.startsWith("rgba(0,0,0,0)")&&(t.fillStyle=o.fill,t.fill()),o.kind==="ring-boundary"||o.kind==="quadrant-boundary"||o.kind==="reticle"?(t.strokeStyle="rgba(0,0,0,0.45)",t.lineWidth=3*kt,t.stroke(),t.strokeStyle="rgba(255,255,255,0.8)",t.lineWidth=1*kt,t.stroke()):(t.strokeStyle=o.lineColor,t.lineWidth=o.lineWidth*kt,t.stroke())}if(t.restore(),e.notchDir){const o=at+e.waferCenter.x*_,a=ct-e.waferCenter.y*_,p=e.notchDir.x,m=-e.notchDir.y,d=e.waferRadius*_,c=4,f=9,l=5,i=o+p*(d+c),n=a+m*(d+c),M=i+p*f,E=n+m*f,A={x:-m,y:p},k=s+Vt+re,q=G-s-ce,et=s+oe,gt=j-s-Te-fe;t.save(),t.beginPath(),t.rect(k,et,q-k,gt-et),t.clip(),t.beginPath(),t.moveTo(i,n),t.lineTo(M+A.x*l,E+A.y*l),t.lineTo(M-A.x*l,E-A.y*l),t.closePath(),t.fillStyle=u.text,t.fill(),t.restore()}t.save(),t.textAlign="center",t.textBaseline="middle";let Pe=0;if(e.rectangles.length>0){let o=1;for(const c of e.texts)c.role!=="indicator"&&c.text.length>o&&(o=c.text.length);const a=e.rectangles[0].width*_,p=e.rectangles[0].height*_,m=Math.min(a,p),d=a/o;Pe=Math.max(8,Math.min(64,Math.round(Math.min(m*.55,d*1.8))))}for(const o of e.texts){const a=at+o.x*_,p=ct-o.y*_;t.font=`${o.role==="indicator"?o.fontSize:Pe}px system-ui, sans-serif`,t.fillStyle=o.color,t.fillText(o.text,a,p)}if(t.restore(),Ht?.(t,{originX:at,originY:ct,ppm:_},{background:Y,text:u.text}),J&&Ro(t,G,j,at,ct,_,s,fe,Vt,R,e.gridToScreen,e.rotation,u,e.compact),Pt){const o=uo(e.valueColorScheme,e.reverseValueScheme),a=Le,p=Ae,m=Math.round(p*.75),d=s+Math.round((p-m)/2),c=G-s-g-a,f=It,l=Wt,i=l-f,n=e.plotMode==="stackedSoftBins"?Ct:mt,{primary:M,secondary:E,note:A}=tt?Ne(e,At,n):{primary:"",secondary:"",note:void 0};if(tt){const r=Math.max(d-6,s+11),O=Ut+Math.max(pt(r),pt(r-12))+8;St(M,G-s,r,"right","bottom",O)}let k=d+m+4;const q=r=>Ut+Math.max(pt(r),pt(r+12))+8,et=e.logScale&&f>0?Math.log10(f):0,gt=e.logScale&&l>0?Math.log10(l)-et:1,I=r=>e.logScale?(1-(Math.log10(r)-et)/gt)*m:(1-(r-f)/i)*m;for(let r=0;r<te;r++){const O=1-r/(te-1),H=d+r/te*m,x=m/te+1;t.fillStyle=o(O),t.fillRect(c,H,g,x)}t.strokeStyle="rgba(0,0,0,0.25)",t.lineWidth=.5,t.strokeRect(c,d,g,m),t.fillStyle=u.text,t.font=lt(),t.textAlign="left",t.strokeStyle="rgba(0,0,0,0.35)",t.lineWidth=.5;const W=Ke,Ot=qe,rt=14;let $;const F=e.logScale&>>0?_o(f,l,m,Ot,rt,et,gt):e.allIntegerValues?(()=>{const r=Math.max(1,Et(i*Ot/m)),O=[],H=Math.ceil(f/r)*r;for(let x=H;x<=l+r*1e-6;x+=r){const B=(1-(x-f)/i)*m;B>rt&&B<m-rt&&O.push(Math.round(x))}return O})():(()=>{const r=i>0?Et(i*Ot/m):0,O=[];if(r>0){$=r;const H=Math.ceil(f/r)*r;for(let x=H;x<=l+r*1e-6;x+=r){const B=(1-(x-f)/i)*m;B>rt&&B<m-rt&&O.push(x)}}return O})(),y=se,L=ne,T=we(l,Se,ke,At,$),w=e.allIntegerValues?le:T.tickFmt,S=e.allIntegerValues?le:T.edgeFmt;t.textBaseline="middle";for(const r of F){const O=d+I(r);t.beginPath(),t.moveTo(c+g,O),t.lineTo(c+g+W,O),t.stroke(),t.fillText(w(r),c+g+W+vt,O)}if(t.beginPath(),t.moveTo(c+g,d),t.lineTo(c+g+W,d),t.stroke(),t.textBaseline="top",t.fillText(S(l),c+g+W+vt,d),t.beginPath(),t.moveTo(c+g,d+m),t.lineTo(c+g+W,d+m),t.stroke(),t.textBaseline="bottom",t.fillText(S(f),c+g+W+vt,d+m),!L&&y&&(y.limitLow!==void 0||y.limitHigh!==void 0)){const r=[],O=e.colorbarRangeMode==="spec";for(const[H,x]of[[y.limitLow,"Lo limit"],[y.limitHigh,"Hi limit"]]){if(H===void 0||e.logScale&&H<=0)continue;const B=I(H);!O&&(B<-rt||B>m+rt)||r.push({value:H,label:x,py:Math.max(0,Math.min(m,B))})}if(r.length>0){t.save(),t.font=lt(),t.textAlign="right",t.textBaseline="middle";for(const{py:H,label:x}of r){const B=d+H;O||(t.strokeStyle="rgba(255,255,255,0.85)",t.lineWidth=3,t.beginPath(),t.moveTo(c,B),t.lineTo(c+g,B),t.stroke(),t.strokeStyle="rgba(0,0,0,0.7)",t.lineWidth=1,t.beginPath(),t.moveTo(c,B),t.lineTo(c+g,B),t.stroke()),t.fillStyle=u.text,t.fillText(x,c-3,B);const _t=x==="Hi limit"?-1:1,Bt=4,Zt=c-3-t.measureText(x).width-Bt-4;t.beginPath(),Ve(t,Zt,B,Bt,_t),t.strokeStyle="#fff",t.lineWidth=2,t.lineJoin="round",t.stroke(),t.fillStyle=u.text,t.fill()}t.restore()}}if(!L){const r=e.logScale?"log\u2081\u2080":e.logScaleRequested?"linear \u2014 log n/a":null;r&&(t.save(),t.fillStyle=u.text,t.font=Ao(),t.textAlign="right",t.textBaseline="top",t.fillText(r,G-s,k),t.restore(),k+=15)}tt&&E&&(St(E,G-s,k,"right","top",q(k),be(),u.text),k+=15),tt&&A&&St(A,G-s,k,"right","top",q(k),be(),u.text)}const me=[];let st;if(ht){const o=ot==="compact",a=e.plotMode==="softBin"?Ct:mt,p=a?new Map(a.map(n=>[n.bin,n])):null,m=e.plotMode==="softBin"?e.binColors.soft:e.binColors.hard,d=n=>m.get(n)??po,c=(n,M)=>{const E=t.measureText(n).width,A=o?0:t.measureText(String(M)).width,k=Z+Lt+E+(A?ee:0);return{labelWidth:E,countWidth:A,totalWidth:k}},f=Xt?.find(n=>n.key===e.activeMetadataKey),l=ft?dt.map(n=>{const M=o?n.compactLabel:n.label;return{key:n.key,color:n.color,count:n.count,label:M,tooltipLabel:n.tooltip,...c(M,n.count)}}):e.plotMode==="metadata"?$t.map(([n,M])=>{const A=f?.values?.find(et=>et.value===n)?.label??n,k=o?n:A,q=e.metadataColorMap?.get(n)??"#d6d9dd";return{key:n,color:q,count:M,label:k,tooltipLabel:`${A} \xB7 ${M} dies`,...c(k,M)}}):Gt.map(([n,M])=>{const E=p?.get(n),A=E?.name?`${n} \xB7 ${E.name}`:`Bin ${n}`,k=o?String(n):A;return{key:n,color:d(n),count:M,label:k,tooltipLabel:`${A} \xB7 ${M} dies`,...c(k,M)}}),i=G-s*2;if(l.length>0){const n=yt?bt*2+(tt?Ue:0):tt&&!Mt?Je+je:0,M=Math.max(1,Math.floor((j-2*s-n)/V));let E=l.length,A=1,k=E*V,q=[],et=0;const gt=K||Mt;if(gt){const $=Qt(l.map(y=>y.totalWidth)),F=Math.max(1,Math.min(l.length,Math.floor((i+8)/($+8))));for(let y=F;y>=1;y--){const L=Math.ceil(l.length/y);if(L>M)continue;const T=new Array(y).fill(0);for(let S=0;S<l.length;S++){const r=S%y;T[r]=Math.max(T[r],l[S].totalWidth)}if(T.reduce((S,r)=>S+r,0)+(y-1)*8<=i||y===1){A=y,q=T,E=L,k=L*V;break}}}else E=Math.min(l.length,M),k=E*V,l.length>M&&(et=l.length-(M-1)),q=[Tt];let I,W;if(yt){const $=Qt(l.map(r=>Z+Lt+t.measureText(r.label).width+ee)),F=Math.ceil($);q=[F];const y=tt?Ue:0,L=F+bt*2,T=k+y+bt*2,w=U?.x??0,S=U?.y??0;I=Math.min(Math.max(G-s-L+w,s),G-s-L),W=Math.min(Math.max(j-s-T+S,s),j-s-T),st={x:I,y:W,w:L,h:T},t.save(),t.globalAlpha=.92,t.fillStyle=u.surface,t.fillRect(I,W,L,T),t.globalAlpha=1,t.strokeStyle=u.axisLine,t.lineWidth=1,t.strokeRect(I,W,L,T),t.restore(),I+=bt,W+=bt+y}else K?(I=s,W=j-s-k):Mt?(I=s,W=s):it?(I=s+4,W=Math.max(s+Math.round((j-2*s-k)/2),s+n)):(I=G-s-Tt+4,W=Math.max(s+Math.round((j-2*s-k)/2),s+n));if(tt){const $=e.plotMode==="softBin"?Ct:mt,{primary:F,secondary:y,note:L}=Ne(e,At,$),T=je,w=[y,L].filter(x=>!!x),S=(x,B,_t)=>w.forEach((Bt,Zt)=>St(Bt,x,B+Zt*16,"left","top",_t(B+Zt*16),be(),u.text)),r=x=>Ut-Math.max(pt(x),pt(x-12))-8,O=x=>b?G-s:r(x),H=yt?st.y+st.h:W+k;if(Mt){const x=H+T;St(F,I,x,"left","top",Ut-Math.max(pt(x),pt(x+12))-8),S(I,x+16,r)}else if(yt)St(F,st.x+bt,st.y+bt,"left","top",st.x+st.w-bt),S(st.x,H+T,()=>st.x+st.w);else{const x=Math.max(W-T,s+Je);St(F,I,x,"left","bottom",O(x)),S(I,H+T,O)}}t.save(),t.font=lt();const Ot=gt?8:0,rt=($,F)=>{if(t.measureText($).width<=F)return $;let y=0,L=$.length;const T="\u2026",w=t.measureText(T).width;for(;y<L;){const S=y+L+1>>1;t.measureText($.slice(0,S)).width+w<=F?y=S:L=S-1}return y===0?T:$.slice(0,y)+T};if(gt){let $=0;for(let F=0;F<E;F++){let y=I;for(let L=0;L<A;L++){const T=l[$++];if(!T)break;const w=ut.includes(T.key),S=!w&&T.key===Q,r=y,O=y+Z+Lt,H=W+F*V+V/2,x=W+F*V+Math.round((V-Z)/2),B=q[L]-Z-Lt-ee;S&&(t.fillStyle=u.hoverRow,t.fillRect(y,W+F*V,q[L],V)),t.fillStyle=T.color,t.fillRect(r,x,Z,Z),t.strokeStyle=w?u.accent:"rgba(0,0,0,0.25)",t.lineWidth=w?2:.75,t.strokeRect(r,x,Z,Z),t.fillStyle=w?u.accent:u.text,t.font=w?`bold ${lt()}`:lt(),t.textAlign="left",t.textBaseline="middle",t.fillText(rt(T.label,B),O,H),t.fillStyle=u.textMuted,t.font=lt(),t.textAlign="right",t.fillText(String(T.count),y+q[L]-2,H),me.push({bin:T.key,x:y,y:W+F*V,w:q[L],h:V,label:T.tooltipLabel}),y+=q[L]+Ot}}}else{const $=q[0],F=ot!=="compact",y=$-Z-Lt-(F?ee:0),L=I+$-2;let T=l;et>0&&(T=l.slice(0,M-1));let w=W;for(const S of T){const r=ut.includes(S.key),O=!r&&S.key===Q,H=I,x=I+Z+Lt,B=w+V/2,_t=w+Math.round((V-Z)/2),Bt=S.label;O&&(t.fillStyle=u.hoverRow,t.fillRect(I-3,w,$+3,V)),t.fillStyle=S.color,t.fillRect(H,_t,Z,Z),t.strokeStyle=r?u.accent:"rgba(0,0,0,0.25)",t.lineWidth=r?2:.75,t.strokeRect(H,_t,Z,Z),t.fillStyle=r?u.accent:u.text,t.font=r?`bold ${lt()}`:lt(),t.textAlign="left",t.textBaseline="middle",t.fillText(rt(Bt,y),x,B),(F||yt)&&(t.fillStyle=u.textMuted,t.font=lt(),t.textAlign="right",t.fillText(String(S.count),L,B)),me.push({bin:S.key,x:I,y:w,w:$,h:V,label:S.tooltipLabel}),w+=V}et>0&&(t.fillStyle=u.textMuted,t.font=lt(),t.textAlign="left",t.textBaseline="middle",t.fillText(`+ ${et} more`,I+Z+Lt,w+V/2))}}l.length>0&&t.restore()}const io={originX:at,originY:ct,ppm:_,snapDist:zt},De=e.rectangles[0]?.width??1,Ie=e.rectangles[0]?.height??1,xt=e.dieBounds,Jt=xt?xt.minX:v.length?He(v.map(o=>o.x)):0,jt=xt?xt.minY:v.length?He(v.map(o=>o.y)):0,ao=xt?xt.maxX:v.length?Qt(v.map(o=>o.x)):1,co=xt?xt.maxY:v.length?Qt(v.map(o=>o.y)):1,{cellW:ue,cellH:pe,nCols:Ft,nRows:xe}=Mo(ao-Jt,co-jt,De*1.5,Ie*1.5,v.length),We=Array.from({length:Ft*xe},()=>[]);for(let o=0;o<v.length;o++){const a=Math.floor((v[o].x-Jt)/ue),p=Math.floor((v[o].y-jt)/pe),m=Number.isFinite(a)?Math.max(0,Math.min(Ft-1,a)):0,d=Number.isFinite(p)?Math.max(0,Math.min(xe-1,p)):0;We[d*Ft+m].push(o)}function Fe(o,a,p){const m=Math.max(0,Math.floor((o-p-Jt)/ue)),d=Math.min(Ft-1,Math.floor((o+p-Jt)/ue)),c=Math.max(0,Math.floor((a-p-jt)/pe)),f=Math.min(xe-1,Math.floor((a+p-jt)/pe)),l=[];for(let i=c;i<=f;i++)for(let n=m;n<=d;n++)for(const M of We[i*Ft+n])l.push(M);return l}return{hitTarget:{getDieAtPoint(o,a){const p=(o-at)/_,m=(ct-a)/_,d=Math.max(De,Ie);for(const l of Fe(p,m,d)){const i=e.rectangles[l];if(i&&Math.abs(p-i.x)<=i.width/2&&Math.abs(m-i.y)<=i.height/2)return e.dies[l]??null}let c=null,f=zt*zt;for(const l of Fe(p,m,zt)){const i=v[l].x-p,n=v[l].y-m,M=i*i+n*n;M<f&&(f=M,c=e.dies[l]??null)}return c}},viewport:io,binLegendRows:me,legendBox:st}}function Ro(h,e,P,u,s,C,z,g,Y,D,U,J,R,X){h.save(),h.font=Co(),h.fillStyle=R.text,h.strokeStyle=R.axisLine,h.lineWidth=.5;const N=P-g+4,Q=z+Y-4,Ht=ho(U),At=Ee(Ht,1,0),Yt=Ee(Ht,0,1),mt=1e-9;function Ct(b){return D?Math.abs(b.y)<mt&&Math.abs(b.x)>mt?{pitch:D.x,sign:Math.sign(b.x),axis:"x"}:Math.abs(b.x)<mt&&Math.abs(b.y)>mt?{pitch:D.y,sign:Math.sign(b.y),axis:"y"}:null:null}function Xt(b,it){if(!X||!b)return null;const K=b.axis==="x"?X.columns:X.rows,Mt=b.axis==="x"?X.columnBreaks:X.rowBreaks,yt=b.axis==="x"?X.centreColumn:X.centreRow;return ro(K.length,Mt,b.pitch*C,it).map(Tt=>({mm:b.sign*(Tt-yt)*b.pitch,label:String(K[Tt])}))}const tt=Ct(At),ut=Ct(Yt);function G(b){return tt?Math.round(b*tt.sign/tt.pitch):b}function j(b){return ut?Math.round(b*ut.sign/ut.pitch):b}function Rt(b){if(!b)return Et(50/C);const it=50/(b*C);return Math.max(1,Math.round(it))*b}const Pt=tt?.pitch,Dt=ut?.pitch,ft=Rt(Pt),ht=Rt(Dt);h.textAlign="center",h.textBaseline="top";const Gt=Math.ceil((z-u)/C/ft)*ft,$t=(e-z-u)/C,dt=Xt(tt,36)??Ze(Gt,$t,ft,b=>D?String(G(b)):$e(b));for(const{mm:b,label:it}of dt){const K=u+b*C;K<z||K>e-z||(h.beginPath(),h.moveTo(K,N-ze),h.lineTo(K,N),h.stroke(),h.fillText(it,K,N+2))}h.textAlign="right",h.textBaseline="middle";const wt=Math.ceil((s-(P-z))/C/ht)*ht,nt=(s-z)/C,ot=Xt(ut,16)??Ze(wt,nt,ht,b=>D?String(j(b)):$e(b));for(const{mm:b,label:it}of ot){const K=s-b*C;K<z||K>P-z||(h.beginPath(),h.moveTo(Q,K),h.lineTo(Q+ze,K),h.stroke(),h.fillText(it,Q-2,K))}h.restore()}function Ze(h,e,P,u){const s=[];for(let C=h;C<=e;C+=P)s.push({mm:C,label:u(C)});return s}function _o(h,e,P,u,s,C,z){const g=[],Y=z;if(Y<1){const R=Et((e-h)*u/P);if(R>0){const X=Math.ceil(h/R)*R;for(let N=X;N<=e+R*1e-6;N+=R){if(N<=h||N>=e)continue;const Q=(1-(Math.log10(N)-C)/z)*P;Q>s&&Q<P-s&&g.push(N)}}return g}const D=Y<3?[1,2,5]:[1],U=Math.floor(Math.log10(h)),J=Math.ceil(Math.log10(e));for(let R=U;R<=J;R++)for(const X of D){const N=X*Math.pow(10,R);if(N<=h||N>=e)continue;const Q=(1-(Math.log10(N)-C)/z)*P;Q>s&&Q<P-s&&g.push(N)}return g}export{fmt,fmtColorbarAxis}from"../renderer/fmt.js";export const PATH_SHAPES=256;const Qe=new WeakMap;export function outlineSegments(h){const e=g=>Math.round(g*1e6),P=new Map,u=new Map,s=(g,Y,D,U)=>{const J=e(Y);let R=g.get(J);R||g.set(J,R={at:Y,spans:[]}),R.spans.push([D,U])};for(const g of h){const Y=g.x-g.width/2,D=g.x+g.width/2,U=g.y-g.height/2,J=g.y+g.height/2;s(P,U,Y,D),s(P,J,Y,D),s(u,Y,U,J),s(u,D,U,J)}const C=[],z=(g,Y)=>{for(const{at:D,spans:U}of g.values()){U.sort((X,N)=>X[0]-N[0]);let[J,R]=U[0];for(let X=1;X<U.length;X++){const[N,Q]=U[X];e(N)<=e(R)?Q>R&&(R=Q):(Y(D,J,R),J=N,R=Q)}Y(D,J,R)}};return z(P,(g,Y,D)=>C.push(Y,g,D,g)),z(u,(g,Y,D)=>C.push(g,Y,g,D)),Float64Array.from(C)}
|
|
@@ -334,6 +334,29 @@ export declare function downloadBlob(blob: Blob, filename: string): void;
|
|
|
334
334
|
* `suggestedName` (already includes its extension), and the `mimeType`.
|
|
335
335
|
*/
|
|
336
336
|
export type SaveTextHandler = (text: string, suggestedName: string, mimeType: string) => void | Promise<void>;
|
|
337
|
+
/**
|
|
338
|
+
* A callback for "a panel just opened or closed beside the map in this box": widens the box by the
|
|
339
|
+
* room the panel took when it opens, and gives it back when it closes. Pass it to whatever
|
|
340
|
+
* renders the map inside `handle`. Only changes of state call it, since the room is measured at
|
|
341
|
+
* the moment the map loses it.
|
|
342
|
+
*/
|
|
343
|
+
export declare function roomForPanel(handle: OverlayHandle): (open: boolean, widthPx: number) => void;
|
|
344
|
+
/**
|
|
345
|
+
* Show what the compact-layout detector saw, for a person to read and send back: counts and
|
|
346
|
+
* scores only (see `diagnoseMpwLayout`), in a box they can read first, copy, or save as a
|
|
347
|
+
* file. Saving goes through the host's `onSaveText`, the one route that works in a desktop
|
|
348
|
+
* webview; the clipboard may not, so a failed copy says so and leaves the text selectable.
|
|
349
|
+
*/
|
|
350
|
+
export declare function openCompactDiagnostics(dies: readonly {
|
|
351
|
+
x?: number | null;
|
|
352
|
+
y?: number | null;
|
|
353
|
+
}[], reticles: readonly ({
|
|
354
|
+
width: number;
|
|
355
|
+
height: number;
|
|
356
|
+
} | undefined)[], opts: {
|
|
357
|
+
anchor: HTMLElement;
|
|
358
|
+
onSaveText?: SaveTextHandler;
|
|
359
|
+
}): OverlayHandle;
|
|
337
360
|
/**
|
|
338
361
|
* Persist a text file (e.g. a CSV export). Routes through the host
|
|
339
362
|
* `onSaveText` hook when provided; otherwise falls back to a browser
|
|
@@ -602,6 +625,12 @@ export type CheckMenuRow = {
|
|
|
602
625
|
* missing feature, and the user has no way to learn the condition.
|
|
603
626
|
*/
|
|
604
627
|
disabledHint?: string;
|
|
628
|
+
/**
|
|
629
|
+
* Close the menu after this row is clicked. For an action that opens something of its own
|
|
630
|
+
* (a dialog), which the menu would otherwise stay open on top of. Toggles keep the menu open
|
|
631
|
+
* so several can be set in one visit.
|
|
632
|
+
*/
|
|
633
|
+
closeMenu?: boolean;
|
|
605
634
|
/**
|
|
606
635
|
* Marks a row that *does* something rather than holding a state — "Clear
|
|
607
636
|
* overlays", "Reset orientation". Rendered as a plain `menuitem` with no
|
|
@@ -701,6 +730,14 @@ export interface OverlayHandle {
|
|
|
701
730
|
/** Replace the box's natural height (see `OverlayOptions.boxSize`) — applied
|
|
702
731
|
* now unless maximized or minimized, and restored to from either. */
|
|
703
732
|
setNaturalHeight: (height: string) => void;
|
|
733
|
+
/**
|
|
734
|
+
* Make room for `px` of extra content beside what the box already holds, by widening it, and
|
|
735
|
+
* return the function that takes that room back. Capped so the box stays on screen (a window is
|
|
736
|
+
* moved left if it would run off the edge), so it may give less than asked. Does nothing while
|
|
737
|
+
* maximised or collapsed, and releasing leaves a width the user has dragged the box to since.
|
|
738
|
+
* For a panel that opens beside a map, so the map keeps its size instead of giving it up.
|
|
739
|
+
*/
|
|
740
|
+
reserveWidth: (px: number) => () => void;
|
|
704
741
|
}
|
|
705
742
|
/** Create and open a resizable, maximizable, exclusive expand modal — dims and
|
|
706
743
|
* blocks the rest of the page. See `openFloatingWindow` for the non-modal form. */
|
|
@@ -797,6 +834,8 @@ export interface OverlayFlags {
|
|
|
797
834
|
showDieLabels?: boolean;
|
|
798
835
|
showReticle?: boolean;
|
|
799
836
|
showXYIndicator?: boolean;
|
|
837
|
+
/** Unset means "while zoomed", the default; see `WaferViewOptions.showAxes`. */
|
|
838
|
+
showAxes?: boolean;
|
|
800
839
|
passFailDisplay?: 'off' | 'spec' | 'test';
|
|
801
840
|
/**
|
|
802
841
|
* Moved here from the Colour scheme menu, where it had been the one entry
|
|
@@ -829,7 +868,14 @@ export declare function overlayMenuRows(flags: OverlayFlags, reticleEnabled: boo
|
|
|
829
868
|
hasLimits: boolean;
|
|
830
869
|
hasRecorded: boolean;
|
|
831
870
|
binMode: boolean;
|
|
832
|
-
}, apply: (patch: OverlayFlags) => void
|
|
871
|
+
}, apply: (patch: OverlayFlags) => void,
|
|
872
|
+
/** The compact layout toggle, for a host that offers it (a single map). */
|
|
873
|
+
compact?: {
|
|
874
|
+
on: boolean;
|
|
875
|
+
offered: boolean;
|
|
876
|
+
onChange: (on: boolean) => void;
|
|
877
|
+
onDiagnostics: () => void;
|
|
878
|
+
}): CheckMenuRow[];
|
|
833
879
|
/** Whether any overlay is on — the Overlays button's "active" state. Shared for
|
|
834
880
|
* the same reason as the rows: it enumerates the same five flags. */
|
|
835
881
|
export declare function anyOverlayActive(flags: OverlayFlags): boolean;
|
|
@@ -884,6 +930,7 @@ export declare function makeOrientationBtn(helpers: ToolbarHelpers, getOpts: ()
|
|
|
884
930
|
rotation?: 0 | 90 | 180 | 270;
|
|
885
931
|
flipX?: boolean;
|
|
886
932
|
flipY?: boolean;
|
|
933
|
+
showXYIndicator?: boolean;
|
|
887
934
|
}) => void): HTMLButtonElement;
|
|
888
935
|
type GuideApi = {
|
|
889
936
|
buildWaferMap: unknown;
|
|
@@ -971,6 +1018,12 @@ export declare function openWaferMapGuide(extension?: UserGuideExtension, anchor
|
|
|
971
1018
|
export declare function openReportModal(html: string, opts?: {
|
|
972
1019
|
anchor?: Element;
|
|
973
1020
|
ownerDocument?: Document;
|
|
1021
|
+
/**
|
|
1022
|
+
* A report built with `live` tells this page which finding a click on its row meant. Called with that
|
|
1023
|
+
* finding's id and the modal's handle, so the host can close the modal and show the finding on the map.
|
|
1024
|
+
* Only messages from this report's own frame are heeded.
|
|
1025
|
+
*/
|
|
1026
|
+
onFinding?: (findingId: string, handle: OverlayHandle) => void;
|
|
974
1027
|
}): OverlayHandle;
|
|
975
1028
|
export {};
|
|
976
1029
|
//# sourceMappingURL=toolbar.d.ts.map
|