Skip to content

Commit df2daa2

Browse files
authored
Merge pull request #975 from OpenBCI/development
GUI 5.0.5
2 parents f78cefa + 408b215 commit df2daa2

17 files changed

+997
-76
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# v5.0.5
2+
3+
### Improvements
4+
* Implement Focus Widget using BrainFlow Metrics! #924
5+
* Throw a popup if users are are running an old version of Windows operating system. GUI v5 supports 64-bit Windows 8, 8.1, and 10. #964
6+
* Throw a popup if Windows users are using 32-bit Java and Processing. #964
7+
* Set Networking Widget default baud rate for Serial output to 57600
8+
9+
### Bug Fixes
10+
* Fix Y axis Autoscale in TimeSeries when all values are less than zero. Example: Cyton with filters off
11+
* Gracefully handle cases when Cyton or Cyton+Daisy users want to use 8 or 16 channels #954
12+
* Update Save Session Settings success message. Session settings are no longer auto-loaded on Session start. #969
13+
* Session settings are no longer auto-saved when system is halted #969
14+
115
# v5.0.4
216

317
### Improvements
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import argparse
2+
import time
3+
import numpy as np
4+
import brainflow
5+
from brainflow.board_shim import BoardShim, BrainFlowInputParams, LogLevels, BoardIds
6+
from brainflow.data_filter import DataFilter, FilterTypes, AggOperations
7+
from pylsl import StreamInfo, StreamOutlet
8+
9+
#from queue import Queue
10+
BoardShim.enable_dev_board_logger()
11+
params = BrainFlowInputParams()
12+
params.serial_port = '/dev/cu.usbserial-DM00D7TW'
13+
board = BoardShim(BoardIds.CYTON_BOARD.value, params) # added cyton board id here
14+
srate = board.get_sampling_rate(BoardIds.CYTON_BOARD.value)
15+
board.prepare_session()
16+
board.start_stream()
17+
eeg_chan = BoardShim.get_eeg_channels(BoardIds.CYTON_BOARD.value)
18+
aux_chan = BoardShim.get_accel_channels(BoardIds.CYTON_BOARD.value)
19+
20+
print('EEG channels:')
21+
print(eeg_chan)
22+
print('Accelerometer channels')
23+
print(aux_chan)
24+
25+
# define lsl streams
26+
27+
# Defining stream info:
28+
name = 'OpenBCIEEG'
29+
ID = 'OpenBCIEEG'
30+
channels = 8
31+
sample_rate = 250
32+
datatype = 'float32'
33+
streamType = 'EEG'
34+
35+
print(f"Creating LSL stream for EEG. \nName: {name}\nID: {ID}\n")
36+
info_eeg = StreamInfo(name, streamType, channels, sample_rate, datatype, ID)
37+
chns = info_eeg.desc().append_child("channels")
38+
for label in ["AFp1", "AFp2", "C3", "C4", "P7", "P8", "O1", "O2"]:
39+
ch = chns.append_child("channel")
40+
ch.append_child_value("label", label)
41+
info_aux = StreamInfo('OpenBCIAUX', 'AUX', 3, 250, 'float32', 'OpenBCItestAUX')
42+
chns = info_aux.desc().append_child("channels")
43+
for label in ["X", "Y", "Z"]:
44+
ch = chns.append_child("channel")
45+
ch.append_child_value("label", label)
46+
outlet_aux = StreamOutlet(info_aux)
47+
outlet_eeg = StreamOutlet(info_eeg)
48+
49+
# construct a numpy array that contains only eeg channels and aux channels with correct scaling
50+
# this streams to lsl
51+
while True:
52+
data = board.get_board_data() # this gets data continiously
53+
# don't send empty data
54+
if len(data[0]) < 1 : continue
55+
eeg_data = data[eeg_chan]
56+
aux_data = data[aux_chan]
57+
#print(scaled_eeg_data)
58+
#print(scaled_aux_data)
59+
#print('------------------------------------------------------------------------------------------')
60+
eegchunk = []
61+
for i in range(len(eeg_data[0])):
62+
eegchunk.append((eeg_data[:,i]).tolist()) #scale data here
63+
outlet_eeg.push_chunk(eegchunk)
64+
auxchunk = []
65+
for i in range(len(aux_data[0])):
66+
auxchunk.append((aux_data[:,i]).tolist()) #scale data here
67+
outlet_aux.push_chunk(auxchunk)

Networking-Test-Kit/splitLargeCSV.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
import os
3+
import csv
4+
5+
6+
def split(filehandler, delimiter=',', row_limit=4000000,
7+
output_name_template='output_%s.csv', output_path='.', keep_headers=True):
8+
9+
reader = csv.reader(filehandler, delimiter=delimiter)
10+
current_piece = 1
11+
current_out_path = os.path.join(
12+
output_path,
13+
output_name_template % current_piece
14+
)
15+
current_out_writer = csv.writer(open(current_out_path, 'w', newline=''), delimiter=delimiter)
16+
current_limit = row_limit
17+
headers = []
18+
if keep_headers:
19+
for i in range (5):
20+
headerRow = next(reader);
21+
headers.append(headerRow)
22+
current_out_writer.writerow(headerRow)
23+
24+
for i, row in enumerate(reader):
25+
if i + 1 > current_limit:
26+
current_piece += 1
27+
current_limit = row_limit * current_piece
28+
current_out_path = os.path.join(
29+
output_path,
30+
output_name_template % current_piece
31+
)
32+
current_out_writer = csv.writer(open(current_out_path, 'w', newline=''), delimiter=delimiter)
33+
if keep_headers:
34+
for headerRowI in headers:
35+
current_out_writer.writerow(headerRowI)
36+
print (headerRowI)
37+
print (i)
38+
current_out_writer.writerow(row)
39+
40+
split(open('OpenBCI-RAW-2021-04-05_21-49-12.txt', 'r'));

OpenBCI_GUI/ADS1299SettingsController.pde

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class ADS1299SettingsController {
218218
resizeDropdowns(chanBar_h);
219219

220220
resizeCustomCommandUI();
221+
221222
}
222223

223224
//Returns true if board and UI are in sync
@@ -382,10 +383,10 @@ class ADS1299SettingsController {
382383
}
383384

384385
private void createCustomCommandUI() {
385-
final Textfield _tf = hwsCp5.addTextfield("customCommand")
386+
customCommandTF = hwsCp5.addTextfield("customCommand")
386387
.setPosition(0, 0)
387388
.setCaptionLabel("")
388-
.setSize(10, 10)
389+
.setSize(120, 20)
389390
.setFont(f2)
390391
.setFocus(false)
391392
.setColor(color(26, 26, 26))
@@ -398,22 +399,21 @@ class ADS1299SettingsController {
398399
.align(5, 10, 20, 40)
399400
.setAutoClear(false) //Don't clear textfield when pressing Enter key
400401
;
401-
_tf.setDescription("Type a custom command and Send to board.");
402+
customCommandTF.setDescription("Type a custom command and Send to board.");
402403
//Clear textfield on double click
403-
_tf.onDoublePress(new CallbackListener() {
404+
customCommandTF.onDoublePress(new CallbackListener() {
404405
public void controlEvent(CallbackEvent theEvent) {
405406
output("[ExpertMode] Enter the custom command you would like to send to the board.");
406-
_tf.clear();
407+
customCommandTF.clear();
407408
}
408409
});
409-
_tf.addCallback(new CallbackListener() {
410+
customCommandTF.addCallback(new CallbackListener() {
410411
public void controlEvent(CallbackEvent theEvent) {
411412
if ((theEvent.getAction() == ControlP5.ACTION_BROADCAST) || (theEvent.getAction() == ControlP5.ACTION_LEAVE)) {
412-
_tf.setFocus(false);
413+
customCommandTF.setFocus(false);
413414
}
414415
}
415416
});
416-
customCommandTF = _tf;
417417

418418
sendCustomCmdButton = createButton(hwsCp5, "sendCustomCommand", "Send Custom Command", 0, 0, 10, 10);
419419
sendCustomCmdButton.setBorderColor(OBJECT_BORDER_GREY);
@@ -434,7 +434,7 @@ class ADS1299SettingsController {
434434
resizeCustomCommandUI();
435435
}
436436

437-
private void resizeCustomCommandUI() {
437+
public void resizeCustomCommandUI() {
438438
customCmdUI_x = x;
439439
customCmdUI_w = w + 1;
440440
int tf_w = Math.round(button_w * 1.8);
@@ -445,7 +445,8 @@ class ADS1299SettingsController {
445445
//int tf_w = Math.round((customCmdUI_w - padding_3*2) * .75);
446446
int tf_h = commandBarH - padding_3*2;
447447
customCommandTF.setPosition(tf_x, tf_y);
448-
customCommandTF.setSize(tf_w, tf_h);
448+
customCommandTF.setWidth(tf_w);
449+
customCommandTF.setHeight(tf_h);
449450
int but_x = tf_x + customCommandTF.getWidth() + padding_3;
450451
sendCustomCmdButton.setPosition(but_x, tf_y);
451452
sendCustomCmdButton.setSize(but_w, tf_h - 1);

OpenBCI_GUI/DataProcessing.pde

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ void processNewData() {
3333

3434
//update the data buffers
3535
for (int Ichan=0; Ichan < channelCount; Ichan++) {
36-
3736
for(int i = 0; i < getCurrentBoardBufferSize(); i++) {
3837
dataProcessingRawBuffer[Ichan][i] = (float)currentData.get(i)[exgChannels[Ichan]];
3938
}

OpenBCI_GUI/Extras.pde

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ private boolean isMac() {
2626
return !isWindows() && !isLinux();
2727
}
2828

29+
//BrainFlow only supports Windows 8 and 10. This will help with OpenBCI support tickets. #964
30+
private void checkIsOldVersionOfWindowsOS() {
31+
boolean isOld = SystemUtils.IS_OS_WINDOWS_7 || SystemUtils.IS_OS_WINDOWS_VISTA || SystemUtils.IS_OS_WINDOWS_XP;
32+
if (isOld) {
33+
PopupMessage msg = new PopupMessage("Old Windows OS Detected", "OpenBCI GUI v5 and BrainFlow are made for 64-bit Windows 8, 8.1, and 10. Please update your OS, computer, or revert to GUI v4.2.0.");
34+
}
35+
}
36+
37+
//Sanity check for 64-bit Java for Windows users #964
38+
private void checkIs64BitJava() {
39+
boolean is64Bit = System.getProperty("sun.arch.data.model").indexOf("64") >= 0;
40+
if (!is64Bit) {
41+
PopupMessage msg = new PopupMessage("32-bit Java Detected", "OpenBCI GUI v5 and BrainFlow are made for 64-bit Java (Windows, Linux, and Mac). Please update your OS, computer, Processing IDE, or revert to GUI v4 or earlier.");
42+
}
43+
}
44+
2945

3046
//compute the standard deviation
3147
float std(float[] data) {

0 commit comments

Comments
 (0)