@wafertools/wafermap 0.21.1

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +751 -0
  2. package/LICENSE +21 -0
  3. package/README.md +79 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.js +1 -0
  6. package/dist/packages/canvas-adapter/canvasTheme.d.ts +28 -0
  7. package/dist/packages/canvas-adapter/canvasTheme.js +1 -0
  8. package/dist/packages/canvas-adapter/charts/barPanel.d.ts +52 -0
  9. package/dist/packages/canvas-adapter/charts/barPanel.js +1 -0
  10. package/dist/packages/canvas-adapter/charts/binCluster.d.ts +17 -0
  11. package/dist/packages/canvas-adapter/charts/binCluster.js +1 -0
  12. package/dist/packages/canvas-adapter/charts/boxplot.d.ts +45 -0
  13. package/dist/packages/canvas-adapter/charts/boxplot.js +1 -0
  14. package/dist/packages/canvas-adapter/charts/capability.d.ts +41 -0
  15. package/dist/packages/canvas-adapter/charts/capability.js +1 -0
  16. package/dist/packages/canvas-adapter/charts/chartShell.d.ts +156 -0
  17. package/dist/packages/canvas-adapter/charts/chartShell.js +1 -0
  18. package/dist/packages/canvas-adapter/charts/correlation.d.ts +35 -0
  19. package/dist/packages/canvas-adapter/charts/correlation.js +1 -0
  20. package/dist/packages/canvas-adapter/charts/histogram.d.ts +30 -0
  21. package/dist/packages/canvas-adapter/charts/histogram.js +1 -0
  22. package/dist/packages/canvas-adapter/charts/index.d.ts +16 -0
  23. package/dist/packages/canvas-adapter/charts/index.js +1 -0
  24. package/dist/packages/canvas-adapter/charts/palette.d.ts +26 -0
  25. package/dist/packages/canvas-adapter/charts/palette.js +1 -0
  26. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.d.ts +18 -0
  27. package/dist/packages/canvas-adapter/charts/regionYieldDiagram.js +1 -0
  28. package/dist/packages/canvas-adapter/charts/scatter.d.ts +37 -0
  29. package/dist/packages/canvas-adapter/charts/scatter.js +1 -0
  30. package/dist/packages/canvas-adapter/icons.d.ts +2 -0
  31. package/dist/packages/canvas-adapter/icons.js +42 -0
  32. package/dist/packages/canvas-adapter/index.d.ts +12 -0
  33. package/dist/packages/canvas-adapter/index.js +1 -0
  34. package/dist/packages/canvas-adapter/insightsTab.d.ts +76 -0
  35. package/dist/packages/canvas-adapter/insightsTab.js +1 -0
  36. package/dist/packages/canvas-adapter/metadataBadge.d.ts +26 -0
  37. package/dist/packages/canvas-adapter/metadataBadge.js +1 -0
  38. package/dist/packages/canvas-adapter/renderWaferGallery.d.ts +181 -0
  39. package/dist/packages/canvas-adapter/renderWaferGallery.js +20 -0
  40. package/dist/packages/canvas-adapter/renderWaferMap.d.ts +316 -0
  41. package/dist/packages/canvas-adapter/renderWaferMap.js +1 -0
  42. package/dist/packages/canvas-adapter/summaryPanel.d.ts +262 -0
  43. package/dist/packages/canvas-adapter/summaryPanel.js +3 -0
  44. package/dist/packages/canvas-adapter/toCanvas.d.ts +106 -0
  45. package/dist/packages/canvas-adapter/toCanvas.js +1 -0
  46. package/dist/packages/canvas-adapter/toolbar.d.ts +496 -0
  47. package/dist/packages/canvas-adapter/toolbar.js +9 -0
  48. package/dist/packages/canvas-adapter/userGuideHtml.d.ts +2 -0
  49. package/dist/packages/canvas-adapter/userGuideHtml.js +968 -0
  50. package/dist/packages/canvas-adapter/version.d.ts +3 -0
  51. package/dist/packages/canvas-adapter/version.js +1 -0
  52. package/dist/packages/core/aggregates.d.ts +54 -0
  53. package/dist/packages/core/aggregates.js +1 -0
  54. package/dist/packages/core/classify.d.ts +24 -0
  55. package/dist/packages/core/classify.js +1 -0
  56. package/dist/packages/core/dies.d.ts +92 -0
  57. package/dist/packages/core/dies.js +1 -0
  58. package/dist/packages/core/index.d.ts +13 -0
  59. package/dist/packages/core/index.js +1 -0
  60. package/dist/packages/core/inference/grid.d.ts +35 -0
  61. package/dist/packages/core/inference/grid.js +1 -0
  62. package/dist/packages/core/inference/index.d.ts +7 -0
  63. package/dist/packages/core/inference/index.js +1 -0
  64. package/dist/packages/core/inference/pitch.d.ts +26 -0
  65. package/dist/packages/core/inference/pitch.js +1 -0
  66. package/dist/packages/core/inference/wafer.d.ts +30 -0
  67. package/dist/packages/core/inference/wafer.js +1 -0
  68. package/dist/packages/core/metadata.d.ts +31 -0
  69. package/dist/packages/core/metadata.js +1 -0
  70. package/dist/packages/core/probe.d.ts +16 -0
  71. package/dist/packages/core/probe.js +1 -0
  72. package/dist/packages/core/reticle.d.ts +68 -0
  73. package/dist/packages/core/reticle.js +1 -0
  74. package/dist/packages/core/transforms.d.ts +142 -0
  75. package/dist/packages/core/transforms.js +1 -0
  76. package/dist/packages/core/utils.d.ts +60 -0
  77. package/dist/packages/core/utils.js +1 -0
  78. package/dist/packages/core/wafer.d.ts +45 -0
  79. package/dist/packages/core/wafer.js +1 -0
  80. package/dist/packages/renderer/buildView.d.ts +420 -0
  81. package/dist/packages/renderer/buildView.js +1 -0
  82. package/dist/packages/renderer/buildWaferMap.d.ts +543 -0
  83. package/dist/packages/renderer/buildWaferMap.js +1 -0
  84. package/dist/packages/renderer/colorMap.d.ts +46 -0
  85. package/dist/packages/renderer/colorMap.js +1 -0
  86. package/dist/packages/renderer/colorSchemes.d.ts +40 -0
  87. package/dist/packages/renderer/colorSchemes.js +1 -0
  88. package/dist/packages/renderer/fmt.d.ts +30 -0
  89. package/dist/packages/renderer/fmt.js +1 -0
  90. package/dist/packages/renderer/index.d.ts +7 -0
  91. package/dist/packages/renderer/index.js +1 -0
  92. package/dist/packages/stats/analyzeWaferLot.d.ts +5 -0
  93. package/dist/packages/stats/analyzeWaferLot.js +1 -0
  94. package/dist/packages/stats/analyzeWaferMap.d.ts +13 -0
  95. package/dist/packages/stats/analyzeWaferMap.js +1 -0
  96. package/dist/packages/stats/binPareto.d.ts +49 -0
  97. package/dist/packages/stats/binPareto.js +1 -0
  98. package/dist/packages/stats/boxplot.d.ts +39 -0
  99. package/dist/packages/stats/boxplot.js +1 -0
  100. package/dist/packages/stats/capability.d.ts +55 -0
  101. package/dist/packages/stats/capability.js +1 -0
  102. package/dist/packages/stats/clusterDetection.d.ts +18 -0
  103. package/dist/packages/stats/clusterDetection.js +1 -0
  104. package/dist/packages/stats/correlation.d.ts +55 -0
  105. package/dist/packages/stats/correlation.js +1 -0
  106. package/dist/packages/stats/facets.d.ts +74 -0
  107. package/dist/packages/stats/facets.js +1 -0
  108. package/dist/packages/stats/filterFindings.d.ts +9 -0
  109. package/dist/packages/stats/filterFindings.js +1 -0
  110. package/dist/packages/stats/findingsNarrative.d.ts +3 -0
  111. package/dist/packages/stats/findingsNarrative.js +1 -0
  112. package/dist/packages/stats/histogram.d.ts +42 -0
  113. package/dist/packages/stats/histogram.js +1 -0
  114. package/dist/packages/stats/index.d.ts +27 -0
  115. package/dist/packages/stats/index.js +1 -0
  116. package/dist/packages/stats/math.d.ts +10 -0
  117. package/dist/packages/stats/math.js +1 -0
  118. package/dist/packages/stats/patternClassification.d.ts +107 -0
  119. package/dist/packages/stats/patternClassification.js +1 -0
  120. package/dist/packages/stats/regions.d.ts +57 -0
  121. package/dist/packages/stats/regions.js +1 -0
  122. package/dist/packages/stats/renderFindingsReport.d.ts +7 -0
  123. package/dist/packages/stats/renderFindingsReport.js +41 -0
  124. package/dist/packages/stats/renderSummaryReport.d.ts +60 -0
  125. package/dist/packages/stats/renderSummaryReport.js +68 -0
  126. package/dist/packages/stats/reportHtml.d.ts +42 -0
  127. package/dist/packages/stats/reportHtml.js +301 -0
  128. package/dist/packages/stats/scatter.d.ts +24 -0
  129. package/dist/packages/stats/scatter.js +1 -0
  130. package/dist/packages/stats/types.d.ts +269 -0
  131. package/dist/packages/stats/types.js +1 -0
  132. package/dist/packages/stats/yield.d.ts +56 -0
  133. package/dist/packages/stats/yield.js +1 -0
  134. package/dist/packages/worker/index.d.ts +44 -0
  135. package/dist/packages/worker/index.js +1 -0
  136. package/dist/packages/worker/wafermap.worker.d.ts +44 -0
  137. package/dist/packages/worker/wafermap.worker.js +1 -0
  138. package/package.json +122 -0
@@ -0,0 +1,301 @@
1
+ import{fmt as i}from"../renderer/fmt.js";import{buildFacetTable as d,prettyKey as s}from"./facets.js";export function escHtml(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}export function renderSection(t,e,r=""){return`<section class="${["report-section",r].filter(Boolean).join(" ")}">
2
+ <h2>${escHtml(t)}</h2>
3
+ ${e}
4
+ </section>`}export function renderDefinitionList(t,e="meta-list"){if(!t.length)return"";const r=t.map(a=>`<div class="definition-item"><dt>${escHtml(a.label)}</dt><dd>${escHtml(a.value)}</dd></div>`).join(`
5
+ `);return`<dl class="${e}">
6
+ ${r}
7
+ </dl>`}export function buildMetadataRows(t){return d(t,{facetableOnly:t.length>1}).map(r=>({label:s(r.key),value:r.values.map(a=>a.value).join(", ")}))}export function renderMetadataSection(t){const e=buildMetadataRows(t);return e.length?renderSection("Wafer Info",renderDefinitionList(e)):""}export function renderMetricGrid(t){return t.length?`<dl class="metric-grid">
8
+ ${t.map(r=>`<div class="metric">
9
+ <dt>${escHtml(r.label)}</dt>
10
+ <dd>${escHtml(r.value)}</dd>
11
+ ${r.hint?`<span class="metric-hint">${escHtml(r.hint)}</span>`:""}
12
+ </div>`).join(`
13
+ `)}
14
+ </dl>`:""}export function renderTable(t,e,r={}){if(!e.length)return`<p class="no-data">${escHtml(r.emptyMessage??"No data")}</p>`;const a=["report-table",r.className].filter(Boolean).join(" "),n=t.map(o=>`<th>${escHtml(o)}</th>`).join(""),p=e.map(o=>`<tr>${o.map(l=>`<td>${l}</td>`).join("")}</tr>`).join(`
15
+ `);return`<table class="${a}">
16
+ <thead><tr>${n}</tr></thead>
17
+ <tbody>${p}</tbody>
18
+ </table>`}export function renderSeverityBadge(t){const e=t.charAt(0).toUpperCase()+t.slice(1);return`<span class="badge badge-${t}">${e}</span>`}export function formatFindingDelta(t){const e=t.effect.absoluteDelta??0,r=e>0?"+":e<0?"\u2212":"";if(t.variable.kind==="yield"||t.variable.kind==="hardBin"||t.variable.kind==="softBin")return`${r}${Math.abs(e*100).toFixed(1)} pp`;if(t.variable.kind==="test"){if(t.effect.relativeDelta!==void 0&&Number.isFinite(t.effect.relativeDelta)){const a=Math.abs(t.effect.relativeDelta*100).toFixed(1);return`${r}${a}%`}return`${r}${i(Math.abs(e),t.variable.unit)}`}return`${r}${i(Math.abs(e),t.variable.unit)}`}export function formatFindingTooltip(t){return t.summary}export function formatFindingCoverage(t,e){return e!==void 0?`${t.stats.sampleSizeLeft}/${e}`:`${t.stats.sampleSizeLeft}/${t.stats.sampleSizeRight}`}export function reportStyles(){return`
19
+ :root {
20
+ --report-font: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
21
+ --report-text: #1f2328;
22
+ --report-muted: #5c6570;
23
+ --report-subtle: #7a828d;
24
+ --report-line: #d8dee6;
25
+ --report-line-strong: #c7ced8;
26
+ --report-surface: #f7f8fa;
27
+ --report-surface-alt: #fbfcfd;
28
+ --report-severity-unusual: #8b3f35;
29
+ --report-severity-notable: #8b6428;
30
+ --report-severity-info: #446883;
31
+ }
32
+
33
+ html {
34
+ background: #fff;
35
+ }
36
+
37
+ body {
38
+ margin: 0;
39
+ color: var(--report-text);
40
+ background: #fff;
41
+ font-family: var(--report-font);
42
+ font-size: 13px;
43
+ line-height: 1.45;
44
+ font-variant-numeric: tabular-nums;
45
+ -webkit-font-smoothing: antialiased;
46
+ text-rendering: optimizeLegibility;
47
+ }
48
+
49
+ .report {
50
+ max-width: 1080px;
51
+ margin: 0 auto;
52
+ padding: 24px 28px 32px;
53
+ }
54
+
55
+ .report-header {
56
+ margin: 0 0 16px;
57
+ padding-bottom: 12px;
58
+ border-bottom: 1px solid var(--report-line);
59
+ }
60
+
61
+ h1 {
62
+ margin: 0;
63
+ font-size: 20px;
64
+ font-weight: 600;
65
+ line-height: 1.2;
66
+ letter-spacing: -0.01em;
67
+ }
68
+
69
+ .report-subtitle {
70
+ margin: 6px 0 0;
71
+ color: var(--report-muted);
72
+ font-size: 12px;
73
+ }
74
+
75
+ section.report-section {
76
+ margin-top: 18px;
77
+ break-inside: avoid;
78
+ page-break-inside: avoid;
79
+ }
80
+
81
+ section.report-section + section.report-section {
82
+ border-top: 1px solid var(--report-line);
83
+ padding-top: 14px;
84
+ }
85
+
86
+ h2 {
87
+ margin: 0 0 8px;
88
+ color: var(--report-muted);
89
+ font-size: 11px;
90
+ font-weight: 600;
91
+ text-transform: uppercase;
92
+ letter-spacing: 0.09em;
93
+ }
94
+
95
+ .no-data {
96
+ margin: 0;
97
+ color: var(--report-muted);
98
+ font-style: italic;
99
+ }
100
+
101
+ .findings-narrative {
102
+ margin: 0 0 14px;
103
+ color: var(--report-muted);
104
+ font-size: 13px;
105
+ font-style: italic;
106
+ line-height: 1.6;
107
+ }
108
+
109
+ .definition-item {
110
+ display: contents;
111
+ }
112
+
113
+ .meta-list {
114
+ display: grid;
115
+ grid-template-columns: max-content minmax(0, 1fr);
116
+ column-gap: 14px;
117
+ row-gap: 6px;
118
+ align-items: baseline;
119
+ }
120
+
121
+ .meta-list dt {
122
+ margin: 0;
123
+ color: var(--report-muted);
124
+ font-size: 12px;
125
+ white-space: nowrap;
126
+ }
127
+
128
+ .meta-list dd {
129
+ margin: 0;
130
+ min-width: 0;
131
+ }
132
+
133
+ .metric-grid {
134
+ display: grid;
135
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
136
+ gap: 10px 14px;
137
+ }
138
+
139
+ .metric {
140
+ padding-top: 10px;
141
+ border-top: 1px solid var(--report-line);
142
+ }
143
+
144
+ .metric dt {
145
+ margin: 0 0 3px;
146
+ color: var(--report-muted);
147
+ font-size: 11px;
148
+ text-transform: uppercase;
149
+ letter-spacing: 0.06em;
150
+ }
151
+
152
+ .metric dd {
153
+ margin: 0;
154
+ font-size: 18px;
155
+ font-weight: 600;
156
+ line-height: 1.15;
157
+ }
158
+
159
+ .metric-hint {
160
+ display: block;
161
+ margin-top: 3px;
162
+ color: var(--report-subtle);
163
+ font-size: 11px;
164
+ }
165
+
166
+ table.report-table {
167
+ width: 100%;
168
+ border-collapse: collapse;
169
+ table-layout: fixed;
170
+ font-variant-numeric: tabular-nums;
171
+ }
172
+
173
+ table.report-table thead {
174
+ display: table-header-group;
175
+ }
176
+
177
+ table.report-table th,
178
+ table.report-table td {
179
+ padding: 4px 8px;
180
+ text-align: left;
181
+ vertical-align: top;
182
+ border-bottom: 1px solid var(--report-line);
183
+ }
184
+
185
+ table.report-table thead th {
186
+ padding-top: 3px;
187
+ padding-bottom: 5px;
188
+ color: var(--report-muted);
189
+ font-size: 10px;
190
+ font-weight: 600;
191
+ text-transform: uppercase;
192
+ letter-spacing: 0.08em;
193
+ border-bottom: 1px solid var(--report-line-strong);
194
+ background: transparent;
195
+ }
196
+
197
+ table.report-table tbody tr:last-child td {
198
+ border-bottom: none;
199
+ }
200
+
201
+ table.report-table.compact th,
202
+ table.report-table.compact td {
203
+ padding-top: 3px;
204
+ padding-bottom: 3px;
205
+ }
206
+
207
+ table.report-table .numeric {
208
+ text-align: right;
209
+ white-space: nowrap;
210
+ }
211
+
212
+ table.report-table .muted {
213
+ color: var(--report-muted);
214
+ }
215
+
216
+ table.report-table .tight {
217
+ white-space: nowrap;
218
+ }
219
+
220
+ table.report-table .summary {
221
+ color: var(--report-muted);
222
+ font-size: 12px;
223
+ }
224
+
225
+ .badge {
226
+ display: inline-flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ min-width: 58px;
230
+ padding: 1px 6px;
231
+ border: 1px solid transparent;
232
+ border-radius: 999px;
233
+ font-size: 10px;
234
+ font-weight: 600;
235
+ line-height: 1.35;
236
+ letter-spacing: 0.04em;
237
+ text-transform: uppercase;
238
+ white-space: nowrap;
239
+ }
240
+
241
+ .badge-unusual {
242
+ color: var(--report-severity-unusual);
243
+ background: #f4eeec;
244
+ border-color: #d9c0bb;
245
+ }
246
+
247
+ .badge-notable {
248
+ color: var(--report-severity-notable);
249
+ background: #f5f0e6;
250
+ border-color: #ddcfb5;
251
+ }
252
+
253
+ .badge-info {
254
+ color: var(--report-severity-info);
255
+ background: #eef4f8;
256
+ border-color: #cfdae4;
257
+ }
258
+
259
+ .footer {
260
+ margin-top: 14px;
261
+ padding-top: 10px;
262
+ border-top: 1px solid var(--report-line);
263
+ color: var(--report-muted);
264
+ font-size: 11px;
265
+ }
266
+
267
+ @media print {
268
+ @page {
269
+ margin: 10mm 8mm 12mm;
270
+ }
271
+
272
+ body {
273
+ -webkit-print-color-adjust: exact;
274
+ print-color-adjust: exact;
275
+ }
276
+
277
+ .report {
278
+ max-width: none;
279
+ padding: 0;
280
+ }
281
+
282
+ section.report-section,
283
+ tr {
284
+ break-inside: avoid;
285
+ page-break-inside: avoid;
286
+ }
287
+
288
+ thead {
289
+ display: table-header-group;
290
+ }
291
+
292
+ .report-header {
293
+ padding-bottom: 8px;
294
+ margin-bottom: 12px;
295
+ }
296
+
297
+ .footer {
298
+ margin-top: 10px;
299
+ }
300
+ }
301
+ `}
@@ -0,0 +1,24 @@
1
+ import type { Die } from '../core/dies.js';
2
+ export interface ScatterPoint {
3
+ x: number;
4
+ y: number;
5
+ hbin: number | undefined;
6
+ /** Facet group this point belongs to — set only by the grouped builder. */
7
+ group?: string;
8
+ }
9
+ export interface ScatterItem {
10
+ dies?: Die[];
11
+ }
12
+ /** One point per die with valid values for both tests, across `items`. */
13
+ export declare function buildScatterData(items: ScatterItem[], xTest: number, yTest: number): ScatterPoint[];
14
+ /**
15
+ * Scatter points tagged with their facet group, for colour-by-group scatter
16
+ * (group replaces hard-bin colour). Unlike capability/boxplot's `groups`
17
+ * (which restrict to one group at a time), every group's points are
18
+ * returned together here — scatter never restricts, it colours.
19
+ */
20
+ export declare function buildScatterDataGrouped(groups: {
21
+ key: string;
22
+ items: ScatterItem[];
23
+ }[], xTest: number, yTest: number): ScatterPoint[];
24
+ //# sourceMappingURL=scatter.d.ts.map
@@ -0,0 +1 @@
1
+ function u(i,o,s,t,n){for(const e of i??[]){const f=e.testValues?.[o],r=e.testValues?.[s];f!==void 0&&r!==void 0&&Number.isFinite(f)&&Number.isFinite(r)&&n.push(t===void 0?{x:f,y:r,hbin:e.hbin}:{x:f,y:r,hbin:e.hbin,group:t})}}export function buildScatterData(i,o,s){const t=[];for(const n of i)u(n.dies,o,s,void 0,t);return t}export function buildScatterDataGrouped(i,o,s){const t=[];for(const n of i)for(const e of n.items)u(e.dies,o,s,n.key,t);return t}
@@ -0,0 +1,269 @@
1
+ import type { WaferMapInput, WaferMapResult } from '../renderer/buildWaferMap.js';
2
+ export type StatsSeverity = 'info' | 'notable' | 'unusual';
3
+ export type StatsLevel = 'wafer' | 'lot' | 'inter-wafer';
4
+ export type StatsVariableKind = 'yield' | 'hardBin' | 'softBin' | 'test' | 'functionalTest' | 'spatialPattern';
5
+ export type StatsComparisonFamily = 'ring' | 'quadrant' | 'reticle-position' | 'test-site' | 'wafer' | 'sector' | 'cluster' | 'edge-arc' | 'spatial-pattern';
6
+ export interface HighlightRegionTarget {
7
+ kind: 'region';
8
+ regionFamily: 'ring' | 'quadrant' | 'reticle-position' | 'test-site' | 'sector';
9
+ /**
10
+ * Provenance only — the region keys this finding covers, e.g. `["ring:1", "ring:2"]`
11
+ * (a merged band lists several). Not used for rendering: the built-in highlight draws
12
+ * per-die rectangles from {@link dieKeys}. Exposed so callers can group or filter findings
13
+ * by region without re-parsing the label, and read by the adjacent-finding merge pass.
14
+ * Same field name and meaning as {@link HighlightBinTarget.regionKeys}.
15
+ */
16
+ regionKeys: string[];
17
+ /** The dies to highlight — what the renderer actually draws. */
18
+ dieKeys?: string[];
19
+ }
20
+ export interface HighlightBinTarget {
21
+ kind: 'bin';
22
+ bin: number;
23
+ /** Provenance only — see {@link HighlightRegionTarget.regionKeys}. The renderer draws from {@link dieKeys}. */
24
+ regionKeys?: string[];
25
+ /** The dies to highlight — what the renderer actually draws. */
26
+ dieKeys?: string[];
27
+ }
28
+ export interface HighlightWaferTarget {
29
+ kind: 'wafer';
30
+ waferIndices: number[];
31
+ }
32
+ export interface HighlightDieTarget {
33
+ kind: 'dies';
34
+ dieKeys: string[];
35
+ }
36
+ export type HighlightTarget = HighlightRegionTarget | HighlightBinTarget | HighlightWaferTarget | HighlightDieTarget;
37
+ export interface StatsFinding {
38
+ id: string;
39
+ level: StatsLevel;
40
+ severity: StatsSeverity;
41
+ variable: {
42
+ kind: StatsVariableKind;
43
+ index?: number;
44
+ bin?: number;
45
+ label: string;
46
+ unit?: string;
47
+ };
48
+ comparison: {
49
+ family: StatsComparisonFamily;
50
+ left: string;
51
+ right: string;
52
+ };
53
+ effect: {
54
+ direction: 'higher' | 'lower' | 'different';
55
+ absoluteDelta?: number;
56
+ relativeDelta?: number;
57
+ effectSize?: number;
58
+ };
59
+ stats: {
60
+ method: string;
61
+ pValue?: number;
62
+ adjustedPValue?: number;
63
+ sampleSizeLeft: number;
64
+ sampleSizeRight: number;
65
+ };
66
+ summary: string;
67
+ highlight: HighlightTarget;
68
+ /** IDs of other findings that describe the same signal at a finer level of detail. */
69
+ relatedIds?: string[];
70
+ }
71
+ export interface StatsSummary {
72
+ level: 'wafer';
73
+ hasNotableFindings: boolean;
74
+ findings: StatsFinding[];
75
+ /** Free-form identity fields from waferConfig.metadata (lot, wafer ID, test date, etc.). */
76
+ wafer?: Record<string, unknown>;
77
+ /** Engine-computed analysis stats for this wafer. */
78
+ stats: {
79
+ totalDies: number;
80
+ analyzedDies: number;
81
+ excludedDies: number;
82
+ /** `(passDies / totalDies) × 100` in [0, 100], or `null` when no bin data is present. */
83
+ yieldPercent: number | null;
84
+ testsConsidered: number[];
85
+ hardBinsConsidered: number[];
86
+ softBinsConsidered: number[];
87
+ /**
88
+ * Die counts per hard/soft bin, keyed by bin code, over the same
89
+ * yield-eligible population `YieldSummary`/`buildBinParetoData` use
90
+ * (`isYieldEligibleDie` — excludes `partial`/`edgeExcluded` dies).
91
+ * Unlike `hardBinsConsidered`/`softBinsConsidered` (which list every bin
92
+ * code that appears anywhere, eligible or not), these are the actual
93
+ * counts a bin-breakdown display should show. Consumed by
94
+ * `buildBinParetoData`/`buildBinClusterData` and the summary panel's bin
95
+ * section when supplied, instead of each independently re-walking dies.
96
+ */
97
+ hardBinCounts?: Record<number, number>;
98
+ softBinCounts?: Record<number, number>;
99
+ /** Structured warnings emitted during analysis (e.g. test-count cap exceeded). */
100
+ warnings?: string[];
101
+ /** True when this summary was produced from lot-aggregated data (lotStack). */
102
+ isLotStack?: boolean;
103
+ /** Aggregation method used to produce the lot-stack (e.g. 'mean', 'countBin'). Present only when isLotStack is true. */
104
+ aggregationMethod?: string;
105
+ /** Number of wafers in the lot stack. Present only when isLotStack is true. */
106
+ lotSize?: number;
107
+ /**
108
+ * Per-test spec yield for each test that has at least one limit defined.
109
+ * Only populated when testDefs with limitLow/limitHigh are provided.
110
+ */
111
+ testSpecYield?: Array<{
112
+ testNumber: number;
113
+ label: string;
114
+ passDies: number;
115
+ failLowDies: number;
116
+ failHighDies: number;
117
+ totalDies: number;
118
+ /** `(passDies / totalDies) × 100` in [0, 100], or `null` when no dies had this test. */
119
+ yieldPercent: number | null;
120
+ }>;
121
+ /**
122
+ * Per-test pass rate for each functional (`testType: 'F'`) test — "functional
123
+ * yield" in fab terms. Verdicts are read via `getTestPassStatus` (recorded
124
+ * `testPass` first, then the legacy 0/1 `testValues` fallback). The
125
+ * denominator is dies with a recorded verdict for the test — partial and
126
+ * edge-excluded dies are excluded, dies never tested are not counted as fails.
127
+ * Only populated when functional testDefs are provided.
128
+ */
129
+ functionalYield?: Array<{
130
+ testNumber: number;
131
+ label: string;
132
+ passDies: number;
133
+ failDies: number;
134
+ /** Dies with a recorded pass/fail verdict for this test. */
135
+ totalDies: number;
136
+ /** `(passDies / totalDies) × 100` in [0, 100], or `null` when no dies had a verdict. */
137
+ passRatePercent: number | null;
138
+ }>;
139
+ /**
140
+ * Descriptive statistics for each test's values across all eligible dies.
141
+ * Only populated when `computePerTestStats` or `enableTestValueAnalysis` is
142
+ * true and the test count is within the cap.
143
+ */
144
+ perTestStats?: Array<{
145
+ testNumber: number;
146
+ label: string;
147
+ count: number;
148
+ min: number;
149
+ max: number;
150
+ mean: number;
151
+ stddev: number;
152
+ median: number;
153
+ q1: number;
154
+ q3: number;
155
+ }>;
156
+ };
157
+ }
158
+ export interface LotStatsSummary {
159
+ level: 'lot';
160
+ hasNotableFindings: boolean;
161
+ findings: StatsFinding[];
162
+ /** Free-form lot-level identity fields (lot ID, product, etc. — wafer-specific keys excluded). */
163
+ lot?: Record<string, unknown>;
164
+ /** Engine-computed analysis stats for this lot. */
165
+ stats: {
166
+ waferCount: number;
167
+ };
168
+ /** Per-wafer yield as a flat series, ordered by waferIndex. `yieldPercent` is in [0, 100]; null when a wafer had no bin data. */
169
+ lotYieldSeries: Array<{
170
+ waferIndex: number;
171
+ yieldPercent: number | null;
172
+ }>;
173
+ perWafer: Array<{
174
+ waferIndex: number;
175
+ summary: StatsSummary;
176
+ }>;
177
+ /**
178
+ * Per-wafer × per-test descriptive statistics, for box-plot rendering.
179
+ * Only populated when `computePerTestStats` or `enableTestValueAnalysis` is
180
+ * true and at least one wafer has test data. Prefer `computePerTestStats` for
181
+ * box plots — it skips the expensive regional Welch pass.
182
+ * Each entry's `tests` array has the same shape as `StatsSummary.stats.perTestStats`.
183
+ */
184
+ perWaferTestStats?: Array<{
185
+ waferIndex: number;
186
+ tests: Array<{
187
+ testNumber: number;
188
+ label: string;
189
+ count: number;
190
+ min: number;
191
+ max: number;
192
+ mean: number;
193
+ stddev: number;
194
+ median: number;
195
+ q1: number;
196
+ q3: number;
197
+ }>;
198
+ }>;
199
+ }
200
+ export interface AnalyzeWaferMapOptions {
201
+ /**
202
+ * Should mirror the ring count used by the renderer for consistent semantics.
203
+ * Defaults to 4, which matches the current render default.
204
+ */
205
+ ringCount?: number;
206
+ passBins?: number[];
207
+ significanceLevel?: number;
208
+ minimumEffectSize?: number;
209
+ /**
210
+ * Minimum relative effect size (|delta / background|) for proportion findings.
211
+ * Catches meaningful signals on low-failure-rate wafers where the absolute delta
212
+ * is small but the relative deviation is large. Default 1.0 (100% of background).
213
+ */
214
+ minimumRelativeEffect?: number;
215
+ includePartial?: boolean;
216
+ includeEdgeExcluded?: boolean;
217
+ enableYieldAnalysis?: boolean;
218
+ enableHardBinAnalysis?: boolean;
219
+ enableSoftBinAnalysis?: boolean;
220
+ /**
221
+ * Full parametric **spatial significance** analysis: Welch comparisons of each
222
+ * test's values between every region (ring/quadrant/reticle/site/sector) and
223
+ * the rest of the wafer, plus spec-limit region findings. This is the expensive
224
+ * pass — it scales with (regions × tests × dies) — so it is **off by default**.
225
+ * Enable it only when you display the resulting regional test-value findings.
226
+ *
227
+ * For per-test descriptive statistics (mean/stddev/quartiles for box plots)
228
+ * **without** the spatial comparisons, use {@link computePerTestStats} instead —
229
+ * it is an order of magnitude cheaper. Enabling `enableTestValueAnalysis` also
230
+ * produces `perTestStats`, so you do not need both.
231
+ */
232
+ enableTestValueAnalysis?: boolean;
233
+ /**
234
+ * Compute per-test descriptive statistics (`count`, `min`, `max`, `mean`,
235
+ * `stddev`, `median`, `q1`, `q3`) into `StatsSummary.stats.perTestStats` —
236
+ * the cheap quartile scan only, **without** the expensive regional Welch
237
+ * comparisons of {@link enableTestValueAnalysis}. Use this for box-plot /
238
+ * histogram panels that need distribution shape but not spatial findings.
239
+ * Off by default. Implied by `enableTestValueAnalysis`.
240
+ */
241
+ computePerTestStats?: boolean;
242
+ enableReticlePositionAnalysis?: boolean;
243
+ /**
244
+ * Analyse yield and bin distributions by test site (`siteNum`).
245
+ * Enabled automatically when the wafer contains meaningful site duplication
246
+ * (at least 2 distinct site numbers each appearing on 3 or more dies).
247
+ * Set to `false` to suppress, or `true` to force-enable regardless of the guard.
248
+ */
249
+ enableTestSiteAnalysis?: boolean;
250
+ /** Detect contiguous failure clusters and edge arc damage. Default true. */
251
+ enableClusterAnalysis?: boolean;
252
+ /** Angular sector analysis (finer-grained than quadrants). Default true. */
253
+ enableAngularAnalysis?: boolean;
254
+ /** Number of angular sectors for sector analysis. Must be 4, 8, 16, or 32. Default 8. */
255
+ sectorCount?: number;
256
+ /** Classify the spatial failure pattern (center, edge-ring, scratch, etc.). Default true. */
257
+ enablePatternClassification?: boolean;
258
+ /**
259
+ * Restrict test value analysis to a specific subset of test numbers.
260
+ * When omitted and more than 250 tests are present in the data, test value
261
+ * analysis is skipped automatically with a console warning — pass this option
262
+ * to analyse a specific subset in that case.
263
+ * Example: `testNumbers: [1050, 1060, 1070]`
264
+ */
265
+ testNumbers?: number[];
266
+ }
267
+ export type AnalyzeWaferMapInput = WaferMapInput | WaferMapResult;
268
+ export type AnalyzeWaferLotInput = Array<WaferMapInput | WaferMapResult>;
269
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ export{};
@@ -0,0 +1,56 @@
1
+ import type { Die } from '../core/dies.js';
2
+ /** Shared row shape for every bar-chart panel (yield, bin pareto, ...). */
3
+ export interface ChartDatum {
4
+ label: string;
5
+ value: number;
6
+ percent: number;
7
+ /** Number of items (wafers) pooled into this row — >1 marks a drillable group row. */
8
+ itemCount: number;
9
+ /** Bin code this datum represents — only set for bin-pareto data. */
10
+ binCode?: number;
11
+ /**
12
+ * Stable identity for a leaf row (`itemCount === 1`), independent of
13
+ * `label` — a caller with an `onOpen` callback should resolve back to its
14
+ * own item by `key`, not by re-searching for `label`. Labels are only
15
+ * guaranteed unique when the caller supplies one per item; an item with no
16
+ * `label` falls back to a shared default elsewhere (e.g. `analysisTab.ts`
17
+ * falls back to `''` when both `label` and `wafer.metadata.waferId` are
18
+ * absent), so two rows can carry an identical, ambiguous label — matching
19
+ * on it would silently resolve to the wrong item. Absent on group rows
20
+ * (`itemCount > 1`), which are drilled into rather than opened directly.
21
+ */
22
+ key?: string | number;
23
+ }
24
+ export interface YieldItem {
25
+ label?: string;
26
+ dies?: Die[];
27
+ /**
28
+ * Precomputed yield percent for this item (e.g. from `analyzeWaferLot`'s
29
+ * `lotYieldSeries[waferIndex].yieldPercent`) — used directly when present.
30
+ * Omit to have it computed from `dies` instead.
31
+ */
32
+ yieldPercent?: number | null;
33
+ /** Carried through to the resulting `ChartDatum.key` unchanged — see its doc comment. */
34
+ key?: string | number;
35
+ }
36
+ export type YieldSortBy = 'yield' | 'label';
37
+ /** One bar per item. */
38
+ export declare function buildYieldData(items: YieldItem[], passBins?: number[], sortBy?: YieldSortBy): ChartDatum[];
39
+ /**
40
+ * Combined yield: one bar per group, pooling the group's items. The pooled
41
+ * yield is the yield-eligible-die-count-weighted mean of per-item yields —
42
+ * exact for the standard pass/total definition (Σ pass / Σ total =
43
+ * Σ(yield·dies)/Σ dies), *provided* `dies` is the same population the rate
44
+ * was computed over. Weighting uses `yieldEligibleDieCount` (excludes
45
+ * partial/edge-excluded dies), not raw `dies.length` — a per-item
46
+ * `yieldPercent` (own or precomputed, e.g. from `analyzeWaferLot`) already
47
+ * excludes those dies from its own numerator/denominator (`resolveYieldPercent`
48
+ * → `isYieldEligibleDie`), so weighting by the raw count would let a wafer's
49
+ * excluded dies (which count toward yield nowhere else) still skew this
50
+ * combined bar.
51
+ */
52
+ export declare function buildYieldDataCombined(groups: {
53
+ key: string;
54
+ items: YieldItem[];
55
+ }[], passBins?: number[], sortBy?: YieldSortBy): ChartDatum[];
56
+ //# sourceMappingURL=yield.d.ts.map
@@ -0,0 +1 @@
1
+ import{isYieldEligibleDie as d}from"../core/dies.js";import{compareNatural as b}from"../core/utils.js";function p(e,n){let i=0,t=0;for(const l of e){if(!d(l))continue;const o=l.hbin??l.sbin;o!==void 0&&(t++,n.includes(o)&&i++)}return t>0?i/t*100:0}function s(e,n){return e.yieldPercent!==void 0?e.yieldPercent??0:p(e.dies??[],n)}function m(e){let n=0;for(const i of e)d(i)&&n++;return n}function f(e,n){n==="yield"?e.sort((i,t)=>t.value-i.value):e.sort((i,t)=>b(i.label,t.label))}export function buildYieldData(e,n=[1],i="label"){const t=e.map((l,o)=>{const r=s(l,n);return{label:l.label??`#${o}`,value:r,percent:r,itemCount:1,key:l.key}});return f(t,i),t}export function buildYieldDataCombined(e,n=[1],i="label"){const t=e.map(l=>{let o=0,r=0;for(const c of l.items){const a=m(c.dies??[]);o+=s(c,n)*a,r+=a}const u=r>0?o/r:0;return{label:l.key,value:u,percent:u,itemCount:l.items.length}});return f(t,i),t}