Skip to content
This repository has been archived by the owner on Apr 13, 2021. It is now read-only.

Commit

Permalink
Added filter switching on the fly, fixed release build issues
Browse files Browse the repository at this point in the history
  • Loading branch information
jdpigeon committed Mar 27, 2017
1 parent 61f082b commit aa73567
Show file tree
Hide file tree
Showing 26 changed files with 175 additions and 78 deletions.
1 change: 1 addition & 0 deletions EEG101/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ android {
}

dependencies {
compile project(':lottie-react-native')
compile project(':react-native-svg')
compile fileTree(dir: "libs", include: ["*.jar"])
// Animated Gif support
Expand Down
1 change: 1 addition & 0 deletions EEG101/android/app/src/main/assets/awakeasleep.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions EEG101/android/app/src/main/assets/epoching.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions EEG101/android/app/src/main/assets/fourier.json

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 44 additions & 38 deletions EEG101/android/app/src/main/assets/index.android.bundle

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
VO��#�n͋b�.�4��]h
,��o�ـ��$\m�X�����
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.choosemuse.libmuse.Muse;
import com.facebook.react.BuildConfig;
import com.facebook.react.ReactApplication;
import com.airbnb.android.react.lottie.LottiePackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
Expand All @@ -32,6 +33,7 @@ protected boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new LottiePackage(),
new SvgPackage(),
new EEGPackage()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void addLast(Number y) {
}
}

public void addAll(Number[] y) {
public void addAll(Double[] y) {
lock.writeLock().lock();
try {
yVals.addAll(Arrays.asList(y));
Expand All @@ -85,6 +85,21 @@ public void removeFirst() {
}
}

public void remove(int nbsamples) {
lock.writeLock().lock();
try {
if (size() <= 0) {
throw new NoSuchElementException();
}

for(int i = 0; i<nbsamples; i++){
yVals.removeFirst();
}
} finally {
lock.writeLock().unlock();
}
}

public void clear() {
lock.writeLock().lock();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class EEGGraph extends FrameLayout {
// Variables

public XYPlot eegPlot;
public static final int PLOT_LENGTH = 220;
public static final int PLOT_LENGTH = 1100;
private static final String PLOT_TITLE = "Raw_EEG";
public PlotUpdater plotUpdater;
EEGDataSource dataSource;
Expand Down Expand Up @@ -175,9 +175,15 @@ public void initView(Context context) {
// This is critical for being able to set the color of the plot
PixelUtils.init(getContext());



// Create line formatter with set color
lineFormatter = new FastLineAndPointRenderer.Formatter(Color.rgb(255, 255, 255), null, null, null);

// Set line thickness
//Float linethickness = new Float(1);
//lineFormatter.getLinePaint().setStrokeWidth(linethickness);

// add series to plot
eegPlot.addSeries(dataSeries,
lineFormatter);
Expand Down Expand Up @@ -284,8 +290,6 @@ class DataListener extends MuseDataListener {
Boolean isLowEnergy;

DataListener() {
Log.w("EEG", "Created Data Listener");
isLowEnergy = appState.connectedMuse.isLowEnergy();
}

@Override
Expand All @@ -294,11 +298,11 @@ public void receiveMuseDataPacket(final MuseDataPacket p, final Muse muse) {
eegBuffer.update(newData);
}

private void getEegChannelValues(double[] buffer, MuseDataPacket p) {
buffer[0] = p.getEegChannelValue(Eeg.EEG1);
buffer[1] = p.getEegChannelValue(Eeg.EEG2);
buffer[2] = p.getEegChannelValue(Eeg.EEG3);
buffer[3] = p.getEegChannelValue(Eeg.EEG4);
private void getEegChannelValues(double[] newData, MuseDataPacket p) {
newData[0] = p.getEegChannelValue(Eeg.EEG1);
newData[1] = p.getEegChannelValue(Eeg.EEG2);
newData[2] = p.getEegChannelValue(Eeg.EEG3);
newData[3] = p.getEegChannelValue(Eeg.EEG4);
}

@Override
Expand Down Expand Up @@ -365,9 +369,9 @@ public void run() {
dataSeries.removeFirst();
}

// Add last 1 datpoint from channel of interest in eegBuffer to dataseries
dataSeries.addLast(eegBuffer.extract(1)[0][channelOfInterest -1]);

//dataSeries.addAll(eegBuffer.extractSingleChannelTransposedAsDouble(10, channelOfInterest - 1));
dataSeries.addLast(eegBuffer.extract(1)[0][channelOfInterest - 1]);
if (isRecording) { fileWriter.addDataToFile(eegBuffer.extract(1)[0]);}

// resets the 'points-since-dataSource-read' value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ public class FilterGraph extends FrameLayout {
// Variables

public XYPlot filterPlot;
private static final int PLOT_LENGTH = 220;
private static final int PLOT_LENGTH = 1100;
private static final String PLOT_TITLE = "Filtered_EEG";
private int PLOT_LOW_BOUND = 600;
private int PLOT_HIGH_BOUND = 1000;
public MyPlotUpdater plotUpdater;
private FilterDataSource dataSource;
public DynamicSeries dataSeries;
Expand All @@ -65,7 +67,6 @@ public class FilterGraph extends FrameLayout {
// polynomial components determined by previous samples in the epoch. For more info, read the Rational Transfer Function description here: https://www.mathworks.com/help/matlab/ref/filter.html
public double[][] filtState;

public double[] newData = new double[4];

// Bridged props
// Default channelOfInterest = 1 (left ear)
Expand All @@ -90,27 +91,46 @@ public void setChannelOfInterest(int channel) {
}

public void setFilterType(String filterType) {
stopThreads();
dataSeries.clear();
Log.w("FilterGraph", "set Filter type");

if(appState.connectedMuse.isLowEnergy()) { filterFreq = 256; }
else { filterFreq = 220; }

Log.w("FilterGraph", filterType);

switch(filterType) {
case "lowpass":
case "LOWPASS":
PLOT_LOW_BOUND = 600;
PLOT_HIGH_BOUND = 1000;
filterPlot.setRangeBoundaries(PLOT_LOW_BOUND, PLOT_HIGH_BOUND, BoundaryMode.FIXED);
activeFilter = new Filter(filterFreq, "lowpass", 5, 36, 0);
filtState = new double[4][activeFilter.getNB()];
Log.w("FilterGraph", "set Rangeboundaries in setFilterType");
break;

case "bandpass":
case "BANDPASS":
PLOT_LOW_BOUND = -200;
PLOT_HIGH_BOUND = 200;
filterPlot.setRangeBoundaries(PLOT_LOW_BOUND, PLOT_HIGH_BOUND, BoundaryMode.FIXED);
activeFilter = new Filter(filterFreq, "bandpass", 5, 1, 36);
filtState = new double[4][activeFilter.getNB()];
Log.w("FilterGraph", "set Rangeboundaries in setFilterType");
break;

case "highpass":
case "HIGHPASS":
PLOT_LOW_BOUND = -200;
PLOT_HIGH_BOUND = 200;
filterPlot.setRangeBoundaries(PLOT_LOW_BOUND, PLOT_HIGH_BOUND, BoundaryMode.FIXED);
activeFilter = new Filter(filterFreq, "highpass", 2, 1, 0);
filtState = new double[4][activeFilter.getNB()];
Log.w("FilterGraph", "set Rangeboundaries in setFilterType");
break;

}
startDataThread();
startRenderingThread();
}

public void startRecording() {
Expand Down Expand Up @@ -143,7 +163,8 @@ public void initView(Context context) {
dataSeries = new DynamicSeries(PLOT_TITLE);

// Set X and Y domain
filterPlot.setRangeBoundaries(-200, 200, BoundaryMode.FIXED);
Log.w("FilterGraph", "Setting plot boundaries in init");
filterPlot.setRangeBoundaries(PLOT_LOW_BOUND, PLOT_HIGH_BOUND, BoundaryMode.FIXED);
filterPlot.setDomainBoundaries(0, PLOT_LENGTH, BoundaryMode.FIXED);

// add dataSeries to plot and define color of plotted line
Expand Down Expand Up @@ -202,11 +223,8 @@ public void onVisibilityChanged(View changedView, int visibility){
stopThreads();
}
else if (dataThread == null || !dataThread.isAlive()) {
startDataThread();
startRenderingThread();
dataListener = new museDataListener();
// Register a listener to receive dataSource packets from Muse. Second argument defines which type(s) of dataSource will be transmitted to listener
appState.connectedMuse.registerDataListener(dataListener, MuseDataPacketType.EEG);
//startDataThread();
//startRenderingThread();
}
}

Expand All @@ -216,22 +234,30 @@ else if (dataThread == null || !dataThread.isAlive()) {
// Start thread that will update the dataSource whenever a Muse dataSource packet is receive series
// and perform dataSource processing
public void startDataThread() {
Log.w("FilterGraph", "starting threads");
dataListener = new museDataListener();

// Register a listener to receive dataSource packets from Muse. Second argument defines which type(s) of dataSource will be transmitted to listener
appState.connectedMuse.registerDataListener(dataListener, MuseDataPacketType.EEG);
dataThread = new Thread (dataSource);
dataThread.start();
}

// Start thread that will render the plot at a fixed speed
public void startRenderingThread(){
Log.w("FilterGraph", "start renderThread");
renderingThread = new Thread (plotUpdater);
renderingThread.start();
}

// Stop all threads
public void stopThreads(){
Log.w("FilterGraph", "Stopping threads");
plotUpdater.stopThread();
dataSource.stopThread();

if (dataListener != null) {
Log.w("FilterGraph", "unregistering dataListener");
appState.connectedMuse.unregisterDataListener(dataListener, MuseDataPacketType.EEG);
}

Expand All @@ -242,8 +268,12 @@ public void stopThreads(){

// Listener that receives incoming Muse dataSource packets and updates the eegbuffer
class museDataListener extends MuseDataListener {
private double[] newData;

// Constructor
museDataListener() {
Log.w("FilterGraph", "dataListener constructed");
newData = new double[4];
}

// Called whenever an incoming dataSource packet is received. Handles different types of incoming dataSource packets and updates dataSource correctly
Expand All @@ -260,8 +290,7 @@ public void receiveMuseDataPacket(final MuseDataPacket p, final Muse muse) {
// Updates newData array based on incoming EEG channel values
private void getEegChannelValues(double[] newData, MuseDataPacket p) {
newData[0] = p.getEegChannelValue(Eeg.EEG1);
newData[1] = p. // Explicity visibility setting handles bug on older devices where graph wasn't starting
getEegChannelValue(Eeg.EEG2);
newData[1] = p.getEegChannelValue(Eeg.EEG2);
newData[2] = p.getEegChannelValue(Eeg.EEG3);
newData[3] = p.getEegChannelValue(Eeg.EEG4);
}
Expand Down Expand Up @@ -308,7 +337,7 @@ public void stopThread() {
public class FilterDataSource implements Runnable {
int stepSize;
private boolean keepRunning = true;
EEGFileWriter fileWriter = new EEGFileWriter(getContext(),PLOT_TITLE);
EEGFileWriter fileWriter = new EEGFileWriter(getContext(), PLOT_TITLE);
public boolean isRecording;

// Choosing these step sizes arbitrarily based on how they look
Expand All @@ -323,11 +352,13 @@ public FilterDataSource(Boolean isLowEnergy) {
@Override
public void run() {
try {
keepRunning = true;
while (keepRunning) {
if (eegBuffer.getPts() >= stepSize) {
if (dataSeries.size() >= PLOT_LENGTH) {
dataSeries.removeFirst();
}

dataSeries.addLast(filtResult[channelOfInterest - 1]);

if (isRecording) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public void setChannelOfInterest(FilterGraph graph, @Nullable int channel) {
// Bridge function for filterType Prop. Calls setFilterType in FilterGraph
@ReactProp(name = "filterType")
public void setFilterType(FilterGraph graph, @Nullable String filterType) {
Log.w("filterType", filterType);
graph.setFilterType(filterType);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.eeg_project.components.signal;

import android.util.Log;

import java.util.Arrays; // For printing arrays when debugging

// A pure Java implementation of a circular buffer
Expand Down Expand Up @@ -98,6 +100,27 @@ public double[] extractSingleChannelTransposed(int nbSamples, int channelofinter
return extractedArray;
}

public Double[] extractSingleChannelTransposedAsDouble(int nbSamples, int channelofinterest) {
// Return an array containing the last `nbSamples` collected in
// the circular buffer.
//
// The shape of the returned array is [nbSamples].
//
// This transposed version is useful to avoid additional looping
// through the returned array when computing FFT (the looping is
// instead done here.)

int extractIndex;
Double[] extractedArray = new Double[nbSamples];

for(int i = 0; i < nbSamples; i++) {
extractIndex = mod(index - nbSamples + i, bufferLength);
extractedArray[i] = buffer[extractIndex][channelofinterest];
}

return extractedArray;
}


public int getPts() { return pts; }

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions EEG101/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
rootProject.name = 'EEG101'
include ':lottie-react-native'
project(':lottie-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/lottie-react-native/lib/android')
include ':lottie-react-native'
project(':lottie-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/lottie-react-native/lib/android')
include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')

Expand Down
1 change: 1 addition & 0 deletions EEG101/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"global": "^4.3.1",
"lodash": "^4.16.4",
"lottie": "^0.0.1",
"lottie-react-native": "^1.0.6",
"react": "^15.4.2",
"react-native": "^0.40.0",
"react-native-responsive": "^1.0.1",
Expand Down
1 change: 1 addition & 0 deletions EEG101/src/assets/awakeasleep.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion EEG101/src/assets/epoching.json
100644 → 100755

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions EEG101/src/assets/fourier.json

Large diffs are not rendered by default.

Binary file added EEG101/src/assets/images/img_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added EEG101/src/assets/images/img_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion EEG101/src/components/SandboxGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class SandboxGraph extends Component {
<FilterGraphView style={{flex: 1}} visibility={this.props.visibility}
ref={(ref) => this.graphRef = ref}
channelOfInterest={this.props.channelOfInterest}
filterType={'bandpass'}
filterType={this.props.filterType}
isRecording={this.props.isRecording}/>
);

Expand Down
Loading

0 comments on commit aa73567

Please sign in to comment.