@@ -77,11 +77,13 @@ 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
80
+ # Moving window for brainwave power
81
+ self .moving_window_size = self .sampling_rate * 3 # 3-second window
82
+ self .moving_window_buffer = np .zeros (self .moving_window_size )
83
+
84
+ # Filters
81
85
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' )
84
- # Low-pass filter (4th order, cutoff at 45 Hz)
86
+ self .b_highpass , self .a_highpass = butter (4 , 1.5 / (0.5 * self .sampling_rate ), btype = 'high' )
85
87
self .b_lowpass , self .a_lowpass = butter (4 , 45 / (0.5 * self .sampling_rate ), btype = 'low' )
86
88
87
89
# Timer for updating the plot
@@ -114,22 +116,36 @@ def update_plot(self):
114
116
self .eeg_curve .setData (self .time_data , filtered_eeg )
115
117
116
118
# Perform FFT on the latest 1-second slice
117
- latest_data = plot_data [- self .sampling_rate :] # Most recent 1-second data
119
+ latest_data = filtered_eeg [- self .sampling_rate :]
118
120
window = hamming (len (latest_data ))
119
121
filtered_eeg_windowed = latest_data * window
120
122
121
123
# Apply zero-padding
122
- zero_padded_length = 2048
124
+ zero_padded_length = 512
123
125
filtered_eeg_windowed_padded = np .pad (filtered_eeg_windowed , (0 , zero_padded_length - len (filtered_eeg_windowed )), 'constant' )
124
126
125
- eeg_fft = np .abs (fft (filtered_eeg_windowed ))[:len (filtered_eeg_windowed ) // 2 ] # Positive frequencies only
126
- freqs = np .fft .fftfreq (len (filtered_eeg_windowed ), 1 / self .sampling_rate )[:len (filtered_eeg_windowed ) // 2 ]
127
+ eeg_fft = np .abs (fft (filtered_eeg_windowed_padded ))[:len (filtered_eeg_windowed_padded ) // 2 ]
128
+ freqs = np .fft .fftfreq (len (filtered_eeg_windowed_padded ), 1 / self .sampling_rate )[:len (filtered_eeg_windowed_padded ) // 2 ]
127
129
128
130
# Update FFT plot
129
131
self .fft_curve .setData (freqs , eeg_fft )
130
132
131
- # Calculate brainwave power
132
- brainwave_power = self .calculate_brainwave_power (eeg_fft , freqs )
133
+ # Update the 3-second moving window buffer
134
+ for sample in latest_data :
135
+ self .moving_window_buffer = np .roll (self .moving_window_buffer , - 1 )
136
+ self .moving_window_buffer [- 1 ] = sample
137
+
138
+ # Apply filters to the moving window buffer
139
+ filtered_window = filtfilt (self .b_notch , self .a_notch , self .moving_window_buffer )
140
+ filtered_window = filtfilt (self .b_highpass , self .a_highpass , filtered_window )
141
+ filtered_window = filtfilt (self .b_lowpass , self .a_lowpass , filtered_window )
142
+
143
+ # Perform FFT on the moving window buffer
144
+ windowed_data = filtered_window * hamming (len (filtered_window ))
145
+ fft_data = np .abs (fft (windowed_data ))[:len (windowed_data ) // 2 ]
146
+ window_freqs = np .fft .fftfreq (len (windowed_data ), 1 / self .sampling_rate )[:len (windowed_data ) // 2 ]
147
+
148
+ brainwave_power = self .calculate_brainwave_power (fft_data , window_freqs )
133
149
self .brainwave_bars .setOpts (height = brainwave_power )
134
150
135
151
def calculate_brainwave_power (self , fft_data , freqs ):
0 commit comments