-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:Mentalab-hub/explorepy into develop
- Loading branch information
Showing
20 changed files
with
448 additions
and
9 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import time | ||
from collections import deque | ||
|
||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
from matplotlib.animation import FuncAnimation | ||
|
||
import explorepy | ||
from explorepy.packet import EEG | ||
from explorepy.stream_processor import TOPICS | ||
|
||
rows, cols = 8, 1024 | ||
data_buf = deque([deque(maxlen=cols) for _ in range(rows)]) | ||
for row in data_buf: | ||
row.extend(range(1024)) | ||
|
||
|
||
def get_data_buf(): | ||
output = np.array([[0] * 1024 for _ in range(rows)]) | ||
for i in range(len(output)): | ||
output[i] = np.array(data_buf[i]) | ||
return output | ||
|
||
|
||
def on_exg_received(packet: EEG): | ||
_, data = packet.get_data() | ||
for r in range(len(data)): | ||
for column in range(len(data[r])): | ||
data_buf[r].append(data[r][column]) | ||
|
||
|
||
exp_device = explorepy.Explore() | ||
# Subscribe your function to the stream publisher | ||
|
||
exp_device.connect(device_name="Explore_AAAK") | ||
exp_device.stream_processor.subscribe(callback=on_exg_received, topic=TOPICS.raw_ExG) | ||
|
||
# Define the frequency bands | ||
bands = { | ||
'Delta': (0.5, 4), | ||
'Theta': (4, 8), | ||
'Alpha': (8, 13), | ||
'Beta': (13, 30), | ||
'Gamma': (30, 50) | ||
} | ||
|
||
# FFT and signal parameters | ||
sampling_rate = 250 # in Hz | ||
num_channels = 8 | ||
num_samples = 1024 | ||
|
||
# Set up the figure and axes for subplots | ||
fig, axs = plt.subplots(4, 2, figsize=(10, 15), sharex=True) | ||
fig.tight_layout(pad=4.0) # Adjust layout padding | ||
|
||
# Flatten the 2D array of axes for easier iteration | ||
axs = axs.flatten() | ||
|
||
# Initialize bar plots for each subplot | ||
bars = [] | ||
for ax in axs: | ||
bars.append(ax.bar(bands.keys(), [0] * len(bands), color='skyblue')) | ||
ax.set_ylim(0, 1) # Set an initial y-limit, can adjust based on your data | ||
ax.set_xlabel('Frequency Band') | ||
ax.set_ylabel('Power') | ||
|
||
|
||
def update(frame): | ||
eeg_signals = get_data_buf() # Generate data for all channels | ||
|
||
for idx, (axis, bar) in enumerate(zip(axs, bars)): | ||
eeg_signal = eeg_signals[idx] | ||
|
||
# Perform FFT | ||
fft_values = np.fft.fft(eeg_signal) | ||
fft_frequencies = np.fft.fftfreq(num_samples, 1 / sampling_rate) | ||
fft_magnitude = np.abs(fft_values) ** 2 # Power spectrum | ||
|
||
# Only consider positive frequencies | ||
positive_frequencies = fft_frequencies[:num_samples // 2] | ||
positive_magnitude = fft_magnitude[:num_samples // 2] | ||
|
||
# Calculate band powers | ||
band_powers = [] | ||
for band, (low, high) in bands.items(): | ||
indices = np.where((positive_frequencies >= low) & (positive_frequencies <= high)) | ||
band_power = np.sum(positive_magnitude[indices]) | ||
band_powers.append(band_power) | ||
|
||
# Update the bar heights | ||
for b, power in zip(bar, band_powers): | ||
b.set_height(power) | ||
|
||
# Optionally adjust y-axis limits based on data | ||
axis.set_ylim(0, max(band_powers) * 1.1) | ||
axis.set_title(f'Channel {idx + 1}') | ||
|
||
return [b for bar in bars for b in bar] # Flatten the list of bars | ||
|
||
|
||
# Create the animation object | ||
ani = FuncAnimation(fig, update, interval=500, blit=True) # Update every 500 ms (0.5 seconds) | ||
|
||
# Display the plot | ||
plt.show() | ||
|
||
while True: | ||
time.sleep(1) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[general] | ||
debug=2 | ||
delay=0.010 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[fieldtrip] | ||
port=1972,1973,1974 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[general] | ||
debug=2 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[history] | ||
window=10 | ||
; window length for smoothing (s) | ||
stepsize=0.05 | ||
; update time (s) | ||
|
||
[input] | ||
; control values to plot, separated by comma | ||
freeze=0 | ||
channels=spectral.channel1.alpha,spectral.channel2.theta,spectral.channel2.beta |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[general] | ||
debug=1 | ||
|
||
[fieldtrip] | ||
hostname=localhost | ||
port=1972 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[lsl] | ||
; this can be used to select the desired stream (in case there are multiple) | ||
name= | ||
type=ExG | ||
timeout=30 ; in seconds |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[general] | ||
debug=1 | ||
delay=0.05 | ||
monophonic=1 ; boolean | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[midi] | ||
device=IAC Driver Bus 1 | ||
channel=1 | ||
|
||
[control] | ||
; you can specify different MIDI message types here: controlXXX, noteXXX, polytouchXXX, aftertouch, pitchwheel, start, continue, stop, reset, note | ||
|
||
[trigger] | ||
; you can specify different MIDI message types here: controlXXX, noteXXX, polytouchXXX, aftertouch, pitchwheel, start, continue, stop, reset, note | ||
note=post.channel1.alpha | ||
start=post.channel1.alpha | ||
|
||
[duration] | ||
note=0.5 ; the note will be switched off after the specified time (in seconds) | ||
|
||
[velocity] | ||
|
||
[scale] | ||
; scale and offset can be used to map Redis values to MIDI values between 0 to 127 | ||
; the default scale for all channels is 127 | ||
|
||
[offset] | ||
; the default offset for all channels is 0 | ||
note=40 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[general] | ||
debug=1 | ||
delay=0.05 | ||
monophonic=1 ; boolean | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[midi] | ||
device=IAC Driver Bus 2 | ||
channel=1 | ||
|
||
[control] | ||
; you can specify different MIDI message types here: controlXXX, noteXXX, polytouchXXX, aftertouch, pitchwheel, start, continue, stop, reset, note | ||
|
||
[trigger] | ||
; you can specify different MIDI message types here: controlXXX, noteXXX, polytouchXXX, aftertouch, pitchwheel, start, continue, stop, reset, note | ||
note=post.channel2.thetabetaratio | ||
start=post.channel2.thetabetaratio | ||
|
||
[duration] | ||
note=0.5 ; the note will be switched off after the specified time (in seconds) | ||
|
||
[velocity] | ||
|
||
[scale] | ||
; scale and offset can be used to map Redis values to MIDI values between 0 to 127 | ||
; the default scale for all channels is 127 | ||
|
||
[offset] | ||
; the default offset for all channels is 0 | ||
note=40 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
[general] | ||
delay=0.05 | ||
debug=2 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[initial] | ||
; here you can specify the initial values of some control values | ||
|
||
[input] | ||
; the keys here can have an arbitrary name, but should map those in the output section | ||
; the keys must be lower-case. values should not contain an equation, only one-to-one mappings | ||
alpha_1=spectral.channel1.alpha | ||
theta_2=spectral.channel2.theta | ||
beta_2=spectral.channel2.beta | ||
|
||
[output] | ||
; besides +, -, /, *, the equations also support log, log2, log10, exp, power from numpy | ||
; and compress, limit, rescale, normalizerange, normalizestandard from EEGsynth | ||
post.channel1.alpha = limit(alpha_1 / 1750, 0, 0.8) | ||
post.channel2.thetabetaratio = limit(theta_2/beta_2 / 6, 0, 0.9) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
[general] | ||
delay=0.10 | ||
debug=1 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[input_fieldtrip] | ||
hostname=localhost | ||
port=1972 | ||
timeout=30 | ||
|
||
[output_fieldtrip] | ||
hostname=localhost | ||
port=1973 | ||
|
||
[processing] | ||
window=0.12 | ||
;smoothing=0.2 | ||
reference=none | ||
lowpassfilter=45 | ||
highpassfilter=2 | ||
filterorder=511 | ||
;downsample=1 | ||
notchfilter=50 | ||
|
||
[scale] | ||
highpassfilter=1 | ||
lowpassfilter=1 | ||
notchfilter=1 | ||
|
||
[offset] | ||
highpassfilter=0 | ||
lowpassfilter=0 | ||
notchfilter=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import explorepy | ||
|
||
expdev = explorepy.Explore() | ||
expdev.connect("Explore_AAAI") | ||
expdev.push2lsl() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
[general] | ||
debug=2 | ||
delay=0.1 | ||
|
||
[redis] | ||
hostname=localhost | ||
port=6379 | ||
|
||
[fieldtrip] | ||
hostname=localhost | ||
port=1973 | ||
timeout=30 | ||
|
||
[input] | ||
; this specifies the channels from the FieldTrip buffer | ||
; the channel names (on the left) can be specified as you like | ||
channel1=1 | ||
channel2=2 | ||
; channel3=3 | ||
; channel4=4 | ||
; channel5=5 | ||
; channel6=6 | ||
; channel7=7 | ||
; channel8=8 | ||
|
||
[processing] | ||
; the sliding window is specified in seconds | ||
window=5.0 | ||
|
||
[scale] | ||
window=1 | ||
|
||
[offset] | ||
window=0 | ||
|
||
[band] | ||
; the frequency bands can be specified as you like, but must be all lower-case | ||
; you should give the lower and upper range of each band | ||
delta=2-5 | ||
theta=5-8 | ||
alpha=8-12 | ||
beta=12-30 | ||
gamma=35-45 | ||
|
||
[output] | ||
; the results will be written to Redis as "spectral.channel1.alpha" etc. | ||
prefix=spectral |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.