Skip to content

Commit 2ec8f9a

Browse files
author
Ritika Mishra
committed
optimizing code
2 parents a4fce1e + b9e37df commit 2ec8f9a

File tree

4 files changed

+1757
-1741
lines changed

4 files changed

+1757
-1741
lines changed

src/components/Canvas.tsx

Lines changed: 84 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import React, {
99
import { useTheme } from "next-themes";
1010
import { BitSelection } from "./DataPass";
1111
import { WebglPlot, ColorRGBA, WebglLine } from "webgl-plot";
12+
import { lightThemeColors, darkThemeColors } from "./Colors";
1213

1314
interface CanvasProps {
1415
pauseRef: React.RefObject<boolean>;
@@ -38,27 +39,31 @@ const Canvas = forwardRef(
3839
}: CanvasProps,
3940
ref
4041
) => {
41-
const { theme } = useTheme(); // Extract theme context
42-
let previousCounter: number | null = null; // Tracks the previous counter value for detecting data loss
42+
const { theme } = useTheme();
43+
let previousCounter: number | null = null; // Variable to store the previous counter value for loss detection
4344
const canvasContainerRef = useRef<HTMLDivElement>(null);
4445
const [numChannels, setNumChannels] = useState<number>(selectedChannels.length);
45-
const dataPointCountRef = useRef<number>(2000); // Ref to track the number of data points per line
46-
const [canvasElements, setCanvasElements] = useState<HTMLCanvasElement[]>([]); // Array of canvas elements
46+
const dataPointCountRef = useRef<number>(2000); // To track the calculated value
47+
const [canvasElements, setCanvasElements] = useState<HTMLCanvasElement[]>([]);
4748
const [wglPlots, setWglPlots] = useState<WebglPlot[]>([]);
4849
const [lines, setLines] = useState<WebglLine[]>([]);
4950
const linesRef = useRef<WebglLine[]>([]);
5051
const [samplingRate, setSamplingRate] = useState<number>(500);
5152
const sweepPositions = useRef<number[]>(new Array(6).fill(0)); // Array for sweep positions
5253
const currentSweepPos = useRef<number[]>(new Array(6).fill(0)); // Array for sweep positions
53-
const array3DRef = useRef<number[][][]>( // 3D buffer array for storing data
54+
const array3DRef = useRef<number[][][]>(
5455
Array.from({ length: 6 }, () =>
5556
Array.from({ length: 6 }, () => Array())
5657
)
5758
);
58-
const selectedChannelsRef = useRef(selectedChannels); // Ref for selected channels
59-
const activeBufferIndexRef = useRef<number>(0); // Ref to track the active buffer index
59+
const selectedChannelsRef = useRef(selectedChannels);
60+
const activeBufferIndexRef = useRef(0); // Initialize useRef with 0
6061
const dataIndicesRef = useRef<number[]>([]); // Ref to store data indices
6162

63+
class ColorRGBA {
64+
constructor(public r: number, public g: number, public b: number, public a: number) { }
65+
}
66+
6267
//select point
6368
const getpoints = useCallback((bits: BitSelection): number => {
6469
switch (bits) {
@@ -118,7 +123,6 @@ const Canvas = forwardRef(
118123
(_, i) => (activeBufferIndexRef.current - i - 1 + 6) % 6
119124
);
120125
};
121-
122126

123127
useEffect(() => {
124128
setNumChannels(selectedChannels.length);
@@ -135,38 +139,31 @@ const Canvas = forwardRef(
135139
ref,
136140
() => ({
137141
updateData(data: number[]) {
138-
const [counter, ...channelData] = data;
139-
140-
// Reset sweep positions if the number of channels changes or when not paused
142+
// Reset the sweep positions if the number of channels has changed
141143
if (currentSweepPos.current.length !== numChannels || !pauseRef.current) {
142-
const resetArray = new Array(numChannels).fill(0);
143-
currentSweepPos.current = resetArray;
144-
sweepPositions.current = resetArray;
144+
currentSweepPos.current = new Array(numChannels).fill(0);
145+
sweepPositions.current = new Array(numChannels).fill(0);
145146
}
146-
147-
// Process and update plots if paused
147+
148148
if (pauseRef.current) {
149149
processIncomingData(data);
150-
updatePlots(channelData, Zoom);
150+
updatePlots(data, Zoom);
151151
}
152-
153-
// Handle counter validation for data loss detection
154152
if (previousCounter !== null) {
155-
const expectedCounter = (previousCounter + 1) % 256;
156-
if (counter !== expectedCounter) {
153+
// If there was a previous counter value
154+
const expectedCounter: number = (previousCounter + 1) % 256; // Calculate the expected counter value
155+
if (data[0] !== expectedCounter) {
156+
// Check for data loss by comparing the current counter with the expected counter
157157
console.warn(
158-
`Data loss detected in canvas! Previous counter: ${previousCounter}, Current counter: ${counter}`
158+
`Data loss detected in canvas! Previous counter: ${previousCounter}, Current counter: ${data[0]}`
159159
);
160160
}
161161
}
162-
163-
// Update the previous counter
164-
previousCounter = counter;
162+
previousCounter = data[0]; // Update the previous counter with the current counter
165163
},
166164
}),
167165
[Zoom, numChannels, timeBase]
168166
);
169-
170167

171168
const createcanvasElements = () => {
172169
const container = canvasContainerRef.current;
@@ -270,106 +267,91 @@ const Canvas = forwardRef(
270267
};
271268

272269
const getLineColor = (i: number, theme: string | undefined): ColorRGBA => {
273-
// Predefine the color arrays for dark and light themes
274-
const colorsDark: ColorRGBA[] = [
275-
new ColorRGBA(180 / 255, 70 / 255, 120 / 255, 1), // Darkened #EC6FAA
276-
new ColorRGBA(150 / 255, 70 / 255, 125 / 255, 1), // Darkened #CE6FAC
277-
new ColorRGBA(130 / 255, 90 / 255, 140 / 255, 1), // Darkened #B47EB7
278-
new ColorRGBA(110 / 255, 110 / 255, 160 / 255, 1), // Darkened #9D8DC4
279-
new ColorRGBA(70 / 255, 100 / 255, 150 / 255, 1), // Darkened #689AD2
280-
new ColorRGBA(40 / 255, 110 / 255, 140 / 255, 1), // Darkened #35A5CC
281-
new ColorRGBA(35 / 255, 120 / 255, 130 / 255, 1), // Darkened #30A8B4
282-
new ColorRGBA(35 / 255, 125 / 255, 120 / 255, 1), // Darkened #32ABA2
283-
284-
];
285-
286-
const colorsLight: ColorRGBA[] = [
287-
new ColorRGBA(236 / 255, 111 / 255, 170 / 255, 0.8), // Slightly transparent #EC6FAA
288-
new ColorRGBA(206 / 255, 111 / 255, 172 / 255, 0.8), // Slightly transparent #CE6FAC
289-
new ColorRGBA(180 / 255, 126 / 255, 183 / 255, 0.8), // Slightly transparent #B47EB7
290-
new ColorRGBA(157 / 255, 141 / 255, 196 / 255, 0.8), // Slightly transparent #9D8DC4
291-
new ColorRGBA(104 / 255, 154 / 255, 210 / 255, 0.8), // Slightly transparent #689AD2
292-
new ColorRGBA(53 / 255, 165 / 255, 204 / 255, 0.8), // Slightly transparent #35A5CC
293-
new ColorRGBA(48 / 255, 168 / 255, 180 / 255, 0.8), // Slightly transparent #30A8B4
294-
new ColorRGBA(50 / 255, 171 / 255, 162 / 255, 0.8), // Slightly transparent #32ABA2
295-
296-
];
297-
298-
// Select the appropriate color array based on the theme
299-
const colors = theme === "dark" ? colorsLight : colorsDark;
300-
301-
// Return the color for the given index, wrapped with modulo for looping
302-
return colors[i % colors.length];
270+
// Get the appropriate colors based on the theme
271+
const colors = theme === "dark" ? darkThemeColors : lightThemeColors;
272+
273+
const hex = colors[i % colors.length];
274+
275+
const r = parseInt(hex.slice(1, 3), 16) / 255;
276+
const g = parseInt(hex.slice(3, 5), 16) / 255;
277+
const b = parseInt(hex.slice(5, 7), 16) / 255;
278+
279+
// Adjust the alpha value based on the theme
280+
const alpha = theme === "dark" ? 1 : 0.8; // Slight transparency for light theme
281+
282+
// Return a ColorRGBA object with adjusted alpha
283+
return new ColorRGBA(r, g, b, alpha);
303284
};
304-
305285

306286
const updatePlots = useCallback(
307287
(data: number[], Zoom: number) => {
288+
// Access the latest selectedChannels via the ref
308289
const currentSelectedChannels = selectedChannelsRef.current;
309-
310-
// Adjust zoom level for each WebglPlot only once per iteration
290+
291+
// Adjust zoom level for each WebglPlot
311292
wglPlots.forEach((wglp, index) => {
312293
if (wglp) {
313294
try {
314295
wglp.gScaleY = Zoom; // Adjust zoom value
315296
} catch (error) {
316-
console.error(`Error setting gScaleY for WebglPlot instance at index ${index}:`, error);
297+
console.error(
298+
`Error setting gScaleY for WebglPlot instance at index ${index}:`,
299+
error
300+
);
317301
}
318302
} else {
319303
console.warn(`WebglPlot instance at index ${index} is undefined.`);
320304
}
321305
});
322-
323-
// Plot each line, with early returns for validation checks
324306
linesRef.current.forEach((line, i) => {
325307
if (!line) {
326308
console.warn(`Line at index ${i} is undefined.`);
327309
return;
328310
}
329-
311+
330312
// Map channel number from selectedChannels
331313
const channelNumber = currentSelectedChannels[i];
332314
if (channelNumber == null || channelNumber < 0 || channelNumber >= data.length) {
333315
console.warn(`Invalid channel number: ${channelNumber}. Skipping.`);
334316
return;
335317
}
336-
318+
337319
const channelData = data[channelNumber];
338-
339-
// Initialize sweepPositions.current[i] if undefined
320+
321+
// Ensure sweepPositions.current[i] is initialized
340322
if (sweepPositions.current[i] === undefined) {
341323
sweepPositions.current[i] = 0;
342324
}
343-
325+
344326
// Calculate the current position
345-
let currentPos = sweepPositions.current[i] % line.numPoints;
327+
const currentPos = sweepPositions.current[i] % line.numPoints;
328+
346329
if (Number.isNaN(currentPos)) {
347330
console.error(`Invalid currentPos at index ${i}. sweepPositions.current[i]:`, sweepPositions.current[i]);
348331
return;
349332
}
350-
333+
351334
// Plot the data
352335
try {
353336
line.setY(currentPos, channelData);
354337
} catch (error) {
355338
console.error(`Error plotting data for line ${i} at position ${currentPos}:`, error);
356339
}
357-
340+
358341
// Clear the next point for visual effect
359342
const clearPosition = Math.ceil((currentPos + dataPointCountRef.current / 100) % line.numPoints);
360343
try {
361344
line.setY(clearPosition, NaN);
362345
} catch (error) {
363346
console.error(`Error clearing data at position ${clearPosition} for line ${i}:`, error);
364347
}
365-
366-
// Increment the sweep position for the next iteration
348+
349+
// Increment the sweep position
367350
sweepPositions.current[i] = (currentPos + 1) % line.numPoints;
368351
});
369352
},
370-
[wglPlots, linesRef, selectedChannelsRef, dataPointCountRef, sweepPositions]
353+
[linesRef, wglPlots, selectedChannelsRef, dataPointCountRef, sweepPositions]
371354
);
372-
373355

374356
useEffect(() => {
375357
createcanvasElements();
@@ -389,52 +371,44 @@ const Canvas = forwardRef(
389371

390372

391373
const updatePlotSnapshot = (currentSnapshot: number) => {
392-
// Access references and validate once to avoid repeated checks
393-
const dataIndices = dataIndicesRef.current;
394-
const array3D = array3DRef.current;
395-
396-
// Early validation to avoid repeated checks inside the loop
397-
if (!dataIndices || !array3D || dataIndices[currentSnapshot] === undefined) {
398-
console.warn("One of the references is undefined or invalid");
399-
return;
400-
}
401-
402-
// Process zoom settings for each WebglPlot only once
403-
wglPlots.forEach((wglp, index) => {
404-
if (wglp) {
405-
try {
406-
wglp.gScaleY = Zoom; // Adjust the zoom value
407-
} catch (error) {
408-
console.error(`Error setting gScaleY for WebglPlot instance at index ${index}:`, error);
409-
}
410-
} else {
411-
console.warn(`WebglPlot instance at index ${index} is undefined.`);
412-
}
413-
});
414-
415-
// Process each canvas (or line) and update
416374
for (let i = 0; i < canvasCount; i++) {
417-
const lineData = array3D[dataIndices[currentSnapshot]];
418-
419-
if (lineData && lineData[i]) {
420-
const yArray = new Float32Array(lineData[i]);
421-
422-
// Ensure line exists before adding data
375+
wglPlots.forEach((wglp, index) => {
376+
if (wglp) {
377+
try {
378+
wglp.gScaleY = Zoom; // Adjust the zoom value
379+
} catch (error) {
380+
console.error(
381+
`Error setting gScaleY for WebglPlot instance at index ${index}:`,
382+
error
383+
);
384+
}
385+
} else {
386+
console.warn(`WebglPlot instance at index ${index} is undefined.`);
387+
}
388+
});
389+
if (
390+
array3DRef.current &&
391+
dataIndicesRef.current &&
392+
dataIndicesRef.current[currentSnapshot] !== undefined &&
393+
array3DRef.current[dataIndicesRef.current[currentSnapshot]] !== undefined
394+
) {
395+
const yArray = new Float32Array(array3DRef.current[dataIndicesRef.current[currentSnapshot]][i]);
396+
// Check if the line exists
423397
const line = linesRef.current[i];
424398
if (line) {
425399
line.shiftAdd(yArray); // Efficiently add new points
426400
} else {
427401
console.error(`Line at index ${i} is undefined or null.`);
428402
}
403+
429404
} else {
430-
console.warn(`No data found for snapshot ${currentSnapshot}, index ${i}.`);
405+
console.warn("One of the references is undefined or invalid");
431406
}
407+
408+
432409
}
433-
434-
// Redraw the plots after all updates
435-
wglPlots.forEach((wglp) => wglp.update());
410+
wglPlots.forEach((wglp) => wglp.update()); // Redraw the plots
436411
};
437-
438412

439413
useEffect(() => {
440414
requestAnimationFrame(animate);
@@ -452,6 +426,7 @@ const Canvas = forwardRef(
452426
};
453427
}, [createcanvasElements]);
454428

429+
455430
return (
456431
<main className=" flex flex-col flex-[1_1_0%] min-h-80 bg-highlight rounded-2xl m-4 relative"
457432
ref={canvasContainerRef}

src/components/Colors.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// colors.ts
2+
export const customColors = {
3+
'custom-1': '#EC6FAA',
4+
'custom-2': '#CE6FAC',
5+
'custom-3': '#B47EB7',
6+
'custom-4': '#9D8DC4',
7+
'custom-5': '#689AD2',
8+
'custom-6': '#35A5CC',
9+
'custom-7': '#30A8B4',
10+
'custom-8': '#32ABA2',
11+
'custom-9': '#2EAD8D',
12+
'custom-10': '#31B068',
13+
'custom-11': '#6CAB43',
14+
'custom-12': '#94A135',
15+
'custom-13': '#B19B31',
16+
'custom-14': '#CC9136',
17+
'custom-15': '#F2793B',
18+
'custom-16': '#F2728B',
19+
};
20+
21+
export const lightThemeColors = Object.values(customColors).map((hex) => {
22+
// Darken the colors more significantly for the light theme
23+
return darkenColor(hex, 0.3); // Stronger darkening for light theme (0.3 instead of 0.1)
24+
});
25+
26+
export const darkThemeColors = Object.values(customColors).map((hex) => {
27+
// Lighten the colors slightly for the dark theme
28+
return lightenColor(hex, 0.1); // Lightening for dark theme
29+
});
30+
31+
// Function to darken a color
32+
function darkenColor(hex: string, amount: number): string {
33+
return adjustColor(hex, -amount); // Negative amount for darkening
34+
}
35+
36+
// Function to lighten a color
37+
function lightenColor(hex: string, amount: number): string {
38+
return adjustColor(hex, amount); // Positive amount for lightening
39+
}
40+
41+
// General color adjustment function (darkens or lightens based on amount)
42+
function adjustColor(hex: string, amount: number): string {
43+
// Ensure that hex starts with '#'
44+
if (hex[0] !== '#') {
45+
throw new Error('Invalid hex color');
46+
}
47+
48+
// Convert hex to RGB
49+
const num = parseInt(hex.slice(1), 16);
50+
let r = (num >> 16) & 0xff;
51+
let g = (num >> 8) & 0xff;
52+
let b = num & 0xff;
53+
54+
// Adjust the color by increasing or decreasing each component
55+
r = Math.min(255, Math.max(0, r + Math.floor(255 * amount)));
56+
g = Math.min(255, Math.max(0, g + Math.floor(255 * amount)));
57+
b = Math.min(255, Math.max(0, b + Math.floor(255 * amount)));
58+
59+
// Convert RGB back to hex
60+
return `#${(1 << 24 | r << 16 | g << 8 | b).toString(16).slice(1)}`;
61+
}

0 commit comments

Comments
 (0)