Semiconductors Dashboard

Creates a Semiconductors Dashboard using SciChart.js, by leveraging the FastRectangleRenderableSeries, and its customTextureOptions property to have a custom tiling texture fill.

Fullscreen

Edit

 Edit

Docs

index.tsx

RandomWalkGenerator.ts

theme.ts

columnChart.ts

lineChart.ts

paretoChart.ts

styles.css

waferData.ts

waferGrid.ts

Copy to clipboard
Minimise
Fullscreen
1import { IPointMetadata } from "scichart";
2
3// Define quality categories as a union type for type safety
4export type WaferQuality = "Good" | "Marginal" | "Fail";
5
6// Constants for measurement parameters
7const MEASUREMENT_PARAMS = {
8    INPUT1: { mean: 1100, stdDev: 20 }, // temperature (°C)
9    INPUT2: { mean: 500, stdDev: 150 }, // flow rate (units)
10    MEASURE1: { mean: 100, stdDev: 5 }, // thickness (nm)
11    MEASURE2: { mean: 50, stdDev: 3 }, // width (nm)
12    MEASURE3: { mean: 10, stdDev: 1 }, // resistance (Ω/□)
13};
14
15// Time constants in milliseconds
16const MS_PER_DAY = 24 * 60 * 60 * 1000;
17
18export interface WaferLotData extends IPointMetadata {
19    isSelected: boolean;
20    Date: string; // Timestamp of the run/lot/batch (ISO format)
21    Batch: number; // Processing group (1-10)
22    Quality: WaferQuality; // Categorical: 'Good', 'Marginal', or 'Fail'
23    Input1: number; // Process input variable (e.g., furnace temperature setpoint)
24    Input2: number; // Another process input (e.g., gas flow rate)
25    Measure1: number; // Output measurement (e.g., film thickness in nm)
26    Measure2: number; // Output measurement (e.g., line width in nm)
27    Measure3: number; // Output measurement (e.g., sheet resistance in Ω/sq)
28}
29
30export interface WaferDayData {
31    Date: string; // Timestamp of the run/lot/batch (ISO format)
32    Mean1: number;
33    Mean2: number;
34    Batches: WaferLotData[];
35}
36
37/**
38 * Generates a value from an approximate normal distribution
39 * Uses Box-Muller transform for better statistical properties
40 * @param mean Mean value of the distribution
41 * @param stdDev Standard deviation of the distribution
42 * @returns Random value from the normal distribution
43 */
44function randomNormal(mean: number, stdDev: number): number {
45    // Box-Muller transform for better normal distribution approximation
46    const u1 = Math.random();
47    const u2 = Math.random();
48
49    // Guard against u1 being zero
50    if (u1 === 0) return randomNormal(mean, stdDev);
51
52    const z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);
53    return mean + z0 * stdDev;
54}
55
56/**
57 * Determines wafer quality based on predefined distribution
58 * 70% Good, 20% Marginal, 10% Fail
59 * @returns Quality category as a string
60 */
61function getQuality(input: number): WaferQuality {
62    if (input > 500) return "Good";
63    if (input > 350) return "Marginal";
64    return "Fail";
65}
66
67/**
68 * Formats a number to a specified precision without string conversion overhead
69 * @param value Number to format
70 * @param precision Decimal places to keep
71 * @returns Formatted number
72 */
73function formatNumber(value: number, precision: number = 2): number {
74    const factor = Math.pow(10, precision);
75    return Math.round(value * factor) / factor;
76}
77
78/**
79 * Generates an array of mock wafer data entries based on the specified structure.
80 * Includes improved error handling, performance optimizations, and better type safety.
81 *
82 * @param numDays Number of data entries to generate
83 * @param startDate Optional starting date (defaults to current date)
84 * @returns Array of WaferLotData objects
85 * @throws Error if numEntries is invalid
86 */
87export function generateWaferLotData(
88    numDays: number,
89    numBatches: number = 15,
90    startDate: Date = new Date()
91): WaferDayData[] {
92    // Validate inputs
93    if (!Number.isInteger(numDays) || numDays <= 0) {
94        throw new Error("numEntries must be a positive integer");
95    }
96
97    if (!(startDate instanceof Date) || isNaN(startDate.getTime())) {
98        throw new Error("startDate must be a valid Date object");
99    }
100
101    const data: WaferDayData[] = [];
102    const startTime = startDate.getTime();
103
104    for (let i = 0; i < numDays; i++) {
105        // Generate date: increment by days for temporal trends
106        const date = new Date(startTime + i * MS_PER_DAY);
107        const isoDate = date.toISOString().split("T")[0]; // YYYY-MM-DD format
108        const Batches: WaferLotData[] = [];
109        let total1 = 0;
110        let total2 = 0;
111        for (let b = 1; b <= numBatches; b++) {
112            const input2 = Math.round(randomNormal(MEASUREMENT_PARAMS.INPUT2.mean, MEASUREMENT_PARAMS.INPUT2.stdDev));
113            // Generate measurements using our helper functions
114            const batch = {
115                isSelected: false,
116                Date: isoDate,
117                Batch: b,
118                Quality: getQuality(input2),
119                Input1: Math.round(randomNormal(MEASUREMENT_PARAMS.INPUT1.mean, MEASUREMENT_PARAMS.INPUT1.stdDev)),
120                Input2: input2,
121                Measure1: formatNumber(randomNormal(input2, MEASUREMENT_PARAMS.MEASURE1.stdDev)),
122                Measure2: formatNumber(randomNormal(input2, MEASUREMENT_PARAMS.MEASURE2.stdDev)),
123                Measure3: formatNumber(randomNormal(input2, MEASUREMENT_PARAMS.MEASURE3.stdDev)),
124            };
125            Batches.push(batch);
126            total1 += batch.Input1;
127            total2 += batch.Input2;
128        }
129        data.push({
130            Date: isoDate,
131            Mean1: total1 / numBatches,
132            Mean2: total2 / numBatches,
133            Batches,
134        } as WaferDayData);
135    }
136
137    return data;
138}
139
140// Simple seeded random generator (LCG)
141function seededRandom(seed: number) {
142    let value = seed % 2147483647;
143    return () => {
144        value = (value * 48271) % 2147483647;
145        return (value - 1) / 2147483646;
146    };
147}
148
149// Simple hashCode for string/number seed generation
150function hashCode(obj: any, subChartIndex: number) {
151    const str = typeof obj === "string" ? obj : JSON.stringify(obj);
152    let hash = 0;
153    for (let i = 0; i < str.length; i++) {
154        hash = (Math.imul(31, hash) + str.charCodeAt(i)) | 0;
155    }
156
157    let result = Math.abs(hash) + subChartIndex;
158
159    return result;
160}
161
162export const generateGridOfPoints = (selectedPoint: WaferLotData, subChartIndex = 0) => {
163    const waferSize = 41;
164    const seed = hashCode(selectedPoint, subChartIndex); // Make seed depend on selectedPoint
165    const random = seededRandom(seed);
166
167    const dataJSON = [];
168
169    for (let row = 0; row < waferSize; row++) {
170        for (let col = 0; col < waferSize; col++) {
171            const centerX = waferSize / 2;
172            const centerY = waferSize / 2;
173            const distance = Math.sqrt(Math.pow(col - centerX, 2) + Math.pow(row - centerY, 2));
174
175            if (distance <= waferSize / 2) {
176                let defectType = "OK";
177
178                // Calculate defect probability inversely related to Input2
179                // Lower Input2 values result in higher defect probability
180                // Normalize Input2 to a 0-1 range based on expected range (200-800)
181                const normalizedInput2 = Math.max(0, Math.min(1, (selectedPoint.Input2 - 200) / 600));
182
183                // Invert the relationship: lower Input2 -> higher defect probability
184                const defectProbabilityMultiplier = 1 - normalizedInput2;
185
186                // Use seeded random with inverse relationship to Input2
187                const randomValue = random();
188
189                // Adjust thresholds based on Input2 - lower Input2 increases defect likelihood
190                const baseThreshold = defectProbabilityMultiplier * 1.5; // Scale factor for defect probability
191
192                if (distance > waferSize / 5) {
193                    if (randomValue < 0.04 * baseThreshold) defectType = "S48"; // red
194                    else if (randomValue < 0.05 * baseThreshold) defectType = "S36"; // orange
195                } else if (distance < waferSize / 5) {
196                    if (randomValue < 0.03 * baseThreshold) defectType = "S28"; // blue
197                }
198
199                dataJSON.push({
200                    MAP_ROW: row,
201                    MAP_COL: col,
202                    DEFECT: defectType,
203                    MR: (random() - 0.5) * 20,
204                    HR: (random() - 0.5) * 10,
205                    HDI: (random() - 0.5) * 5,
206                    MR2: (random() - 0.5) * 30,
207                });
208            }
209        }
210    }
211
212    return dataJSON;
213};
214

javascript Chart Examples & Demos

See Also: Scientific & Medical Charts (10 Demos)

JavaScript Vital Signs ECG/EKG Medical Demo | SciChart.js

JavaScript Vital Signs ECG/EKG Medical Demo

In this example we are simulating four channels of data showing that SciChart.js can be used to draw real-time ECG/EKG charts and graphs to monitor heart reate, body temperature, blood pressure, pulse rate, SPO2 blood oxygen, volumetric flow and more.

JavaScript Chart with Logarithmic Axis Example | SciChart

JavaScript Chart with Logarithmic Axis Example

Demonstrates Logarithmic Axis on a JavaScript Chart using SciChart.js. SciChart supports logarithmic axis with scientific or engineering notation and positive and negative values

LiDAR 3D Point Cloud of Geospatial Data | SciChart.js

LiDAR 3D Point Cloud of Geospatial Data

Demonstrating the capability of SciChart.js to create JavaScript 3D Point Cloud charts and visualize LiDAR data from the UK Defra Survey.

JavaScript Chart with Vertically Stacked Axes | SciChart

JavaScript Chart with Vertically Stacked Axes

Demonstrates Vertically Stacked Axes on a JavaScript Chart using SciChart.js, allowing data to overlap

Realtime Audio Spectrum Analyzer Chart | SciChart.js Demo

Realtime Audio Spectrum Analyzer Chart Example

See the frequency of recordings with the JavaScript audio spectrum analyzer example from SciChart. This real-time visualizer demo uses a Fourier Transform.

Realtime Audio Analyzer Bars Demo | SciChart.js Demo

Realtime Audio Analyzer Bars Demo

Demonstrating the capability of SciChart.js to create a JavaScript Audio Analyzer Bars and visualize the Fourier-Transform of an audio waveform in realtime.

Interactive Waterfall Chart | Javascript Charts | SciChart.js

Interactive Waterfall Spectral Chart

Demonstrates how to create a Waterfall chart in SciChart.js, showing chromotragraphy data with interactive selection of points.

Interactive Phasor Diagram chart | Javascript Charts | SciChart.js

Phasor Diagram Chart Example

See the JavaScript Phasor Diagram example to combine a Cartesian surface with a Polar subsurface. Get seamless JS integration with SciChart. View demo now.

NEW!
JavaScript Correlation Plot | Javascript Charts | SciChart.js

JavaScript Correlation Plot

Create JavaScript Correlation Plot with high performance SciChart.js. Easily render pre-defined point types. Supports custom shapes. Get your free trial now.

NEW!
Wafer Analysis Chart | JavaScript Charts | SciChart.js

Wafer Analysis Chart

JavaScript **Wafer Analysis Chart** using SciChart.js, by leveraging the **FastRectangleRenderableSeries**, and crossfilter to enable live filtering.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.