6
6
import pyqtgraph as pg
7
7
import pylsl
8
8
import sys
9
- from scipy .signal import butter , filtfilt
9
+ from scipy .signal import butter , filtfilt , iirnotch
10
10
from scipy .fft import fft
11
11
12
12
class EEGMonitor (QMainWindow ):
@@ -27,7 +27,7 @@ def __init__(self):
27
27
self .eeg_plot_widget .setLabel ('bottom' , 'EEG Plot' )
28
28
self .eeg_plot_widget .setYRange (0 , 15000 , padding = 0 )
29
29
self .eeg_plot_widget .setXRange (0 , 10 , padding = 0 )
30
- self .eeg_plot_widget .setMouseEnabled (x = False , y = False ) # Disable zoom
30
+ self .eeg_plot_widget .setMouseEnabled (x = False , y = True ) # Disable zoom
31
31
self .main_layout .addWidget (self .eeg_plot_widget )
32
32
33
33
# Second half for FFT and Brainwave Power, aligned horizontally
@@ -77,6 +77,10 @@ def __init__(self):
77
77
self .time_data = np .linspace (0 , 10 , self .buffer_size ) # Fixed time array for plotting
78
78
self .current_index = 0 # Index for overwriting data
79
79
80
+ # Notch filter at 50 Hz
81
+ self .b_notch , self .a_notch = iirnotch (50 , 30 , self .sampling_rate )
82
+ # High-pass filter (cutoff at 0.5 Hz)
83
+ self .b_highpass , self .a_highpass = butter (4 , 0.5 / (0.5 * self .sampling_rate ), btype = 'high' )
80
84
# Low-pass filter (4th order, cutoff at 45 Hz)
81
85
self .b_lowpass , self .a_lowpass = butter (4 , 45 / (0.5 * self .sampling_rate ), btype = 'low' )
82
86
@@ -96,15 +100,27 @@ def update_plot(self):
96
100
self .eeg_data [self .current_index ] = sample [0 ]
97
101
self .current_index = (self .current_index + 1 ) % self .buffer_size # Circular increment
98
102
99
- # Apply low-pass filter
100
- filtered_eeg = filtfilt (self .b_lowpass , self .a_lowpass , self .eeg_data )
103
+ if self .current_index >= self .buffer_size :
104
+ plot_data = self .eeg_data
105
+ else :
106
+ plot_data = np .concatenate ((self .eeg_data [self .current_index :], self .eeg_data [:self .current_index ]))
107
+
108
+ # Apply filters to the full data for EEG plot
109
+ filtered_eeg = filtfilt (self .b_notch , self .a_notch , plot_data )
110
+ filtered_eeg = filtfilt (self .b_highpass , self .a_highpass , filtered_eeg )
111
+ filtered_eeg = filtfilt (self .b_lowpass , self .a_lowpass , filtered_eeg )
101
112
102
113
# Update the EEG plot with the filtered data
103
114
self .eeg_curve .setData (self .time_data , filtered_eeg )
104
115
105
- # Perform FFT with windowing (Hamming window)
106
- window = hamming (len (filtered_eeg )) # Apply Hamming window to reduce spectral leakage
107
- filtered_eeg_windowed = filtered_eeg * window # Element-wise multiply
116
+ # Perform FFT on the latest 1-second slice
117
+ latest_data = plot_data [- self .sampling_rate :] # Most recent 1-second data
118
+ window = hamming (len (latest_data ))
119
+ filtered_eeg_windowed = latest_data * window
120
+
121
+ # Apply zero-padding
122
+ zero_padded_length = 2048
123
+ filtered_eeg_windowed_padded = np .pad (filtered_eeg_windowed , (0 , zero_padded_length - len (filtered_eeg_windowed )), 'constant' )
108
124
109
125
eeg_fft = np .abs (fft (filtered_eeg_windowed ))[:len (filtered_eeg_windowed ) // 2 ] # Positive frequencies only
110
126
freqs = np .fft .fftfreq (len (filtered_eeg_windowed ), 1 / self .sampling_rate )[:len (filtered_eeg_windowed ) // 2 ]
0 commit comments