Merge pull request #104 from OpenBCI/development

Development
Esse commit está contido em:
AJ Keller
2017-01-06 15:09:57 -05:00
commit de GitHub
2429 arquivos alterados com 13156 adições e 1752784 exclusões
BIN
Ver Arquivo
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 170 KiB

@@ -1,303 +0,0 @@
/**
* ControlP5 ScrollableList
*
* replaces DropdownList and and ListBox.
* List can be scrolled by dragging the list or using the scroll-wheel.
*
* by Andreas Schlegel, 2014
* www.sojamo.de/libraries/controlp5
*
*/
import controlP5.*;
import java.util.*;
PFont[] _controlFonts = new PFont[5];
ControlFont[] controlFonts = new ControlFont[5];
ControlP5 cp5_GUI;
CColor cp5_colors;
color[] colors = new color[10];
void setup() {
textAlign(CENTER, BOTTOM);
size(400, 400);
cp5_GUI = new ControlP5(this);
_controlFonts[0] = createFont("Arial", 10, true);
_controlFonts[1] = createFont("Arial", 12, true);
_controlFonts[2] = createFont("Arial", 14, true);
_controlFonts[3] = createFont("Arial", 16, true);
_controlFonts[4] = createFont("Arial", 18, true);
for (int i = 0; i < controlFonts.length; i++) {
controlFonts[i] = new ControlFont(_controlFonts[i]);
}
List l = Arrays.asList("a", "b", "c", "d");
/* add a ScrollableList, by default it behaves like a DropdownList */
//colors to be sent to cp5_GUI
cp5_colors = new CColor();
cp5_colors.setActive(color(0, 0, 255));
cp5_colors.setForeground(color(0, 255, 0));
cp5_colors.setBackground(color(255, 0, 0));
cp5_colors.setCaptionLabel(color(255, 255, 0));
cp5_colors.setValueLabel(color(255, 0, 255));
cp5_GUI.setColor(cp5_colors);
cp5_GUI.setFont(controlFonts[1]);
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//color1.
cp5_GUI.addScrollableList("dropdown")
.setPosition(100, 100)
.setSize(100, 100)
.setScrollSensitivity(0.0)
.setBarHeight(20)
.setItemHeight(20)
.addItems(l)
// .setType(ScrollableList.LIST) // currently supported DROPDOWN and LIST
;
cp5_GUI.getController("dropdown")
.getCaptionLabel()
//.setFont(controlFonts[0])
//.setSize(12)
.getStyle()
.setPaddingTop(4)
;
//cp5.getController("dropdown")
// .setColor(int(color(255,0,0)))
// ;
}
void draw() {
background(240);
}
void dropdown(int n) {
/* request the selected item based on index n */
println(n, cp5_GUI.get(ScrollableList.class, "dropdown").getItem(n));
/* here an item is stored as a Map with the following key-value pairs:
* name, the given name of the item
* text, the given text of the item by default the same as name
* value, the given value of the item, can be changed by using .getItem(n).put("value", "abc"); a value here is of type Object therefore can be anything
* color, the given color of the item, how to change, see below
* view, a customizable view, is of type CDrawable
*/
CColor c = new CColor();
c.setBackground(color(255, 0, 0));
cp5_GUI.get(ScrollableList.class, "dropdown").getItem(n).put("color", c);
}
void keyPressed() {
switch(key) {
case('1'):
/* make the ScrollableList behave like a ListBox */
cp5_GUI.get(ScrollableList.class, "dropdown").setType(ControlP5.LIST);
break;
case('2'):
/* make the ScrollableList behave like a DropdownList */
cp5_GUI.get(ScrollableList.class, "dropdown").setType(ControlP5.DROPDOWN);
break;
case('3'):
/*change content of the ScrollableList */
List l = Arrays.asList("a-1", "b-1", "c-1", "d-1", "e-1", "f-1", "g-1", "h-1", "i-1", "j-1", "k-1");
cp5_GUI.get(ScrollableList.class, "dropdown").setItems(l);
break;
case('4'):
/* remove an item from the ScrollableList */
cp5_GUI.get(ScrollableList.class, "dropdown").removeItem("k-1");
break;
case('5'):
/* clear the ScrollableList */
cp5_GUI.get(ScrollableList.class, "dropdown").clear();
break;
}
}
/*
a list of all methods available for the ScrollableList Controller
use ControlP5.printPublicMethodsFor(ScrollableList.class);
to print the following list into the console.
You can find further details about class ScrollableList in the javadoc.
Format:
ClassName : returnType methodName(parameter type)
controlP5.Controller : CColor getColor()
controlP5.Controller : ControlBehavior getBehavior()
controlP5.Controller : ControlWindow getControlWindow()
controlP5.Controller : ControlWindow getWindow()
controlP5.Controller : ControllerProperty getProperty(String)
controlP5.Controller : ControllerProperty getProperty(String, String)
controlP5.Controller : ControllerView getView()
controlP5.Controller : Label getCaptionLabel()
controlP5.Controller : Label getValueLabel()
controlP5.Controller : List getControllerPlugList()
controlP5.Controller : Pointer getPointer()
controlP5.Controller : ScrollableList addCallback(CallbackListener)
controlP5.Controller : ScrollableList addListener(ControlListener)
controlP5.Controller : ScrollableList addListenerFor(int, CallbackListener)
controlP5.Controller : ScrollableList align(int, int, int, int)
controlP5.Controller : ScrollableList bringToFront()
controlP5.Controller : ScrollableList bringToFront(ControllerInterface)
controlP5.Controller : ScrollableList hide()
controlP5.Controller : ScrollableList linebreak()
controlP5.Controller : ScrollableList listen(boolean)
controlP5.Controller : ScrollableList lock()
controlP5.Controller : ScrollableList onChange(CallbackListener)
controlP5.Controller : ScrollableList onClick(CallbackListener)
controlP5.Controller : ScrollableList onDoublePress(CallbackListener)
controlP5.Controller : ScrollableList onDrag(CallbackListener)
controlP5.Controller : ScrollableList onDraw(ControllerView)
controlP5.Controller : ScrollableList onEndDrag(CallbackListener)
controlP5.Controller : ScrollableList onEnter(CallbackListener)
controlP5.Controller : ScrollableList onLeave(CallbackListener)
controlP5.Controller : ScrollableList onMove(CallbackListener)
controlP5.Controller : ScrollableList onPress(CallbackListener)
controlP5.Controller : ScrollableList onRelease(CallbackListener)
controlP5.Controller : ScrollableList onReleaseOutside(CallbackListener)
controlP5.Controller : ScrollableList onStartDrag(CallbackListener)
controlP5.Controller : ScrollableList onWheel(CallbackListener)
controlP5.Controller : ScrollableList plugTo(Object)
controlP5.Controller : ScrollableList plugTo(Object, String)
controlP5.Controller : ScrollableList plugTo(Object[])
controlP5.Controller : ScrollableList plugTo(Object[], String)
controlP5.Controller : ScrollableList registerProperty(String)
controlP5.Controller : ScrollableList registerProperty(String, String)
controlP5.Controller : ScrollableList registerTooltip(String)
controlP5.Controller : ScrollableList removeBehavior()
controlP5.Controller : ScrollableList removeCallback()
controlP5.Controller : ScrollableList removeCallback(CallbackListener)
controlP5.Controller : ScrollableList removeListener(ControlListener)
controlP5.Controller : ScrollableList removeListenerFor(int, CallbackListener)
controlP5.Controller : ScrollableList removeListenersFor(int)
controlP5.Controller : ScrollableList removeProperty(String)
controlP5.Controller : ScrollableList removeProperty(String, String)
controlP5.Controller : ScrollableList setArrayValue(float[])
controlP5.Controller : ScrollableList setArrayValue(int, float)
controlP5.Controller : ScrollableList setBehavior(ControlBehavior)
controlP5.Controller : ScrollableList setBroadcast(boolean)
controlP5.Controller : ScrollableList setCaptionLabel(String)
controlP5.Controller : ScrollableList setColor(CColor)
controlP5.Controller : ScrollableList setColorActive(int)
controlP5.Controller : ScrollableList setColorBackground(int)
controlP5.Controller : ScrollableList setColorCaptionLabel(int)
controlP5.Controller : ScrollableList setColorForeground(int)
controlP5.Controller : ScrollableList setColorLabel(int)
controlP5.Controller : ScrollableList setColorValue(int)
controlP5.Controller : ScrollableList setColorValueLabel(int)
controlP5.Controller : ScrollableList setDecimalPrecision(int)
controlP5.Controller : ScrollableList setDefaultValue(float)
controlP5.Controller : ScrollableList setHeight(int)
controlP5.Controller : ScrollableList setId(int)
controlP5.Controller : ScrollableList setImage(PImage)
controlP5.Controller : ScrollableList setImage(PImage, int)
controlP5.Controller : ScrollableList setImages(PImage, PImage, PImage)
controlP5.Controller : ScrollableList setImages(PImage, PImage, PImage, PImage)
controlP5.Controller : ScrollableList setLabel(String)
controlP5.Controller : ScrollableList setLabelVisible(boolean)
controlP5.Controller : ScrollableList setLock(boolean)
controlP5.Controller : ScrollableList setMax(float)
controlP5.Controller : ScrollableList setMin(float)
controlP5.Controller : ScrollableList setMouseOver(boolean)
controlP5.Controller : ScrollableList setMoveable(boolean)
controlP5.Controller : ScrollableList setPosition(float, float)
controlP5.Controller : ScrollableList setPosition(float[])
controlP5.Controller : ScrollableList setSize(PImage)
controlP5.Controller : ScrollableList setSize(int, int)
controlP5.Controller : ScrollableList setStringValue(String)
controlP5.Controller : ScrollableList setUpdate(boolean)
controlP5.Controller : ScrollableList setValue(float)
controlP5.Controller : ScrollableList setValueLabel(String)
controlP5.Controller : ScrollableList setValueSelf(float)
controlP5.Controller : ScrollableList setView(ControllerView)
controlP5.Controller : ScrollableList setVisible(boolean)
controlP5.Controller : ScrollableList setWidth(int)
controlP5.Controller : ScrollableList show()
controlP5.Controller : ScrollableList unlock()
controlP5.Controller : ScrollableList unplugFrom(Object)
controlP5.Controller : ScrollableList unplugFrom(Object[])
controlP5.Controller : ScrollableList unregisterTooltip()
controlP5.Controller : ScrollableList update()
controlP5.Controller : ScrollableList updateSize()
controlP5.Controller : String getAddress()
controlP5.Controller : String getInfo()
controlP5.Controller : String getName()
controlP5.Controller : String getStringValue()
controlP5.Controller : String toString()
controlP5.Controller : Tab getTab()
controlP5.Controller : boolean isActive()
controlP5.Controller : boolean isBroadcast()
controlP5.Controller : boolean isInside()
controlP5.Controller : boolean isLabelVisible()
controlP5.Controller : boolean isListening()
controlP5.Controller : boolean isLock()
controlP5.Controller : boolean isMouseOver()
controlP5.Controller : boolean isMousePressed()
controlP5.Controller : boolean isMoveable()
controlP5.Controller : boolean isUpdate()
controlP5.Controller : boolean isVisible()
controlP5.Controller : float getArrayValue(int)
controlP5.Controller : float getDefaultValue()
controlP5.Controller : float getMax()
controlP5.Controller : float getMin()
controlP5.Controller : float getValue()
controlP5.Controller : float[] getAbsolutePosition()
controlP5.Controller : float[] getArrayValue()
controlP5.Controller : float[] getPosition()
controlP5.Controller : int getDecimalPrecision()
controlP5.Controller : int getHeight()
controlP5.Controller : int getId()
controlP5.Controller : int getWidth()
controlP5.Controller : int listenerSize()
controlP5.Controller : void remove()
controlP5.Controller : void setView(ControllerView, int)
controlP5.ScrollableList : List getItems()
controlP5.ScrollableList : Map getItem(String)
controlP5.ScrollableList : Map getItem(int)
controlP5.ScrollableList : ScrollableList addItem(String, Object)
controlP5.ScrollableList : ScrollableList addItems(List)
controlP5.ScrollableList : ScrollableList addItems(Map)
controlP5.ScrollableList : ScrollableList addItems(String[])
controlP5.ScrollableList : ScrollableList clear()
controlP5.ScrollableList : ScrollableList close()
controlP5.ScrollableList : ScrollableList open()
controlP5.ScrollableList : ScrollableList removeItem(String)
controlP5.ScrollableList : ScrollableList removeItems(List)
controlP5.ScrollableList : ScrollableList setBackgroundColor(int)
controlP5.ScrollableList : ScrollableList setBarHeight(int)
controlP5.ScrollableList : ScrollableList setBarVisible(boolean)
controlP5.ScrollableList : ScrollableList setItemHeight(int)
controlP5.ScrollableList : ScrollableList setItems(List)
controlP5.ScrollableList : ScrollableList setItems(Map)
controlP5.ScrollableList : ScrollableList setItems(String[])
controlP5.ScrollableList : ScrollableList setOpen(boolean)
controlP5.ScrollableList : ScrollableList setScrollSensitivity(float)
controlP5.ScrollableList : ScrollableList setType(int)
controlP5.ScrollableList : boolean isBarVisible()
controlP5.ScrollableList : boolean isOpen()
controlP5.ScrollableList : int getBackgroundColor()
controlP5.ScrollableList : int getBarHeight()
controlP5.ScrollableList : int getHeight()
controlP5.ScrollableList : void controlEvent(ControlEvent)
controlP5.ScrollableList : void keyEvent(KeyEvent)
controlP5.ScrollableList : void setDirection(int)
controlP5.ScrollableList : void updateItemIndexOffset()
java.lang.Object : String toString()
java.lang.Object : boolean equals(Object)
created: 2014/09/08 01:19:14
*/
@@ -1,314 +0,0 @@
/**
* ControlP5 ScrollableList
*
* replaces DropdownList and and ListBox.
* List can be scrolled by dragging the list or using the scroll-wheel.
*
* by Andreas Schlegel, 2014
* www.sojamo.de/libraries/controlp5
*
*/
import controlP5.*;
import java.util.*;
PFont[] _controlFonts = new PFont[5];
ControlFont[] controlFonts = new ControlFont[5];
ControlP5 cp5_FFT;
CColor cp5_colors;
color[] colors = new color[10];
void setup() {
textAlign(CENTER, BOTTOM);
size(400, 400);
cp5_FFT = new ControlP5(this);
_controlFonts[0] = createFont("Arial", 10, true);
_controlFonts[1] = createFont("Arial", 12, true);
_controlFonts[2] = createFont("Arial", 14, true);
_controlFonts[3] = createFont("Arial", 16, true);
_controlFonts[4] = createFont("Arial", 18, true);
for (int i = 0; i < controlFonts.length; i++) {
controlFonts[i] = new ControlFont(_controlFonts[i]);
}
List l = Arrays.asList("20 Hz", "40 Hz", "60 Hz", "120 Hz");
/* add a ScrollableList, by default it behaves like a DropdownList */
//colors to be sent to cp5_FFT
cp5_colors = new CColor();
cp5_colors.setActive(color(0, 255, 255)); //when clicked
cp5_colors.setForeground(color(125,125,125)); //when hovering
cp5_colors.setBackground(color(255,255,255)); //color of buttons
cp5_colors.setCaptionLabel(color(1, 18, 41)); //color of text
cp5_colors.setValueLabel(color(0, 0, 255));
cp5_FFT.setColor(cp5_colors);
cp5_FFT.setFont(controlFonts[1]);
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//cp5_colors.setActive(color(0,255,255));
//color1.
cp5_FFT.addScrollableList("MaxFreq")
.setPosition(100, 100)
.setSize(100, 100)
.setScrollSensitivity(0.0)
.setBarHeight(20)
.setItemHeight(20)
.addItems(l)
// .setType(ScrollableList.LIST) // currently supported DROPDOWN and LIST
;
cp5_FFT.getController("MaxFreq")
.getCaptionLabel()
.toUpperCase(false)
//.setFont(controlFonts[0])
//.setSize(12)
.getStyle()
.setPaddingTop(4)
;
//cp5.getController("dropdown")
// .setColor(int(color(255,0,0)))
// ;
for(int i = 0; i < l.size(); i++){
println(i);
println(cp5_FFT.get(ScrollableList.class, "MaxFreq").getItem(i));
//cp5_FFT.get(ScrollableList.class, "MaxFreq.").getItem(i).get("captionlabel").getStyle().setPaddingTop(4);
//Map myMap = cp5_FFT.get(ScrollableList.class, "MaxFreq.").getItem("captionLabel");
println(cp5_FFT.get(ScrollableList.class, "MaxFreq").getItem("value"));
println(cp5_FFT.get(ScrollableList.class, "MaxFreq").getItem(i).get("view"));
//cp5_FFT.get(ScrollableList.class, "MaxFreq.").getController("20 Hz").
}
}
void draw() {
background(240);
}
void MaxFreq(int n) { //function must have the same name as "NameOfList" aka MaxFreq in this case
/* request the selected item based on index n */
println(n, cp5_FFT.get(ScrollableList.class, "MaxFreq").getItem(n));
/* here an item is stored as a Map with the following key-value pairs:
* name, the given name of the item
* text, the given text of the item by default the same as name
* value, the given value of the item, can be changed by using .getItem(n).put("value", "abc"); a value here is of type Object therefore can be anything
* color, the given color of the item, how to change, see below
* view, a customizable view, is of type CDrawable
*/
CColor c = new CColor();
c.setBackground(color(255, 0, 0));
cp5_FFT.get(ScrollableList.class, "MaxFreq").getItem(n).put("color", c);
}
void keyPressed() {
switch(key) {
case('1'):
/* make the ScrollableList behave like a ListBox */
cp5_FFT.get(ScrollableList.class, "dropdown").setType(ControlP5.LIST);
break;
case('2'):
/* make the ScrollableList behave like a DropdownList */
cp5_FFT.get(ScrollableList.class, "dropdown").setType(ControlP5.DROPDOWN);
break;
case('3'):
/*change content of the ScrollableList */
List l = Arrays.asList("a-1", "b-1", "c-1", "d-1", "e-1", "f-1", "g-1", "h-1", "i-1", "j-1", "k-1");
cp5_FFT.get(ScrollableList.class, "dropdown").setItems(l);
break;
case('4'):
/* remove an item from the ScrollableList */
cp5_FFT.get(ScrollableList.class, "dropdown").removeItem("k-1");
break;
case('5'):
/* clear the ScrollableList */
cp5_FFT.get(ScrollableList.class, "dropdown").clear();
break;
}
}
/*
a list of all methods available for the ScrollableList Controller
use ControlP5.printPublicMethodsFor(ScrollableList.class);
to print the following list into the console.
You can find further details about class ScrollableList in the javadoc.
Format:
ClassName : returnType methodName(parameter type)
controlP5.Controller : CColor getColor()
controlP5.Controller : ControlBehavior getBehavior()
controlP5.Controller : ControlWindow getControlWindow()
controlP5.Controller : ControlWindow getWindow()
controlP5.Controller : ControllerProperty getProperty(String)
controlP5.Controller : ControllerProperty getProperty(String, String)
controlP5.Controller : ControllerView getView()
controlP5.Controller : Label getCaptionLabel()
controlP5.Controller : Label getValueLabel()
controlP5.Controller : List getControllerPlugList()
controlP5.Controller : Pointer getPointer()
controlP5.Controller : ScrollableList addCallback(CallbackListener)
controlP5.Controller : ScrollableList addListener(ControlListener)
controlP5.Controller : ScrollableList addListenerFor(int, CallbackListener)
controlP5.Controller : ScrollableList align(int, int, int, int)
controlP5.Controller : ScrollableList bringToFront()
controlP5.Controller : ScrollableList bringToFront(ControllerInterface)
controlP5.Controller : ScrollableList hide()
controlP5.Controller : ScrollableList linebreak()
controlP5.Controller : ScrollableList listen(boolean)
controlP5.Controller : ScrollableList lock()
controlP5.Controller : ScrollableList onChange(CallbackListener)
controlP5.Controller : ScrollableList onClick(CallbackListener)
controlP5.Controller : ScrollableList onDoublePress(CallbackListener)
controlP5.Controller : ScrollableList onDrag(CallbackListener)
controlP5.Controller : ScrollableList onDraw(ControllerView)
controlP5.Controller : ScrollableList onEndDrag(CallbackListener)
controlP5.Controller : ScrollableList onEnter(CallbackListener)
controlP5.Controller : ScrollableList onLeave(CallbackListener)
controlP5.Controller : ScrollableList onMove(CallbackListener)
controlP5.Controller : ScrollableList onPress(CallbackListener)
controlP5.Controller : ScrollableList onRelease(CallbackListener)
controlP5.Controller : ScrollableList onReleaseOutside(CallbackListener)
controlP5.Controller : ScrollableList onStartDrag(CallbackListener)
controlP5.Controller : ScrollableList onWheel(CallbackListener)
controlP5.Controller : ScrollableList plugTo(Object)
controlP5.Controller : ScrollableList plugTo(Object, String)
controlP5.Controller : ScrollableList plugTo(Object[])
controlP5.Controller : ScrollableList plugTo(Object[], String)
controlP5.Controller : ScrollableList registerProperty(String)
controlP5.Controller : ScrollableList registerProperty(String, String)
controlP5.Controller : ScrollableList registerTooltip(String)
controlP5.Controller : ScrollableList removeBehavior()
controlP5.Controller : ScrollableList removeCallback()
controlP5.Controller : ScrollableList removeCallback(CallbackListener)
controlP5.Controller : ScrollableList removeListener(ControlListener)
controlP5.Controller : ScrollableList removeListenerFor(int, CallbackListener)
controlP5.Controller : ScrollableList removeListenersFor(int)
controlP5.Controller : ScrollableList removeProperty(String)
controlP5.Controller : ScrollableList removeProperty(String, String)
controlP5.Controller : ScrollableList setArrayValue(float[])
controlP5.Controller : ScrollableList setArrayValue(int, float)
controlP5.Controller : ScrollableList setBehavior(ControlBehavior)
controlP5.Controller : ScrollableList setBroadcast(boolean)
controlP5.Controller : ScrollableList setCaptionLabel(String)
controlP5.Controller : ScrollableList setColor(CColor)
controlP5.Controller : ScrollableList setColorActive(int)
controlP5.Controller : ScrollableList setColorBackground(int)
controlP5.Controller : ScrollableList setColorCaptionLabel(int)
controlP5.Controller : ScrollableList setColorForeground(int)
controlP5.Controller : ScrollableList setColorLabel(int)
controlP5.Controller : ScrollableList setColorValue(int)
controlP5.Controller : ScrollableList setColorValueLabel(int)
controlP5.Controller : ScrollableList setDecimalPrecision(int)
controlP5.Controller : ScrollableList setDefaultValue(float)
controlP5.Controller : ScrollableList setHeight(int)
controlP5.Controller : ScrollableList setId(int)
controlP5.Controller : ScrollableList setImage(PImage)
controlP5.Controller : ScrollableList setImage(PImage, int)
controlP5.Controller : ScrollableList setImages(PImage, PImage, PImage)
controlP5.Controller : ScrollableList setImages(PImage, PImage, PImage, PImage)
controlP5.Controller : ScrollableList setLabel(String)
controlP5.Controller : ScrollableList setLabelVisible(boolean)
controlP5.Controller : ScrollableList setLock(boolean)
controlP5.Controller : ScrollableList setMax(float)
controlP5.Controller : ScrollableList setMin(float)
controlP5.Controller : ScrollableList setMouseOver(boolean)
controlP5.Controller : ScrollableList setMoveable(boolean)
controlP5.Controller : ScrollableList setPosition(float, float)
controlP5.Controller : ScrollableList setPosition(float[])
controlP5.Controller : ScrollableList setSize(PImage)
controlP5.Controller : ScrollableList setSize(int, int)
controlP5.Controller : ScrollableList setStringValue(String)
controlP5.Controller : ScrollableList setUpdate(boolean)
controlP5.Controller : ScrollableList setValue(float)
controlP5.Controller : ScrollableList setValueLabel(String)
controlP5.Controller : ScrollableList setValueSelf(float)
controlP5.Controller : ScrollableList setView(ControllerView)
controlP5.Controller : ScrollableList setVisible(boolean)
controlP5.Controller : ScrollableList setWidth(int)
controlP5.Controller : ScrollableList show()
controlP5.Controller : ScrollableList unlock()
controlP5.Controller : ScrollableList unplugFrom(Object)
controlP5.Controller : ScrollableList unplugFrom(Object[])
controlP5.Controller : ScrollableList unregisterTooltip()
controlP5.Controller : ScrollableList update()
controlP5.Controller : ScrollableList updateSize()
controlP5.Controller : String getAddress()
controlP5.Controller : String getInfo()
controlP5.Controller : String getName()
controlP5.Controller : String getStringValue()
controlP5.Controller : String toString()
controlP5.Controller : Tab getTab()
controlP5.Controller : boolean isActive()
controlP5.Controller : boolean isBroadcast()
controlP5.Controller : boolean isInside()
controlP5.Controller : boolean isLabelVisible()
controlP5.Controller : boolean isListening()
controlP5.Controller : boolean isLock()
controlP5.Controller : boolean isMouseOver()
controlP5.Controller : boolean isMousePressed()
controlP5.Controller : boolean isMoveable()
controlP5.Controller : boolean isUpdate()
controlP5.Controller : boolean isVisible()
controlP5.Controller : float getArrayValue(int)
controlP5.Controller : float getDefaultValue()
controlP5.Controller : float getMax()
controlP5.Controller : float getMin()
controlP5.Controller : float getValue()
controlP5.Controller : float[] getAbsolutePosition()
controlP5.Controller : float[] getArrayValue()
controlP5.Controller : float[] getPosition()
controlP5.Controller : int getDecimalPrecision()
controlP5.Controller : int getHeight()
controlP5.Controller : int getId()
controlP5.Controller : int getWidth()
controlP5.Controller : int listenerSize()
controlP5.Controller : void remove()
controlP5.Controller : void setView(ControllerView, int)
controlP5.ScrollableList : List getItems()
controlP5.ScrollableList : Map getItem(String)
controlP5.ScrollableList : Map getItem(int)
controlP5.ScrollableList : ScrollableList addItem(String, Object)
controlP5.ScrollableList : ScrollableList addItems(List)
controlP5.ScrollableList : ScrollableList addItems(Map)
controlP5.ScrollableList : ScrollableList addItems(String[])
controlP5.ScrollableList : ScrollableList clear()
controlP5.ScrollableList : ScrollableList close()
controlP5.ScrollableList : ScrollableList open()
controlP5.ScrollableList : ScrollableList removeItem(String)
controlP5.ScrollableList : ScrollableList removeItems(List)
controlP5.ScrollableList : ScrollableList setBackgroundColor(int)
controlP5.ScrollableList : ScrollableList setBarHeight(int)
controlP5.ScrollableList : ScrollableList setBarVisible(boolean)
controlP5.ScrollableList : ScrollableList setItemHeight(int)
controlP5.ScrollableList : ScrollableList setItems(List)
controlP5.ScrollableList : ScrollableList setItems(Map)
controlP5.ScrollableList : ScrollableList setItems(String[])
controlP5.ScrollableList : ScrollableList setOpen(boolean)
controlP5.ScrollableList : ScrollableList setScrollSensitivity(float)
controlP5.ScrollableList : ScrollableList setType(int)
controlP5.ScrollableList : boolean isBarVisible()
controlP5.ScrollableList : boolean isOpen()
controlP5.ScrollableList : int getBackgroundColor()
controlP5.ScrollableList : int getBarHeight()
controlP5.ScrollableList : int getHeight()
controlP5.ScrollableList : void controlEvent(ControlEvent)
controlP5.ScrollableList : void keyEvent(KeyEvent)
controlP5.ScrollableList : void setDirection(int)
controlP5.ScrollableList : void updateItemIndexOffset()
java.lang.Object : String toString()
java.lang.Object : boolean equals(Object)
created: 2014/09/08 01:19:14
*/
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package=""
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<application android:label=""
android:icon="@drawable/icon"
android:debuggable="true">
<activity android:name="">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
@@ -1,196 +0,0 @@
////////////////////
//
// This class creates and manages a button for use on the screen to trigger actions.
//
// Created: Chip Audette, Oct 2013.
// Modified: Conor Russomanno, Oct 2014
//
// Based on Processing's "Button" example code
//
////////////////////
class Button {
int but_x, but_y, but_dx, but_dy; // Position of square button
//int rectSize = 90; // Diameter of rect
color currentColor;
color color_hover = color(127, 134, 143);//color(252, 221, 198);
color color_pressed = color(150,170,200); //bgColor;
color color_highlight = color(102);
color color_notPressed = color(255); //color(227,118,37);
color buttonStrokeColor = bgColor;
color textColorActive = color(255);
color textColorNotActive = bgColor;
color rectHighlight;
boolean drawHand = false;
//boolean isMouseHere = false;
boolean buttonHasStroke = true;
boolean isActive = false;
boolean isDropdownButton = false;
boolean wasPressed = false;
public String but_txt;
PFont buttonFont = f2;
public Button(int x, int y, int w, int h, String txt, int fontSize) {
setup(x, y, w, h, txt);
//println(PFont.list()); //see which fonts are available
//font = createFont("SansSerif.plain",fontSize);
//font = createFont("Lucida Sans Regular",fontSize);
// font = createFont("Arial",fontSize);
//font = loadFont("SansSerif.plain.vlw");
}
public void setup(int x, int y, int w, int h, String txt) {
but_x = x;
but_y = y;
but_dx = w;
but_dy = h;
setString(txt);
}
public void setString(String txt) {
but_txt = txt;
//println("Button: setString: string = " + txt);
}
public boolean isActive() {
return isActive;
}
public void setIsActive(boolean val) {
isActive = val;
}
public void makeDropdownButton(boolean val) {
isDropdownButton = val;
}
public boolean isMouseHere() {
if ( overRect(but_x, but_y, but_dx, but_dy) ) {
cursor(HAND);
return true;
} else {
return false;
}
}
color getColor() {
if (isActive) {
currentColor = color_pressed;
} else if (isMouseHere()) {
currentColor = color_hover;
} else {
currentColor = color_notPressed;
}
return currentColor;
}
public void setCurrentColor(color _color){
currentColor = _color;
}
public void setColorPressed(color _color) {
color_pressed = _color;
}
public void setColorNotPressed(color _color) {
color_notPressed = _color;
}
public void setStrokeColor(color _color) {
buttonStrokeColor = _color;
}
public void hasStroke(boolean _trueORfalse) {
buttonHasStroke = _trueORfalse;
}
boolean overRect(int x, int y, int width, int height) {
if (mouseX >= x && mouseX <= x+width &&
mouseY >= y && mouseY <= y+height) {
return true;
} else {
return false;
}
}
public void draw(int _x, int _y) {
but_x = _x;
but_y = _y;
draw();
}
public void draw() {
//draw the button
fill(getColor());
if (buttonHasStroke) {
stroke(buttonStrokeColor); //button border
} else {
noStroke();
}
// noStroke();
rect(but_x, but_y, but_dx, but_dy);
//draw the text
if (isActive) {
fill(textColorActive);
} else {
fill(textColorNotActive);
}
stroke(255);
textFont(buttonFont); //load f2 ... from control panel
textSize(12);
textAlign(CENTER, CENTER);
textLeading(round(0.9*(textAscent()+textDescent())));
// int x1 = but_x+but_dx/2;
// int y1 = but_y+but_dy/2;
int x1, y1;
//no auto wrap
x1 = but_x+but_dx/2;
y1 = but_y+but_dy/2;
text(but_txt, x1, y1);
//draw open/close arrow if it's a dropdown button
if (isDropdownButton) {
pushStyle();
fill(255);
noStroke();
// smooth();
// stroke(255);
// strokeWeight(1);
if (isActive) {
float point1x = but_x + (but_dx - ((3f*but_dy)/4f));
float point1y = but_y + but_dy/3f;
float point2x = but_x + (but_dx-(but_dy/4f));
float point2y = but_y + but_dy/3f;
float point3x = but_x + (but_dx - (but_dy/2f));
float point3y = but_y + (2f*but_dy)/3f;
triangle(point1x, point1y, point2x, point2y, point3x, point3y); //downward triangle, indicating open
} else {
float point1x = but_x + (but_dx - ((3f*but_dy)/4f));
float point1y = but_y + (2f*but_dy)/3f;
float point2x = but_x + (but_dx-(but_dy/4f));
float point2y = but_y + (2f*but_dy)/3f;
float point3x = but_x + (but_dx - (but_dy/2f));
float point3y = but_y + but_dy/3f;
triangle(point1x, point1y, point2x, point2y, point3x, point3y); //upward triangle, indicating closed
}
popStyle();
}
if (true) {
if (!isMouseHere() && drawHand) {
cursor(ARROW);
drawHand = false;
verbosePrint("don't draw hand");
}
//if cursor is over button change cursor icon to hand!
if (isMouseHere() && !drawHand) {
cursor(HAND);
drawHand = true;
verbosePrint("draw hand");
}
}
}
};
@@ -1,583 +0,0 @@
//these arrays of channel values need to be global so that they don't reset on screen resize, when GUI reinitializes (there's definitely a more efficient way to do this...)
int numSettingsPerChannel = 6; //each channel has 6 different settings
char[][] channelSettingValues = new char [nchan][numSettingsPerChannel]; // [channel#][Button#-value] ... this will incfluence text of button
char[][] impedanceCheckValues = new char [nchan][2];
public void updateChannelArrays(int _nchan) {
channelSettingValues = new char [_nchan][numSettingsPerChannel]; // [channel#][Button#-value] ... this will incfluence text of button
impedanceCheckValues = new char [_nchan][2];
}
// color[] channelColors = new color[16];
color[] channelColors = {
color(129, 129, 129),
color(124, 75, 141),
color(54, 87, 158),
color(49, 113, 89),
color(221, 178, 13),
color(253, 94, 52),
color(224, 56, 45),
color(162, 82, 49)
};
class ChannelController {
public float x1, y1, w1, h1, x2, y2, w2, h2; //all 1 values refer to the left panel that is always visible ... al 2 values refer to the right panel that is only visible when showFullController = true
public int montage_w, montage_h;
public int rowHeight;
public int buttonSpacing;
boolean showFullController = false;
boolean[] drawImpedanceValues = new boolean [nchan];
int spacer1 = 3;
int spacer2 = 5; //space between buttons
// [Number of Channels] x 6 array of buttons for channel settings
Button[][] channelSettingButtons = new Button [nchan][numSettingsPerChannel]; // [channel#][Button#]
// char[][] channelSettingValues = new char [nchan][numSettingsPerChannel]; // [channel#][Button#-value] ... this will incfluence text of button
//buttons just to the left of
Button[][] impedanceCheckButtons = new Button [nchan][2];
// char [][] impedanceCheckValues = new char [nchan][2];
// Array for storing SRB2 history settings of channels prior to shutting off .. so you can return to previous state when reactivating channel
char[] previousSRB2 = new char [nchan];
// Array for storing SRB2 history settings of channels prior to shutting off .. so you can return to previous state when reactivating channel
char[] previousBIAS = new char [nchan];
//maximum different values for the different settings (Power Down, Gain, Input Type, BIAS, SRB2, SRB1) of
//refer to page 44 of ADS1299 Datasheet: http://www.ti.com/lit/ds/symlink/ads1299.pdf
char[] maxValuesPerSetting = {
'1', // Power Down :: (0)ON, (1)OFF
'6', // Gain :: (0) x1, (1) x2, (2) x4, (3) x6, (4) x8, (5) x12, (6) x24 ... default
'7', // Channel Input :: (0)Normal Electrode Input, (1)Input Shorted, (2)Used in conjunction with BIAS_MEAS, (3)MVDD for supply measurement, (4)Temperature Sensor, (5)Test Signal, (6)BIAS_DRP ... positive electrode is driver, (7)BIAS_DRN ... negative electrode is driver
'1', // BIAS :: (0) Yes, (1) No
'1', // SRB2 :: (0) Open, (1) Closed
'1'
}; // SRB1 :: (0) Yes, (1) No ... this setting affects all channels ... either all on or all off
//variables used for channel write timing in writeChannelSettings()
//long timeOfLastChannelWrite = 0;
int channelToWrite = -1;
//int channelWriteCounter = 0;
//boolean isWritingChannel = false;
//variables use for imp write timing with writeImpedanceSettings()
//long timeOfLastImpWrite = 0;
int impChannelToWrite = -1;
//int impWriteCounter = 0;
//boolean isWritingImp = false;
boolean rewriteChannelWhenDoneWriting = false;
int channelToWriteWhenDoneWriting = 0;
boolean rewriteImpedanceWhenDoneWriting = false;
int impChannelToWriteWhenDoneWriting = 0;
char final_pORn = '0';
char final_onORoff = '0';
ChannelController(float _xPos, float _yPos, float _width, float _height, float _montage_w, float _montage_h) {
//positioning values for left panel (that is always visible)
x1 = _xPos;
y1 = _yPos;
w1 = _width;
h1 = _height;
//positioning values for right panel that is only visible when showFullController = true (behind the graph)
x2 = x1 + w1;
// x2 = gui.showMontageButton.but_x;
y2 = y1;
w2 = _montage_w;
h2 = h1;
createChannelSettingButtons();
// set on/off buttons to default channel colors
for (int i = 0; i < nchan; i++) {
channelSettingButtons[i][0].setColorNotPressed(channelColors[i%8]);
}
}
public void loadDefaultChannelSettings() {
verbosePrint("ChannelController: loading default channel settings to GUI's channel controller...");
for (int i = 0; i < nchan; i++) {
verbosePrint("chan: " + i + " ");
for (int j = 0; j < numSettingsPerChannel; j++) { //channel setting values
channelSettingValues[i][j] = char(openBCI.get_defaultChannelSettings().toCharArray()[j]); //parse defaultChannelSettings string created in the OpenBCI_ADS1299 class
if (j == numSettingsPerChannel - 1) {
println(char(openBCI.get_defaultChannelSettings().toCharArray()[j]));
} else {
print(char(openBCI.get_defaultChannelSettings().toCharArray()[j]) + ",");
}
}
for (int k = 0; k < 2; k++) { //impedance setting values
impedanceCheckValues[i][k] = '0';
}
}
verbosePrint("made it!");
update(); //update 1 time to refresh button values based on new loaded settings
}
public void update() {
//make false to check again below
for (int i = 0; i < nchan; i++) {
drawImpedanceValues[i] = false;
}
for (int i = 0; i < nchan; i++) { //for every channel
//update buttons based on channelSettingValues[i][j]
for (int j = 0; j < numSettingsPerChannel; j++) {
switch(j) { //what setting are we looking at
case 0: //on/off ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][0].setColorNotPressed(channelColors[i%8]);// power down == false, set color to vibrant
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][0].setColorNotPressed(color(75)); // channelSettingButtons[i][0].setString("B"); // power down == true, set color to dark gray, indicating power down
break;
case 1: //GAIN ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][1].setString("x1");
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][1].setString("x2");
if (channelSettingValues[i][j] == '2') channelSettingButtons[i][1].setString("x4");
if (channelSettingValues[i][j] == '3') channelSettingButtons[i][1].setString("x6");
if (channelSettingValues[i][j] == '4') channelSettingButtons[i][1].setString("x8");
if (channelSettingValues[i][j] == '5') channelSettingButtons[i][1].setString("x12");
if (channelSettingValues[i][j] == '6') channelSettingButtons[i][1].setString("x24");
break;
case 2: //input type ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][2].setString("Normal");
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][2].setString("Shorted");
if (channelSettingValues[i][j] == '2') channelSettingButtons[i][2].setString("BIAS_MEAS");
if (channelSettingValues[i][j] == '3') channelSettingButtons[i][2].setString("MVDD");
if (channelSettingValues[i][j] == '4') channelSettingButtons[i][2].setString("Temp.");
if (channelSettingValues[i][j] == '5') channelSettingButtons[i][2].setString("Test");
if (channelSettingValues[i][j] == '6') channelSettingButtons[i][2].setString("BIAS_DRP");
if (channelSettingValues[i][j] == '7') channelSettingButtons[i][2].setString("BIAS_DRN");
break;
case 3: //BIAS ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][3].setString("Don't Include");
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][3].setString("Include");
break;
case 4: // SRB2 ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][4].setString("Off");
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][4].setString("On");
break;
case 5: // SRB1 ??
if (channelSettingValues[i][j] == '0') channelSettingButtons[i][5].setString("No");
if (channelSettingValues[i][j] == '1') channelSettingButtons[i][5].setString("Yes");
break;
}
}
for (int k = 0; k < 2; k++) {
switch(k) {
case 0: // P Imp Buttons
if (impedanceCheckValues[i][k] == '0') {
impedanceCheckButtons[i][0].setColorNotPressed(color(75));
impedanceCheckButtons[i][0].setString("");
}
if (impedanceCheckValues[i][k] == '1') {
impedanceCheckButtons[i][0].setColorNotPressed(isSelected_color);
impedanceCheckButtons[i][0].setString("");
if (showFullController) {
drawImpedanceValues[i] = false;
} else {
drawImpedanceValues[i] = true;
}
}
break;
case 1: // N Imp Buttons
if (impedanceCheckValues[i][k] == '0') {
impedanceCheckButtons[i][1].setColorNotPressed(color(75));
impedanceCheckButtons[i][1].setString("");
}
if (impedanceCheckValues[i][k] == '1') {
impedanceCheckButtons[i][1].setColorNotPressed(isSelected_color);
impedanceCheckButtons[i][1].setString("");
if (showFullController) {
drawImpedanceValues[i] = false;
} else {
drawImpedanceValues[i] = true;
}
}
break;
}
}
}
//then reset to 1
//
if (openBCI.get_isWritingChannel()) {
openBCI.writeChannelSettings(channelToWrite,channelSettingValues);
}
if (rewriteChannelWhenDoneWriting == true && openBCI.get_isWritingChannel() == false) {
initChannelWrite(channelToWriteWhenDoneWriting);
rewriteChannelWhenDoneWriting = false;
}
if (openBCI.get_isWritingImp()) {
openBCI.writeImpedanceSettings(impChannelToWrite,impedanceCheckValues);
}
if (rewriteImpedanceWhenDoneWriting == true && openBCI.get_isWritingImp() == false) {
initImpWrite(impChannelToWriteWhenDoneWriting, final_pORn, final_onORoff);
rewriteImpedanceWhenDoneWriting = false;
}
}
public void draw() {
pushStyle();
noStroke();
//draw phantom rectangle to cover up random crap from Graph2D... we are replacing this stuff with the Montage Controller
fill(bgColor);
rect(x1 - 2, y1-(height*0.01f), w1, h1+(height*0.02f));
//draw light green rect behind pane title
fill(216, 233, 171);
rect(x2-2, y2-25, w2+1, 25);
//BG of montage controller (for debugging mainly)
// fill(255,255,255,123);
// rect(x1, y1 - 1, w1, h1);
//draw background pane of impedance buttons
fill(221);
rect(x1 + w1/3 + 1, y1, 2*(w1/3) - 3, h1 - 2);
//draw slightly darker line guides/separators for impedance buttons
stroke(175);
strokeWeight(2);
for (int i = 0; i < nchan; i++) {
line(x1 + w1/3 + 2, y1 + (((h1-1)/(nchan+1))*(i+1)), x2 - 3, y1 + (((h1-1)/(nchan+1))*(i+1)));
}
line(x1 + 2*(w1/3) - 1, y1 + 1, x1 + 2*(w1/3) - 1, y1 + (h1-1) - 1);
strokeWeight(0);
//channel buttons
for (int i = 0; i < nchan; i++) {
channelSettingButtons[i][0].draw(); //draw on/off channel buttons
//draw impedance buttons
for (int j = 0; j < 2; j++) {
impedanceCheckButtons[i][j].draw();
}
}
//label impedance button columns
fill(bgColor);
text("P", x1 + 1*(w1/2), y1 + 12);
text("N", x1 + 5*(w1/6) - 2, y1 + 12);
if (showFullController) {
//background
noStroke();
fill(0, 0, 0, 100);
rect(x1 + w1, y1, w2, h2);
// [numChan] x 5 ... all channel setting buttons (other than on/off)
for (int i = 0; i < nchan; i++) {
for (int j = 1; j < 6; j++) {
// println("drawing button " + i + "," + j);
// println("Button: " + channelSettingButtons[i][j]);
channelSettingButtons[i][j].draw();
}
}
//draw column headers for channel settings behind EEG graph
fill(bgColor);
text("PGA Gain", x2 + (w2/10)*1, y1 - 12);
text("Input Type", x2 + (w2/10)*3, y1 - 12);
text(" Bias ", x2 + (w2/10)*5, y1 - 12);
text("SRB2", x2 + (w2/10)*7, y1 - 12);
text("SRB1", x2 + (w2/10)*9, y1 - 12);
//if mode is not from OpenBCI, draw a dark overlay to indicate that you cannot edit these settings
if (eegDataSource != DATASOURCE_NORMAL && eegDataSource != DATASOURCE_NORMAL_W_AUX) {
fill(0, 0, 0, 200);
noStroke();
rect(x2-2, y2, w2+1, h2);
fill(255);
textSize(24);
text("DATA SOURCE (LIVE) only", x2 + (w2/2), y2 + (h2/2));
}
}
if ((eegDataSource != DATASOURCE_NORMAL) && (eegDataSource != DATASOURCE_NORMAL_W_AUX)) {
fill(0, 0, 0, 200);
rect(x1 + w1/3 + 1, y1, 2*(w1/3) - 3, h1 - 2);
}
for (int i = 0; i < nchan; i++) {
if (drawImpedanceValues[i] == true) {
gui.impValuesMontage[i].draw(); //impedance values on montage plot
}
}
popStyle();
}
public void mousePressed() {
//if fullChannelController and one of the buttons (other than ON/OFF) is clicked
//if dataSource is coming from OpenBCI, allow user to interact with channel controller
if ( (eegDataSource == DATASOURCE_NORMAL) || (eegDataSource == DATASOURCE_NORMAL_W_AUX) ) {
if (showFullController) {
for (int i = 0; i < nchan; i++) { //When [i][j] button is clicked
for (int j = 1; j < numSettingsPerChannel; j++) {
if (channelSettingButtons[i][j].isMouseHere()) {
//increment [i][j] channelSettingValue by, until it reaches max values per setting [j],
channelSettingButtons[i][j].wasPressed = true;
channelSettingButtons[i][j].isActive = true;
}
}
}
}
}
//on/off button and Imp buttons can always be clicked/released
for (int i = 0; i < nchan; i++) {
if (channelSettingButtons[i][0].isMouseHere()) {
channelSettingButtons[i][0].wasPressed = true;
channelSettingButtons[i][0].isActive = true;
}
//only allow editing of impedance if dataSource == from OpenBCI
if ((eegDataSource == DATASOURCE_NORMAL) || (eegDataSource == DATASOURCE_NORMAL_W_AUX)) {
if (impedanceCheckButtons[i][0].isMouseHere()) {
impedanceCheckButtons[i][0].wasPressed = true;
impedanceCheckButtons[i][0].isActive = true;
}
if (impedanceCheckButtons[i][1].isMouseHere()) {
impedanceCheckButtons[i][1].wasPressed = true;
impedanceCheckButtons[i][1].isActive = true;
}
}
}
}
public void mouseReleased() {
//if fullChannelController and one of the buttons (other than ON/OFF) is released
if (showFullController) {
for (int i = 0; i < nchan; i++) { //When [i][j] button is clicked
for (int j = 1; j < numSettingsPerChannel; j++) {
if (channelSettingButtons[i][j].isMouseHere() && channelSettingButtons[i][j].wasPressed == true) {
if (channelSettingValues[i][j] < maxValuesPerSetting[j]) {
channelSettingValues[i][j]++; //increment [i][j] channelSettingValue by, until it reaches max values per setting [j],
} else {
channelSettingValues[i][j] = '0';
}
// if you're not currently writing a channel and not waiting to rewrite after you've finished mashing the button
if (!openBCI.get_isWritingChannel() && rewriteChannelWhenDoneWriting == false) {
initChannelWrite(i);//write new ADS1299 channel row values to OpenBCI
} else { //else wait until a the current write has finished and then write again ... this is to not overwrite the wrong values while writing a channel
verbosePrint("CONGRATULATIONS, YOU'RE MASHING BUTTONS!");
rewriteChannelWhenDoneWriting = true;
channelToWriteWhenDoneWriting = i;
}
}
// if(!channelSettingButtons[i][j].isMouseHere()){
channelSettingButtons[i][j].isActive = false;
channelSettingButtons[i][j].wasPressed = false;
// }
}
}
}
//ON/OFF button can always be clicked/released
for (int i = 0; i < nchan; i++) {
//was on/off clicked?
if (channelSettingButtons[i][0].isMouseHere() && channelSettingButtons[i][0].wasPressed == true) {
if (channelSettingValues[i][0] < maxValuesPerSetting[0]) {
channelSettingValues[i][0] = '1'; //increment [i][j] channelSettingValue by, until it reaches max values per setting [j],
// channelSettingButtons[i][0].setColorNotPressed(color(25,25,25));
// powerDownChannel(i);
deactivateChannel(i);
} else {
channelSettingValues[i][0] = '0';
// channelSettingButtons[i][0].setColorNotPressed(color(255));
// powerUpChannel(i);
activateChannel(i);
}
// writeChannelSettings(i);//write new ADS1299 channel row values to OpenBCI
}
//was P imp check button clicked?
if (impedanceCheckButtons[i][0].isMouseHere() && impedanceCheckButtons[i][0].wasPressed == true) {
if (impedanceCheckValues[i][0] < '1') {
// impedanceCheckValues[i][0] = '1'; //increment [i][j] channelSettingValue by, until it reaches max values per setting [j],
// channelSettingButtons[i][0].setColorNotPressed(color(25,25,25));
// writeImpedanceSettings(i);
initImpWrite(i, 'p', '1');
//initImpWrite
verbosePrint("a");
} else {
// impedanceCheckValues[i][0] = '0';
// channelSettingButtons[i][0].setColorNotPressed(color(255));
// writeImpedanceSettings(i);
initImpWrite(i, 'p', '0');
verbosePrint("b");
}
// writeChannelSettings(i);//write new ADS1299 channel row values to OpenBCI
}
//was N imp check button clicked?
if (impedanceCheckButtons[i][1].isMouseHere() && impedanceCheckButtons[i][1].wasPressed == true) {
if (impedanceCheckValues[i][1] < '1') {
initImpWrite(i, 'n', '1');
//initImpWrite
verbosePrint("c");
} else {
initImpWrite(i, 'n', '0');
verbosePrint("d");
}
// writeChannelSettings(i);//write new ADS1299 channel row values to OpenBCI
}
channelSettingButtons[i][0].isActive = false;
channelSettingButtons[i][0].wasPressed = false;
impedanceCheckButtons[i][0].isActive = false;
impedanceCheckButtons[i][0].wasPressed = false;
impedanceCheckButtons[i][1].isActive = false;
impedanceCheckButtons[i][1].wasPressed = false;
}
update(); //update once to refresh button values
}
public void fillValuesBasedOnDefault(byte _defaultValues) {
//interpret incoming HEX value (from OpenBCI) and pass into all default channelSettingValues
//dencode byte from OpenBCI and break it apart into the channelSettingValues[][] array
}
public void powerDownChannel(int _numChannel) {
verbosePrint("Powering down channel " + str(int(_numChannel) + int(1)));
//save SRB2 and BIAS settings in 2D history array (to turn back on when channel is reactivated)
previousBIAS[_numChannel] = channelSettingValues[_numChannel][3];
previousSRB2[_numChannel] = channelSettingValues[_numChannel][4];
channelSettingValues[_numChannel][3] = '0'; //make sure to disconnect from BIAS
channelSettingValues[_numChannel][4] = '0'; //make sure to disconnect from SRB2
// initChannelWrite(_numChannel);//writeChannelSettings
channelSettingValues[_numChannel][0] = '1'; //update powerUp/powerDown value of 2D array
//if(_numChannel < 8){
verbosePrint("Command: " + command_deactivate_channel[_numChannel]);
//openBCI.serial_openBCI.write(command_deactivate_channel[_numChannel]);
openBCI.deactivateChannel(_numChannel); //assumes numChannel counts from zero (not one)...handles regular and daisy channels
//}else{ //if a daisy channel
// verbosePrint("Command: " + command_deactivate_channel_daisy[_numChannel - 8]);
// openBCI.serial_openBCI.write(command_deactivate_channel_daisy[_numChannel - 8]);
//}
}
public void powerUpChannel(int _numChannel) {
verbosePrint("Powering up channel " + str(int(_numChannel) + int(1)));
//replace SRB2 and BIAS settings with values from 2D history array
channelSettingValues[_numChannel][3] = previousBIAS[_numChannel];
channelSettingValues[_numChannel][4] = previousSRB2[_numChannel];
// initChannelWrite(_numChannel);//writeChannelSettings
channelSettingValues[_numChannel][0] = '0'; //update powerUp/powerDown value of 2D array
//if(_numChannel < 8){
verbosePrint("Command: " + command_activate_channel[_numChannel]);
//openBCI.serial_openBCI.write(command_activate_channel[_numChannel]);
openBCI.activateChannel(_numChannel); //assumes numChannel counts from zero (not one)...handles regular and daisy channels//assumes numChannel counts from zero (not one)...handles regular and daisy channels
//} else{ //if a daisy channel
// verbosePrint("Command: " + command_activate_channel_daisy[_numChannel - 8]);
// openBCI.serial_openBCI.write(command_activate_channel_daisy[_numChannel - 8]);
//}
}
public void initChannelWrite(int _numChannel) {
//after clicking any button, write the new settings for that channel to OpenBCI
if (!openBCI.get_isWritingImp()) { //make sure you aren't currently writing imp settings for a channel
verbosePrint("Writing channel settings for channel " + str(_numChannel+1) + " to OpenBCI!");
openBCI.initChannelWrite(_numChannel);
channelToWrite = _numChannel;
}
}
public void initImpWrite(int _numChannel, char pORn, char onORoff) {
//after clicking any button, write the new settings for that channel to OpenBCI
if (!openBCI.get_isWritingChannel()) { //make sure you aren't currently writing imp settings for a channel
// if you're not currently writing a channel and not waiting to rewrite after you've finished mashing the button
if (!openBCI.get_isWritingImp() && rewriteImpedanceWhenDoneWriting == false) {
verbosePrint("Writing impedance check settings (" + pORn + "," + onORoff + ") for channel " + str(_numChannel+1) + " to OpenBCI!");
if (pORn == 'p') {
impedanceCheckValues[_numChannel][0] = onORoff;
}
if (pORn == 'n') {
impedanceCheckValues[_numChannel][1] = onORoff;
}
openBCI.initImpWrite(_numChannel);
impChannelToWrite = _numChannel;
} else { //else wait until a the current write has finished and then write again ... this is to not overwrite the wrong values while writing a channel
verbosePrint("CONGRATULATIONS, YOU'RE MASHING BUTTONS!");
rewriteImpedanceWhenDoneWriting = true;
impChannelToWriteWhenDoneWriting = _numChannel;
if (pORn == 'p') {
final_pORn = 'p';
}
if (pORn == 'n') {
final_pORn = 'n';
}
final_onORoff = onORoff;
}
}
}
public void createChannelSettingButtons() {
//the size and space of these buttons are dependendant on the size of the screen and full ChannelController
verbosePrint("ChannelController: createChannelSettingButtons: creating channel setting buttons...");
int buttonW = 0;
int buttonX = 0;
int buttonH = 0;
int buttonY = 0; //variables to be used for button creation below
String buttonString = "";
Button tempButton;
//create all activate/deactivate buttons (left-most button in widget left of EEG graph). These buttons are always visible
for (int i = 0; i < nchan; i++) {
buttonW = int((w1 - (spacer1 *4)) / 3);
buttonX = int(x1 + (spacer1));
// buttonH = int((h1 / (nchan + 1)) - (spacer1/2));
buttonH = buttonW;
buttonY = int(y1 + ((h1/(nchan+1))*(i+1)) - (buttonH/2));
buttonString = str(i+1);
tempButton = new Button (buttonX, buttonY, buttonW, buttonH, buttonString, 14);
channelSettingButtons[i][0] = tempButton;
}
//create all (P)ositive impedance check butttons ... these are the buttons just to the right of activate/deactivate buttons ... These are also always visible
//create all (N)egative impedance check butttons ... these are the buttons just to the right of activate/deactivate buttons ... These are also always visible
int downSizer = 6;
for (int i = 0; i < nchan; i++) {
for (int j = 1; j < 3; j++) {
buttonW = int(((w1 - (spacer1 *4)) / 3) - downSizer);
buttonX = int((x1 + j*(buttonW+6) + (j+1)*(spacer1)) + (downSizer/2) + 1);
// buttonH = int((h2 / (nchan + 1)) - (spacer2/2));
buttonY = int((y1 + (((h1-1)/(nchan+1))*(i+1)) - (buttonH/2)) + (downSizer/2) + 1);
buttonString = "";
tempButton = new Button (buttonX, buttonY, buttonW, buttonW, buttonString, 14);
impedanceCheckButtons[i][j-1] = tempButton;
}
}
//create all other channel setting buttons... these are only visible when the user toggles to "showFullController = true"
for (int i = 0; i < nchan; i++) {
for (int j = 1; j < 6; j++) {
buttonW = int((w2 - (spacer2*6)) / 5);
buttonX = int((x2 + (spacer2 * (j))) + ((j-1) * buttonW));
// buttonH = int((h2 / (nchan + 1)) - (spacer2/2));
buttonY = int(y2 + (((h2-1)/(nchan+1))*(i+1)) - (buttonH/2));
buttonString = "N/A";
tempButton = new Button (buttonX, buttonY, buttonW, buttonH, buttonString, 14);
channelSettingButtons[i][j] = tempButton;
}
}
}
};
@@ -1,158 +0,0 @@
//------------------------Added by TaoLin, for ChannelFigureComponent(visualizer)-------------------------------------------
boolean drawEMG = false; //if true... toggles on EEG_Processing_User.draw and toggles off the headplot in Gui_Manager
class Channel_Figure_Component extends Container {
private float fs_Hz; //sample rate
private int nchan;
//new
ChannelFigureComponent[] CFCArray; //ChannelFigureComponentArray
class ChannelFigureComponent {
//variables
boolean isTriggered = false;
float upperThreshold = 25; //default uV upper threshold value ... this will automatically change over time
float lowerThreshold = 0; //default uV lower threshold value ... this will automatically change over time
int averagePeriod = 250; //number of data packets to average over (250 = 1 sec)
int thresholdPeriod = 1250; //number of packets
int ourChan = 0; //channel being monitored ... "3 - 1" means channel 3 (with a 0 index)
float myAverage = 0.0; //this will change over time ... used for calculations below
float acceptableLimitUV = 200; //uV values above this limit are excluded, as a result of them almost certainly being noise...
//prez related
boolean switchTripped = false;
int switchCounter = 0;
float timeOfLastTrip = 0;
float tripThreshold = 0.75;
float untripThreshold = 0.6;
//if writing to a serial port
int output = 0; //value between 0-255 that is the relative position of the current uV average between the rolling lower and upper uV thresholds
float output_normalized = 0; //converted to between 0-1
float output_adjusted = 0; //adjusted depending on range that is expected on the other end, ie 0-255?
}
//class constructor
Channel_Figure_Component(int NCHAN, float sample_rate_Hz, Container container) {
super(container, "WHOLE");
nchan = NCHAN;
fs_Hz = sample_rate_Hz;
//new
CFCArray = new ChannelFigureComponent[NCHAN];
for (int i = 0; i < NCHAN; i++) {
CFCArray[i] = new ChannelFigureComponent();
CFCArray[i].ourChan = i;
}
}
//here is the processing routine called by the OpenBCI main program...update this with whatever you'd like to do
public void process(float[][] data_newest_uV, //holds raw EEG data that is new since the last call
float[][] data_long_uV, //holds a longer piece of buffered EEG data, of same length as will be plotted on the screen
float[][] data_forDisplay_uV, //this data has been filtered and is ready for plotting on the screen
FFT[] fftData) { //holds the FFT (frequency spectrum) of the latest data
//for example, you could loop over each EEG channel to do some sort of time-domain processing
//using the sample values that have already been filtered, as will be plotted on the display
float EEG_value_uV;
//looping over channels and analyzing input data
for (ChannelFigureComponent cfc : CFCArray) {
cfc.myAverage = 0.0;
for(int i = data_forDisplay_uV[cfc.ourChan].length - cfc.averagePeriod; i < data_forDisplay_uV[cfc.ourChan].length; i++){
if(abs(data_forDisplay_uV[cfc.ourChan][i]) <= cfc.acceptableLimitUV){ //prevent BIG spikes from effecting the average
cfc.myAverage += abs(data_forDisplay_uV[cfc.ourChan][i]); //add value to average ... we will soon divide by # of packets
} else {
cfc.myAverage += cfc.acceptableLimitUV; //if it's greater than the limit, just add the limit
}
}
cfc.myAverage = cfc.myAverage / float(cfc.averagePeriod); //finishing the average
if(cfc.myAverage >= cfc.upperThreshold && cfc.myAverage <= cfc.acceptableLimitUV){ //
cfc.upperThreshold = cfc.myAverage;
}
if(cfc.myAverage <= cfc.lowerThreshold){
cfc.lowerThreshold = cfc.myAverage;
}
if(cfc.upperThreshold >= (cfc.myAverage + 35)){
cfc.upperThreshold *= .97;
}
if(cfc.lowerThreshold <= cfc.myAverage){
cfc.lowerThreshold += (10 - cfc.lowerThreshold)/(frameRate * 5); //have lower threshold creep upwards to keep range tight
}
//output_L = (int)map(myAverage_L, lowerThreshold_L, upperThreshold_L, 0, 255);
cfc.output_normalized = map(cfc.myAverage, cfc.lowerThreshold, cfc.upperThreshold, 0, 1);
cfc.output_adjusted = ((-0.1/(cfc.output_normalized*255.0)) + 255.0);
}
//-----------------what is this part used for---------------------------------------
//OR, you could loop over each EEG channel and do some sort of frequency-domain processing from the FFT data
float FFT_freq_Hz, FFT_value_uV;
for (int Ichan=0;Ichan < nchan; Ichan++) {
//loop over each new sample
for (int Ibin=0; Ibin < fftBuff[Ichan].specSize(); Ibin++){
FFT_freq_Hz = fftData[Ichan].indexToFreq(Ibin);
FFT_value_uV = fftData[Ichan].getBand(Ibin);
//add your processing here...
//println("EEG_Processing_User: Ichan = " + Ichan + ", Freq = " + FFT_freq_Hz + "Hz, FFT Value = " + FFT_value_uV + "uV/bin");
}
}
//---------------------------------------------------------------------------------
}
public void draw(){
super.draw();
if(drawEMG){
pushStyle();
//float rx = 0.6 * width, ry = 0.07 * height, rw = 0.4 * width, rh = 0.45 * height;
float rx = CON_X, ry = CON_Y, rw = CON_W, rh = CON_H;
float scaleFactor = 3.0;
float scaleFactorJaw = 1.5;
int rowNum = 4;
int colNum = CFCArray.length / rowNum;
float rowOffset = rh / rowNum;
float colOffset = rw / colNum;
//new
for (int i = 0; i < rowNum; i++) {
for (int j = 0; j < colNum; j++) {
pushMatrix();
translate(rx + j * colOffset, ry + i * rowOffset);
//draw visulizer
noFill();
stroke(0,255,0);
strokeWeight(2);
//circle for outer threshold
ellipse(2*colOffset/8, rowOffset / 2, scaleFactor * CFCArray[i * colNum + j].upperThreshold, scaleFactor * CFCArray[i * colNum + j].upperThreshold);
//circle for inner threshold
stroke(0,255,255);
ellipse(2*colOffset/8, rowOffset / 2, scaleFactor * CFCArray[i * colNum + j].lowerThreshold, scaleFactor * CFCArray[i * colNum + j].lowerThreshold);
//realtime
fill(255,0,0, 125);
noStroke();
ellipse(2*colOffset/8, rowOffset / 2, scaleFactor * CFCArray[i * colNum + j].myAverage, scaleFactor * CFCArray[i * colNum + j].myAverage);
//draw background bar for mapped uV value indication
fill(0,255,255,125);
rect(5*colOffset/8, 2 * rowOffset / 8, (3*colOffset/32), (4*rowOffset/8));
//draw real time bar of actually mapped value
rect(5*colOffset/8, 6 *rowOffset / 8, (3*colOffset/32), map(CFCArray[i * colNum + j].output_normalized, 0, 1, 0, (-1) * (4*rowOffset/8)));
popMatrix();
}
}
popStyle();
}
//drawTriggerFeedback();
} //end of draw
public void drawTriggerFeedback(){
}
}
@@ -1,249 +0,0 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Container {
//key Container Variables
public float CON_X0, CON_Y0, CON_W0, CON_H0; //true dimensions.. without margins
public float CON_X, CON_Y, CON_W, CON_H; //dimensions with margins
public float margin; //margin
public color bdColor, mgColor; //body color and margin color
public boolean visible; //if this container is visible
//constructor 1 -- comprehensive
public Container(float _CON_X0, float _CON_Y0, float _CON_W0, float _CON_H0, float _margin, color _bdColor, color _mgColor, boolean _visible) {
CON_X0 = _CON_X0;
CON_Y0 = _CON_Y0;
CON_W0 = _CON_W0;
CON_H0 = _CON_H0;
CON_X = CON_X0 + margin;
CON_Y = CON_Y0 + margin;
CON_W = CON_W0 - margin*2;
CON_H = CON_H0 - margin*2;
margin = _margin;
bdColor = _bdColor;
mgColor = _mgColor;
visible = _visible;
}
//constructor 2 -- recursive constructor -- for quickly building sub-containers based on a super container (aka master)
public Container(Container master, String _type) {
bdColor = master.bdColor;
mgColor = master.mgColor;
margin = master.margin;
visible = master.visible;
if(_type == "WHOLE"){
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0;
CON_H0 = master.CON_H0;
CON_W = master.CON_W;
CON_H = master.CON_H;
CON_X = master.CON_X;
CON_Y = master.CON_Y;
} else if (_type == "LEFT") {
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0;
CON_W = (master.CON_W - margin)/2;
CON_H = master.CON_H;
CON_X = master.CON_X;
CON_Y = master.CON_Y;
} else if (_type == "RIGHT") {
CON_X0 = master.CON_X0 + master.CON_W0/2;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0;
CON_W = (master.CON_W - margin)/2;
CON_H = master.CON_H;
CON_X = master.CON_X + CON_W + margin;
CON_Y = master.CON_Y;
} else if (_type == "TOP") {
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0;
CON_H0 = master.CON_H0/2;
CON_W = master.CON_W;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X;
CON_Y = master.CON_Y;
} else if (_type == "BOTTOM") {
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0 + master.CON_H0/2;
CON_W0 = master.CON_W0;
CON_H0 = master.CON_H0/2;
CON_W = master.CON_W;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X;
CON_Y = master.CON_Y + CON_H + margin;
} else if (_type == "UPPER_LEFT") {
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0/2;
CON_W = (master.CON_W - margin)/2;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X;
CON_Y = master.CON_Y;
} else if (_type == "UPPER_RIGHT") {
CON_X0 = master.CON_X0 + master.CON_W0/2;
CON_Y0 = master.CON_Y0;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0/2;
CON_W = (master.CON_W - margin)/2;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X + CON_W + margin;
CON_Y = master.CON_Y;
} else if (_type == "LOWER_LEFT") {
CON_X0 = master.CON_X0;
CON_Y0 = master.CON_Y0 + master.CON_H0/2;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0/2;
CON_W = (master.CON_W - margin)/2;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X;
CON_Y = master.CON_Y + CON_H + margin;
} else if (_type == "LOWER_RIGHT") {
CON_X0 = master.CON_X0 + master.CON_W0/2;
CON_Y0 = master.CON_Y0 + master.CON_H0/2;
CON_W0 = master.CON_W0/2;
CON_H0 = master.CON_H0/2;
CON_W = (master.CON_W - margin)/2;
CON_H = (master.CON_H - margin)/2;
CON_X = master.CON_X + CON_W + margin;
CON_Y = master.CON_Y + CON_H + margin;
}
}
public void draw() {
if(visible){
pushStyle();
//draw margin area
fill(mgColor);
noStroke();
rect(CON_X0, CON_Y0, CON_W0, CON_H0);
//noFill();
//stroke(255, 0, 0);
//rect(CON_X0, CON_Y0, CON_W0, CON_H0);
fill(bdColor);
noStroke();
rect(CON_X, CON_Y, CON_W, CON_H);
popStyle();
}
}
};
//class Draggable {
// boolean dragging = false; // Is the object being dragged?
// boolean rollover = false; // Is the mouse over the ellipse?
// float dragX,dragY,dragW,dragH; // Location and size
// float dragOffsetX, dragOffsetY; // Mouseclick offset
// float dragRangeX, dragRangeY, dragRangeW, dragRangeH; //range of dragging
// Draggable(float tempX, float tempY, float tempW, float tempH) {
// dragX = tempX;
// dragY = tempY;
// dragW = tempW;
// dragH = tempH;
// dragOffsetX = 0;
// dragOffsetY = 0;
// dragRangeX = 0;
// dragRangeY = 0;
// dragRangeW = width;
// dragRangeH = height;
// }
// // // Method to display
// // void display() {
// // stroke(0);
// // if (dragging) fill (50);
// // else if (rollover) fill(100);
// // else fill(175,200);
// // ellipse(x,y,w,h);
// // }
// // Is a point inside the rectangle (for click)?
// void clicked(float mx, float my) {
// //if (isInsideCircle((int)dragX, (int)dragY, (int)dragW, (int)dragH, mx, my)) {
// if (isInsideCircle(dragX, dragY, dragW, dragH, mx, my)) {
// dragging = true;
// // If so, keep track of relative location of click to corner of rectangle
// dragOffsetX = dragX-mx;
// dragOffsetY = dragY-my;
// }
// }
// // Is a point inside the rectangle (for rollover)
// void rollover(float mx, float my) {
// // if (isInsideCircle(dragX, dragY, dragW, dragH, mx, my)) {
// // rollover = true;
// // } else {
// // rollover = false;
// // }
// }
// // Stop dragging
// void stopDragging() {
// dragging = false;
// }
// // Drag the rectangle
// void drag(float mx, float my) {
// if (isOutOfRange(0.5 * width, 0.5 * height, width, height, mx, my)) return;
// if (dragging) {
// dragX = mx + dragOffsetX;
// dragY = my + dragOffsetY;
// }
// }
// boolean isInsideCircle(float x, float y, float w, float h, float mX, float mY) {
// float dx = mX - x;
// float dy = mY - y;
// float r = sqrt(dx*dx + dy*dy);
// if (r <= 0.5 * w) {
// return true;
// } else {
// return false;
// }
// }
// boolean isInsideRect(float x, float y, float w, float h, float mX, float mY) {
// if (mX < x || mY < y || mX > x + w || mY > y + h) return false;
// else return true;
// }
// boolean isOutOfRange(float x, float y, float w, float h, float mX, float mY) {
// //if (mX < x || mY < y || mX > x + w || mY > y + h) return true;
// float dx = mX - x;
// float dy = mY - y;
// float r = sqrt(dx*dx + dy*dy);
// if (r > 0.5 * w) return true;
// else return false;
// }
//}
@@ -1,792 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// System Control Panel
// - Select serial port from dropdown
// - Select default configuration (EEG, EKG, EMG)
// - Select Electrode Count (8 vs 16)
// - Select data mode (synthetic, playback file, real-time)
// - Record data? (y/n)
// - select output location
// - link to help guide
// - buttons to start/stop/reset application
//
// Written by: Conor Russomanno (Oct. 2014)
//
//////////////////////////////////////////////////////////////////////////
import controlP5.*;
ControlP5 cp5; //program-wide instance of ControlP5
CallbackListener cb = new CallbackListener() { //used by ControlP5 to clear text field on double-click
public void controlEvent(CallbackEvent theEvent) {
println("CallbackListener: controlEvent: clearing");
cp5.get(Textfield.class, "fileName").clear();
}
};
MenuList sourceList;
//Global buttons and elements for the control panel (changed within the classes below)
MenuList serialList;
String[] serialPorts = new String[Serial.list().length];
MenuList sdTimes;
color boxColor = color(200);
color boxStrokeColor = color(138, 146, 153);
color isSelected_color = color(184, 220, 105);
// Button openClosePort;
// boolean portButtonPressed;
Button refreshPort;
boolean refreshButtonPressed = false;
Button initSystemButton;
boolean initButtonPressed = false; //default false
Button autoFileName;
boolean fileButtonPressed = false;
Button chanButton8;
boolean chanButton8Pressed = false;
Button chanButton16;
boolean chanButton16Pressed = false;
Button selectPlaybackFile;
boolean selectPlaybackFilePressed = false;
Button selectSDFile;
boolean selectSDFilePressed = false;
class ControlPanel {
public int x, y, w, h;
public boolean isOpen;
boolean showSourceBox, showSerialBox, showFileBox, showChannelBox, showInitBox;
PlotFontInfo fontInfo;
//various control panel elements that are unique to specific datasources
DataSourceBox dataSourceBox;
SerialBox serialBox;
DataLogBox dataLogBox;
ChannelCountBox channelCountBox;
InitBox initBox;
PlaybackFileBox playbackFileBox;
SDConverterBox sdConverterBox;
SDBox sdBox;
boolean drawStopInstructions;
int globalPadding; //design feature: passed through to all box classes as the global spacing .. in pixels .. for all elements/subelements
int globalBorder;
boolean convertingSD = false;
ControlPanel(OpenBCI_GUI_TAO mainClass) {
x = 2;
y = 2 + controlPanelCollapser.but_dy;
w = controlPanelCollapser.but_dx;
h = height - int(helpWidget.h);
isOpen = true;
fontInfo = new PlotFontInfo();
// f1 = createFont("Raleway-SemiBold.otf", 16);
// f2 = createFont("Raleway-Regular.otf", 15);
// f3 = createFont("Raleway-SemiBold.otf", 15);
globalPadding = 10; //controls the padding of all elements on the control panel
globalBorder = 0; //controls the border of all elements in the control panel ... using processing's stroke() instead
cp5 = new ControlP5(mainClass);
//boxes active when eegDataSource = Normal (OpenBCI)
dataSourceBox = new DataSourceBox(x, y, w, h, globalPadding);
serialBox = new SerialBox(x + w, dataSourceBox.y, w, h, globalPadding);
dataLogBox = new DataLogBox(x + w, (serialBox.y + serialBox.h), w, h, globalPadding);
channelCountBox = new ChannelCountBox(x + w, (dataLogBox.y + dataLogBox.h), w, h, globalPadding);
sdBox = new SDBox(x + w, (channelCountBox.y + channelCountBox.h), w, h, globalPadding);
//boxes active when eegDataSource = Playback
playbackFileBox = new PlaybackFileBox(x + w, dataSourceBox.y, w, h, globalPadding);
sdConverterBox = new SDConverterBox(x + w, (playbackFileBox.y + playbackFileBox.h), w, h, globalPadding);
initBox = new InitBox(x, (dataSourceBox.y + dataSourceBox.h), w, h, globalPadding);
}
public void update() {
//toggle view of cp5 / serial list selection table
if (isOpen) { // if control panel is open
if (!cp5.isVisible()) { //and cp5 is not visible
cp5.show(); // shot it
}
} else { //the opposite of above
if (cp5.isVisible()) {
cp5.hide();
}
}
//update all boxes if they need to be
dataSourceBox.update();
serialBox.update();
dataLogBox.update();
channelCountBox.update();
sdBox.update();
initBox.update();
serialList.updateMenu();
//SD File Conversion
while (convertingSD == true) {
convertSDFile();
}
}
public void draw() {
pushStyle();
noStroke();
//dark overlay of rest of interface to indicate it's not clickable
fill(0, 0, 0, 185);
rect(0, 0, width, height);
pushStyle();
fill(255);
noStroke();
rect(0, 0, width, 32);
popStyle();
// //background pane of control panel
// fill(35,35,35);
// rect(0,0,w,h);
popStyle();
initBox.draw();
if (systemMode == 10) {
drawStopInstructions = true;
}
if (systemMode != 10) { // only draw control panel boxes if system running is false
dataSourceBox.draw();
drawStopInstructions = false;
cp5.setVisible(true);//make sure controlP5 elements are visible
if (eegDataSource == 0) { //when data source is from OpenBCI
serialBox.draw();
dataLogBox.draw();
channelCountBox.draw();
sdBox.draw();
cp5.get(Textfield.class, "fileName").setVisible(true); //make sure the data file field is visible
cp5.get(MenuList.class, "serialList").setVisible(true); //make sure the serialList menulist is visible
cp5.get(MenuList.class, "sdTimes").setVisible(true); //make sure the SD time record options menulist is visible
//make sure serial list is visible
//set other CP5 controllers invisible
} else if (eegDataSource == 1) { //when data source is from playback file
playbackFileBox.draw();
sdConverterBox.draw();
//set other CP5 controllers invisible
cp5.get(Textfield.class, "fileName").setVisible(false); //make sure the data file field is visible
cp5.get(MenuList.class, "serialList").setVisible(false);
cp5.get(MenuList.class, "sdTimes").setVisible(false);
} else if (eegDataSource == 2) {
//make sure serial list is visible
//set other CP5 controllers invisible
cp5.get(Textfield.class, "fileName").setVisible(false); //make sure the data file field is visible
cp5.get(MenuList.class, "serialList").setVisible(false);
cp5.get(MenuList.class, "sdTimes").setVisible(false);
} else {
//set other CP5 controllers invisible
cp5.get(Textfield.class, "fileName").setVisible(false); //make sure the data file field is visible
cp5.get(MenuList.class, "serialList").setVisible(false);
cp5.get(MenuList.class, "sdTimes").setVisible(false);
}
} else {
cp5.setVisible(false); // if isRunning is true, hide all controlP5 elements
}
//draw the box that tells you to stop the system in order to edit control settings
if (drawStopInstructions) {
pushStyle();
fill(boxColor);
strokeWeight(1);
stroke(boxStrokeColor);
rect(x, y, w, dataSourceBox.h); //draw background of box
String stopInstructions = "Press the \"STOP SYSTEM\" button to edit system settings.";
textAlign(CENTER, TOP);
textFont(f2);
fill(bgColor);
text(stopInstructions, x + globalPadding*2, y + globalPadding*4, w - globalPadding*4, dataSourceBox.h - globalPadding*4);
popStyle();
}
}
//mouse pressed in control panel
public void CPmousePressed() {
verbosePrint("CPmousePressed");
if (initSystemButton.isMouseHere()) {
initSystemButton.setIsActive(true);
initButtonPressed = true;
}
//only able to click buttons of control panel when system is not running
if (systemMode != 10) {
//active buttons during DATASOURCE_NORMAL
if (eegDataSource == 0) {
if (refreshPort.isMouseHere()) {
refreshPort.setIsActive(true);
refreshButtonPressed = true;
}
if (autoFileName.isMouseHere()) {
autoFileName.setIsActive(true);
fileButtonPressed = true;
}
if (chanButton8.isMouseHere()) {
chanButton8.setIsActive(true);
chanButton8Pressed = true;
chanButton8.color_notPressed = isSelected_color;
chanButton16.color_notPressed = autoFileName.color_notPressed; //default color of button
}
if (chanButton16.isMouseHere()) {
chanButton16.setIsActive(true);
chanButton16Pressed = true;
chanButton8.color_notPressed = autoFileName.color_notPressed; //default color of button
chanButton16.color_notPressed = isSelected_color;
}
}
//active buttons during DATASOURCE_PLAYBACKFILE
if (eegDataSource == 1) {
if (selectPlaybackFile.isMouseHere()) {
selectPlaybackFile.setIsActive(true);
selectPlaybackFilePressed = true;
}
if (selectSDFile.isMouseHere()) {
selectSDFile.setIsActive(true);
selectSDFilePressed = true;
}
}
}
// output("Text File Name: " + cp5.get(Textfield.class,"fileName").getText());
}
//mouse released in control panel
public void CPmouseReleased() {
verbosePrint("CPMouseReleased: CPmouseReleased start...");
if (initSystemButton.isMouseHere() && initButtonPressed) {
//if system is not active ... initate system and flip button state
if (initSystemButton.but_txt == "START SYSTEM") {
if ((eegDataSource == DATASOURCE_NORMAL || eegDataSource == DATASOURCE_NORMAL_W_AUX) && openBCI_portName == "N/A") { //if data source == normal && if no serial port selected OR no SD setting selected
output("No Serial/COM port selected. Please select your Serial/COM port and retry system initiation.");
initButtonPressed = false;
initSystemButton.setIsActive(false);
return;
} else if (eegDataSource == DATASOURCE_PLAYBACKFILE && playbackData_fname == "N/A") { //if data source == playback && playback file == 'N/A'
output("No playback file selected. Please select a playback file and retry system initiation."); // tell user that they need to select a file before the system can be started
initButtonPressed = false;
initSystemButton.setIsActive(false);
return;
} else if (eegDataSource == -1) {//if no data source selected
output("No DATA SOURCE selected. Please select a DATA SOURCE and retry system initiation.");//tell user they must select a data source before initiating system
initButtonPressed = false;
initSystemButton.setIsActive(false);
return;
} else { //otherwise, initiate system!
verbosePrint("ControlPanel: CPmouseReleased: init");
initSystemButton.setString("STOP SYSTEM");
//global steps to START SYSTEM
// prepare the serial port
verbosePrint("ControlPanel — port is open: " + openBCI.isSerialPortOpen());
if (openBCI.isSerialPortOpen() == true) {
openBCI.closeSerialPort();
}
fileName = cp5.get(Textfield.class, "fileName").getText(); // store the current text field value of "File Name" to be passed along to dataFiles
initSystem();
}
}
//if system is already active ... stop system and flip button state back
else {
output("SYSTEM STOPPED");
initSystemButton.setString("START SYSTEM");
haltSystem();
}
//cursor(ARROW); //this this back to ARROW
}
//open or close serial port if serial port button is pressed (left button in serial widget)
if (refreshPort.isMouseHere() && refreshButtonPressed) {
output("Serial/COM List Refreshed");
serialPorts = new String[Serial.list().length];
serialPorts = Serial.list();
serialList.items.clear();
for (int i = 0; i < serialPorts.length; i++) {
String tempPort = serialPorts[(serialPorts.length-1) - i]; //list backwards... because usually our port is at the bottom
serialList.addItem(makeItem(tempPort));
}
serialList.updateMenu();
}
//open or close serial port if serial port button is pressed (left button in serial widget)
if (autoFileName.isMouseHere() && fileButtonPressed) {
output("Autogenerated \"File Name\" based on current date/time");
cp5.get(Textfield.class, "fileName").setText(getDateString());
}
if (chanButton8.isMouseHere() && chanButton8Pressed) {
nchan = 8;
fftBuff = new FFT[nchan]; //from the minim library
yLittleBuff_uV = new float[nchan][nPointsPerUpdate];
output("channel count set to " + str(nchan));
updateChannelArrays(nchan); //make sure to reinitialize the channel arrays with the right number of channels
}
if (chanButton16.isMouseHere() && chanButton16Pressed) {
nchan = 16;
fftBuff = new FFT[nchan]; //reinitialize the FFT buffer
yLittleBuff_uV = new float[nchan][nPointsPerUpdate];
output("channel count set to " + str(nchan));
updateChannelArrays(nchan); //make sure to reinitialize the channel arrays with the right number of channels
}
if (selectPlaybackFile.isMouseHere() && selectPlaybackFilePressed) {
output("select a file for playback");
selectInput("Select a pre-recorded file for playback:", "playbackSelected");
}
if (selectSDFile.isMouseHere() && selectSDFilePressed) {
output("select an SD file to convert to a playback file");
createPlaybackFileFromSD();
selectInput("Select an SD file to convert for playback:", "sdFileSelected");
}
//reset all buttons to false
refreshPort.setIsActive(false);
refreshButtonPressed = false;
initSystemButton.setIsActive(false);
initButtonPressed = false;
autoFileName.setIsActive(false);
fileButtonPressed = false;
chanButton8.setIsActive(false);
chanButton8Pressed = false;
chanButton16.setIsActive(false);
chanButton16Pressed = false;
selectPlaybackFile.setIsActive(false);
selectPlaybackFilePressed = false;
selectSDFile.setIsActive(false);
selectSDFilePressed = false;
}
};
public void controlEvent(ControlEvent theEvent) {
if (theEvent.isFrom("sourceList")) {
Map bob = ((MenuList)theEvent.getController()).getItem(int(theEvent.getValue()));
String str = (String)bob.get("headline");
str = str.substring(0, str.length()-5);
//output("Data Source = " + str);
int newDataSource = int(theEvent.getValue());
eegDataSource = newDataSource; // reset global eegDataSource to the selected value from the list
output("The new data source is " + str);
}
if (theEvent.isFrom("serialList")) {
Map bob = ((MenuList)theEvent.getController()).getItem(int(theEvent.getValue()));
openBCI_portName = (String)bob.get("headline");
output("OpenBCI Port Name = " + openBCI_portName);
}
if (theEvent.isFrom("sdTimes")) {
Map bob = ((MenuList)theEvent.getController()).getItem(int(theEvent.getValue()));
sdSettingString = (String)bob.get("headline");
sdSetting = int(theEvent.getValue());
if (sdSetting != 0) {
output("OpenBCI microSD Setting = " + sdSettingString + " recording time");
} else {
output("OpenBCI microSD Setting = " + sdSettingString);
}
verbosePrint("SD setting = " + sdSetting);
}
}
//==============================================================================//
// BELOW ARE THE CLASSES FOR THE VARIOUS //
// CONTROL PANEL BOXes (control widgets) //
//==============================================================================//
class DataSourceBox {
int x, y, w, h, padding; //size and position
CheckBox sourceCheckBox;
DataSourceBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 115;
padding = _padding;
sourceList = new MenuList(cp5, "sourceList", w - padding*2, 72, f2);
// sourceList.itemHeight = 28;
// sourceList.padding = 9;
sourceList.setPosition(x + padding, y + padding*2 + 13);
sourceList.addItem(makeItem("LIVE (from OpenBCI) >"));
sourceList.addItem(makeItem("PLAYBACK (from file) >"));
sourceList.addItem(makeItem("SYNTHETIC (algorithmic) >"));
sourceList.scrollerLength = 10;
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("DATA SOURCE", x + padding, y + padding);
popStyle();
//draw contents of Data Source Box at top of control panel
//Title
//checkboxes of system states
}
};
class SerialBox {
int x, y, w, h, padding; //size and position
//connect/disconnect button
//Refresh list button
//String port status;
SerialBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 147;
padding = _padding;
// openClosePort = new Button (padding + border, y + padding*3 + 13 + 150, (w-padding*3)/2, 24, "OPEN PORT", fontInfo.buttonLabel_size);
refreshPort = new Button (x + padding, y + padding*3 + 13 + 71, w - padding*2, 24, "REFRESH LIST", fontInfo.buttonLabel_size);
serialList = new MenuList(cp5, "serialList", w - padding*2, 72, f2);
serialList.setPosition(x + padding, y + padding*2 + 13);
serialPorts = Serial.list();
for (int i = 0; i < serialPorts.length; i++) {
String tempPort = serialPorts[(serialPorts.length-1) - i]; //list backwards... because usually our port is at the bottom
serialList.addItem(makeItem(tempPort));
}
}
public void update() {
// serialList.updateMenu();
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("SERIAL/COM PORT", x + padding, y + padding);
popStyle();
// openClosePort.draw();
refreshPort.draw();
}
public void refreshSerialList() {
}
};
class DataLogBox {
int x, y, w, h, padding; //size and position
String fileName;
//text field for inputing text
//create/open/closefile button
String fileStatus;
boolean isFileOpen; //true if file has been activated and is ready to write to
//String port status;
DataLogBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 101;
padding = _padding;
//instantiate button
//figure out default file name (from Chip's code)
isFileOpen = false; //set to true on button push
fileStatus = "NO FILE CREATED";
//button to autogenerate file name based on time/date
autoFileName = new Button (x + padding, y + 66, w-(padding*2), 24, "AUTOGENERATE FILE NAME", fontInfo.buttonLabel_size);
cp5.addTextfield("fileName")
.setPosition(x + 90, y + 32)
.setCaptionLabel("")
.setSize(157, 26)
.setFont(f2)
.setFocus(false)
.setColor(color(26, 26, 26))
.setColorBackground(color(255, 255, 255)) // text field bg color
.setColorValueLabel(color(0, 0, 0)) // text color
.setColorForeground(isSelected_color) // border color when not selected
.setColorActive(isSelected_color) // border color when selected
.setColorCursor(color(26, 26, 26))
.setText(getDateString())
.align(5, 10, 20, 40)
.onDoublePress(cb)
.setAutoClear(true);
//clear text field on double click
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("DATA LOG FILE", x + padding, y + padding);
textFont(f3);
text("File Name", x + padding, y + padding*2 + 18);
popStyle();
autoFileName.draw();
}
};
class ChannelCountBox {
int x, y, w, h, padding; //size and position
boolean isSystemInitialized;
// button for init/halt system
ChannelCountBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 73;
padding = _padding;
chanButton8 = new Button (x + padding, y + padding*2 + 18, (w-padding*3)/2, 24, "8 CHANNELS", fontInfo.buttonLabel_size);
if (nchan == 8) chanButton8.color_notPressed = isSelected_color; //make it appear like this one is already selected
chanButton16 = new Button (x + padding*2 + (w-padding*3)/2, y + padding*2 + 18, (w-padding*3)/2, 24, "16 CHANNELS", fontInfo.buttonLabel_size);
if (nchan == 16) chanButton16.color_notPressed = isSelected_color; //make it appear like this one is already selected
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("CHANNEL COUNT", x + padding, y + padding);
fill(bgColor); //set color to green
textFont(f1);
textAlign(LEFT, TOP);
text("(" + str(nchan) + ")", x + padding + 142, y + padding); // print the channel count in green next to the box title
popStyle();
chanButton8.draw();
chanButton16.draw();
}
};
class PlaybackFileBox {
int x, y, w, h, padding; //size and position
PlaybackFileBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 67;
padding = _padding;
selectPlaybackFile = new Button (x + padding, y + padding*2 + 13, w - padding*2, 24, "SELECT PLAYBACK FILE", fontInfo.buttonLabel_size);
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("PLAYBACK FILE", x + padding, y + padding);
popStyle();
selectPlaybackFile.draw();
// chanButton16.draw();
}
};
class SDBox {
int x, y, w, h, padding; //size and position
SDBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 150;
padding = _padding;
sdTimes = new MenuList(cp5, "sdTimes", w - padding*2, 108, f2);
sdTimes.setPosition(x + padding, y + padding*2 + 13);
serialPorts = Serial.list();
//add items for the various SD times
sdTimes.addItem(makeItem("Do not write to SD..."));
sdTimes.addItem(makeItem("5 minute maximum"));
sdTimes.addItem(makeItem("15 minute maximum"));
sdTimes.addItem(makeItem("30 minute maximum"));
sdTimes.addItem(makeItem("1 hour maximum"));
sdTimes.addItem(makeItem("2 hours maximum"));
sdTimes.addItem(makeItem("4 hour maximum"));
sdTimes.addItem(makeItem("12 hour maximum"));
sdTimes.addItem(makeItem("24 hour maximum"));
sdTimes.activeItem = sdSetting; //added to indicate default choice (sdSetting is in OpenBCI_GUI)
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("WRITE TO SD (Y/N)?", x + padding, y + padding);
popStyle();
//the drawing of the sdTimes is handled earlier in ControlPanel.draw()
}
};
class SDConverterBox {
int x, y, w, h, padding; //size and position
SDConverterBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 67;
padding = _padding;
selectSDFile = new Button (x + padding, y + padding*2 + 13, w - padding*2, 24, "SELECT SD FILE", fontInfo.buttonLabel_size);
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
fill(bgColor);
textFont(f1);
textAlign(LEFT, TOP);
text("CONVERT SD FOR PLAYBACK", x + padding, y + padding);
popStyle();
selectSDFile.draw();
}
};
class InitBox {
int x, y, w, h, padding; //size and position
boolean initButtonPressed; //default false
boolean isSystemInitialized;
// button for init/halt system
InitBox(int _x, int _y, int _w, int _h, int _padding) {
x = _x;
y = _y;
w = _w;
h = 50;
padding = _padding;
//init button
initSystemButton = new Button (padding, y + padding, w-padding*2, h - padding*2, "START SYSTEM", fontInfo.buttonLabel_size);
//initSystemButton.color_notPressed = color(boolor);
//initSystemButton.buttonStrokeColor = color(boxColor);
initButtonPressed = false;
}
public void update() {
}
public void draw() {
pushStyle();
fill(boxColor);
stroke(boxStrokeColor);
strokeWeight(1);
rect(x, y, w, h);
popStyle();
initSystemButton.draw();
}
};
void playbackSelected(File selection) {
if (selection == null) {
println("ControlPanel: playbackSelected: Window was closed or the user hit cancel.");
} else {
println("ControlPanel: playbackSelected: User selected " + selection.getAbsolutePath());
output("You have selected \"" + selection.getAbsolutePath() + "\" for playback.");
playbackData_fname = selection.getAbsolutePath();
}
}
@@ -1,196 +0,0 @@
//import ddf.minim.analysis.*; //for FFT
class EEG_Processing {
private float fs_Hz; //sample rate
private int nchan;
final int N_FILT_CONFIGS = 5;
FilterConstants[] filtCoeff_bp = new FilterConstants[N_FILT_CONFIGS];
final int N_NOTCH_CONFIGS = 3;
FilterConstants[] filtCoeff_notch = new FilterConstants[N_NOTCH_CONFIGS];
private int currentFilt_ind = 0;
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[];
EEG_Processing(int NCHAN, float sample_rate_Hz) {
nchan = NCHAN;
fs_Hz = sample_rate_Hz;
data_std_uV = new float[nchan];
polarity = new float[nchan];
//check to make sure the sample rate is acceptable and then define the filters
if (abs(fs_Hz-250.0f) < 1.0) {
defineFilters();
}
else {
println("EEG_Processing: *** ERROR *** Filters can currently only work at 250 Hz");
defineFilters(); //define the filters anyway just so that the code doesn't bomb
}
}
public float getSampleRateHz() {
return fs_Hz;
};
//define filters...assumes sample rate of 250 Hz !!!!!
private void defineFilters() {
int n_filt;
double[] b, a, b2, a2;
String filt_txt, filt_txt2;
String short_txt, short_txt2;
//loop over all of the pre-defined filter types
n_filt = filtCoeff_notch.length;
for (int Ifilt=0; Ifilt < n_filt; Ifilt++) {
switch (Ifilt) {
case 0:
//60 Hz notch filter, assumed fs = 250 Hz. 2nd Order Butterworth: b, a = signal.butter(2,[59.0 61.0]/(fs_Hz / 2.0), 'bandstop')
b2 = new double[] { 9.650809863447347e-001, -2.424683201757643e-001, 1.945391494128786e+000, -2.424683201757643e-001, 9.650809863447347e-001 };
a2 = new double[] { 1.000000000000000e+000, -2.467782611297853e-001, 1.944171784691352e+000, -2.381583792217435e-001, 9.313816821269039e-001 };
filtCoeff_notch[Ifilt] = new FilterConstants(b2, a2, "Notch 60Hz", "60Hz");
break;
case 1:
//50 Hz notch filter, assumed fs = 250 Hz. 2nd Order Butterworth: b, a = signal.butter(2,[49.0 51.0]/(fs_Hz / 2.0), 'bandstop')
b2 = new double[] { 0.96508099, -1.19328255, 2.29902305, -1.19328255, 0.96508099 };
a2 = new double[] { 1.0 , -1.21449348, 2.29780334, -1.17207163, 0.93138168 };
filtCoeff_notch[Ifilt] = new FilterConstants(b2, a2, "Notch 50Hz", "50Hz");
break;
case 2:
//no notch filter
b2 = new double[] { 1.0 };
a2 = new double[] { 1.0 };
filtCoeff_notch[Ifilt] = new FilterConstants(b2, a2, "No Notch", "None");
break;
}
} // end loop over notch filters
n_filt = filtCoeff_bp.length;
for (int Ifilt=0;Ifilt<n_filt;Ifilt++) {
//define bandpass filter
switch (Ifilt) {
case 0:
//butter(2,[1 50]/(250/2)); %bandpass filter
b = new double[] {
2.001387256580675e-001, 0.0f, -4.002774513161350e-001, 0.0f, 2.001387256580675e-001
};
a = new double[] {
1.0f, -2.355934631131582e+000, 1.941257088655214e+000, -7.847063755334187e-001, 1.999076052968340e-001
};
filt_txt = "Bandpass 1-50Hz";
short_txt = "1-50 Hz";
break;
case 1:
//butter(2,[7 13]/(250/2));
b = new double[] {
5.129268366104263e-003, 0.0f, -1.025853673220853e-002, 0.0f, 5.129268366104263e-003
};
a = new double[] {
1.0f, -3.678895469764040e+000, 5.179700413522124e+000, -3.305801890016702e+000, 8.079495914209149e-001
};
filt_txt = "Bandpass 7-13Hz";
short_txt = "7-13 Hz";
break;
case 2:
//[b,a]=butter(2,[15 50]/(250/2)); %matlab command
b = new double[] {
1.173510367246093e-001, 0.0f, -2.347020734492186e-001, 0.0f, 1.173510367246093e-001
};
a = new double[] {
1.0f, -2.137430180172061e+000, 2.038578008108517e+000, -1.070144399200925e+000, 2.946365275879138e-001
};
filt_txt = "Bandpass 15-50Hz";
short_txt = "15-50 Hz";
break;
case 3:
//[b,a]=butter(2,[5 50]/(250/2)); %matlab command
b = new double[] {
1.750876436721012e-001, 0.0f, -3.501752873442023e-001, 0.0f, 1.750876436721012e-001
};
a = new double[] {
1.0f, -2.299055356038497e+000, 1.967497759984450e+000, -8.748055564494800e-001, 2.196539839136946e-001
};
filt_txt = "Bandpass 5-50Hz";
short_txt = "5-50 Hz";
break;
default:
//no filtering
b = new double[] {
1.0
};
a = new double[] {
1.0
};
filt_txt = "No BP Filter";
short_txt = "No Filter";
} //end switch block
//create the bandpass filter
filtCoeff_bp[Ifilt] = new FilterConstants(b, a, filt_txt, short_txt);
} //end loop over band pass filters
} //end defineFilters method
public String getFilterDescription() {
return filtCoeff_bp[currentFilt_ind].name + ", " + filtCoeff_notch[currentNotch_ind].name;
}
public String getShortFilterDescription() {
return filtCoeff_bp[currentFilt_ind].short_name;
}
public String getShortNotchDescription() {
return filtCoeff_notch[currentNotch_ind].short_name;
}
public void incrementFilterConfiguration() {
//increment the index
currentFilt_ind++;
if (currentFilt_ind >= N_FILT_CONFIGS) currentFilt_ind = 0;
}
public void incrementNotchConfiguration() {
//increment the index
currentNotch_ind++;
if (currentNotch_ind >= N_NOTCH_CONFIGS) currentNotch_ind = 0;
}
public void process(float[][] data_newest_uV, //holds raw EEG data that is new since the last call
float[][] data_long_uV, //holds a longer piece of buffered EEG data, of same length as will be plotted on the screen
float[][] data_forDisplay_uV, //put data here that should be plotted on the screen
FFT[] fftData) { //holds the FFT (frequency spectrum) of the latest data
//loop over each EEG channel
for (int Ichan=0;Ichan < nchan; Ichan++) {
//filter the data in the time domain
filterIIR(filtCoeff_notch[currentNotch_ind].b, filtCoeff_notch[currentNotch_ind].a, data_forDisplay_uV[Ichan]); //notch
filterIIR(filtCoeff_bp[currentFilt_ind].b, filtCoeff_bp[currentFilt_ind].a, data_forDisplay_uV[Ichan]); //bandpass
//compute the standard deviation of the filtered signal...this is for the head plot
float[] fooData_filt = dataBuffY_filtY_uV[Ichan]; //use the filtered data
fooData_filt = Arrays.copyOfRange(fooData_filt, fooData_filt.length-((int)fs_Hz), fooData_filt.length); //just grab the most recent second of data
data_std_uV[Ichan]=std(fooData_filt); //compute the standard deviation for the whole array "fooData_filt"
} //close loop over channels
//find strongest channel
int refChanInd = findMax(data_std_uV);
//println("EEG_Processing: strongest chan (one referenced) = " + (refChanInd+1));
float[] refData_uV = dataBuffY_filtY_uV[refChanInd]; //use the filtered data
refData_uV = Arrays.copyOfRange(refData_uV, refData_uV.length-((int)fs_Hz), refData_uV.length); //just grab the most recent second of data
//compute polarity of each channel
for (int Ichan=0; Ichan < nchan; Ichan++) {
float[] fooData_filt = dataBuffY_filtY_uV[Ichan]; //use the filtered data
fooData_filt = Arrays.copyOfRange(fooData_filt, fooData_filt.length-((int)fs_Hz), fooData_filt.length); //just grab the most recent second of data
float dotProd = calcDotProduct(fooData_filt,refData_uV);
if (dotProd >= 0.0f) {
polarity[Ichan]=1.0;
} else {
polarity[Ichan]=-1.0;
}
}
}
}
@@ -1,22 +0,0 @@
class EEG_Processing_User {
// Constructor function
public EEG_Processing_User() {}
// gets called only once
public void setup() {
// initialization
}
// processing routine called by the main function
public void process() {
// processing data
}
// rendering routine called by the main function
public void draw() {
// rendering code
}
}
@@ -1,938 +0,0 @@
////////////////////////////////////////////////////
//
// This class creates and manages all of the graphical user interface (GUI) elements
// for the primary display. This is the display with the head, with the FFT frequency
// traces, and with the montage of time-domain traces. It also holds all of the buttons.
//
// Chip Audette, Oct 2013 - May 2014
//
// Requires the plotting library from gwoptics. Built on gwoptics 0.5.0
// http://www.gwoptics.org/processing/gwoptics_p5lib/
//
///////////////////////////////////////////////////
//import processing.core.PApplet;
import org.gwoptics.graphics.*;
import org.gwoptics.graphics.graph2D.*;
import org.gwoptics.graphics.graph2D.Graph2D;
import org.gwoptics.graphics.graph2D.LabelPos;
import org.gwoptics.graphics.graph2D.traces.Blank2DTrace;
import org.gwoptics.graphics.graph2D.backgrounds.*;
import ddf.minim.analysis.*; //for FFT
import java.util.*; //for Array.copyOfRange()
class Gui_Manager {
ScatterTrace montageTrace;
ScatterTrace_FFT fftTrace;
Graph2D gMontage, gFFT, gSpectrogram;
GridBackground gbMontage, gbFFT;
Button stopButton;
PlotFontInfo fontInfo;
HeadPlot headPlot1;
Button[] chanButtons;
// Button guiPageButton;
//boolean showImpedanceButtons;
Button[] impedanceButtonsP;
Button[] impedanceButtonsN;
Button biasButton;
Button intensityFactorButton;
Button loglinPlotButton;
Button filtBPButton;
Button filtNotchButton;
Button fftNButton;
Button smoothingButton;
Button maxDisplayFreqButton;
Button showPolarityButton;
//these two buttons toggle between EEG graph state (they are mutually exclusive states)
Button showMontageButton; // to show uV time graph as opposed to channel controller
Button showChannelControllerButton; //to drawChannelController on top of gMontage
// boolean isChannelControllerVisible;
TextBox titleMontage, titleFFT,titleSpectrogram;
TextBox[] chanValuesMontage;
TextBox[] impValuesMontage;
boolean showMontageValues;
public int guiPage;
boolean vertScaleAsLog = true;
Spectrogram spectrogram;
boolean showSpectrogram;
int whichChannelForSpectrogram;
//define some color variables
int bgColorGraphs = 255;
int gridColor = 200;
int borderColor = 50;
int axisColor = 50;
int fontColor = 255;
// MontageController mc;
ChannelController cc;
private float fftYOffset[];
private float default_vertScale_uV=200.0; //this defines the Y-scale on the montage plots...this is the vertical space between traces
private float[] vertScaleFactor = {1.0f, 2.0f, 5.0f, 50.0f, 0.25f, 0.5f};
private int vertScaleFactor_ind = 0;
float vertScale_uV=default_vertScale_uV;
float vertScaleMin_uV_whenLog = 0.1f;
float montage_yoffsets[];
private float[] maxDisplayFreq_Hz = {20.0f, 40.0f, 60.0f, 120.0f};
private int maxDisplayFreq_ind = 2;
public final static int GUI_PAGE_CHANNEL_ONOFF = 0;
public final static int GUI_PAGE_IMPEDANCE_CHECK = 1;
public final static int GUI_PAGE_HEADPLOT_SETUP = 2;
public final static int N_GUI_PAGES = 3;
public final static String stopButton_pressToStop_txt = "Stop Data Stream";
public final static String stopButton_pressToStart_txt = "Start Data Stream";
Gui_Manager(PApplet parent,int win_x, int win_y,int nchan,float displayTime_sec, float default_yScale_uV,
String filterDescription, float smooth_fac) {
// Gui_Manager(PApplet parent,int win_x, int win_y,int nchan,float displayTime_sec, float yScale_uV, float fs_Hz,
// String montageFilterText, String detectName) {
showSpectrogram = false;
whichChannelForSpectrogram = 0; //assume
//define some layout parameters
float axes_x, axes_y;
float spacer_bottom = 30/float(win_y); //want this to be a fixed 30 pixels
float spacer_top = float(controlPanelCollapser.but_dy)/float(win_y);
float gutter_topbot = 0.03f;
float gutter_left = 0.08f; //edge around the GUI
float gutter_right = 0.015f; //edge around the GUI
float height_UI_tray = 0.1f + spacer_bottom; //0.1f;//0.10f; //empty space along bottom for UI elements
float left_right_split = 0.45f; //notional dividing line between left and right plots, measured from left
float available_top2bot = 1.0f - 2*gutter_topbot - height_UI_tray;
float up_down_split = 0.5f; //notional dividing line between top and bottom plots, measured from top
float gutter_between_buttons = 0.005f; //space between buttons
float title_gutter = 0.02f;
float headPlot_fromTop = 0.12f;
//float headPlot_fromTop = 0;
fontInfo = new PlotFontInfo();
//montage control panel variables
// float x_cc = float(win_x)*(left_right_split+gutter_right - 0.01f);
float x_cc = 5;
// float y_cc = float(win_y)*(gutter_topbot+title_gutter+spacer_top);
float y_cc = float(win_y)*(height_UI_tray);
float w_cc = float(win_x)*(0.09f-gutter_right); //width of montage controls (on left of montage)
float h_cc = float(win_y)*(available_top2bot-title_gutter-spacer_top); //height of montage controls (on left of montage)
//setup the montage plot...the right side
default_vertScale_uV = default_yScale_uV; //here is the vertical scaling of the traces
// float[] axisMontage_relPos = {
// left_right_split+gutter_left,
// gutter_topbot+title_gutter+spacer_top,
// (1.0f-left_right_split)-gutter_left-gutter_right,
// available_top2bot-title_gutter-spacer_top
// }; //from left, from top, width, height
float[] axisMontage_relPos = {
gutter_left,
height_UI_tray,
(1.0f-left_right_split)-gutter_left-gutter_right,
available_top2bot-title_gutter-spacer_top
}; //from left, from top, width, height
axes_x = float(win_x)*axisMontage_relPos[2]; //width of the axis in pixels
axes_y = float(win_y)*axisMontage_relPos[3]; //height of the axis in pixels
gMontage = new Graph2D(parent, int(axes_x), int(axes_y), false); //last argument is whether the axes cross at zero
setupMontagePlot(gMontage, win_x, win_y, axisMontage_relPos,displayTime_sec,fontInfo,filterDescription);
verbosePrint("Gui_Manager: Buttons: " + int(float(win_x)*axisMontage_relPos[0]) + ", " + (int(float(win_y)*axisMontage_relPos[1])-40));
showMontageButton = new Button (int(float(win_x)*axisMontage_relPos[0]) - 1, int(float(win_y)*axisMontage_relPos[1])-45, 125, 21, "EEG DATA", 14);
showMontageButton.makeDropdownButton(true);
showMontageButton.setColorPressed(color(184,220,105));
showMontageButton.setColorNotPressed(color(255));
showMontageButton.hasStroke(false);
showMontageButton.setIsActive(true);
showMontageButton.buttonFont = f1;
showMontageButton.textColorActive = bgColor;
showChannelControllerButton = new Button (int(float(win_x)*axisMontage_relPos[0])+127, int(float(win_y)*axisMontage_relPos[1])-45, 125, 21, "CHAN SET", 14);
showChannelControllerButton.makeDropdownButton(true);
showChannelControllerButton.setColorPressed(color(184,220,105));
showChannelControllerButton.setColorNotPressed(color(255));
showChannelControllerButton.hasStroke(false);
showChannelControllerButton.setIsActive(false);
showChannelControllerButton.textColorActive = bgColor;
//setup montage controller
cc = new ChannelController(x_cc, y_cc, w_cc, h_cc, axes_x, axes_y);
//setup the FFT plot...bottom on left side
//float height_subplot = 0.5f*(available_top2bot-2*gutter_topbot);
// float[] axisFFT_relPos = {
// gutter_left,
// gutter_topbot+ up_down_split*available_top2bot + gutter_topbot+title_gutter + spacer_top,
// left_right_split-gutter_left-gutter_right,
// available_top2bot*(1.0f-up_down_split) - gutter_topbot-title_gutter - spacer_top
// }; //from left, from top, width, height
float[] axisFFT_relPos = {
gutter_left + left_right_split + 0.1f,
up_down_split*available_top2bot + height_UI_tray + gutter_topbot,
left_right_split-gutter_left-gutter_right,
available_top2bot*(1.0f-up_down_split) - gutter_topbot-title_gutter - spacer_top
}; //from left, from top, width, height
axes_x = int(float(win_x)*axisFFT_relPos[2]); //width of the axis in pixels
axes_y = int(float(win_y)*axisFFT_relPos[3]); //height of the axis in pixels
gFFT = new Graph2D(parent, int(axes_x), int(axes_y), false); //last argument is whether the axes cross at zero
setupFFTPlot(gFFT, win_x, win_y, axisFFT_relPos,fontInfo);
//setup the spectrogram plot
// float[] axisSpectrogram_relPos = axisMontage_relPos;
// axes_x = int(float(win_x)*axisSpectrogram_relPos[2]);
// axes_y = int(float(win_y)*axisSpectrogram_relPos[3]);
// gSpectrogram = new Graph2D(parent, axes_x, axes_y, false); //last argument is wheter the axes cross at zero
// setupSpectrogram(gSpectrogram, win_x, win_y, axisMontage_relPos,displayTime_sec,fontInfo);
// int Nspec = 256;
// int Nstep = 32;
// spectrogram = new Spectrogram(Nspec,openBCI.fs_Hz,Nstep,displayTime_sec);
// spectrogram.clim[0] = java.lang.Math.log(gFFT.getYAxis().getMinValue()); //set the minium value for the color scale on the spectrogram
// spectrogram.clim[1] = java.lang.Math.log(gFFT.getYAxis().getMaxValue()/10.0); //set the maximum value for the color scale on the spectrogram
// updateMaxDisplayFreq();
//setup the head plot...top on the left side
float[] axisHead_relPos = axisFFT_relPos.clone();
// axisHead_relPos[1] = gutter_topbot + spacer_top; //set y position to be at top of left side
axisHead_relPos[1] = headPlot_fromTop; //set y position to be at top of right side
axisHead_relPos[3] = available_top2bot*up_down_split - gutter_topbot;
headPlot1 = new HeadPlot(axisHead_relPos[0],axisHead_relPos[1],axisHead_relPos[2],axisHead_relPos[3],win_x,win_y,nchan);
setSmoothFac(smooth_fac);
//setup the buttons
int w,h,x,y;
h = 26; //button height, was 25
y = 2; //button y position, measured top
// //// Is this block used anymore? Chip 2014-11-23
//setup the gui page button
w = 80; //button width
x = (int)((3*gutter_between_buttons + left_right_split) * win_x);
// x = int(float(win_x)*0.3f);
// guiPageButton = new Button(x,y,w,h,"Page\n" + (guiPage+1) + " of " + N_GUI_PAGES,fontInfo.buttonLabel_size);
// //// End Ques by Chip 2014-11-12
//setup the channel on/off buttons...only plot 8 buttons, even if there are more channels
//because as of 4/3/2014, you can only turn on/off the higher channels (the ones above chan 8)
//by also turning off the corresponding lower channel. So, deactiving channel 9 must also
//deactivate channel 1, therefore, we might as well use just the 1 button.
// int xoffset = x + w + (int)(2*gutter_between_buttons*win_x);
// int xoffset = (int)(float(win_x)*gutter_left);
int xoffset = (int)(float(win_x)*0.5f);
w = 80; //button width
int w_orig = w;
//if (nchan > 10) w -= (nchan-8)*2; //make the buttons skinnier
int nChanBut = min(nchan,8);
chanButtons = new Button[nChanBut];
String txt;
for (int Ibut = 0; Ibut < nChanBut; Ibut++) {
x = calcButtonXLocation(Ibut, win_x, w, xoffset,gutter_between_buttons);
txt = "Chan\n" + Integer.toString(Ibut+1);
if (nchan > 8+Ibut) txt = txt + "+" + Integer.toString(Ibut+1+8);
chanButtons[Ibut] = new Button(x,y,w,h,txt,fontInfo.buttonLabel_size);
}
//setup the impedance measurement (lead-off) control buttons
//showImpedanceButtons = false; //by default, do not show the buttons
int vertspace_pix = max(1,int(gutter_between_buttons*win_x/4));
int w1 = w_orig; //use same width as for buttons above
int h1 = h/2-vertspace_pix; //use buttons with half the height
impedanceButtonsP = new Button[nchan];
for (int Ibut = 0; Ibut < nchan; Ibut++) {
x = calcButtonXLocation(Ibut, win_x, w1, xoffset, gutter_between_buttons);
impedanceButtonsP[Ibut] = new Button(x,y,w1,h1,"Imp P" + (Ibut+1),fontInfo.buttonLabel_size);
}
impedanceButtonsN = new Button[nchan];
for (int Ibut = 0; Ibut < nchan; Ibut++) {
x = calcButtonXLocation(Ibut, win_x, w1, xoffset, gutter_between_buttons);
impedanceButtonsN[Ibut] = new Button(x,y+h-h1,w1,h1,"Imp N" + (Ibut+1),fontInfo.buttonLabel_size);
}
h1 = h;
x = calcButtonXLocation(nchan, win_x, w1, xoffset, gutter_between_buttons);
biasButton = new Button(x,y,w1,h1,"Bias\n" + "Auto",fontInfo.buttonLabel_size);
//setup the buttons to control the processing and frequency displays
int Ibut=0;
w = 70;
h = 26;
y = 2;
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
maxDisplayFreqButton = new Button(x,y,w,h,"Max Freq\n" + round(maxDisplayFreq_Hz[maxDisplayFreq_ind]) + " Hz",fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
showPolarityButton = new Button(x,y,w,h,"Polarity\n" + headPlot1.getUsePolarityTrueFalse(),fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
smoothingButton = new Button(x,y,w,h,"Smooth\n" + headPlot1.smooth_fac,fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
loglinPlotButton = new Button(x,y,w,h,"Vert Scale\n" + get_vertScaleAsLogText(),fontInfo.buttonLabel_size);
//x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
//fftNButton = new Button(x,y,w,h,"FFT N\n" + Nfft,fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
intensityFactorButton = new Button(x,y,w,h,"Vert Scale\n" + round(vertScale_uV) + "uV",fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
filtNotchButton = new Button(x,y,w,h,"Notch\n" + eegProcessing.getShortNotchDescription(),fontInfo.buttonLabel_size);
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
filtBPButton = new Button(x,y,w,h,"BP Filt\n" + eegProcessing.getShortFilterDescription(),fontInfo.buttonLabel_size);
set_vertScaleAsLog(true);
//setup start/stop button
// x = win_x - int(gutter_right*float(win_x)) - w;
//x = width/2 - w;
x = calcButtonXLocation(Ibut++, win_x, w, xoffset,gutter_between_buttons);
int w_wide = 120; //button width, wider
x = x + w - w_wide-((int)(gutter_between_buttons*win_x)); //adjust the x position for the wider button, plus double the gutter
stopButton = new Button(x,y,w_wide,h,stopButton_pressToStart_txt,fontInfo.buttonLabel_size);
//set the initial display page for the GUI
setGUIpage(GUI_PAGE_HEADPLOT_SETUP);
}
private int calcButtonXLocation(int Ibut,int win_x,int w, int xoffset, float gutter_between_buttons) {
// return xoffset + (Ibut * (w + (int)(gutter_between_buttons*win_x)));
return width - ((Ibut+1) * (w + 2)) - 1;
}
public void setDefaultVertScale(float val_uV) {
default_vertScale_uV = val_uV;
updateVertScale();
}
public void setVertScaleFactor_ind(int ind) {
vertScaleFactor_ind = max(0,ind);
if (ind >= vertScaleFactor.length) vertScaleFactor_ind = 0;
updateVertScale();
}
public void incrementVertScaleFactor() {
setVertScaleFactor_ind(vertScaleFactor_ind+1); //wrap-around is handled inside the function
}
public void updateVertScale() {
vertScale_uV = default_vertScale_uV*vertScaleFactor[vertScaleFactor_ind];
//println("Gui_Manager: updateVertScale: vertScale_uV = " + vertScale_uV);
//update how the plots are scaled
if (montageTrace != null) montageTrace.setYScale_uV(vertScale_uV); //the Y-axis on the montage plot is fixed...the data is simply scaled prior to plotting
if (gFFT != null) gFFT.setYAxisMax(vertScale_uV);
headPlot1.setMaxIntensity_uV(vertScale_uV);
intensityFactorButton.setString("Vert Scale\n" + round(vertScale_uV) + "uV");
//update the Yticks on the FFT plot
if (gFFT != null) {
if (vertScaleAsLog) {
gFFT.setYAxisTickSpacing(1);
} else {
gFFT.setYAxisTickSpacing(pow(10.0,floor(log10(vertScale_uV/4))));
}
}
}
public String get_vertScaleAsLogText() {
if (vertScaleAsLog) {
return "Log";
} else {
return "Linear";
}
}
public void set_vertScaleAsLog(boolean state) {
vertScaleAsLog = state;
//change the FFT Plot
if (gFFT != null) {
if (vertScaleAsLog) {
gFFT.setYAxisMin(vertScaleMin_uV_whenLog);
Axis2D ay=gFFT.getYAxis();
ay.setLogarithmicAxis(true);
updateVertScale(); //force a re-do of the Yticks
} else {
Axis2D ay=gFFT.getYAxis();
ay.setLogarithmicAxis(false);
gFFT.setYAxisMin(0.0f);
updateVertScale(); //force a re-do of the Yticks
}
}
//change the head plot
headPlot1.set_plotColorAsLog(vertScaleAsLog);
//change the button
if (loglinPlotButton != null) {
loglinPlotButton.setString("Vert Scale\n" + get_vertScaleAsLogText());
}
}
public void setSmoothFac(float fac) {
headPlot1.smooth_fac = fac;
}
public void setMaxDisplayFreq_ind(int ind) {
maxDisplayFreq_ind = max(0,ind);
if (ind >= maxDisplayFreq_Hz.length) maxDisplayFreq_ind = 0;
updateMaxDisplayFreq();
}
public void incrementMaxDisplayFreq() {
setMaxDisplayFreq_ind(maxDisplayFreq_ind+1); //wrap-around is handled inside the function
}
public void updateMaxDisplayFreq() {
//set the frequency limit of the display
float foo_Hz = maxDisplayFreq_Hz[maxDisplayFreq_ind];
gFFT.setXAxisMax(foo_Hz);
if (fftTrace != null) fftTrace.set_plotXlim(0.0f,foo_Hz);
//gSpectrogram.setYAxisMax(foo_Hz);
//set the ticks
if (foo_Hz < 38.0f) {
foo_Hz = 5.0f;
} else if (foo_Hz < 78.0f) {
foo_Hz = 10.0f;
} else if (foo_Hz < 168.0f) {
foo_Hz = 20.0f;
} else {
foo_Hz = (float)floor(foo_Hz / 50.0) * 50.0f;
}
gFFT.setXAxisTickSpacing(foo_Hz);
//gSpectrogram.setYAxisTickSpacing(foo_Hz);
if (maxDisplayFreqButton != null) maxDisplayFreqButton.setString("Max Freq\n" + round(maxDisplayFreq_Hz[maxDisplayFreq_ind]) + " Hz");
}
public void setDoNotPlotOutsideXlim(boolean state) {
if (state) {
//println("GUI_Manager: setDoNotPlotAboveXlim: " + gFFT.getXAxis().getMaxValue());
fftTrace.set_plotXlim(gFFT.getXAxis().getMinValue(),gFFT.getXAxis().getMaxValue());
montageTrace.set_plotXlim(gMontage.getXAxis().getMinValue(),gMontage.getXAxis().getMaxValue());
} else {
fftTrace.set_plotXlim(Float.NaN,Float.NaN);
}
}
public void setDecimateFactor(int fac) {
montageTrace.setDecimateFactor(fac);
}
public void setupMontagePlot(Graph2D g, int win_x, int win_y, float[] axis_relPos,float displayTime_sec, PlotFontInfo fontInfo,String filterDescription) {
g.setAxisColour(axisColor, axisColor, axisColor);
g.setFontColour(fontColor, fontColor, fontColor);
int x1,y1;
x1 = int(axis_relPos[0]*float(win_x));
g.position.x = x1;
y1 = int(axis_relPos[1]*float(win_y));
g.position.y = y1;
//g.position.y = 0;
g.setYAxisMin(-nchan-1.0f);
g.setYAxisMax(0.0f);
g.setYAxisTickSpacing(1f);
g.setYAxisMinorTicks(0);
g.setYAxisLabelAccuracy(0);
g.setYAxisLabel("EEG Channel");
g.setYAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, true);
g.setYAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
g.setXAxisMin(-displayTime_sec);
g.setXAxisMax(0f);
g.setXAxisTickSpacing(1f);
g.setXAxisMinorTicks(1);
g.setXAxisLabelAccuracy(0);
g.setXAxisLabel("Time (sec)");
g.setXAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, false);
g.setXAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
// switching on Grid, with different colours for X and Y lines
gbMontage = new GridBackground(new GWColour(bgColorGraphs));
gbMontage.setGridColour(gridColor, gridColor, gridColor, gridColor, gridColor, gridColor);
g.setBackground(gbMontage);
g.setBorderColour(borderColor,borderColor,borderColor);
// add title
titleMontage = new TextBox("EEG Data (" + filterDescription + ")",0,0);
int x2 = x1 + int(round(0.5*axis_relPos[2]*float(win_x)));
int y2 = y1 - 2; //deflect two pixels upward
titleMontage.x = x2;
titleMontage.y = y2;
titleMontage.textColor = color(bgColor);
titleMontage.setFontSize(14);
titleMontage.alignH = CENTER;
//add channel data values and impedance values
int x3, y3;
//float w = int(round(axis_relPos[2]*win_x));
TextBox fooBox = new TextBox("",0,0);
chanValuesMontage = new TextBox[nchan];
impValuesMontage = new TextBox[nchan];
Axis2D xAxis = g.getXAxis();
Axis2D yAxis = g.getYAxis();
int h = int(round(axis_relPos[3]*win_y));
for (int i=0; i<nchan; i++) {
y3 = y1 + h - yAxis.valueToPosition((float)(-(i+1))); //set to be on the centerline of the trace
for (int j=0; j<2; j++) { //loop over the different text box types
switch (j) {
case 0:
//voltage value text
x3 = x1 + xAxis.valueToPosition(xAxis.getMaxValue()) - 2; //set to right edge of plot. nudge 2 pixels to the left
fooBox = new TextBox("0.00 uVrms",x3,y3);
break;
case 1:
//impedance value text
x3 = x1 + xAxis.valueToPosition(xAxis.getMinValue()) + 2; //set to left edge of plot. nudge 2 pixels to the right
fooBox = new TextBox("0.00 kOhm",x3,y3);
break;
}
fooBox.textColor = color(0,0,0);
fooBox.drawBackground = true;
fooBox.backgroundColor = color(255,255,255, 125);
noStroke();
switch (j) {
case 0:
//voltage value text
fooBox.alignH = RIGHT;
chanValuesMontage[i] = fooBox;
break;
case 1:
//impedance value text
fooBox.alignH = LEFT;
impValuesMontage[i] = fooBox;
break;
}
}
}
showMontageValues = true; // default to having them NOT displayed
}
public void setupFFTPlot(Graph2D g, int win_x, int win_y, float[] axis_relPos,PlotFontInfo fontInfo) {
g.setAxisColour(axisColor, axisColor, axisColor);
g.setFontColour(fontColor, fontColor, fontColor);
int x1,y1;
x1 = int(axis_relPos[0]*float(win_x));
g.position.x = x1;
y1 = int(axis_relPos[1]*float(win_y));
g.position.y = y1;
//g.position.y = 0;
//setup the y axis
g.setYAxisMin(vertScaleMin_uV_whenLog);
g.setYAxisMax(vertScale_uV);
g.setYAxisTickSpacing(1);
g.setYAxisMinorTicks(0);
g.setYAxisLabelAccuracy(0);
//g.setYAxisLabel("EEG Amplitude (uV/sqrt(Hz))"); // Some people prefer this...but you'll have to change the normalization in OpenBCI_GUI\processNewData()
g.setYAxisLabel("EEG Amplitude (uV per bin)"); // CHIP 2014-10-24...currently, this matches the normalization in OpenBCI_GUI\processNewData()
g.setYAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, false);
g.setYAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
//get the Y-axis and make it log
Axis2D ay=g.getYAxis();
ay.setLogarithmicAxis(true);
//setup the x axis
g.setXAxisMin(0f);
g.setXAxisMax(maxDisplayFreq_Hz[maxDisplayFreq_ind]);
g.setXAxisTickSpacing(10f);
g.setXAxisMinorTicks(2);
g.setXAxisLabelAccuracy(0);
g.setXAxisLabel("Frequency (Hz)");
g.setXAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, false);
g.setXAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
// switching on Grid, with differetn colours for X and Y lines
gbFFT = new GridBackground(new GWColour(bgColorGraphs));
gbFFT.setGridColour(gridColor, gridColor, gridColor, gridColor, gridColor, gridColor);
g.setBackground(gbFFT);
g.setBorderColour(borderColor,borderColor,borderColor);
// add title
titleFFT = new TextBox("FFT Plot",0,0);
int x2 = x1 + int(round(0.5*axis_relPos[2]*float(win_x)));
int y2 = y1 - 2; //deflect two pixels upward
titleFFT.x = x2;
titleFFT.y = y2;
titleFFT.textColor = color(255,255,255);
titleFFT.setFontSize(16);
titleFFT.alignH = CENTER;
}
public void setupSpectrogram(Graph2D g, int win_x, int win_y, float[] axis_relPos,float displayTime_sec, PlotFontInfo fontInfo) {
//start by setting up as if it were the montage plot
//setupMontagePlot(g, win_x, win_y, axis_relPos,displayTime_sec,fontInfo,title);
g.setAxisColour(220, 220, 220);
g.setFontColour(255, 255, 255);
int x1 = int(axis_relPos[0]*float(win_x));
g.position.x = x1;
int y1 = int(axis_relPos[1]*float(win_y));
g.position.y = y1;
//setup the x axis
g.setXAxisMin(-displayTime_sec);
g.setXAxisMax(0f);
g.setXAxisTickSpacing(1f);
g.setXAxisMinorTicks(1);
g.setXAxisLabelAccuracy(0);
g.setXAxisLabel("Time (sec)");
g.setXAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, false);
g.setXAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
//setup the y axis...frequency
g.setYAxisMin(0.0f-0.5f);
g.setYAxisMax(maxDisplayFreq_Hz[maxDisplayFreq_ind]);
g.setYAxisTickSpacing(10.0f);
g.setYAxisMinorTicks(2);
g.setYAxisLabelAccuracy(0);
g.setYAxisLabel("Frequency (Hz)");
g.setYAxisLabelFont(fontInfo.fontName,fontInfo.axisLabel_size, false);
g.setYAxisTickFont(fontInfo.fontName,fontInfo.tickLabel_size, false);
//make title
titleSpectrogram = new TextBox(makeSpectrogramTitle(),0,0);
int x2 = x1 + int(round(0.5*axis_relPos[2]*float(win_x)));
int y2 = y1 - 2; //deflect two pixels upward
titleSpectrogram.x = x2;
titleSpectrogram.y = y2;
titleSpectrogram.textColor = color(255,255,255);
titleSpectrogram.setFontSize(16);
titleSpectrogram.alignH = CENTER;
}
public void initializeMontageTraces(float[] dataBuffX, float [][] dataBuffY) {
//create the trace object, add it to the plotting object, and set the data and scale factor
//montageTrace = new ScatterTrace(); //I can't have this here because it dies. It must be in setup()
gMontage.addTrace(montageTrace);
montageTrace.setXYData_byRef(dataBuffX, dataBuffY);
montageTrace.setYScaleFac(1f / vertScale_uV);
//montageTrace.setYScaleFac(1.0f); //for OpenBCI_GUI_Simpler
//set the y-offsets for each trace in the fft plot.
//have each trace bumped down by -1.0.
for (int Ichan=0; Ichan < nchan; Ichan++) {
montage_yoffsets[Ichan]=(float)(-(Ichan+1));
}
montageTrace.setYOffset_byRef(montage_yoffsets);
}
public void initializeFFTTraces(ScatterTrace_FFT fftTrace,FFT[] fftBuff,float[] fftYOffset,Graph2D gFFT) {
for (int Ichan = 0; Ichan < fftYOffset.length; Ichan++) {
//set the Y-offste for the individual traces in the plots
fftYOffset[Ichan]= 0f; //set so that there is no additional offset
}
//make the trace for the FFT and add it to the FFT Plot axis
//fftTrace = new ScatterTrace_FFT(fftBuff); //can't put this here...must be in setup()
fftTrace.setYOffset(fftYOffset);
gFFT.addTrace(fftTrace);
}
public void initDataTraces(float[] dataBuffX,float[][] dataBuffY,FFT[] fftBuff,float[] dataBuffY_std, DataStatus[] is_railed, float[] dataBuffY_polarity) {
//initialize the time-domain montage-plot traces
montageTrace = new ScatterTrace();
montage_yoffsets = new float[nchan];
initializeMontageTraces(dataBuffX,dataBuffY);
montageTrace.set_isRailed(is_railed);
//initialize the FFT traces
fftTrace = new ScatterTrace_FFT(fftBuff); //can't put this here...must be in setup()
fftYOffset = new float[nchan];
initializeFFTTraces(fftTrace,fftBuff,fftYOffset,gFFT);
//link the data to the head plot
headPlot1.setIntensityData_byRef(dataBuffY_std,is_railed);
headPlot1.setPolarityData_byRef(dataBuffY_polarity);
}
public void setShowSpectrogram(boolean show) {
showSpectrogram = show;
}
public void tellGUIWhichChannelForSpectrogram(int Ichan) { // Ichan starts at zero
if (Ichan != whichChannelForSpectrogram) {
whichChannelForSpectrogram = Ichan;
titleSpectrogram.string = makeSpectrogramTitle();
}
}
public String makeSpectrogramTitle() {
return ("Spectrogram, Channel " + (whichChannelForSpectrogram+1) + " (As Received)");
}
public void setGUIpage(int page) {
if ((page >= 0) && (page < N_GUI_PAGES)) {
guiPage = page;
} else {
guiPage = 0;
}
//update the text on the button
// guiPageButton.setString("Page\n" + (guiPage+1) + " of " + N_GUI_PAGES);
}
public void incrementGUIpage() {
setGUIpage( (guiPage+1) % N_GUI_PAGES );
}
public boolean isMouseOnGraph2D(Graph2D g, int mouse_x, int mouse_y) {
GraphDataPoint dataPoint = new GraphDataPoint();
getGraph2DdataPoint(g,mouse_x,mouse_y,dataPoint);
if ( (dataPoint.x >= g.getXAxis().getMinValue()) &
(dataPoint.x <= g.getXAxis().getMaxValue()) &
(dataPoint.y >= g.getYAxis().getMinValue()) &
(dataPoint.y <= g.getYAxis().getMaxValue()) ) {
return true;
} else {
return false;
}
}
public boolean isMouseOnMontage(int mouse_x, int mouse_y) {
return isMouseOnGraph2D(gMontage,mouse_x,mouse_y);
}
public boolean isMouseOnFFT(int mouse_x, int mouse_y) {
return isMouseOnGraph2D(gFFT,mouse_x,mouse_y);
}
public void getGraph2DdataPoint(Graph2D g, int mouse_x,int mouse_y, GraphDataPoint dataPoint) {
int rel_x = mouse_x - int(g.position.x);
int rel_y = g.getYAxis().getLength() - (mouse_y - int(g.position.y));
dataPoint.x = g.getXAxis().positionToValue(rel_x);
dataPoint.y = g.getYAxis().positionToValue(rel_y);
}
public void getMontageDataPoint(int mouse_x, int mouse_y, GraphDataPoint dataPoint) {
getGraph2DdataPoint(gMontage,mouse_x,mouse_y,dataPoint);
dataPoint.x_units = "sec";
dataPoint.y_units = "uV";
}
public void getFFTdataPoint(int mouse_x,int mouse_y,GraphDataPoint dataPoint) {
getGraph2DdataPoint(gFFT, mouse_x,mouse_y,dataPoint);
dataPoint.x_units = "Hz";
dataPoint.y_units = "uV/sqrt(Hz)";
}
// public boolean isMouseOnHeadPlot(int mouse_x, int mouse_y) {
// return headPlot1.isPixelInsideHead(mouse_x,mouse_y) {
// }
public void update(float[] data_std_uV,float[] data_elec_imp_ohm) {
//assume new data has already arrived via the pre-existing references to dataBuffX and dataBuffY and FftBuff
montageTrace.generate(); //graph doesn't update without this
fftTrace.generate(); //graph doesn't update without this
headPlot1.update();
cc.update();
//update the text strings
String fmt; float val;
for (int Ichan=0; Ichan < data_std_uV.length; Ichan++) {
//update the voltage values
val = data_std_uV[Ichan];
chanValuesMontage[Ichan].string = String.format(getFmt(val),val) + " uVrms";
if (montageTrace.is_railed != null) {
if (montageTrace.is_railed[Ichan].is_railed == true) {
chanValuesMontage[Ichan].string = "RAILED";
} else if (montageTrace.is_railed[Ichan].is_railed_warn == true) {
chanValuesMontage[Ichan].string = "NEAR RAILED";
}
}
//update the impedance values
val = data_elec_imp_ohm[Ichan]/1000;
impValuesMontage[Ichan].string = String.format(getFmt(val),val) + " kOhm";
if (montageTrace.is_railed != null) {
if (montageTrace.is_railed[Ichan].is_railed == true) {
impValuesMontage[Ichan].string = "RAILED";
}
}
}
}
private String getFmt(float val) {
String fmt;
if (val > 100.0f) {
fmt = "%.0f";
} else if (val > 10.0f) {
fmt = "%.1f";
} else {
fmt = "%.2f";
}
return fmt;
}
public void draw() {
if(!drawEMG){
// for dragging purpose
headPlot1.drag(mouseX, mouseY);
headPlot1.draw();
}
//draw montage or spectrogram
if (showSpectrogram == false) {
//show time-domain montage, only if full channel controller is not visible, to save some processing
gMontage.draw();
//add annotations
if (showMontageValues) {
for (int Ichan = 0; Ichan < chanValuesMontage.length; Ichan++) {
chanValuesMontage[Ichan].draw();
}
}
} else {
//show the spectrogram
gSpectrogram.draw(); //draw the spectrogram axes
titleSpectrogram.draw(); //draw the spectrogram title
//draw the spectrogram image
PVector pos = gSpectrogram.position;
Axis2D ax = gSpectrogram.getXAxis();
int x = ax.valueToPosition(ax.getMinValue())+(int)pos.x;
int w = ax.valueToPosition(ax.getMaxValue());
ax = gSpectrogram.getYAxis();
int y = (int) pos.y - ax.valueToPosition(ax.getMinValue()); //position needs top-left. The MAX value is at the top-left for this plot.
int h = ax.valueToPosition(ax.getMaxValue());
//println("gui_Manager.draw(): x,y,w,h = " + x + " " + y + " " + w + " " + h);
float max_freq_Hz = gSpectrogram.getYAxis().getMaxValue()-0.5f;
spectrogram.draw(x,y,w,h,max_freq_Hz);
}
//draw the regular FFT spectrum display
gFFT.draw();
titleFFT.draw();//println("completed FFT draw...");
//draw the UI buttons and other elements
stopButton.draw();
//commented out because pages 1-2 are being moved to the left of the EEG montage
// guiPageButton.draw();
switch (guiPage) { //the rest of the elements depend upon what GUI page we're on
//note: GUI_PAGE_CHANNEL_ON_OFF is the default at the end
case GUI_PAGE_IMPEDANCE_CHECK:
//show impedance buttons and text
for (int Ichan = 0; Ichan < chanButtons.length; Ichan++) {
impedanceButtonsP[Ichan].draw(); //P-channel buttons
impedanceButtonsN[Ichan].draw(); //N-channel buttons
}
for (int Ichan = 0; Ichan < impValuesMontage.length; Ichan++) {
impValuesMontage[Ichan].draw(); //impedance values on montage plot
}
biasButton.draw();
break;
case GUI_PAGE_HEADPLOT_SETUP:
intensityFactorButton.draw();
loglinPlotButton.draw();
filtBPButton.draw();
filtNotchButton.draw();
//fftNButton.draw();
smoothingButton.draw();
showPolarityButton.draw();
maxDisplayFreqButton.draw();
break;
default: //assume GUI_PAGE_CHANNEL_ONOFF:
//show channel buttons
for (int Ichan = 0; Ichan < chanButtons.length; Ichan++) { chanButtons[Ichan].draw(); }
//detectButton.draw();
//spectrogramButton.draw();
}
if (showMontageValues) {
for (int Ichan = 0; Ichan < chanValuesMontage.length; Ichan++) {
chanValuesMontage[Ichan].draw();
}
}
// if(controlPanelCollapser.isActive){
// controlPanel.draw();
// }
// controlPanelCollapser.draw();
cc.draw();
if(cc.showFullController == false){
titleMontage.draw();
}
showMontageButton.draw();
showChannelControllerButton.draw();
}
public void mousePressed(){
verbosePrint("Gui_Manager: mousePressed: mouse pressed.");
//if showMontage button pressed
if(showMontageButton.isMouseHere()){
//turn off visibility of channel full controller
cc.showFullController = false;
showMontageButton.setIsActive(true);
showMontageButton.buttonFont = f1;
showChannelControllerButton.setIsActive(false);
showChannelControllerButton.buttonFont = f2;
}
//if showChannelController is pressed
if(showChannelControllerButton.isMouseHere()){
cc.showFullController = true;
showMontageButton.setIsActive(false);
showMontageButton.buttonFont = f2;
showChannelControllerButton.setIsActive(true);
showChannelControllerButton.buttonFont = f1;
}
//if cursor inside channel controller
// if(mouseX >= cc.x1 && mouseX <= (cc.x2 - cc.w2) && mouseY >= cc.y1 && mouseY <= (cc.y1 + cc.h1) ){
verbosePrint("Gui_Manager: mousePressed: Channel Controller mouse pressed...");
cc.mousePressed();
// }
//turn off visibility of graph
// turn on drawing and interactivity of channel controller
//however, the on/off & impedance values must show to the right at all times ... so it should change a boolean in ChannelController
//for dragging purpose, added by TaoLin
headPlot1.clicked(mouseX, mouseY);
}
public void mouseReleased(){
//verbosePrint("Gui_Manager: mouseReleased()");
// if(mouseX >= cc.x1 && mouseX <= (cc.x2 - cc.w2) && mouseY >= cc.y1 && mouseY <= (cc.y1 + cc.h1) ){
verbosePrint("Gui_Manager: mouseReleased(): Channel Controller mouse released...");
cc.mouseReleased();
stopButton.setIsActive(false);
// guiPageButton.setIsActive(false);
intensityFactorButton.setIsActive(false);
loglinPlotButton.setIsActive(false);
filtBPButton.setIsActive(false);
filtNotchButton.setIsActive(false);
smoothingButton.setIsActive(false);
showPolarityButton.setIsActive(false);
maxDisplayFreqButton.setIsActive(false);
biasButton.setIsActive(false);
// for dragging purpose, added by TaoLin
headPlot1.stopDragging();
}
};
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
@@ -1,58 +0,0 @@
//this class is used to create the help widget that provides system feedback in response to interactivity
//it is intended to serve as a pseudo-console, allowing us to print useful information to the interface as opposed to an IDE console
class HelpWidget {
public float x, y, w, h;
// ArrayList<String> prevOutputs; //growing list of all previous system interactivity
String currentOutput = "..."; //current text shown in help widget, based on most recent command
int padding = 5;
HelpWidget(float _xPos, float _yPos, float _width, float _height) {
x = _xPos;
y = _yPos;
w = _width;
h = _height;
}
public void update() {
}
public void draw() {
pushStyle();
noStroke();
// draw background of widget
fill(255);
rect(x, height-h, width, h);
//draw bg of text field of widget
strokeWeight(1);
stroke(color(0, 5, 11));
fill(color(0, 5, 11));
rect(x + padding, height-h + padding, width - padding*5 - 128, h - padding *2);
textSize(14);
fill(255);
textAlign(LEFT, TOP);
text(currentOutput, padding*2, height - h + padding + 4);
//draw OpenBCI LOGO
image(logo, width - (128+padding*2), height - 26, 128, 22);
popStyle();
}
public void output(String _output) {
currentOutput = _output;
// prevOutputs.add(_output);
}
};
public void output(String _output) {
helpWidget.output(_output);
}
@@ -1,185 +0,0 @@
//===================== MENU LIST CLASS ===========================//
//==================EXTENSION OF CONTROLP5=========================//
//==============USED FOR SOURCEBOX & SERIALBOX=====================//
//
// Created: Conor Russomanno Oct. 2014
// Based on ControlP5 Processing Library example, written by Andreas Schlegel
//
/////////////////////////////////////////////////////////////////////
//makeItem function used by MenuList class below
Map<String, Object> makeItem(String theHeadline) {
Map m = new HashMap<String, Object>();
m.put("headline", theHeadline);
return m;
}
public class MenuList extends Controller {
float pos, npos;
int itemHeight = 24;
int scrollerLength = 40;
int scrollerWidth = 15;
List< Map<String, Object>> items = new ArrayList< Map<String, Object>>();
PGraphics menu;
boolean updateMenu;
boolean drawHand;
int hoverItem = -1;
int activeItem = -1;
PFont menuFont = f2;
int padding = 7;
MenuList(ControlP5 c, String theName, int theWidth, int theHeight, PFont theFont) {
super( c, theName, 0, 0, theWidth, theHeight );
c.register( this );
menu = createGraphics(getWidth(),getHeight());
menuFont = theFont;
setView(new ControllerView<MenuList>() {
public void display(PGraphics pg, MenuList t) {
if (updateMenu) {
updateMenu();
}
if (inside()) {
if(!drawHand){
cursor(HAND);
drawHand = true;
}
menu.beginDraw();
int len = -(itemHeight * items.size()) + getHeight();
int ty;
if(len != 0){
ty = int(map(pos, len, 0, getHeight() - scrollerLength - 2, 2 ) );
} else {
ty = 0;
}
menu.fill(bgColor, 100);
if(ty > 0){
menu.rect(getWidth()-scrollerWidth-2, ty, scrollerWidth, scrollerLength );
}
menu.endDraw();
}
else {
if(drawHand){
drawHand = false;
cursor(ARROW);
}
}
pg.image(menu, 0, 0);
}
}
);
updateMenu();
}
/* only update the image buffer when necessary - to save some resources */
void updateMenu() {
int len = -(itemHeight * items.size()) + getHeight();
npos = constrain(npos, len, 0);
pos += (npos - pos) * 0.1;
// pos += (npos - pos) * 0.1;
menu.beginDraw();
menu.noStroke();
menu.background(255, 64);
menu.textFont(cp5.getFont().getFont());
menu.pushMatrix();
menu.translate( 0, pos );
menu.pushMatrix();
int i0;
if((itemHeight * items.size()) != 0){
i0 = PApplet.max( 0, int(map(-pos, 0, itemHeight * items.size(), 0, items.size())));
} else{
i0 = 0;
}
int range = ceil((float(getHeight())/float(itemHeight))+1);
int i1 = PApplet.min( items.size(), i0 + range );
menu.translate(0, i0*itemHeight);
for (int i=i0; i<i1; i++) {
Map m = items.get(i);
menu.fill(255, 100);
if (i == hoverItem) {
menu.fill(127, 134, 143);
}
if (i == activeItem) {
menu.stroke(184, 220, 105, 255);
menu.strokeWeight(1);
menu.fill(184, 220, 105, 255);
menu.rect(0, 0, getWidth()-1, itemHeight-1 );
menu.noStroke();
} else {
menu.rect(0, 0, getWidth(), itemHeight-1 );
}
menu.fill(bgColor);
menu.textFont(menuFont);
menu.text(m.get("headline").toString(), 8, itemHeight - padding); // 5/17
menu.translate( 0, itemHeight );
}
menu.popMatrix();
menu.popMatrix();
menu.endDraw();
updateMenu = abs(npos-pos)>0.01 ? true:false;
}
/* when detecting a click, check if the click happend to the far right, if yes, scroll to that position,
* otherwise do whatever this item of the list is supposed to do.
*/
public void onClick() {
if (getPointer().x()>getWidth()-scrollerWidth) {
npos= -map(getPointer().y(), 0, getHeight(), 0, items.size()*itemHeight);
updateMenu = true;
} else {
int len = itemHeight * items.size();
int index = int( map( getPointer().y() - pos, 0, len, 0, items.size() ) ) ;
setValue(index);
activeItem = index;
}
updateMenu = true;
}
public void onMove() {
if (getPointer().x()>getWidth() || getPointer().x()<0 || getPointer().y()<0 || getPointer().y()>getHeight() ) {
hoverItem = -1;
} else {
int len = itemHeight * items.size();
int index = int( map( getPointer().y() - pos, 0, len, 0, items.size() ) ) ;
hoverItem = index;
}
updateMenu = true;
}
public void onDrag() {
if (getPointer().x() > (getWidth()-scrollerWidth)) {
npos= -map(getPointer().y(), 0, getHeight(), 0, items.size()*itemHeight);
updateMenu = true;
} else {
npos += getPointer().dy() * 2;
updateMenu = true;
}
}
public void onScroll(int n) {
npos += ( n * 4 );
updateMenu = true;
}
void addItem(Map<String, Object> m) {
items.add(m);
updateMenu = true;
}
void removeItem(Map<String, Object> m) {
items.remove(m);
updateMenu = true;
}
Map<String, Object> getItem(int theIndex) {
return items.get(theIndex);
}
};
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
@@ -1,377 +0,0 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This file contains all key commands for interactivity with GUI & OpenBCI
// Created by Chip Audette, Joel Murphy, & Conor Russomanno
// - Extracted from OpenBCI_GUI because it was getting too klunky
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//interpret a keypress...the key pressed comes in as "key"
void keyPressed() {
//note that the Processing variable "key" is the keypress as an ASCII character
//note that the Processing variable "keyCode" is the keypress as a JAVA keycode. This differs from ASCII
//println("OpenBCI_GUI: keyPressed: key = " + key + ", int(key) = " + int(key) + ", keyCode = " + keyCode);
if(!controlPanel.isOpen){ //don't parse the key if the control panel is open
if ((int(key) >=32) && (int(key) <= 126)) { //32 through 126 represent all the usual printable ASCII characters
parseKey(key);
} else {
parseKeycode(keyCode);
}
}
if(key==27){
key=0; //disable 'esc' quitting program
}
}
void parseKey(char val) {
int Ichan; boolean activate; int code_P_N_Both;
//assumes that val is a usual printable ASCII character (ASCII 32 through 126)
switch (val) {
case '.':
drawEMG = !drawEMG;
break;
case '1':
deactivateChannel(1-1);
break;
case '2':
deactivateChannel(2-1);
break;
case '3':
deactivateChannel(3-1);
break;
case '4':
deactivateChannel(4-1);
break;
case '5':
deactivateChannel(5-1);
break;
case '6':
deactivateChannel(6-1);
break;
case '7':
deactivateChannel(7-1);
break;
case '8':
deactivateChannel(8-1);
break;
case 'q':
if(nchan == 16){
deactivateChannel(9-1);
}
break;
case 'w':
if(nchan == 16){
deactivateChannel(10-1);
}
break;
case 'e':
if(nchan == 16){
deactivateChannel(11-1);
}
break;
case 'r':
if(nchan == 16){
deactivateChannel(12-1);
}
break;
case 't':
if(nchan == 16){
deactivateChannel(13-1);
}
break;
case 'y':
if(nchan == 16){
deactivateChannel(14-1);
}
break;
case 'u':
if(nchan == 16){
deactivateChannel(15-1);
}
break;
case 'i':
if(nchan == 16){
deactivateChannel(16-1);
}
break;
//activate channels 1-8
case '!':
activateChannel(1-1);
break;
case '@':
activateChannel(2-1);
break;
case '#':
activateChannel(3-1);
break;
case '$':
activateChannel(4-1);
break;
case '%':
activateChannel(5-1);
break;
case '^':
activateChannel(6-1);
break;
case '&':
activateChannel(7-1);
break;
case '*':
activateChannel(8-1);
break;
//activate channels 9-16 (DAISY MODE ONLY)
case 'Q':
if(nchan == 16){
activateChannel(9-1);
}
break;
case 'W':
if(nchan == 16){
activateChannel(10-1);
}
break;
case 'E':
if(nchan == 16){
activateChannel(11-1);
}
break;
case 'R':
if(nchan == 16){
activateChannel(12-1);
}
break;
case 'T':
if(nchan == 16){
activateChannel(13-1);
}
break;
case 'Y':
if(nchan == 16){
activateChannel(14-1);
}
break;
case 'U':
if(nchan == 16){
activateChannel(15-1);
}
break;
case 'I':
if(nchan == 16){
activateChannel(16-1);
}
break;
//other controls
case 's':
println("case s...");
stopRunning();
// stopButtonWasPressed();
break;
case 'b':
println("case b...");
startRunning();
// stopButtonWasPressed();
break;
case 'n':
println("openBCI: " + openBCI);
break;
case '?':
printRegisters();
break;
case 'd':
verbosePrint("Updating GUI's channel settings to default...");
gui.cc.loadDefaultChannelSettings();
//openBCI.serial_openBCI.write('d');
openBCI.configureAllChannelsToDefault();
break;
// //change the state of the impedance measurements...activate the N-channels
// case 'A':
// Ichan = 1; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'S':
// Ichan = 2; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'D':
// Ichan = 3; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'F':
// Ichan = 4; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'G':
// Ichan = 5; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'H':
// Ichan = 6; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'J':
// Ichan = 7; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'K':
// Ichan = 8; activate = true; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// //change the state of the impedance measurements...deactivate the N-channels
// case 'Z':
// Ichan = 1; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'X':
// Ichan = 2; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'C':
// Ichan = 3; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'V':
// Ichan = 4; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'B':
// Ichan = 5; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'N':
// Ichan = 6; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case 'M':
// Ichan = 7; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
// case '<':
// Ichan = 8; activate = false; code_P_N_Both = 1; setChannelImpedanceState(Ichan-1,activate,code_P_N_Both);
// break;
case 'm':
String picfname = "OpenBCI-" + getDateString() + ".jpg";
println("OpenBCI_GUI: 'm' was pressed...taking screenshot:" + picfname);
saveFrame("./SavedData/" + picfname); // take a shot of that!
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;
}
}
void parseKeycode(int val) {
//assumes that val is Java keyCode
switch (val) {
case 8:
println("OpenBCI_GUI: parseKeycode(" + val + "): received BACKSPACE keypress. Ignoring...");
break;
case 9:
println("OpenBCI_GUI: parseKeycode(" + val + "): received TAB keypress. Ignoring...");
//gui.showImpedanceButtons = !gui.showImpedanceButtons;
// gui.incrementGUIpage(); //deprecated with new channel controller
break;
case 10:
println("Entering Presentation Mode");
drawPresentation = !drawPresentation;
break;
case 16:
println("OpenBCI_GUI: parseKeycode(" + val + "): received SHIFT keypress. Ignoring...");
break;
case 17:
//println("OpenBCI_GUI: parseKeycode(" + val + "): received CTRL keypress. Ignoring...");
break;
case 18:
println("OpenBCI_GUI: parseKeycode(" + val + "): received ALT keypress. Ignoring...");
break;
case 20:
println("OpenBCI_GUI: parseKeycode(" + val + "): received CAPS LOCK keypress. Ignoring...");
break;
case 27:
println("OpenBCI_GUI: parseKeycode(" + val + "): received ESC keypress. Stopping OpenBCI...");
//stopRunning();
break;
case 33:
println("OpenBCI_GUI: parseKeycode(" + val + "): received PAGE UP keypress. Ignoring...");
break;
case 34:
println("OpenBCI_GUI: parseKeycode(" + val + "): received PAGE DOWN keypress. Ignoring...");
break;
case 35:
println("OpenBCI_GUI: parseKeycode(" + val + "): received END keypress. Ignoring...");
break;
case 36:
println("OpenBCI_GUI: parseKeycode(" + val + "): received HOME keypress. Ignoring...");
break;
case 37:
println("Slide Back!");
if (millis() - myPresentation.timeOfLastSlideChange >= 250) {
myPresentation.slideBack();
myPresentation.timeOfLastSlideChange = millis();
}
break;
case 38:
println("OpenBCI_GUI: parseKeycode(" + val + "): received UP ARROW keypress. Ignoring...");
break;
case 39:
println("Forward!");
if (millis() - myPresentation.timeOfLastSlideChange >= 250) {
myPresentation.slideForward();
myPresentation.timeOfLastSlideChange = millis();
}
break;
case 40:
println("OpenBCI_GUI: parseKeycode(" + val + "): received DOWN ARROW keypress. Ignoring...");
break;
case 112:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F1 keypress. Ignoring...");
break;
case 113:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F2 keypress. Ignoring...");
break;
case 114:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F3 keypress. Ignoring...");
break;
case 115:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F4 keypress. Ignoring...");
break;
case 116:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F5 keypress. Ignoring...");
break;
case 117:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F6 keypress. Ignoring...");
break;
case 118:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F7 keypress. Ignoring...");
break;
case 119:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F8 keypress. Ignoring...");
break;
case 120:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F9 keypress. Ignoring...");
break;
case 121:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F10 keypress. Ignoring...");
break;
case 122:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F11 keypress. Ignoring...");
break;
case 123:
println("OpenBCI_GUI: parseKeycode(" + val + "): received F12 keypress. Ignoring...");
break;
case 127:
println("OpenBCI_GUI: parseKeycode(" + val + "): received DELETE keypress. Ignoring...");
break;
case 155:
println("OpenBCI_GUI: parseKeycode(" + val + "): received INSERT keypress. Ignoring...");
break;
default:
println("OpenBCI_GUI: parseKeycode(" + val + "): value is not known. Ignoring...");
break;
}
}
@@ -1,122 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// Playground Class
// Created: 11/22/14 by Conor Russomanno
// An extra interface pane for additional GUI features
//
//////////////////////////////////////////////////////////////////////////
class Playground {
//button for opening and closing
float x, y, w, h;
color boxBG;
color strokeColor;
float topMargin, bottomMargin;
boolean isOpen;
boolean collapsing;
Button collapser;
Playground(int _topMargin) {
topMargin = _topMargin;
bottomMargin = helpWidget.h;
isOpen = false;
collapsing = true;
boxBG = color(255);
strokeColor = color(138, 146, 153);
collapser = new Button(0, 0, 20, 60, "<", 14);
x = width;
y = topMargin;
w = 0;
h = height - (topMargin+bottomMargin);
}
public void update() {
// verbosePrint("uh huh");
if (collapsing) {
collapse();
} else {
expand();
}
if (x > width) {
x = width;
}
}
public void draw() {
// verbosePrint("yeaaa");
pushStyle();
fill(boxBG);
stroke(strokeColor);
rect(width - w, topMargin, w, height - (topMargin + bottomMargin));
textFont(f1);
textAlign(LEFT, TOP);
fill(bgColor);
text("Developer Playground", x + 10, y + 10);
fill(255, 0, 0);
collapser.draw(int(x - collapser.but_dx), int(topMargin + (h-collapser.but_dy)/2));
popStyle();
}
boolean isMouseHere() {
if (mouseX >= x && mouseX <= width && mouseY >= y && mouseY <= height - bottomMargin) {
return true;
} else {
return false;
}
}
boolean isMouseInButton() {
verbosePrint("Playground: isMouseInButton: attempting");
if (mouseX >= collapser.but_x && mouseX <= collapser.but_x+collapser.but_dx && mouseY >= collapser.but_y && mouseY <= collapser.but_y + collapser.but_dy) {
return true;
} else {
return false;
}
}
public void toggleWindow() {
if (isOpen) {//if open
verbosePrint("close");
collapsing = true;//collapsing = true;
isOpen = false;
collapser.but_txt = "<";
} else {//if closed
verbosePrint("open");
collapsing = false;//expanding = true;
isOpen = true;
collapser.but_txt = ">";
}
}
public void mousePressed() {
verbosePrint("Playground >> mousePressed()");
}
public void mouseReleased() {
verbosePrint("Playground >> mouseReleased()");
}
public void expand() {
if (w <= width/3) {
w = w + 50;
x = width - w;
}
}
public void collapse() {
if (w >= 0) {
w = w - 50;
x = width - w;
}
}
};
@@ -1,97 +0,0 @@
///////////////////////////////////////////////////////////////////////////
//
// Created: 2/19/16
// by Conor Russomanno for BodyHacking Con DIY Cyborgia Presentation
// This code is used to organize a neuro-powered presentation... refer to triggers in the EEG_Processing_User class of the EEG_Processing.pde file
//
///////////////////////////////////////////////////////////////////////////
boolean drawPresentation = false;
class Presentation {
//presentation images
PImage presentationSlides[] = new PImage[63];
float timeOfLastSlideChange = 0;
int currentSlide = 1;
int slideCount = 0;
Presentation (){
//loading presentation images
println("attempting to load images for presentation...");
presentationSlides[0] = loadImage("prez-images/DIY_Cyborgia.001.jpg");
presentationSlides[1] = loadImage("prez-images/DIY_Cyborgia.001.jpg");
presentationSlides[2] = loadImage("prez-images/DIY_Cyborgia.002.jpg");
//presentationSlides[3] = loadImage("prez-images/DIY_Cyborgia.003.jpg");
//presentationSlides[4] = loadImage("prez-images/DIY_Cyborgia.004.jpg");
//presentationSlides[5] = loadImage("prez-images/DIY_Cyborgia.005.jpg");
//presentationSlides[6] = loadImage("prez-images/DIY_Cyborgia.006.jpg");
//presentationSlides[7] = loadImage("prez-images/DIY_Cyborgia.007.jpg");
//presentationSlides[8] = loadImage("prez-images/DIY_Cyborgia.008.jpg");
//presentationSlides[9] = loadImage("prez-images/DIY_Cyborgia.009.jpg");
//presentationSlides[10] = loadImage("prez-images/DIY_Cyborgia.010.jpg");
//presentationSlides[11] = loadImage("prez-images/DIY_Cyborgia.011.jpg");
//presentationSlides[12] = loadImage("prez-images/DIY_Cyborgia.012.jpg");
//presentationSlides[13] = loadImage("prez-images/DIY_Cyborgia.013.jpg");
//presentationSlides[14] = loadImage("prez-images/DIY_Cyborgia.014.jpg");
//presentationSlides[15] = loadImage("prez-images/DIY_Cyborgia.015.jpg");
//presentationSlides[16] = loadImage("prez-images/DIY_Cyborgia.016.jpg");
//presentationSlides[17] = loadImage("prez-images/DIY_Cyborgia.017.jpg");
//presentationSlides[18] = loadImage("prez-images/DIY_Cyborgia.018.jpg");
//presentationSlides[19] = loadImage("prez-images/DIY_Cyborgia.019.jpg");
//presentationSlides[20] = loadImage("prez-images/DIY_Cyborgia.020.jpg");
//presentationSlides[21] = loadImage("prez-images/DIY_Cyborgia.021.jpg");
//presentationSlides[22] = loadImage("prez-images/DIY_Cyborgia.022.jpg");
//presentationSlides[23] = loadImage("prez-images/DIY_Cyborgia.023.jpg");
//presentationSlides[24] = loadImage("prez-images/DIY_Cyborgia.024.jpg");
//presentationSlides[25] = loadImage("prez-images/DIY_Cyborgia.025.jpg");
//presentationSlides[26] = loadImage("prez-images/DIY_Cyborgia.026.jpg");
//presentationSlides[27] = loadImage("prez-images/DIY_Cyborgia.027.jpg");
//presentationSlides[28] = loadImage("prez-images/DIY_Cyborgia.028.jpg");
//presentationSlides[29] = loadImage("prez-images/DIY_Cyborgia.029.jpg");
//presentationSlides[30] = loadImage("prez-images/DIY_Cyborgia.030.jpg");
//presentationSlides[31] = loadImage("prez-images/DIY_Cyborgia.031.jpg");
//presentationSlides[32] = loadImage("prez-images/DIY_Cyborgia.032.jpg");
//presentationSlides[33] = loadImage("prez-images/DIY_Cyborgia.033.jpg");
//presentationSlides[34] = loadImage("prez-images/DIY_Cyborgia.034.jpg");
//presentationSlides[35] = loadImage("prez-images/DIY_Cyborgia.035.jpg");
//presentationSlides[36] = loadImage("prez-images/DIY_Cyborgia.036.jpg");
//presentationSlides[37] = loadImage("prez-images/DIY_Cyborgia.037.jpg");
//presentationSlides[38] = loadImage("prez-images/DIY_Cyborgia.038.jpg");
//presentationSlides[39] = loadImage("prez-images/DIY_Cyborgia.039.jpg");
//presentationSlides[40] = loadImage("prez-images/DIY_Cyborgia.040.jpg");
//presentationSlides[41] = loadImage("prez-images/DIY_Cyborgia.041.jpg");
//presentationSlides[42] = loadImage("prez-images/DIY_Cyborgia.042.jpg");
//presentationSlides[43] = loadImage("prez-images/DIY_Cyborgia.043.jpg");
//presentationSlides[44] = loadImage("prez-images/DIY_Cyborgia.044.jpg");
//presentationSlides[45] = loadImage("prez-images/DIY_Cyborgia.045.jpg");
//presentationSlides[46] = loadImage("prez-images/DIY_Cyborgia.046.jpg");
//presentationSlides[47] = loadImage("prez-images/DIY_Cyborgia.047.jpg");
//presentationSlides[48] = loadImage("prez-images/DIY_Cyborgia.048.jpg");
slideCount = 3;
println("DONE loading images!");
}
public void slideForward() {
if(currentSlide < slideCount - 1 && drawPresentation){
println("Slide Forward!");
currentSlide++;
}
}
public void slideBack() {
if(currentSlide > 0 && drawPresentation){
println("Slide Back!");
currentSlide--;
}
}
public void draw() {
// ----- Drawing Presentation -------
if (drawPresentation == true) {
image(presentationSlides[currentSlide], 0, 0, width, height);
}
}
}
@@ -1,107 +0,0 @@
//////////////////////////////////
//
// This file contains code used to convert HEX files (stored by OpenBCI on the local SD) into
// text files that can be used for PLAYBACK mode.
// Created: Conor Russomanno - 10/22/14 (based on code written by Joel Murphy summer 2014)
//
//////////////////////////////////
//variables for SD file conversion
BufferedReader dataReader;
String dataLine;
PrintWriter dataWriter;
String convertedLine;
String thisLine;
String h;
float[] intData = new float[20];
String logFileName;
long thisTime;
long thatTime;
public void convertSDFile() {
println("");
try {
dataLine = dataReader.readLine();
}
catch (IOException e) {
e.printStackTrace();
dataLine = null;
}
if (dataLine == null) {
// Stop reading because of an error or file is empty
thisTime = millis() - thatTime;
controlPanel.convertingSD = false;
println("nothing left in file");
println("SD file conversion took "+thisTime+" mS");
dataWriter.flush();
dataWriter.close();
} else {
// println(dataLine);
String[] hexNums = splitTokens(dataLine, ",");
if (hexNums[0].charAt(0) == '%') {
// println(dataLine);
dataWriter.println(dataLine);
println(dataLine);
} else {
for (int i=0; i<hexNums.length; i++) {
h = hexNums[i];
if (i > 0) {
if (h.charAt(0) > '7') { // if the number is negative
h = "FF" + hexNums[i]; // keep it negative
} else { // if the number is positive
h = "00" + hexNums[i]; // keep it positive
}
if (i > 8) { // accelerometer data needs another byte
if (h.charAt(0) == 'F') {
h = "FF" + h;
} else {
h = "00" + h;
}
}
}
// println(h); // use for debugging
if (h.length()%2 == 0) { // make sure this is a real number
intData[i] = unhex(h);
} else {
intData[i] = 0;
}
//if not first column(sample #) or columns 9-11 (accelerometer), convert to uV
if (i>=1 && i<=8) {
intData[i] *= openBCI.get_scale_fac_uVolts_per_count();
}
//print the current channel value
dataWriter.print(intData[i]);
if (i < hexNums.length-1) {
//print "," separator
dataWriter.print(",");
}
}
//println();
dataWriter.println();
}
}
}
void createPlaybackFileFromSD() {
logFileName = "data/EEG_Data/SDconverted-"+getDateString()+".txt";
dataWriter = createWriter(logFileName);
dataWriter.println("%OBCI Data Log - " + getDateString());
}
void sdFileSelected(File selection) {
if (selection == null) {
println("Window was closed or the user hit cancel.");
} else {
println("User selected " + selection.getAbsolutePath());
dataReader = createReader(selection.getAbsolutePath()); // ("positions.txt");
controlPanel.convertingSD = true;
println("Timing SD file conversion...");
thatTime = millis();
}
}
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 186 KiB

@@ -1,4 +0,0 @@
Should be about 23 minutes long....
5 minutes of baseline (reading google news on my cell phone, my default activity)
15 minutes of breathing meditation (there were two interval bells at 5 minute intervals tha tmay be visible on eeg)
then, another ~ 3 min of baseline google news reading.
@@ -1,4 +0,0 @@
Should be about 9 minutes long....
2 minutes of baseline (reading google news on my cell phone, my default activity)
5 minutes of relaxation, letting thoughts wander, pondering last minute christmas presents
then, 2 min of reading chip's blog post on eye blinks.
@@ -1,414 +0,0 @@
//////////////////
//
// The ScatterTrace class is used to draw and manage the traces on each
// X-Y line plot created using gwoptics graphing library
//
// Created: Chip Audette, May 2014
//
// Based on examples in gwoptics graphic library v0.5.0
// http://www.gwoptics.org/processing/gwoptics_p5lib/
//
// Note that this class does NOT store any of the data used for the
// plot. Instead, you point it to the data that lives in your
// own program. In Java-speak, I believe that this is called
// "aliasing"...in this class, I have made an "alias" to your data.
// Some people consider this dangerous. Because Processing is slow,
// this was one technique for making it faster. By making an alias
// to your data, you don't need to pass me the data for every update
// and I don't need to make a copy of it. Instead, once you update
// your data array, the alias in this class is already pointing to
// the right place. Cool, huh?
//
////////////////
//import processing.core.PApplet;
import org.gwoptics.graphics.*;
import org.gwoptics.graphics.graph2D.*;
import org.gwoptics.graphics.graph2D.Graph2D;
import org.gwoptics.graphics.graph2D.LabelPos;
import org.gwoptics.graphics.graph2D.traces.Blank2DTrace;
import org.gwoptics.graphics.graph2D.backgrounds.*;
import java.awt.Color;
class ScatterTrace extends Blank2DTrace {
private float[] dataX;
private float[][] dataY;
private float plotYScale = 1f; //multiplied to data prior to plotting
private float plotYOffset[]; //added to data prior to plotting, after applying plotYScale
private int decimate_factor = 1; // set to 1 to plot all points, 2 to plot every other point, 3 for every third point
private DataStatus[] is_railed;
PFont font = createFont("Arial", 16);
float[] plotXlim;
public ScatterTrace() {
//font = createFont("Arial",10);
plotXlim = new float[] {
Float.NaN, Float.NaN
};
}
/* set the plot's X and Y data by overwriting the existing data */
public void setXYData_byRef(float[] x, float[][] y) {
//dataX = x.clone(); //makes a copy
dataX = x; //just copies the reference!
setYData_byRef(y);
}
public void setYData_byRef(float[][] y) {
//dataY = y.clone(); //makes a copy
dataY = y;//just copies the reference!
}
public void setYOffset_byRef(float[] yoff) {
plotYOffset = yoff; //just copies the reference!
}
public void setYScale_uV(float yscale_uV) {
setYScaleFac(1.0f/yscale_uV);
}
public void setYScaleFac(float yscale) {
plotYScale = yscale;
}
public void set_plotXlim(float val_low, float val_high) {
if (val_high < val_low) {
float foo = val_low;
val_low = val_high;
val_high = foo;
}
plotXlim[0]=val_low;
plotXlim[1]=val_high;
}
public void set_isRailed(DataStatus[] is_rail) {
is_railed = is_rail;
}
//here is the fucntion that gets called with every call to the GUI's own draw() fucntion
public void TraceDraw(Blank2DTrace.PlotRenderer pr) {
float x_val;
if (dataX.length > 0) {
pr.canvas.pushStyle(); //save whatever was the previous style
//pr.canvas.stroke(255, 0, 0); //set the new line's color
//pr.canvas.strokeWeight(1); //set the new line's linewidth
//draw all the individual segments
for (int Ichan = 0; Ichan < dataY.length; Ichan++) {
//if colorMode == 1 ...
switch (Ichan % 8) {
case 0:
pr.canvas.stroke(129, 129, 129); //set the new line's color;
break;
case 1:
pr.canvas.stroke(124, 75, 141); //set the new line's color;
break;
case 2:
pr.canvas.stroke(54, 87, 158); //set the new line's color;
break;
case 3:
pr.canvas.stroke(49, 113, 89); //set the new line's color;
break;
case 4:
pr.canvas.stroke(221, 178, 13); //set the new line's color;
break;
case 5:
pr.canvas.stroke(253, 94, 52); //set the new line's color;
break;
case 6:
pr.canvas.stroke(224, 56, 45); //set the new line's color;
break;
case 7:
pr.canvas.stroke(162, 82, 49); //set the new line's color;
break;
}
//if colorMode == 2 ... for future dev work ... want to be able to edit colors of EEG montage traces
// color _RGB = Color.HSBtoRGB(float((255/OpenBCI_Nchannels)*Ichan), 100.0f, 100.0f);
// println("_RGB: " + _RGB);
// pr.canvas.stroke(_RGB);
// pr.canvas.stroke((int((255/OpenBCI_Nchannels)*Ichan)), 125-(int(((255/OpenBCI_Nchannels)*Ichan)/2)), 255-(int((255/OpenBCI_Nchannels)*Ichan)));
// pr.canvas.stroke((int((255/nchan)*Ichan)), 125-(int(((255/nchan)*Ichan)/2)), 255-(int((255/nchan)*Ichan)));
float new_x = pr.valToX(dataX[0]); //first point, convert from data coordinates to pixel coordinates
float new_y = pr.valToY(dataY[Ichan][0]*plotYScale+plotYOffset[Ichan]); //first point, convert from data coordinates to pixel coordinate
float prev_x, prev_y;
for (int i=1; i < dataY[Ichan].length; i+= decimate_factor) {
prev_x = new_x;
prev_y = new_y;
x_val = dataX[i];
if ( (Float.isNaN(plotXlim[0])) || ((x_val >= plotXlim[0]) && (x_val <= plotXlim[1])) ) {
new_x = pr.valToX(x_val);
new_y = pr.valToY(dataY[Ichan][i]*plotYScale+plotYOffset[Ichan]);
pr.canvas.line(prev_x, prev_y, new_x, new_y);
//if (i==1) println("ScatterTrace: first point: new_x, new_y = " + new_x + ", " + new_y);
} else {
//do nothing
}
}
//add annotation for is_railed...doesn't work right
// if (is_railed != null) {
// if (Ichan < is_railed.length) {
// if (is_railed[Ichan]) {
// new_x = pr.valToX(-2.0); //near time zero
// new_y = pr.valToY(0.0+plotYOffset[Ichan]);
// println("ScatterTrace: text: new_x, new_y = " + new_x + ", " + new_y);
// fill(50,50,50);
// textFont(font);
// textAlign(RIGHT, BOTTOM);
// pr.canvas.text("RAILED",new_x,new_y,100);
// }
// }
// }
}
pr.canvas.popStyle(); //restore whatever was the previous style
}
}
public void setDecimateFactor(int val) {
decimate_factor = max(1, val);
//println("ScatterTrace: setDecimateFactor to " + decimate_factor);
}
}
// /////////////////////////////////////////////////////////////////////////////////////////////
class ScatterTrace_FFT extends Blank2DTrace {
private FFT[] fftData;
private float plotYOffset[];
private float[] plotXlim = new float[] {
Float.NaN, Float.NaN
};
private float[] goodBand_Hz = {
-1.0f, -1.0f
};
private float[] badBand_Hz = {
-1.0f, -1.0f
};
private boolean showFFTFilteringData = false;
private DetectionData_FreqDomain[] detectionData;
private Oscil wave;
public ScatterTrace_FFT() {
}
public ScatterTrace_FFT(FFT foo_fft[]) {
setFFT_byRef(foo_fft);
// if (foo_fft.length != plotYOffset.length) {
// plotYOffset = new float[foo_fft.length];
// }
}
public void setFFT_byRef(FFT foo_fft[]) {
fftData = foo_fft;//just copies the reference!
}
public void setYOffset(float yoff[]) {
plotYOffset = yoff;
}
public void set_plotXlim(float val_low, float val_high) {
if (val_high < val_low) {
float foo = val_low;
val_low = val_high;
val_high = foo;
}
plotXlim[0]=val_low;
plotXlim[1]=val_high;
}
public void setGoodBand(float band_Hz[]) {
for (int i=0; i<2; i++) {
goodBand_Hz[i]=band_Hz[i];
};
}
public void setBadBand(float band_Hz[]) {
for (int i=0; i<2; i++) {
badBand_Hz[i]=band_Hz[i];
};
}
public void showFFTFilteringData(boolean show) {
showFFTFilteringData = show;
}
public void setDetectionData_freqDomain(DetectionData_FreqDomain[] data) {
detectionData = data.clone();
}
public void setAudioOscillator(Oscil wave_given) {
wave = wave_given;
}
public void TraceDraw(Blank2DTrace.PlotRenderer pr) {
float x_val, spec_value;
//save whatever was the previous style
pr.canvas.pushStyle();
// //add FFT processing bands
// float[] fooBand_Hz;
// for (int i=0; i<2; i++) {
// if (i==0) {
// fooBand_Hz = goodBand_Hz;
// pr.canvas.stroke(100,255,100);
// } else {
// fooBand_Hz = badBand_Hz;
// pr.canvas.stroke(255,100,100);
// }
// pr.canvas.strokeWeight(13);
// float x1 = pr.valToX(fooBand_Hz[0]);
// float x2 = pr.valToX(fooBand_Hz[1]);
// if (!showFFTFilteringData) {
// x1 = -1.0f; x2=-1.0f; //draw offscreen when not active
// }
// float y1 = pr.valToY(0.13f);
// float y2 = pr.valToY(0.13f);
// pr.canvas.line(x1,y1,x2,y2);
// }
if (fftData != null) {
pr.canvas.pushStyle(); //save whatever was the previous style
//draw all the individual segments
for (int Ichan=0; Ichan < fftData.length; Ichan++) {
//if colorMode == 1 ...
switch (Ichan % 8) {
case 0:
pr.canvas.stroke(129, 129, 129); //set the new line's color;
break;
case 1:
pr.canvas.stroke(124, 75, 141); //set the new line's color;
break;
case 2:
pr.canvas.stroke(54, 87, 158); //set the new line's color;
break;
case 3:
pr.canvas.stroke(49, 113, 89); //set the new line's color;
break;
case 4:
pr.canvas.stroke(221, 178, 13); //set the new line's color;
break;
case 5:
pr.canvas.stroke(253, 94, 52); //set the new line's color;
break;
case 6:
pr.canvas.stroke(224, 56, 45); //set the new line's color;
break;
case 7:
pr.canvas.stroke(162, 82, 49); //set the new line's color;
break;
}
// //if colorMode == 2...
// // pr.canvas.stroke((int((255/OpenBCI_Nchannels)*Ichan)), 125-(int(((255/OpenBCI_Nchannels)*Ichan)/2)), 255-(int((255/OpenBCI_Nchannels)*Ichan)));
// pr.canvas.stroke((int((255/nchan)*Ichan)), 125-(int(((255/nchan)*Ichan)/2)), 255-(int((255/nchan)*Ichan)));
float new_x = pr.valToX(fftData[Ichan].indexToFreq(0)); //first point, convert from data coordinates to pixel coordinates
float new_y = pr.valToY(fftData[Ichan].getBand(0)+plotYOffset[Ichan]); //first point, convert from data coordinates to pixel coordinate
float prev_x, prev_y;
for (int i=1; i < fftData[Ichan].specSize (); i++) {
prev_x = new_x;
prev_y = new_y;
x_val = fftData[Ichan].indexToFreq(i);
//only plot those points that are within the frequency limits of the plot
if ( (Float.isNaN(plotXlim[0])) || ((x_val >= plotXlim[0]) && (x_val <= plotXlim[1])) ) {
new_x = pr.valToX(x_val);
//spec_value = fftData[Ichan].getBand(i)/fftData[Ichan].specSize(); //uV_per_bin...this normalization is now done elsewhere
spec_value = fftData[Ichan].getBand(i);
new_y = pr.valToY(spec_value+plotYOffset[Ichan]);
pr.canvas.line(prev_x, prev_y, new_x, new_y);
} else {
//do nothing
} // end if Float.isNan
} //end of loop over spec size
// //add detection-related graphics
// if (showFFTFilteringData) {
// //add ellipse showing peak
// float new_x2 = pr.valToX(detectionData[Ichan].inband_freq_Hz);
// float new_y2 = pr.valToY(detectionData[Ichan].inband_uV);
// int diam = 8;
// pr.canvas.strokeWeight(1); //set the new line's linewidth
// if (detectionData[Ichan].isDetected) { //if there is a detection, make more prominent
// diam = 8;
// pr.canvas.strokeWeight(4); //set the new line's linewidth
// }
// ellipseMode(CENTER);
// pr.canvas.ellipse(new_x2,new_y2,diam,diam);
//
// //add horizontal lines indicating the detction threshold and guard level (use a dashed line)
// for (int Iband=0;Iband<2;Iband++) {
// float x1, x2,y;
// if (Iband==1) {
// x1 = pr.valToX(badBand_Hz[0]);
// x2 = pr.valToX(badBand_Hz[1]);
// y = pr.valToY(detectionData[Ichan].guard_uV);
// } else {
// x1 = pr.valToX(goodBand_Hz[0]);
// x2 = pr.valToX(goodBand_Hz[1]);
// y = pr.valToY(detectionData[Ichan].thresh_uV);
// }
//
// pr.canvas.strokeWeight(1.5);
// float dx = 8; //how big is the dash+space
// float nudge = 2;
// float foo_x=min(x1+dx,x2); //start here
// while (foo_x < x2) {
// pr.canvas.line(foo_x-dx+nudge,y,foo_x-(5*dx)/8+nudge,y);
// foo_x += dx;
// }
// }
// }
} // end loop over channels
// //update the audio
// if (showFFTFilteringData & (wave != null)) {
// //find if any channels have detected, and which is the strongest SNR
// float maxExcessSNR = -100.0f;
// for (int Ichan=0; Ichan < detectionData.length; Ichan++) {
// if (detectionData[Ichan].isDetected) {
// //how much above the threshold are we
// maxExcessSNR = max(maxExcessSNR,(detectionData[Ichan].inband_uV)/(detectionData[Ichan].thresh_uV));
// }
// }
// float audioFreq_Hz = calcDesiredAudioFrequency(maxExcessSNR);
// if (audioFreq_Hz > 0) {
// wave.amplitude.setLastValue(0.8); //turn on
// wave.frequency.setLastValue(audioFreq_Hz); //set the desired frequency
// println("ScatterTrace: excessSNR = " + maxExcessSNR + ", freq = " + audioFreq_Hz + " Hz");
// } else {
// //turn off
// wave.amplitude.setLastValue(0.0);
// }
// } else {
// //ensure that the audio is off
// wave.amplitude.setLastValue(0);
// }
pr.canvas.popStyle(); //restore whatever was the previous style
}
}
float calcDesiredAudioFrequency(float excessSNR) {
//set some constants
final float excessSNRRange[] = {
1.0f, 3.0f
}; //not dB, just linear units
final float freqRange_Hz[] = {
200.0f, 600.0f
};
//compute the desired snr
float outputFreq_Hz = -1.0f;
if (excessSNR >= excessSNRRange[0]) {
excessSNR = constrain(excessSNR, excessSNRRange[0], excessSNRRange[1]);
outputFreq_Hz = map(excessSNR, excessSNRRange[0], excessSNRRange[1], freqRange_Hz[0], freqRange_Hz[1]);
}
return outputFreq_Hz;
}
};
@@ -1,178 +0,0 @@
///////////////////////////////////////////////
//
// Created: Chip Audette, Oct 2013
// Modified: through May 2014
//
// No warranty. Use at your own risk. Use for whatever you'd like.
//
///////////////////////////////////////////////
//import ddf.minim.analysis.*; //for FFT
class Spectrogram {
public int Nfft;
//public float dataSlices[][]; //holds the data in [Nslices][Nfft] manner
//public float dT_perSlice_sec; //time interval between slices
public float fs_Hz; //sample rate
public PImage img;
public double clim[] = {0.0d, 1.0d};
private FFT localFftData;
private float[] localDataBuff;
private int localDataBuffCounter;
public int fft_stepsize;
public int Nslices;
Spectrogram(int N, float fs, int fft_step, float tmax_sec) {
println("Spectrogram: N, fs, fft_step, tmax_sec = " + N + " " + fs + " " + fft_step + " " + tmax_sec);
Nfft=N;
fs_Hz = fs;
//dT_perSlice_sec = ((float)Nfft) / fs;
fft_stepsize = constrain(fft_step,1,Nfft);
// clim[0] = java.lang.Math.log(0.01f);
// clim[1] = java.lang.Math.log(200.0f);
//create zero data for the local time-domain buffer
localDataBuff = new float[Nfft];
for (int I=0; I < Nfft; I++) {
localDataBuff[I] = 0.0f; //initialize
}
localDataBuffCounter = Nfft-fft_stepsize;
//initialize FFT
localFftData = new FFT(Nfft, fs_Hz);
localFftData.window(FFT.HAMMING);
//create the image
int tmax_samps = (int)(tmax_sec * fs_Hz + 0.5f); //the 0.5 is to round, not truncate
Nslices = (int)(((float)(tmax_samps-Nfft))/((float)fft_stepsize+0.5)) + 1;
img = createImage(Nslices,localFftData.specSize(),RGB);
println("Spectrogram: image is " + Nslices + " x " + localFftData.specSize());
img.loadPixels(); //this is apparently necessary to allocate the space for the pixels
int count=0;
for (int J=0; J < localFftData.specSize(); J++) {
for (int I=0; I<Nslices;I++) {
img.pixels[count]=getColor(java.lang.Math.log(0.0001f));
count++;
}
}
img.updatePixels();
}
public void addDataPoint(float dataPoint) {
//add point
localDataBuff[localDataBuffCounter] = dataPoint;
//println("Spectrogram.addDataPoint(): counter = " + localDataBuffCounter + ", data = " + localDataBuff[localDataBuffCounter]);
//increment counter for next time
localDataBuffCounter++;
//are we full?
if (localDataBuffCounter >= Nfft) {
//println("Spectrogra.addDataPoint(): processing the FFT block");
//compute the new FFT and update the overall image
addDataBlock(localDataBuff);
//shift the data buffer to make space for the next points
//println("addDataPoint: Nfft, fft_stepsize + " + Nfft + " " + fft_stepsize);
for (int I=0; I < (Nfft-fft_stepsize); I++) {
localDataBuff[I]=localDataBuff[(int)(I+fft_stepsize)];
//println("addDataPoint: Shifting " + I + " from " + (I+fft_stepsize) + ", val = " + (localDataBuff[I]));
}
//point the counter to the new location to start accumulating data
localDataBuffCounter = Nfft-fft_stepsize;
}
}
public void addDataBlock(float[] dataHere) {
float foo;
//do the FFT on the data block
float[] localCopy = new float[dataHere.length];
localCopy = Arrays.copyOfRange(dataHere,0, dataHere.length);
float meanVal = mean(localCopy);
for (int I=0; I<localCopy.length;I++) localCopy[I] -= meanVal; //remove mean before doing FFT
localFftData.forward(localCopy);
//convert fft data to uV_per_sqrtHz
//final float mean_winpow_sqr = 0.3966; //account for power lost when windowing...mean(hamming(N).^2) = 0.3966
final float mean_winpow = 1.0f/sqrt(2.0f); //account for power lost when windowing...mean(hamming(N).^2) = 0.3966
final float scale_rawPSDtoPSDPerHz = ((float)localFftData.specSize())*fs_Hz*mean_winpow; //normalize the amplitude by the number of bins to get the correct scaling to uV/sqrt(Hz)???
for (int I=0; I < localFftData.specSize(); I++) { //loop over each FFT bin
foo = sqrt(pow(localFftData.getBand(I),2)/scale_rawPSDtoPSDPerHz);
//if ((I > 5) & (I < 15)) println("Spectrogram: uV/rtHz = " + I + " " + foo);
localFftData.setBand(I,foo);
}
//update image...shift all previous pixels to the left
int pixel_ind=0;
int nPixelsWide = Nslices;
for (int J=0; J < localFftData.specSize(); J++) {
for (int I=0; I < (nPixelsWide-1); I++) {
pixel_ind = J*nPixelsWide + I;
img.pixels[pixel_ind] = img.pixels[pixel_ind+1];
}
}
//update image...set the color based on the latest data
for (int J=0; J < localFftData.specSize(); J++) {
pixel_ind = (localFftData.specSize()-J-1)*nPixelsWide + (nPixelsWide-1); //build from bottom-left
foo = localFftData.getBand(J); foo=max(foo,0.001f);
img.pixels[pixel_ind] = getColor(java.lang.Math.log(foo));
}
//we're finished with the pixels, so update the image
//println("addNewData: updating the pixels");
img.updatePixels();
}
//model after matlab's "jet" color scheme
private color getColor(double given_val) {
float r,b,g;
float val = (float)((given_val - clim[0])/(clim[1]-clim[0]));
val = min(1.0f,max(0.0f,val)); //span [0.0 1.0]
//compute color
float[] bounds = {1.0f/8.0f, 3.0f/8.0f, 5.0f/8.0f, 7.0f/8.0f};
if (val < bounds[0]) {
r = 0.0f;
g = 0.0f;
b = map(val,0.0f,bounds[0],0.5f,1.0f);
} else if (val < bounds[1]) {
r = 0.0f;
g = map(val,bounds[0],bounds[1],0.0f,1.0f);
b = 1.0f;
} else if (val < bounds[2]) {
r = map(val,bounds[1],bounds[2],0.0f,1.0f);
g = 1.0f;
b = map(val,bounds[1],bounds[2],1.0f,0.0f);
} else if (val < bounds[3]) {
r = 1.0f;
g = map(val,bounds[2],bounds[3],1.0f,0.0f);
b = 0.0f;
} else {
r = map(val,bounds[3],1.0f,1.0f,0.5f);
g = 0.0f;
b = 0.0f;
}
return color((int)(r*255.f),(int)(g*255.f),(int)(b*255.f));
}
public void draw(int x, int y, int w, int h,float max_freq_Hz) {
//float max_freq_Hz = freq_lim_Hz[1];
int max_ind = 0;
while ((localFftData.indexToFreq(max_ind) <= max_freq_Hz) & (max_ind < localFftData.specSize()-1)) max_ind++;
//println("Spectrogram.draw(): max_ind = " + max_ind);
//PImage foo = (PImage)(img.get(0,localFftData.specSize()-1-max_ind,Nslices,localFftData.specSize()-1)).clone();
//println("spectrogram.draw() max freq = " + localFftData.indexToFreq(max_ind));
int img_x = 0;
int img_y = localFftData.specSize()-1-max_ind;
int img_w = Nslices - img_x + 1;
int img_h = localFftData.specSize()-1 - img_y + 1;
image(img.get(img_x,img_y,img_w,img_h),x,y,w,h); //plot a subset
}
}
@@ -1,18 +0,0 @@
X,Y
-0.30,-0.275
-0.225,-0.05
-0.225,0.175
-0.275,0.335
0.0,-0.4
0.0,-0.15
0.0,0.025
0.0,0.25
0.3,-0.275
0.225,-0.025
0.225,0.175
0.275,0.335
+0.1,0
+0.1,0
+0.1,0
+0.1,0
0.0,0.025
@@ -1,18 +0,0 @@
X,Y
-0.125,-0.416
0.125,-0.416
-0.2,0.0
0.2,0.0
-0.3425,0.27
0.3425,0.27
-0.125,0.416
0.125,0.416
-0.3425,-0.27
0.3425,-0.27
-0.18,-0.15
0.18,-0.15
-0.416,0.0
0.416,0.0
-0.18,0.15
0.18,0.15
0.0,0.0
@@ -1,18 +0,0 @@
X,Y
-0.125,-0.416
0.125,-0.416
-0.2,0.0
0.2,0.0
-0.3425,0.27
0.3425,0.27
-0.125,0.416
0.125,0.416
0.0,0.0
0.0,0.0
0.0,0.0
0.0,0.0
0.0,0.0
0.0,0.0
0.0,0.0
0.0,0.0
0.0,-0.275
Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 4.0 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 597 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 679 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 321 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 679 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 559 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 456 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 577 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 295 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.5 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.2 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 428 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 299 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 450 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 925 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 326 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 745 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.2 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 393 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 558 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 601 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 846 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 759 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 827 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 353 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.6 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.6 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.6 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 1.4 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 2.1 MiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 199 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 980 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 980 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 980 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 980 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 980 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 347 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 258 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 557 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 954 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 323 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 692 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 554 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 256 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 239 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 260 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 160 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 556 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 454 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 187 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 110 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 228 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 392 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 520 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 937 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 489 KiB

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais