Skip to content

Commit 394d457

Browse files
committed
Updating eog.py file: Now blink detection is better and also now the peaks are to marked till new data is overwrite on the old one.
1 parent 16c9555 commit 394d457

File tree

1 file changed

+4
-319
lines changed

1 file changed

+4
-319
lines changed

applications/eog.py

Lines changed: 4 additions & 319 deletions
Original file line numberDiff line numberDiff line change
@@ -1,318 +1,3 @@
1-
# import numpy as np
2-
# from scipy.signal import butter, filtfilt
3-
# from PyQt5.QtWidgets import QApplication, QVBoxLayout, QMainWindow, QWidget, QHBoxLayout
4-
# import pyqtgraph as pg
5-
# import pylsl
6-
# import sys
7-
8-
# class EOGMonitor(QMainWindow):
9-
# def __init__(self):
10-
# super().__init__()
11-
12-
# self.setWindowTitle("Real-Time EOG Monitor - Eye Blink Detection")
13-
# self.setGeometry(100, 100, 800, 400)
14-
15-
# # Create layout
16-
# layout = QVBoxLayout()
17-
# central_widget = QWidget()
18-
# central_widget.setLayout(layout)
19-
# self.setCentralWidget(central_widget)
20-
21-
# # Create plot widget for EOG
22-
# self.eog_plot = pg.PlotWidget(self)
23-
# self.eog_plot.setBackground('w')
24-
# self.eog_plot.showGrid(x=True, y=True)
25-
# self.eog_plot.setTitle("Filtered EOG Signal (Low Pass: 10 Hz)")
26-
27-
# # Bottom layout for Blink Detection
28-
# self.bottom_layout = QHBoxLayout()
29-
30-
# # Blink detection plot
31-
# self.blink_plot = pg.PlotWidget(self)
32-
# self.blink_plot.setBackground('w')
33-
# self.blink_plot.showGrid(x=True, y=True)
34-
# self.blink_plot.setYRange(0, 1, padding=0)
35-
# self.blink_plot.setMouseEnabled(x=False, y=False) # Disable zoom
36-
# self.blink_plot.setTitle("Blink Detection")
37-
38-
# # Add both plots to the layout
39-
# layout.addWidget(self.eog_plot)
40-
# layout.addWidget(self.blink_plot)
41-
42-
# # Set up LSL stream inlet
43-
# streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
44-
# if not streams:
45-
# print("No LSL stream found!")
46-
# sys.exit(0)
47-
# self.inlet = pylsl.StreamInlet(streams[0])
48-
49-
# self.sampling_rate = int(self.inlet.info().nominal_srate())
50-
# print(f"Sampling rate: {self.sampling_rate} Hz")
51-
52-
# self.buffer_size = self.sampling_rate * 5 # 5 seconds buffer for recent data
53-
# self.eog_data = np.zeros(self.buffer_size)
54-
# self.time_data = np.linspace(0, 5, self.buffer_size)
55-
# self.blink_data = np.zeros(self.buffer_size) # Blink data array
56-
# self.current_index = 0
57-
58-
# # Low-pass filter for EOG (10 Hz)
59-
# self.b, self.a = butter(4, 10.0 / (0.5 * self.sampling_rate), btype='low')
60-
61-
# self.eog_plot.setXRange(0, 5, padding=0)
62-
# if self.sampling_rate == 250:
63-
# self.eog_plot.setYRange(-((2**10)/2), ((2**10)/2), padding=0)
64-
# elif self.sampling_rate == 500:
65-
# self.eog_plot.setYRange(-((2**14)/2), ((2**14)/2), padding=0)
66-
67-
# # Plot curves
68-
# self.eog_curve = self.eog_plot.plot(self.time_data, self.eog_data, pen=pg.mkPen('b', width=1))
69-
# self.blink_curve = self.blink_plot.plot(self.time_data, self.blink_data, pen=pg.mkPen('r', width=2))
70-
71-
# # Timer for plot update
72-
# self.timer = pg.QtCore.QTimer()
73-
# self.timer.timeout.connect(self.update_plot)
74-
# self.timer.start(15)
75-
76-
# def update_plot(self):
77-
# samples, _ = self.inlet.pull_chunk(timeout=0.0, max_samples=30)
78-
# if samples:
79-
# for sample in samples:
80-
# # Overwrite the oldest data point in the buffer
81-
# self.eog_data[self.current_index] = sample[0]
82-
# self.current_index = (self.current_index + 1) % self.buffer_size
83-
84-
# filtered_eog = filtfilt(self.b, self.a, self.eog_data)
85-
86-
# # Update curve with the filtered EOG signal (5-second window)
87-
# self.eog_plot.clear() # Clear the previous peaks from the plot
88-
# self.eog_curve = self.eog_plot.plot(self.time_data, filtered_eog, pen=pg.mkPen('b', width=1))
89-
90-
# # Peak detection (1-second moving window)
91-
# self.detect_blinks(filtered_eog)
92-
93-
# def detect_blinks(self, filtered_eog):
94-
# mean_signal = np.mean(filtered_eog)
95-
# stdev_signal = np.std(filtered_eog)
96-
97-
# threshold = mean_signal + (2 * stdev_signal)
98-
99-
# # Calculate the start and end indices for the 1-second window
100-
# window_size = 1 * self.sampling_rate # 1 seconds in samples
101-
# start_index = self.current_index - window_size
102-
# if start_index < 0:
103-
# start_index = 0
104-
# end_index = self.current_index
105-
106-
# # Use a 1-second window for peak detection
107-
# filtered_window = filtered_eog[start_index:end_index]
108-
# peaks = self.detect_peaks(filtered_window, threshold)
109-
110-
# # Reset blink data to zero
111-
# self.blink_data[:] = 0
112-
113-
# # Mark detected peaks in blink_data
114-
# for peak in peaks:
115-
# full_peak_index = start_index + peak
116-
# self.blink_data[full_peak_index] = 1
117-
118-
# # Mark peaks with red dots on the EOG plot
119-
# self.eog_plot.plot(self.time_data[start_index:end_index][peaks], filtered_window[peaks], pen=None, symbol='o', symbolPen='r', symbolSize=6)
120-
121-
# # Update the blink plot with the current blink data
122-
# self.blink_curve.setData(self.time_data, self.blink_data)
123-
124-
# def detect_peaks(self, signal, threshold):
125-
# # List to store detected peak indices
126-
# peaks = []
127-
# prev_peak_time = None # Variable to store the timestamp of the previous peak
128-
# min_peak_gap = 0.1 # Minimum time gap between two peaks in seconds
129-
130-
# for i in range(1, len(signal) - 1):
131-
# # Check if the current point is greater than the previous and next point (local maximum)
132-
# if signal[i] > signal[i - 1] and signal[i] > signal[i + 1] and signal[i] > threshold:
133-
# current_peak_time = i / self.sampling_rate # Time in seconds based on the sampling rate
134-
135-
# if prev_peak_time is not None:
136-
# time_gap = current_peak_time - prev_peak_time
137-
# if time_gap < min_peak_gap: # Ignore if the time gap is less than the threshold
138-
# continue
139-
140-
# peaks.append(i)
141-
# prev_peak_time = current_peak_time # Update previous peak time
142-
143-
# return peaks
144-
145-
# if __name__ == "__main__":
146-
# app = QApplication(sys.argv)
147-
# window = EOGMonitor()
148-
# window.show()
149-
# sys.exit(app.exec_())
150-
151-
152-
153-
154-
155-
# import numpy as np
156-
# from scipy.signal import butter, lfilter
157-
# from PyQt5.QtWidgets import QApplication, QVBoxLayout, QMainWindow, QWidget, QHBoxLayout
158-
# import pyqtgraph as pg
159-
# import pylsl
160-
# import sys
161-
# import time
162-
163-
# class EOGMonitor(QMainWindow):
164-
# def __init__(self):
165-
# super().__init__()
166-
167-
# self.setWindowTitle("Real-Time EOG Monitor - Eye Blink Detection")
168-
# self.setGeometry(100, 100, 800, 400)
169-
170-
# # Create layout
171-
# layout = QVBoxLayout()
172-
# central_widget = QWidget()
173-
# central_widget.setLayout(layout)
174-
# self.setCentralWidget(central_widget)
175-
176-
# # Create plot widget for EOG
177-
# self.eog_plot = pg.PlotWidget(self)
178-
# self.eog_plot.setBackground('w')
179-
# self.eog_plot.showGrid(x=True, y=True)
180-
# self.eog_plot.setTitle("Filtered EOG Signal (Low Pass: 10 Hz)")
181-
182-
# # Bottom layout for Blink Detection
183-
# self.bottom_layout = QHBoxLayout()
184-
185-
# # Blink detection plot
186-
# self.blink_plot = pg.PlotWidget(self)
187-
# self.blink_plot.setBackground('w')
188-
# self.blink_plot.showGrid(x=True, y=True)
189-
# self.blink_plot.setYRange(0, 1, padding=0)
190-
# self.blink_plot.setMouseEnabled(x=False, y=False) # Disable zoom
191-
# self.blink_plot.setTitle("Blink Detection")
192-
193-
# # Add both plots to the layout
194-
# layout.addWidget(self.eog_plot)
195-
# layout.addWidget(self.blink_plot)
196-
197-
# # Set up LSL stream inlet
198-
# streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
199-
# if not streams:
200-
# print("No LSL stream found!")
201-
# sys.exit(0)
202-
# self.inlet = pylsl.StreamInlet(streams[0])
203-
204-
# self.sampling_rate = int(self.inlet.info().nominal_srate())
205-
# print(f"Sampling rate: {self.sampling_rate} Hz")
206-
207-
# self.buffer_size = self.sampling_rate * 5 # 5 seconds buffer for recent data
208-
# self.eog_data = np.zeros(self.buffer_size)
209-
# self.time_data = np.linspace(0, 5, self.buffer_size)
210-
# self.blink_data = np.zeros(self.buffer_size) # Blink data array
211-
# self.current_index = 0
212-
213-
# # Low-pass filter for EOG (10 Hz)
214-
# self.b, self.a = butter(4, 10.0 / (0.5 * self.sampling_rate), btype='low')
215-
216-
# self.eog_plot.setXRange(0, 5, padding=0)
217-
# if self.sampling_rate == 250:
218-
# self.eog_plot.setYRange(-((2**10)/2), ((2**10)/2), padding=0)
219-
# elif self.sampling_rate == 500:
220-
# self.eog_plot.setYRange(-((2**14)/2), ((2**14)/2), padding=0)
221-
222-
# # Plot curves
223-
# self.eog_curve = self.eog_plot.plot(self.time_data, self.eog_data, pen=pg.mkPen('b', width=1))
224-
# self.blink_curve = self.blink_plot.plot(self.time_data, self.blink_data, pen=pg.mkPen('r', width=2))
225-
226-
# # List to store detected peaks with timestamps
227-
# self.detected_peaks = []
228-
229-
# # Timer for plot update
230-
# self.timer = pg.QtCore.QTimer()
231-
# self.timer.timeout.connect(self.update_plot)
232-
# self.timer.start(15)
233-
234-
# def update_plot(self):
235-
# samples, _ = self.inlet.pull_chunk(timeout=0.0, max_samples=30)
236-
# if samples:
237-
# for sample in samples:
238-
# # Overwrite the oldest data point in the buffer
239-
# self.eog_data[self.current_index] = sample[0]
240-
# self.current_index = (self.current_index + 1) % self.buffer_size
241-
242-
# filtered_eog = lfilter(self.b, self.a, self.eog_data)
243-
244-
# # Update curve with the filtered EOG signal (5-second window)
245-
# self.eog_plot.clear() # Clear the previous peaks from the plot
246-
# self.eog_curve = self.eog_plot.plot(self.time_data, filtered_eog, pen=pg.mkPen('b', width=1))
247-
248-
# # Peak detection (1-second moving window)
249-
# self.detect_blinks(filtered_eog)
250-
251-
# # Clear out old peaks from self.detected_peaks after 5 seconds
252-
# current_time = time.time()
253-
# self.detected_peaks = [(index, t) for index, t in self.detected_peaks if current_time - t < 5]
254-
255-
# # Update the blink plot based on stored peaks
256-
# self.blink_data[:] = 0 # Reset blink data
257-
# for index, _ in self.detected_peaks:
258-
# if 0 <= index < self.buffer_size:
259-
# self.blink_data[index] = 1 # Keep blink data high at detected peaks
260-
261-
# # Mark the stored peaks on the EOG plot
262-
# peak_indices = [index for index, t in self.detected_peaks]
263-
# peak_values = [filtered_eog[i] for i in peak_indices]
264-
# self.eog_plot.plot(self.time_data[peak_indices], peak_values, pen=None, symbol='o', symbolPen='r', symbolSize=6)
265-
266-
# # Update the blink plot with the current blink data
267-
# self.blink_curve.setData(self.time_data, self.blink_data)
268-
269-
# def detect_blinks(self, filtered_eog):
270-
# mean_signal = np.mean(filtered_eog)
271-
# stdev_signal = np.std(filtered_eog)
272-
# threshold = mean_signal + (2 * stdev_signal)
273-
274-
# # Calculate the start and end indices for the 1-second window
275-
# window_size = 1 * self.sampling_rate
276-
# start_index = self.current_index - window_size
277-
# if start_index < 0:
278-
# start_index = 0
279-
# end_index = self.current_index
280-
281-
# # Use a 1-second window for peak detection
282-
# filtered_window = filtered_eog[start_index:end_index]
283-
# peaks = self.detect_peaks(filtered_window, threshold)
284-
285-
# # Mark detected peaks and store them with timestamps
286-
# for peak in peaks:
287-
# full_peak_index = start_index + peak
288-
# self.detected_peaks.append((full_peak_index, time.time())) # Add detected peak with current timestamp
289-
290-
# def detect_peaks(self, signal, threshold):
291-
# peaks = []
292-
# prev_peak_time = None # Variable to store the timestamp of the previous peak
293-
# min_peak_gap = 0.1 # Minimum time gap between two peaks in seconds
294-
295-
# for i in range(1, len(signal) - 1):
296-
# if signal[i] > signal[i - 1] and signal[i] > signal[i + 1] and signal[i] > threshold:
297-
# current_peak_time = i / self.sampling_rate # Time in seconds based on the sampling rate
298-
299-
# if prev_peak_time is not None:
300-
# time_gap = current_peak_time - prev_peak_time
301-
# if time_gap < min_peak_gap:
302-
# continue
303-
304-
# peaks.append(i)
305-
# prev_peak_time = current_peak_time
306-
307-
# return peaks
308-
309-
# if __name__ == "__main__":
310-
# app = QApplication(sys.argv)
311-
# window = EOGMonitor()
312-
# window.show()
313-
# sys.exit(app.exec_())
314-
315-
#Use deque that remove the oldest peak after 5 seconds.
3161
import numpy as np
3172
from scipy.signal import butter, lfilter
3183
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QMainWindow, QWidget, QHBoxLayout
@@ -349,7 +34,7 @@ def __init__(self):
34934
self.blink_plot.setBackground('w')
35035
self.blink_plot.showGrid(x=True, y=True)
35136
self.blink_plot.setYRange(0, 1, padding=0)
352-
self.blink_plot.setMouseEnabled(x=False, y=False) # Disable zoom
37+
self.blink_plot.setMouseEnabled(x=False, y=False) # To Disable zoom functionality mark it as true
35338
self.blink_plot.setTitle("Blink Detection")
35439

35540
# Add both plots to the layout
@@ -410,7 +95,7 @@ def update_plot(self):
41095
# Peak detection (1-second moving window)
41196
self.detect_blinks(filtered_eog)
41297

413-
# Clear out old peaks from the circular buffer after 4 seconds(because we want to clear the peaks just after the data overwrite.)
98+
# Clear out old peaks from the circular buffer after 4 seconds(As we want to clear the peaks just after the data overwrite.)
41499
current_time = time.time()
415100
while self.detected_peaks and (current_time - self.detected_peaks[0][1] > 4):
416101
self.detected_peaks.popleft() # Remove old peaks from the buffer
@@ -432,7 +117,7 @@ def update_plot(self):
432117
def detect_blinks(self, filtered_eog):
433118
mean_signal = np.mean(filtered_eog)
434119
stdev_signal = np.std(filtered_eog)
435-
threshold = mean_signal + (1.5 * stdev_signal)
120+
threshold = mean_signal + (1.8 * stdev_signal)
436121

437122
# Calculate the start and end indices for the 1-second window
438123
window_size = 1 * self.sampling_rate
@@ -453,7 +138,7 @@ def detect_blinks(self, filtered_eog):
453138
def detect_peaks(self, signal, threshold):
454139
peaks = []
455140
prev_peak_time = None # Variable to store the timestamp of the previous peak
456-
min_peak_gap = 0.01 # Minimum time gap between two peaks in seconds
141+
min_peak_gap = 0.1 # Minimum time gap between two peaks in seconds
457142

458143
for i in range(1, len(signal) - 1):
459144
if signal[i] > signal[i - 1] and signal[i] > signal[i + 1] and signal[i] > threshold:

0 commit comments

Comments
 (0)