@@ -9,6 +9,7 @@ import React, {
99import { useTheme } from "next-themes" ;
1010import { BitSelection } from "./DataPass" ;
1111import { WebglPlot , ColorRGBA , WebglLine } from "webgl-plot" ;
12+ import { lightThemeColors , darkThemeColors } from "./Colors" ;
1213
1314interface 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 }
0 commit comments