Skip to content

Commit 355b268

Browse files
committed
flush
1 parent b8ec76b commit 355b268

File tree

8 files changed

+234
-1
lines changed

8 files changed

+234
-1
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
*.DS_Store
44

55
# npm packages
6-
logger/node_modules/*
6+
logger/node_modules/*
7+
8+
analysis

explorer_analysis/README.md

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Fusion Explorer Analysis
2+
3+
A set of scripts and resources for analyzing data recorded on [Fusion](https://usefusion.app)
4+
5+
eeg.py is a file that helps one analyze the data they have collected. Below is a description of what each of the functions in it do.
6+
7+
rnOccur: finds the nth occurrence of v in arr
8+
9+
extractBundledEEG: init: creates files to separte useful information by tags such as event or description addMeta: helps make data more understandable by adding categorical information to the csv file prune: filters out all events that do not have any eeg data to support them extractByID: finds the location of all the json files that have a specific event extractByTags: finds the location of all the json fiels that have a specific tag mergeTagsWithRegex: consolidates data by combining data that have the same tag mergeCategories: creates a new category with all the categories passed in
10+
11+
load_data: loads the eeg data to be used
12+
13+
get_signal_quality_summary: counts how many signals from each eeg channel is good and then returns the percentage of those that are good
14+
15+
load_session_epochs: I was a little confused about this one- i don't know what an epoch is
16+
17+
load_session_summery: computes a quantitive summary of eeg data including average power by band, average power by channel, etc
18+
19+
analysisEngine: init: Generates basic analytics for recording groups distributionVetting: generates graphs for each epoch wave basicComparisons: generates graphs that compare the accummulated power bands for each wave trendAnalysis: generates a graph with how a specific variable progressed with time
20+
21+
get_rolling_powerByBand: checks whether there is a difference in data depending on the time interval in which the data is collected
22+
23+
unix_to_period: converts the timestamps collected to one more readable to us
24+
25+
unix_to_localdate: converts the date collected to one more readable to us
26+
27+
load_sessions: loads the sessions
28+
29+
load_fileset: loads data

explorer_analysis/eeg.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# run fooof implementation
File renamed without changes.
File renamed without changes.

explorer_recordings/read_brainflow.py

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import argparse
2+
import time
3+
4+
from brainflow.board_shim import BoardShim, BrainFlowInputParams
5+
6+
7+
def main():
8+
BoardShim.enable_dev_board_logger()
9+
10+
parser = argparse.ArgumentParser()
11+
# use docs to check which parameters are required for specific board, e.g. for Cyton - set serial port
12+
parser.add_argument('--timeout', type=int, help='timeout for device discovery or connection', required=False,
13+
default=0)
14+
parser.add_argument('--ip-port', type=int, help='ip port', required=False, default=0)
15+
parser.add_argument('--ip-protocol', type=int, help='ip protocol, check enum', required=False,
16+
default=0)
17+
parser.add_argument('--ip-address', type=str, help='ip address', required=False, default='')
18+
parser.add_argument('--serial-port', type=str, help='serial port', required=False, default='')
19+
parser.add_argument('--mac-address', type=str, help='mac address', required=False, default='')
20+
parser.add_argument('--other-info', type=str, help='other info', required=False, default='')
21+
parser.add_argument('--streamer-params', type=str, help='streamer params', required=False, default='')
22+
parser.add_argument('--serial-number', type=str, help='serial number', required=False, default='')
23+
parser.add_argument('--board-id', type=int, help='board id, check docs to get a list of supported boards',
24+
required=True)
25+
parser.add_argument('--file', type=str, help='file', required=False, default='')
26+
args = parser.parse_args()
27+
28+
params = BrainFlowInputParams()
29+
params.ip_port = args.ip_port
30+
params.serial_port = args.serial_port
31+
params.mac_address = args.mac_address
32+
params.other_info = args.other_info
33+
params.serial_number = args.serial_number
34+
params.ip_address = args.ip_address
35+
params.ip_protocol = args.ip_protocol
36+
params.timeout = args.timeout
37+
params.file = args.file
38+
39+
board = BoardShim(args.board_id, params)
40+
board.prepare_session()
41+
# board.start_stream () # use this for default options
42+
board.start_stream(45000, args.streamer_params)
43+
# time.sleep(10)
44+
data = board.get_current_board_data (256) # get latest 256 packages or less, doesnt remove them from internal buffer
45+
data = board.get_board_data() # get all data and remove it from internal buffer
46+
board.stop_stream()
47+
board.release_session()
48+
49+
print(data)
50+
51+
52+
if __name__ == "__main__":
53+
main()
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import time
2+
3+
from brainflow.board_shim import BoardShim, BrainFlowInputParams, LogLevels, BoardIds
4+
from brainflow.data_filter import DataFilter, WindowOperations, DetrendOperations
5+
6+
7+
def main():
8+
BoardShim.enable_dev_board_logger()
9+
10+
# use synthetic board for demo
11+
params = BrainFlowInputParams()
12+
board_id = BoardIds.SYNTHETIC_BOARD.value
13+
board_descr = BoardShim.get_board_descr(board_id)
14+
sampling_rate = int(board_descr['sampling_rate'])
15+
board = BoardShim(board_id, params)
16+
board.prepare_session()
17+
board.start_stream()
18+
BoardShim.log_message(LogLevels.LEVEL_INFO.value, 'start sleeping in the main thread')
19+
time.sleep(10)
20+
nfft = DataFilter.get_nearest_power_of_two(sampling_rate)
21+
data = board.get_board_data()
22+
board.stop_stream()
23+
board.release_session()
24+
25+
eeg_channels = board_descr['eeg_channels']
26+
# second eeg channel of synthetic board is a sine wave at 10Hz, should see huge alpha
27+
eeg_channel = eeg_channels[1]
28+
# optional detrend
29+
DataFilter.detrend(data[eeg_channel], DetrendOperations.LINEAR.value)
30+
psd = DataFilter.get_psd_welch(data[eeg_channel], nfft, nfft // 2, sampling_rate,
31+
WindowOperations.BLACKMAN_HARRIS.value)
32+
33+
band_power_alpha = DataFilter.get_band_power(psd, 7.0, 13.0)
34+
band_power_beta = DataFilter.get_band_power(psd, 14.0, 30.0)
35+
print("alpha/beta:%f", band_power_alpha / band_power_beta)
36+
37+
38+
if __name__ == "__main__":
39+
main()
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import argparse
2+
import logging
3+
4+
import pyqtgraph as pg
5+
from brainflow.board_shim import BoardShim, BrainFlowInputParams, BoardIds
6+
from brainflow.data_filter import DataFilter, FilterTypes, DetrendOperations
7+
from pyqtgraph.Qt import QtGui, QtCore
8+
9+
10+
class Graph:
11+
def __init__(self, board_shim):
12+
self.board_id = board_shim.get_board_id()
13+
self.board_shim = board_shim
14+
self.exg_channels = BoardShim.get_exg_channels(self.board_id)
15+
self.sampling_rate = BoardShim.get_sampling_rate(self.board_id)
16+
self.update_speed_ms = 50
17+
self.window_size = 4
18+
self.num_points = self.window_size * self.sampling_rate
19+
20+
self.app = QtGui.QApplication([])
21+
self.win = pg.GraphicsWindow(title='BrainFlow Plot', size=(800, 600))
22+
23+
self._init_timeseries()
24+
25+
timer = QtCore.QTimer()
26+
timer.timeout.connect(self.update)
27+
timer.start(self.update_speed_ms)
28+
QtGui.QApplication.instance().exec_()
29+
30+
def _init_timeseries(self):
31+
self.plots = list()
32+
self.curves = list()
33+
for i in range(len(self.exg_channels)):
34+
p = self.win.addPlot(row=i, col=0)
35+
p.showAxis('left', False)
36+
p.setMenuEnabled('left', False)
37+
p.showAxis('bottom', False)
38+
p.setMenuEnabled('bottom', False)
39+
if i == 0:
40+
p.setTitle('TimeSeries Plot')
41+
self.plots.append(p)
42+
curve = p.plot()
43+
self.curves.append(curve)
44+
45+
def update(self):
46+
data = self.board_shim.get_current_board_data(self.num_points)
47+
for count, channel in enumerate(self.exg_channels):
48+
# plot timeseries
49+
DataFilter.detrend(data[channel], DetrendOperations.CONSTANT.value)
50+
DataFilter.perform_bandpass(data[channel], self.sampling_rate, 3.0, 45.0, 2,
51+
FilterTypes.BUTTERWORTH.value, 0)
52+
DataFilter.perform_bandstop(data[channel], self.sampling_rate, 48.0, 52.0, 2,
53+
FilterTypes.BUTTERWORTH.value, 0)
54+
DataFilter.perform_bandstop(data[channel], self.sampling_rate, 58.0, 62.0, 2,
55+
FilterTypes.BUTTERWORTH.value, 0)
56+
self.curves[count].setData(data[channel].tolist())
57+
58+
self.app.processEvents()
59+
60+
61+
def main():
62+
BoardShim.enable_dev_board_logger()
63+
logging.basicConfig(level=logging.DEBUG)
64+
65+
parser = argparse.ArgumentParser()
66+
# use docs to check which parameters are required for specific board, e.g. for Cyton - set serial port
67+
parser.add_argument('--timeout', type=int, help='timeout for device discovery or connection', required=False,
68+
default=0)
69+
parser.add_argument('--ip-port', type=int, help='ip port', required=False, default=0)
70+
parser.add_argument('--ip-protocol', type=int, help='ip protocol, check IpProtocolType enum', required=False,
71+
default=0)
72+
parser.add_argument('--ip-address', type=str, help='ip address', required=False, default='')
73+
parser.add_argument('--serial-port', type=str, help='serial port', required=False, default='')
74+
parser.add_argument('--mac-address', type=str, help='mac address', required=False, default='')
75+
parser.add_argument('--other-info', type=str, help='other info', required=False, default='')
76+
parser.add_argument('--streamer-params', type=str, help='streamer params', required=False, default='')
77+
parser.add_argument('--serial-number', type=str, help='serial number', required=False, default='')
78+
parser.add_argument('--board-id', type=int, help='board id, check docs to get a list of supported boards',
79+
required=False, default=BoardIds.SYNTHETIC_BOARD)
80+
parser.add_argument('--file', type=str, help='file', required=False, default='')
81+
args = parser.parse_args()
82+
83+
params = BrainFlowInputParams()
84+
params.ip_port = args.ip_port
85+
params.serial_port = args.serial_port
86+
params.mac_address = args.mac_address
87+
params.other_info = args.other_info
88+
params.serial_number = args.serial_number
89+
params.ip_address = args.ip_address
90+
params.ip_protocol = args.ip_protocol
91+
params.timeout = args.timeout
92+
params.file = args.file
93+
94+
try:
95+
board_shim = BoardShim(args.board_id, params)
96+
board_shim.prepare_session()
97+
board_shim.start_stream(450000, args.streamer_params)
98+
Graph(board_shim)
99+
except BaseException:
100+
logging.warning('Exception', exc_info=True)
101+
finally:
102+
logging.info('End')
103+
if board_shim.is_prepared():
104+
logging.info('Releasing session')
105+
board_shim.release_session()
106+
107+
108+
if __name__ == '__main__':
109+
main()

0 commit comments

Comments
 (0)