Permalink
Browse files

Merge branch 'development' into development

  • Loading branch information...
2 parents 0566b2e + 4059179 commit 0b30e219be85751338df2734f80bb09ef4968407 @biomurph biomurph committed on GitHub Jun 12, 2017
Showing with 2,138 additions and 933 deletions.
  1. +1 −0 .gitignore
  2. +11 −0 CHANGELOG.md
  3. 0 Icon
  4. +100 −423 OpenBCI_GUI/ControlPanel.pde
  5. +1 −1 OpenBCI_GUI/DataLogging.pde
  6. +85 −8 OpenBCI_GUI/DataProcessing.pde
  7. +12 −3 OpenBCI_GUI/GanglionSync.pde
  8. +0 −8 OpenBCI_GUI/HardwareSync.pde
  9. +18 −6 OpenBCI_GUI/Interactivity.pde
  10. +0 −228 OpenBCI_GUI/Networking.pde
  11. +23 −24 OpenBCI_GUI/OpenBCI_GUI.pde
  12. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-17_19-04-34.jpg
  13. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-17_19-04-36.jpg
  14. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-17_19-04-37.jpg
  15. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-17_19-04-38.jpg
  16. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-17_19-04-40.jpg
  17. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-22_10-18-48.jpg
  18. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-22_10-18-52.jpg
  19. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-22_10-19-15.jpg
  20. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-41-32.jpg
  21. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-41-55.jpg
  22. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-06.jpg
  23. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-26.jpg
  24. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-29.jpg
  25. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-31.jpg
  26. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-33.jpg
  27. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-01-27_13-42-34.jpg
  28. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-02-02_23-06-29.jpg
  29. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-02-02_23-06-30.jpg
  30. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-02-02_23-06-34.jpg
  31. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-02-02_23-06-35.jpg
  32. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-02-02_23-06-36.jpg
  33. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-03-04_02-26-27.jpg
  34. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-03-04_02-26-29.jpg
  35. BIN OpenBCI_GUI/SavedData/OpenBCI-2017-03-04_02-26-32.jpg
  36. +137 −0 OpenBCI_GUI/W_BandPower.pde
  37. +56 −3 OpenBCI_GUI/W_headPlot.pde
  38. +1,502 −63 OpenBCI_GUI/W_networking.pde
  39. +4 −0 OpenBCI_GUI/Widget.pde
  40. +26 −4 OpenBCI_GUI/WidgetManager.pde
  41. +1 −1 README.md
  42. BIN libraries/LSLLink/library/LSLLink.jar
  43. +130 −130 libraries/LSLLink/src/main/java/edu/ucsd/sccn/LSL.java
  44. BIN libraries/LSLLink/src/main/resources/{ → darwin}/liblsl32.dylib
  45. BIN libraries/LSLLink/src/main/resources/{ → darwin}/liblsl64.dylib
  46. BIN libraries/LSLLink/src/main/resources/linux-x86-64/liblsl64.so
  47. BIN libraries/LSLLink/src/main/resources/{ → win32-amd64}/liblsl32.dll
  48. BIN libraries/LSLLink/src/main/resources/{ → win32-amd64}/liblsl64.dll
  49. BIN libraries/LSLLink/src/main/resources/win32-x86-64/liblsl32.dll
  50. BIN libraries/LSLLink/src/main/resources/win32-x86-64/liblsl64.dll
  51. +8 −8 libraries/controlP5/src/controlP5/ControllerGroup.java
  52. +23 −23 libraries/controlP5/src/controlP5/RadioButton.java
View
@@ -8,3 +8,4 @@ OpenBCI_GUI/build/source/*.java
*.app
OpenBCI_GUI/SavedData
OpenBCI_GUI/SavedData/EEG_Data/SDconverted-*
+OpenBCI_GUI/data/EEG_Data/*
View
@@ -1,3 +1,14 @@
+# 2.2.0
+
+### Bug Fixes
+* Fix #151 - Incorrect number of channels on playback caused index out of bounds errors.
+* Addresses #149 - Allows for proper scaling of channels with four thanks to #151 #157
+
+### New Features
+* Band power widget #153 (thanks @sunwangshu)
+* Closes #138 - Able to drag and drop the electrodes on the head map (thanks @liqwid)
+* Closes #142 - GUI needs to pass key strokes to Ganglion
+
# 2.1.2
### Bug Fixes
View
No changes.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -1475,4 +1475,4 @@ public void convertSDFile() {
dataWriter.println();
}
}
-}
+}
@@ -11,6 +11,14 @@ HashMap<String,float[][]> processed_file;
HashMap<Integer,String> index_of_times;
HashMap<String,Integer> index_of_times_rev;
+// indexs
+final int DELTA = 0; // 1-4 Hz
+final int THETA = 1; // 4-8 Hz
+final int ALPHA = 2; // 8-13 Hz
+final int BETA = 3; // 13-30 Hz
+final int GAMMA = 4; // 30-55 Hz
+
+
//------------------------------------------------------------------------
// Global Functions
//------------------------------------------------------------------------
@@ -109,6 +117,8 @@ int getDataIfAvailable(int pointCounter) {
//if (eegDataSource==DATASOURCE_PLAYBACKFILE) println("OpenBCI_GUI: getDataIfAvailable: currentTableRowIndex = " + currentTableRowIndex);
//println("OpenBCI_GUI: getDataIfAvailable: pointCounter = " + pointCounter);
} // close "has enough time passed"
+ else{
+ }
}
return pointCounter;
}
@@ -154,6 +164,7 @@ void processNewData() {
// w_openbionics.process();
dataProcessing_user.process(yLittleBuff_uV, dataBuffY_uV, dataBuffY_filtY_uV, fftBuff);
+ dataProcessing.newDataToSend = true;
//look to see if the latest data is railed so that we can notify the user on the GUI
for (int Ichan=0; Ichan < nchan; Ichan++) is_railed[Ichan].update(dataPacketBuff[lastReadDataPacketInd].values[Ichan]);
@@ -330,12 +341,14 @@ int getPlaybackDataFromTable(Table datatable, int currentTableRowIndex, float sc
if(!isRunning){
try{
- if(!isOldData) row.getString(nchan+4);
- else row.getString(nchan+3);
+ row.getString(nchan+3);
- nchan = 16;
+ // nchan = 16; AJK 5/31/17 see issue #151
+ }
+ catch (ArrayIndexOutOfBoundsException e){
+ println(e);
+ println("8 Channel");
}
- catch (ArrayIndexOutOfBoundsException e){ println("8 Channel");}
}
}
@@ -357,14 +370,26 @@ class DataProcessing {
private int currentNotch_ind = 0; // set to 0 to default to 60Hz, set to 1 to default to 50Hz
float data_std_uV[];
float polarity[];
-
+ boolean newDataToSend;
+ private String[] binNames;
+ final int[] processing_band_low_Hz = {
+ 1, 4, 8, 13, 30
+ }; //lower bound for each frequency band of interest (2D classifier only)
+ final int[] processing_band_high_Hz = {
+ 4, 8, 13, 30, 55
+ }; //upper bound for each frequency band of interest
+ float avgPowerInBins[][];
+ float headWidePower[];
+ int numBins;
DataProcessing(int NCHAN, float sample_rate_Hz) {
nchan = NCHAN;
fs_Hz = sample_rate_Hz;
data_std_uV = new float[nchan];
polarity = new float[nchan];
-
+ newDataToSend = false;
+ avgPowerInBins = new float[nchan][processing_band_low_Hz.length];
+ headWidePower = new float[processing_band_low_Hz.length];
//check to make sure the sample rate is acceptable and then define the filters
if (abs(fs_Hz-250.0f) < 1.0) {
@@ -650,8 +675,15 @@ class DataProcessing {
//convert to uV_per_bin...still need to confirm the accuracy of this code.
//Do we need to account for the power lost in the windowing function? CHIP 2014-10-24
- for (int I=0; I < fftBuff[Ichan].specSize(); I++) { //loop over each FFT bin
- fftBuff[Ichan].setBand(I, (float)(fftBuff[Ichan].getBand(I) / fftBuff[Ichan].specSize()));
+
+ // FFT ref: https://www.mathworks.com/help/matlab/ref/fft.html
+ // first calculate double-sided FFT amplitude spectrum
+ for (int I=0; I <= Nfft/2; I++) {
+ fftBuff[Ichan].setBand(I, (float)(fftBuff[Ichan].getBand(I) / Nfft));
+ }
+ // then convert into single-sided FFT spectrum: DC & Nyquist (i=0 & i=N/2) remain the same, others multiply by two.
+ for (int I=1; I < Nfft/2; I++) {
+ fftBuff[Ichan].setBand(I, (float)(fftBuff[Ichan].getBand(I) * 2));
}
//average the FFT with previous FFT data so that it makes it smoother in time
@@ -674,9 +706,47 @@ class DataProcessing {
foo = java.lang.Math.sqrt(foo);
}
fftBuff[Ichan].setBand(I, (float)foo); //put the smoothed data back into the fftBuff data holder for use by everyone else
+ // fftBuff[Ichan].setBand(I, 1.0f); // test
} //end loop over FFT bins
+
+ // calculate single-sided psd by single-sided FFT amplitude spectrum
+ // PSD ref: https://www.mathworks.com/help/dsp/ug/estimate-the-power-spectral-density-in-matlab.html
+ // when i = 1 ~ (N/2-1), psd = (N / fs) * mag(i)^2 / 4
+ // when i = 0 or i = N/2, psd = (N / fs) * mag(i)^2
+
+ for (int i = 0; i < processing_band_low_Hz.length; i++) {
+ float sum = 0;
+ // int binNum = 0;
+ for (int Ibin = 0; Ibin <= Nfft/2; Ibin ++) { // loop over FFT bins
+ float FFT_freq_Hz = fftBuff[Ichan].indexToFreq(Ibin); // center frequency of this bin
+ float psdx = 0;
+ // if the frequency matches a band
+ if (FFT_freq_Hz >= processing_band_low_Hz[i] && FFT_freq_Hz < processing_band_high_Hz[i]) {
+ if (Ibin != 0 && Ibin != Nfft/2) {
+ psdx = fftBuff[Ichan].getBand(Ibin) * fftBuff[Ichan].getBand(Ibin) * Nfft/get_fs_Hz_safe() / 4;
+ }
+ else {
+ psdx = fftBuff[Ichan].getBand(Ibin) * fftBuff[Ichan].getBand(Ibin) * Nfft/get_fs_Hz_safe();
+ }
+ sum += psdx;
+ // binNum ++;
+ }
+ }
+ avgPowerInBins[Ichan][i] = sum; // total power in a band
+ // println(i, binNum, sum);
+ }
} //end the loop over channels.
+ for (int i = 0; i < processing_band_low_Hz.length; i++) {
+ float sum = 0;
+
+ for (int j = 0; j < nchan; j++) {
+ sum += avgPowerInBins[j][i];
+ }
+ headWidePower[i] = sum/nchan; // averaging power over all channels
+ }
+ //delta in channel 2 ... avgPowerInBins[1][DELTA];
+ //headwide beta ... headWidePower[BETA];
//find strongest channel
int refChanInd = findMax(data_std_uV);
@@ -696,5 +766,12 @@ class DataProcessing {
polarity[Ichan]=-1.0;
}
}
+
+ // println("Brain Wide DELTA = " + headWidePower[DELTA]);
+ // println("Brain Wide THETA = " + headWidePower[THETA]);
+ // println("Brain Wide ALPHA = " + headWidePower[ALPHA]);
+ // println("Brain Wide BETA = " + headWidePower[BETA]);
+ // println("Brain Wide GAMMA = " + headWidePower[GAMMA]);
+
}
}
@@ -419,7 +419,7 @@ class OpenBCI_Ganglion {
}
}
}
-
+
private void processStatus(String msg) {
String[] list = split(msg, ',');
int code = Integer.parseInt(list[1]);
@@ -430,7 +430,7 @@ class OpenBCI_Ganglion {
if (code == RESP_ERROR_BAD_NOBLE_START) {
println("OpenBCI_Ganglion: processStatus: Problem in the Hub");
output("Problem starting Ganglion Hub. Please make sure compatible USB is configured, then restart this GUI.");
- } else {
+ } else {
println("OpenBCI_Ganglion: processStatus: Started Successfully");
}
}
@@ -611,6 +611,15 @@ class OpenBCI_Ganglion {
safeTCPWrite(TCP_CMD_COMMAND + "," + command_stop + TCP_STOP);
}
+
+ /**
+ * @description Sends a command to ganglion board
+ */
+ public void passthroughCommand(char c) {
+ println("OpenBCI_Ganglion: passthroughCommand(): sending \'" + c);
+ safeTCPWrite(TCP_CMD_COMMAND + "," + c + TCP_STOP);
+ }
+
/**
* @description Write to TCP server
* @params out {String} - The string message to write to the server.
@@ -718,4 +727,4 @@ class OpenBCI_Ganglion {
controlPanel.open();
output("Ganglion now in bootloader mode! Enjoy!");
}
-};
+};
@@ -98,14 +98,6 @@ void serialEvent(Serial port){
numPacketsDropped = 0;
}
- //If networking enabled --> send data every sample if 8 channels or every other sample if 16 channels
- if (networkType !=0) {
- if (nchan==8) {
- sendRawData_dataPacket(dataPacketBuff[curDataPacketInd], openBCI.get_scale_fac_uVolts_per_count(), openBCI.get_scale_fac_accel_G_per_count());
- } else if ((nchan==16) && ((dataPacketBuff[curDataPacketInd].sampleIndex %2)!=1)) {
- sendRawData_dataPacket(dataPacketBuff[curDataPacketInd], openBCI.get_scale_fac_uVolts_per_count(), openBCI.get_scale_fac_accel_G_per_count());
- }
- }
switch (outputDataSource) {
case OUTPUT_SOURCE_ODF:
fileoutput_odf.writeRawData_dataPacket(dataPacketBuff[curDataPacketInd], openBCI.get_scale_fac_uVolts_per_count(), openBCI.get_scale_fac_accel_G_per_count());
@@ -236,6 +236,7 @@ void parseKey(char val) {
case 's':
println("case s...");
stopRunning();
+
// stopButtonWasPressed();
break;
case 'b':
@@ -319,12 +320,14 @@ void parseKey(char val) {
break;
default:
- println("OpenBCI_GUI: '" + key + "' Pressed...sending to OpenBCI...");
- // if (openBCI.serial_openBCI != null) openBCI.serial_openBCI.write(key);//send the value as ascii with a newline character
- //if (openBCI.serial_openBCI != null) openBCI.serial_openBCI.write(key);//send the value as ascii with a newline character
- openBCI.sendChar(key);
-
- break;
+ if (eegDataSource == DATASOURCE_NORMAL_W_AUX) {
+ println("Interactivity: '" + key + "' Pressed...sending to Cyton...");
+ openBCI.sendChar(key);
+ } else if (eegDataSource == DATASOURCE_GANGLION) {
+ println("Interactivity: '" + key + "' Pressed...sending to Ganglion...");
+ ganglion.passthroughCommand(key);
+ }
+ break;
}
}
@@ -443,7 +446,16 @@ void parseKeycode(int val) {
}
}
+void mouseDragged() {
+ if (systemMode >= SYSTEMMODE_POSTINIT) {
+
+ //calling mouse dragged inly outside of Control Panel
+ if (controlPanel.isOpen == false) {
+ wm.mouseDragged();
+ }
+ }
+}
//swtich yard if a click is detected
void mousePressed() {
Oops, something went wrong.

0 comments on commit 0b30e21

Please sign in to comment.