Skip to content

Commit e9da3c6

Browse files
committed
Now, it auto detect the available LSL Stream and connect to it whether it is BioAmpDataStream or ORIC
1 parent 63d5415 commit e9da3c6

File tree

8 files changed

+207
-64
lines changed

8 files changed

+207
-64
lines changed

beetle.py

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,31 @@
22
import pylsl
33
import numpy as np
44
import time
5-
from pylsl import StreamInlet, resolve_stream
5+
from pylsl import StreamInlet, resolve_streams, resolve_byprop
66
from scipy.signal import iirnotch, butter, lfilter
77
import math
88

99
# Initialize LSL stream
10-
streams = resolve_stream('name', 'BioAmpDataStream')
11-
if not streams:
12-
print("No LSL stream found!")
13-
exit()
10+
print("Searching for available LSL streams...")
11+
streams = resolve_streams()
12+
available_streams = [s.name() for s in streams]
13+
14+
if not available_streams:
15+
print("No LSL streams found!")
16+
17+
for stream_name in available_streams:
18+
print(f"Trying to connect to {stream_name}...")
19+
resolved_streams = resolve_byprop('name', stream_name, timeout=2)
1420

15-
inlet = StreamInlet(streams[0])
16-
print("LSL Stream Started")
21+
if resolved_streams:
22+
print(f"Successfully connected to {stream_name}!")
23+
inlet = StreamInlet(resolved_streams[0])
24+
break
25+
else:
26+
print(f"Failed to connect to {stream_name}.")
27+
28+
if inlet is None:
29+
print("Could not connect to any stream.")
1730
sampling_rate = int(inlet.info().nominal_srate())
1831
print(f"Sampling rate: {sampling_rate} Hz")
1932

@@ -26,7 +39,7 @@
2639

2740
# Beetle properties
2841
beetle_x, beetle_y = 380, 530
29-
focus_speed_upward = 15
42+
focus_speed_upward = 10
3043
focus_speed_downward = 5
3144
focus_timeout = 2
3245
focus_threshold = None
@@ -36,14 +49,19 @@
3649
screen = pygame.display.set_mode((800, 600))
3750
pygame.display.set_caption('Beetle Game')
3851

39-
# Load beetle image
40-
beetle_image = pygame.image.load('media\\beetle.jpg')
41-
beetle_image = pygame.transform.scale(beetle_image, (80, 80))
52+
sprite_count = 10
53+
beetle_sprites = [pygame.image.load(f'media/beetle{i}.JPG') for i in range(1, sprite_count + 1)]
54+
beetle_sprites = [pygame.transform.scale(sprite, (140, 160)) for sprite in beetle_sprites]
55+
56+
# Animation Variables
57+
current_sprite = 0
58+
animation_speed = 100
59+
sprite_timer = 0
4260

4361
# Function to display a message on the screen
4462
def show_message(message, duration=3):
4563
start_time = time.time()
46-
font = pygame.font.Font(None, 50)
64+
font = pygame.font.SysFont("Arial", 50)
4765
text = font.render(message, True, (0, 0, 0))
4866
text_rect = text.get_rect(center=(400, 300))
4967

@@ -72,7 +90,6 @@ def calculate_focus_level(eeg_data, sampling_rate=500):
7290
gamma_power = math.sqrt(np.sum((fft_data[(freqs >= 30) & (freqs <= 45)]) ** 2))
7391

7492
power = (beta_power + gamma_power) / (delta_power + theta_power + alpha_power + beta_power + gamma_power)
75-
print(power)
7693
return power
7794

7895
# Calibration Phase
@@ -97,21 +114,23 @@ def calculate_focus_level(eeg_data, sampling_rate=500):
97114
std_focus = np.std(baseline_focus_levels)
98115

99116
focus_threshold = mean_focus + 1.5 * std_focus
100-
print(f"Calibration Complete. Focus Threshold set at: {focus_threshold:.2f}")
117+
print(f"Calibration Complete. Focus Threshold set at: {focus_threshold:.3f}")
101118
else:
102119
print("Calibration failed due to insufficient data.")
103120
exit()
104121

105122
# Show Game Start Message
106123
show_message("Game Starting...", 1)
124+
game_start_time = time.time()
125+
game_duration = 45 # Game lasts 45 seconds
107126

108127
# Update beetle position
109128
def update_beetle_position(focus_level, is_focus_stable):
110129
global beetle_y
111130
if is_focus_stable:
112-
beetle_y = max(10 + beetle_image.get_height() // 2, beetle_y - focus_speed_upward)
131+
beetle_y = max(10 + beetle_sprites[0].get_height() // 2, beetle_y - focus_speed_upward)
113132
else:
114-
beetle_y = min(580 - beetle_image.get_height() // 2, beetle_y + focus_speed_downward)
133+
beetle_y = min(580 - beetle_sprites[0].get_height() // 2, beetle_y + focus_speed_downward)
115134

116135
print("STARTING GAME...")
117136
running = True
@@ -131,6 +150,8 @@ def update_beetle_position(focus_level, is_focus_stable):
131150
buffer.append(filtered_sample)
132151

133152
current_time = time.time()
153+
elapsed_time = int(current_time - game_start_time)
154+
134155
if current_time - last_time >= 1:
135156
last_time = current_time
136157
buffer = buffer[int(len(buffer) * 0.2):]
@@ -140,6 +161,7 @@ def update_beetle_position(focus_level, is_focus_stable):
140161
buffer = []
141162

142163
focus_level = calculate_focus_level(eeg_data)
164+
print(focus_level)
143165

144166
if focus_level > focus_threshold:
145167
focus_timer = min(focus_timeout, focus_timer + (current_time - last_focus_time))
@@ -152,10 +174,32 @@ def update_beetle_position(focus_level, is_focus_stable):
152174

153175
last_focus_time = current_time
154176

177+
# Update sprite animation
178+
sprite_timer += (current_time - last_focus_time)
179+
if sprite_timer >= animation_speed:
180+
sprite_timer = 0
181+
current_sprite = (current_sprite + 1) % len(beetle_sprites)
182+
183+
# Check win condition
184+
if beetle_y <= 80:
185+
show_message("You Win!", 1)
186+
running = False
187+
188+
# Check game over condition
189+
if elapsed_time >= game_duration:
190+
show_message("Game Over! Try Again.", 1)
191+
running = False
192+
193+
# Draw everything
155194
screen.fill("#FFFFFF")
156195
pygame.draw.rect(screen, (0, 0, 0), (10, 10, 780, 580), 5)
157-
screen.blit(beetle_image, (beetle_x - beetle_image.get_width() // 2, beetle_y - beetle_image.get_height() // 2))
158-
196+
screen.blit(beetle_sprites[current_sprite], (beetle_x - 40, beetle_y - 40))
197+
198+
# Display Timer
199+
font = pygame.font.SysFont("Arial", 30)
200+
timer_text = font.render(f"Time: {game_duration - elapsed_time}s", True, (0, 0, 0))
201+
screen.blit(timer_text, (650, 20))
202+
159203
pygame.display.update()
160204

161205
except KeyboardInterrupt:

emgenvelope.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,25 @@ def __init__(self):
3939
self.setCentralWidget(central_widget)
4040

4141
# Set up LSL stream inlet
42-
streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
43-
if not streams:
44-
print("No LSL stream found!")
42+
print("Searching for available LSL streams...")
43+
available_streams = pylsl.resolve_streams()
44+
45+
if not available_streams:
46+
print("No LSL streams found! Exiting...")
47+
sys.exit(0)
48+
49+
self.inlet = None
50+
for stream in available_streams:
51+
try:
52+
self.inlet = pylsl.StreamInlet(stream)
53+
print(f"Connected to LSL stream: {stream.name()}")
54+
break
55+
except Exception as e:
56+
print(f"Failed to connect to {stream.name()}: {e}")
57+
58+
if self.inlet is None:
59+
print("Unable to connect to any LSL stream! Exiting...")
4560
sys.exit(0)
46-
self.inlet = pylsl.StreamInlet(streams[0])
4761

4862
# Sampling rate
4963
self.sampling_rate = int(self.inlet.info().nominal_srate())

eog.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,25 @@ def __init__(self):
4444
layout.addWidget(self.blink_plot)
4545

4646
# Set up LSL stream inlet
47-
streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
48-
if not streams:
49-
print("No LSL stream found!")
47+
print("Searching for available LSL streams...")
48+
available_streams = pylsl.resolve_streams()
49+
50+
if not available_streams:
51+
print("No LSL streams found! Exiting...")
52+
sys.exit(0)
53+
54+
self.inlet = None
55+
for stream in available_streams:
56+
try:
57+
self.inlet = pylsl.StreamInlet(stream)
58+
print(f"Connected to LSL stream: {stream.name()}")
59+
break
60+
except Exception as e:
61+
print(f"Failed to connect to {stream.name()}: {e}")
62+
63+
if self.inlet is None:
64+
print("Unable to connect to any LSL stream! Exiting...")
5065
sys.exit(0)
51-
self.inlet = pylsl.StreamInlet(streams[0])
5266

5367
self.sampling_rate = int(self.inlet.info().nominal_srate())
5468
print(f"Sampling rate: {self.sampling_rate} Hz")

ffteeg.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,25 @@ def __init__(self):
6363
self.setCentralWidget(self.central_widget)
6464

6565
# Set up LSL stream inlet
66-
streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
67-
if not streams:
68-
print("No LSL stream found!")
66+
print("Searching for available LSL streams...")
67+
available_streams = pylsl.resolve_streams()
68+
69+
if not available_streams:
70+
print("No LSL streams found! Exiting...")
71+
sys.exit(0)
72+
73+
self.inlet = None
74+
for stream in available_streams:
75+
try:
76+
self.inlet = pylsl.StreamInlet(stream)
77+
print(f"Connected to LSL stream: {stream.name()}")
78+
break
79+
except Exception as e:
80+
print(f"Failed to connect to {stream.name()}: {e}")
81+
82+
if self.inlet is None:
83+
print("Unable to connect to any LSL stream! Exiting...")
6984
sys.exit(0)
70-
self.inlet = pylsl.StreamInlet(streams[0])
7185

7286
# Sampling rate
7387
self.sampling_rate = int(self.inlet.info().nominal_srate())

game.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
import queue
44
import threading
5-
from pylsl import StreamInlet, resolve_stream
5+
from pylsl import StreamInlet, resolve_streams, resolve_byprop
66
import numpy as np
77
from scipy.signal import welch
88
from scipy.integrate import simpson
@@ -89,12 +89,28 @@ def bandpower(data, sf, band, window_sec=None, relative=False):
8989

9090
def eeg_data_thread(eeg_queue):
9191
global powerData1, powerData2
92-
streams = resolve_stream('name', 'BioAmpDataStream')
93-
if not streams:
94-
print("No LSL stream found!")
95-
return
96-
97-
inlet = StreamInlet(streams[0])
92+
print("Searching for available LSL streams...")
93+
streams = resolve_streams()
94+
available_streams = [s.name() for s in streams]
95+
96+
if not available_streams:
97+
print("No LSL streams found!")
98+
return None
99+
100+
for stream_name in available_streams:
101+
print(f"Trying to connect to {stream_name}...")
102+
resolved_streams = resolve_byprop('name', stream_name, timeout=2)
103+
104+
if resolved_streams:
105+
print(f"Successfully connected to {stream_name}!")
106+
inlet = StreamInlet(resolved_streams[0])
107+
break
108+
else:
109+
print(f"Failed to connect to {stream_name}.")
110+
111+
if inlet is None:
112+
print("Could not connect to any stream.")
113+
return None
98114
channel_assignments = {0:'Player A', 1:'Player B'}
99115
sampling_frequency = 500
100116
bands = {'Alpha': [8, 13],'Beta': [13, 30]}

gui.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import sys
2-
from pylsl import StreamInlet, resolve_stream
2+
from pylsl import StreamInlet, resolve_streams, resolve_byprop
33
import pyqtgraph as pg # For real-time plotting
44
from pyqtgraph.Qt import QtWidgets, QtCore # PyQt components for GUI
55
import numpy as np
@@ -28,16 +28,30 @@ def update_plots():
2828

2929
def plot_lsl_data():
3030
global inlet, num_channels, data
31-
print("Looking for LSL Stream.")
32-
streams = resolve_stream('name', 'BioAmpDataStream')
3331

34-
if not streams:
35-
print("No LSL Stream found.")
36-
return
37-
38-
inlet = StreamInlet(streams[0])
32+
print("Searching for available LSL streams...")
33+
streams = resolve_streams()
34+
available_streams = [s.name() for s in streams]
35+
36+
if not available_streams:
37+
print("No LSL streams found!")
38+
return None
39+
40+
for stream_name in available_streams:
41+
print(f"Trying to connect to {stream_name}...")
42+
resolved_streams = resolve_byprop('name', stream_name, timeout=2)
43+
44+
if resolved_streams:
45+
print(f"Successfully connected to {stream_name}!")
46+
inlet = StreamInlet(resolved_streams[0])
47+
break
48+
else:
49+
print(f"Failed to connect to {stream_name}.")
50+
51+
if inlet is None:
52+
print("Could not connect to any stream.")
53+
return None
3954

40-
# Get the number of channels from the stream
4155
info = inlet.info()
4256
num_channels = info.channel_count()
4357
print(f"Detected {num_channels} channels.")
@@ -94,4 +108,5 @@ def init_gui():
94108

95109
if __name__ == "__main__":
96110
plot_lsl_data()
97-
sys.exit(app.exec_()) # Start the Qt application
111+
if inlet:
112+
sys.exit(app.exec_()) # Start the Qt application only if a stream was connected

heartbeat_ecg.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,25 @@ def __init__(self):
3333
self.setCentralWidget(central_widget)
3434

3535
# Set up LSL stream inlet
36-
streams = pylsl.resolve_stream('name', 'BioAmpDataStream')
37-
if not streams:
38-
print("No LSL stream found!")
36+
print("Searching for available LSL streams...")
37+
available_streams = pylsl.resolve_streams()
38+
39+
if not available_streams:
40+
print("No LSL streams found! Exiting...")
41+
sys.exit(0)
42+
43+
self.inlet = None
44+
for stream in available_streams:
45+
try:
46+
self.inlet = pylsl.StreamInlet(stream)
47+
print(f"Connected to LSL stream: {stream.name()}")
48+
break
49+
except Exception as e:
50+
print(f"Failed to connect to {stream.name()}: {e}")
51+
52+
if self.inlet is None:
53+
print("Unable to connect to any LSL stream! Exiting...")
3954
sys.exit(0)
40-
self.inlet = pylsl.StreamInlet(streams[0])
4155

4256
# Sampling rate
4357
self.sampling_rate = int(self.inlet.info().nominal_srate())

0 commit comments

Comments
 (0)