Skip to content

Commit 11118d1

Browse files
author
Ritika Mishra
committed
updated plotting logic
1 parent 7fcbec5 commit 11118d1

File tree

1 file changed

+63
-54
lines changed

1 file changed

+63
-54
lines changed

src/app/serial-plotter/page.tsx

Lines changed: 63 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ const SerialPlotter = () => {
2020
const [isConnected, setIsConnected] = useState(false);
2121
const [rawData, setRawData] = useState<string>("");
2222
const [selectedChannels, setSelectedChannels] = useState<number[]>(Array.from({ length: maxChannels }, (_, i) => i));
23-
const [showCombined, setShowCombined] = useState(true);
2423
const selectedChannelsRef = useRef<number[]>([]);
2524
const rawDataRef = useRef<HTMLDivElement | null>(null);
2625
const maxPoints = 1000;
@@ -36,6 +35,8 @@ const SerialPlotter = () => {
3635
const channelsref = useRef<number>(1);
3736
const sweepPositions = useRef<number[]>(new Array(channelsref.current).fill(0)); // Array for sweep positions
3837

38+
const dataRef = useRef<DataPoint[]>([]);
39+
3940
useEffect(() => {
4041
if (rawDataRef.current) {
4142
rawDataRef.current.scrollTop = rawDataRef.current.scrollHeight;
@@ -70,32 +71,49 @@ const SerialPlotter = () => {
7071

7172
useEffect(() => {
7273
if (!canvasRef.current) return;
73-
7474
const canvas = canvasRef.current;
7575
canvas.width = canvas.clientWidth;
7676
canvas.height = canvas.clientHeight;
7777

78-
if (viewMode === "both" || viewMode === "plotter") {
79-
const wglp = new WebglPlot(canvas);
80-
wglpRef.current = wglp;
78+
// Only (re)initialize if viewMode or selectedChannels change
79+
const wglp = new WebglPlot(canvas);
80+
wglpRef.current = wglp;
81+
linesRef.current = [];
8182

82-
// Clear and re-add lines
83-
linesRef.current = [];
83+
selectedChannels.forEach((_, i) => {
84+
const line = new WebglLine(getLineColor(i), maxPoints);
85+
line.lineSpaceX(-1, 2 / maxPoints);
86+
wglp.addLine(line);
87+
linesRef.current.push(line);
88+
});
89+
// You can call wglp.update() here once for the initial setup.
90+
wglp.update();
91+
}, [selectedChannels, viewMode, isConnected]); // Remove data from dependencies if you handle data updates elsewhere
8492

85-
selectedChannels.forEach((_, i) => {
86-
const line = new WebglLine(getLineColor(i), maxPoints);
87-
line.lineSpaceX(-1, 2 / maxPoints);
88-
wglp.addLine(line);
89-
linesRef.current.push(line);
90-
});
93+
useEffect(() => {
94+
if (data.length === 0) return;
9195

92-
// Re-plot existing data
93-
updateWebGLPlot(data); // Ensure existing data is plotted
94-
wglp.update();
96+
// Calculate autoscale on the entire data state
97+
const allValues = data.flatMap(dp => dp.values);
98+
const MIN_POINTS_FOR_SCALING = 10;
99+
let yMin, yMax;
100+
101+
if (allValues.length < MIN_POINTS_FOR_SCALING) {
102+
yMin = -1;
103+
yMax = 1;
95104
} else {
96-
wglpRef.current = null; // Reset the WebGL plot reference when hiding
105+
yMin = Math.min(...allValues);
106+
yMax = Math.max(...allValues);
97107
}
98-
}, [selectedChannels, showCombined, data, viewMode]); // Include viewMode in dependencies
108+
const yRange = yMax - yMin || 1;
109+
110+
// Optionally, update all current lines with the new scale
111+
linesRef.current.forEach((line, i) => {
112+
113+
});
114+
}, [data]);
115+
116+
99117

100118
const getLineColor = (index: number): ColorRGBA => {
101119
const hex = channelColors[index % channelColors.length];
@@ -193,9 +211,12 @@ const SerialPlotter = () => {
193211
});
194212

195213
if (newData.length > 0) {
196-
updateWebGLPlot(newData);
197-
setData((prev) => [...prev, ...newData].slice(-maxPoints));
214+
// Update the ref synchronously
215+
dataRef.current = [...dataRef.current, ...newData].slice(-maxPoints);
216+
updateWebGLPlot(newData, dataRef.current);
217+
setData(dataRef.current);
198218
}
219+
199220
}
200221
}
201222
serialReader.releaseLock();
@@ -241,61 +262,49 @@ const SerialPlotter = () => {
241262
return () => clearInterval(interval);
242263
}, [port]);
243264

244-
const updateWebGLPlot = (newData: DataPoint[]) => {
265+
const updateWebGLPlot = (newData: DataPoint[], windowData: DataPoint[]) => {
245266
if (!wglpRef.current || linesRef.current.length === 0 || newData.length === 0) return;
246-
// Calculate Y-axis min and max values
247-
const yMin = Math.min(...newData.flatMap(dp => dp.values));
248-
const yMax = Math.max(...newData.flatMap(dp => dp.values));
249-
const yRange = yMax - yMin || 1; // Avoid division by zero
250-
251-
// Iterate over new data points and update plots
252-
newData.forEach((dataPoint) => {
253-
linesRef.current.forEach((line, i) => {
254267

255-
if (i >= dataPoint.values.length) return; // Prevent out-of-bounds errors
268+
// Use the entire window for autoscaling
269+
const allValues = windowData.flatMap(dp => dp.values);
270+
const MIN_POINTS_FOR_SCALING = 10;
271+
let yMin, yMax;
256272

257-
// Clamp Y-value to be within -1 and 1
258-
const yValue = Math.max(-1, Math.min(1, ((dataPoint.values[i] - yMin) / yRange) * 2 - 1));
259-
260-
// Update combined plot
261-
// Ensure sweepPositions.current[i] is initialized
262-
if (sweepPositions.current[i] === undefined) {
263-
sweepPositions.current[i] = 0;
264-
}
273+
if (allValues.length < MIN_POINTS_FOR_SCALING) {
274+
yMin = -1;
275+
yMax = 1;
276+
} else {
277+
yMin = Math.min(...allValues);
278+
yMax = Math.max(...allValues);
279+
}
280+
const yRange = yMax - yMin || 1;
265281

282+
newData.forEach((dataPoint) => {
283+
linesRef.current.forEach((line, i) => {
284+
if (i >= dataPoint.values.length) return;
285+
const yValue = ((dataPoint.values[i] - yMin) / yRange) * 2 - 1;
266286
const currentPos = sweepPositions.current[i] % line.numPoints;
267-
if (Number.isNaN(currentPos)) {
268-
console.error(`Invalid currentPos at i ${i}. sweepPositions.current[i]:`, sweepPositions.current[i]);
269-
return;
270-
}
271-
272-
if (line) {
273-
try {
274-
line.setY(currentPos, yValue);
275-
} catch (error) {
276-
console.error(`Error plotting data for line ${i} at position ${currentPos}:`, error);
277-
}
278-
287+
try {
288+
line.setY(currentPos, yValue);
289+
} catch (error) {
290+
console.error(`Error plotting data for line ${i} at position ${currentPos}:`, error);
279291
}
280-
// Clear the next point for visual effect
281292
const clearPosition = Math.ceil((currentPos + maxPoints / 100) % line.numPoints);
282293
try {
283294
line.setY(clearPosition, NaN);
284295
} catch (error) {
285296
console.error(`Error clearing data at position ${clearPosition} for line ${i}:`, error);
286297
}
287-
288-
// Increment the sweep position
289298
sweepPositions.current[i] = (currentPos + 1) % line.numPoints;
290299
});
291300
});
292301

293-
// Efficiently trigger a render update
294302
requestAnimationFrame(() => {
295303
if (wglpRef.current) wglpRef.current.update();
296304
});
297305
};
298306

307+
299308
const disconnectSerial = async () => {
300309
if (reader) {
301310
await reader.cancel();

0 commit comments

Comments
 (0)