Browse Source

add gui Dateien

grafische-Oberfläche
Nicole Weber 2 years ago
parent
commit
8334ead7e5
16 changed files with 1582 additions and 1 deletions
  1. 10
    0
      BCI.desktop
  2. 358
    0
      Code/UIController.py
  3. 180
    0
      Code/UIModell.py
  4. 228
    0
      Code/UIModellTaktil.py
  5. 230
    0
      Code/UIModellVisuell.py
  6. 284
    0
      Code/UIViewTKinter.py
  7. 227
    0
      Code/dll.cpp
  8. 8
    0
      Code/gui.py
  9. BIN
      Ordnerstruktur.PNG
  10. 5
    0
      Projekte/OpenVibe_THN-p300-bci-main/README.md
  11. 36
    1
      README.md
  12. BIN
      dll.so
  13. BIN
      gui
  14. BIN
      icon.png
  15. 7
    0
      script.sh
  16. 9
    0
      start.sh

+ 10
- 0
BCI.desktop View File

@@ -0,0 +1,10 @@
#!/usr/bin/env xdg-open
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Icon[C]=/home/ubuntu/Downloads/icon.ico
Name[C]=BCI
Exec=/home/ubuntu/Desktop/BCIProjekt/start.sh
Name=BCI
Icon=/home/ubuntu/Downloads/icon.ico

+ 358
- 0
Code/UIController.py View File

@@ -0,0 +1,358 @@
'''--------------------------------------------------------------------------------------------------
Im Controller wird in der Init eine View erstellt und gestartet. Zudem wird der Acquisitionserver
gestartet, die shared Librarz geladen, die Konstanten Initialtisiert.
Mittels der Funktion Action Performed wird die jeweilige Reaktion auf die Benutyeraktion ausgeloest.
Hierfuer stehen die verschiedenen eigenen Funktionen die die Reaktion in der richtigen reihenfolge
an ein neu instanizieertes Modell weitergibt.
Zudem stehen einige Funktionen zur Informationsuebergabe an die View oder das Modell zur Verfuegung
'''


from UIModellVisuell import *
from UIModellTaktil import *
from UIModell import *
import UIViewTKinter as viewTkinter
from shutil import copyfile
import ctypes
import os



class Controller():
def __init__(self):
'''--------------------------------------------------------------------------------------------------
In der Init wird die shared Library geladen, die View erstellt und geoeffnet und die verschiedenen
Konstanten gesetzt
'''

self.getSharedLibrary()

self.view = viewTkinter.View(self, self.dll.getDefaultPath_visuell())
self.modi = "visuellesBCI"
self.pathOVFile = self.dll.getPathOVFile_visuell()
self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
self.infotext = ""

self.commands = {
"copySpelling": self.commandoCopySpelling,
"stop": self.commandStop,
"freeSpelling": self.commandFreeSpelling,
"test": self.test,
"wechsel": self.wechsel,
"speicherort": self.setDataset
}

self.nexts = {
"filterXdawn" : self.filterXdawn,
"filterClassic": self.filterClassic,
"save": self.speichern
}

self.pagesTaktil = {
"stop": "StartPage",
"copySpelling": "WorkingPageTaktil",
"freeSpelling": "WorkingPageTaktil",
"test": "WorkingPageTaktil"
}
self.pagesVisuell = {
"stop": "StartPage",
"copySpelling": "WorkingPageVisuell",
"freeSpelling": "WorkingPageVisuell",
"test": "WorkingPageVisuell"
}
self.acquisitionServer = Modell(self, self.dll)
self.acquisitionServer.start()

self.model = None
self.view.mainloop()

def getSharedLibrary(self):
'''--------------------------------------------------------------------------------------------------
Laedt die shared Library (diese muss sich im gleichen Ordner wie die ausfuehrunde Datei befinden)
und setzt die Eingabe und Rueckgabewerte.
'''

path = os.path.abspath(".")
path = path + "/dll.so"
self.dll = ctypes.CDLL(path)

self.dll.getCommandFreespellingTaktil.argtypes = []
self.dll.getCommandFreespellingTaktil.restype = ctypes.c_char_p

self.dll.getCommandFreespellingVisuell.argtypes = []
self.dll.getCommandFreespellingVisuell.restype = ctypes.c_char_p

self.dll.getCommandCopyspellingTaktil.argtypes = []
self.dll.getCommandCopyspellingTaktil.restype = ctypes.c_char_p

self.dll.getCommandCopyspellingVisuell.argtypes = []
self.dll.getCommandCopyspellingVisuell.restype = ctypes.c_char_p

self.dll.getCommandXDawn_taktil.argtypes = []
self.dll.getCommandXDawn_taktil.restype = ctypes.c_char_p

self.dll.getCommandXDawn_visuell.argtypes = []
self.dll.getCommandXDawn_visuell.restype = ctypes.c_char_p

self.dll.getCommandClassifier_visuell.argtypes = []
self.dll.getCommandClassifier_visuell.restype = ctypes.c_char_p

self.dll.getCommandClassifier_taktil.argtypes = []
self.dll.getCommandClassifier_taktil.restype = ctypes.c_char_p

self.dll.getDefaultPath_visuell.argtypes = []
self.dll.getDefaultPath_visuell.restype = ctypes.c_char_p

self.dll.getDefaultPath_taktil.argtypes = []
self.dll.getDefaultPath_taktil.restype = ctypes.c_char_p

self.dll.getPathOVFile_visuell.argtypes = []
self.dll.getPathOVFile_visuell.restype = ctypes.c_char_p

self.dll.getSpatialCFGFile_visuell.argtypes = []
self.dll.getSpatialCFGFile_visuell.restype = ctypes.c_char_p

self.dll.getClassifierCFGFile_visuell.argtypes = []
self.dll.getClassifierCFGFile_visuell.restype = ctypes.c_char_p

self.dll.getPathOVFile_taktil.argtypes = []
self.dll.getPathOVFile_taktil.restype = ctypes.c_char_p

self.dll.getSpatialCFGFile_taktil.argtypes = []
self.dll.getSpatialCFGFile_taktil.restype = ctypes.c_char_p

self.dll.getClassifierCFGFile_taktil.argtypes = []
self.dll.getClassifierCFGFile_taktil.restype = ctypes.c_char_p

self.dll.getCommandStartAquisitionServer.argtypes = []
self.dll.getCommandStartAquisitionServer.restype = ctypes.c_char_p
def actionPerformed(self, action):
'''--------------------------------------------------------------------------------------------------
Wird aufgerufen wenn ein Button in der Init gedrueckt wird zuerst wird kontrolliert ob die Seite
gewechselt werden muss, dann nach dem Buttonnamen die Funktion zugeordnert. Der Funktion zum
Buttomnamen wird in der Init festgelegt
'''

self.changePage(action)
func = self.commands.get(action)
if(func is not None):
func()
else:
print("Kommado existiert nicht")


def changePage(self,action):
'''--------------------------------------------------------------------------------------------------
Change Page ruft je nach Aktion und Modi die jeweilige Seite auf
'''

if(self.modi == "taktilesBCI"):
page = self.pagesTaktil.get(action)
elif(self.modi == "visuellesBCI"):
page = self.pagesVisuell.get(action)
if(page is not None):
self.view.changeFrame(page)

def wechsel(self):
'''--------------------------------------------------------------------------------------------------
Wechsel aendert den Modi. Dafuer wird zuerst der aktuelle Modi ueberprueft und dann auf den anderen
Modi gesetzt.
'''

self.resetInfo()
self.addInfoText("")
if(self.modi == "taktilesBCI"):
self.view.setChangeBtnText("Wechsel zu taktilen BCI")
self.view.setTitleText("visuelles BCI")
self.view.setDefaultPath(self.dll.getDefaultPath_visuell())
self.pathOVFile = self.dll.getPathOVFile_visuell()
self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
self.modi = "visuellesBCI"
elif(self.modi == "visuellesBCI"):
self.setTitle("taktiles BCI")
self.view.setChangeBtnText("Wechsel zu visuellen BCI")
self.view.setDefaultPath(self.dll.getDefaultPath_taktil())
self.pathOVFile = self.dll.getPathOVFile_taktil()
self.pathSpatialCfg = self.dll.getSpatialCFGFile_taktil()
self.pathClassifierCfg = self.dll.getClassifierCFGFile_taktil()
self.modi = "taktilesBCI"

def speichern(self):
'''--------------------------------------------------------------------------------------------------
wird nach dem Classifier Training aufgerufen und speichert die erstellte .ov Datei und die
spatial.cfg, classifier.cgf-Dateine unter dem ausgewaehlten Ordnername.
(Ordnername wird zu Beginn des CopySpellings festgelegt)
'''
print("saveFile")
print(self.file)
if not os.path.exists(self.file):
os.mkdir(self.file)
copyfile(self.pathOVFile, (self.file + "/p300-xdawn-train.ov"))
copyfile(self.pathClassifierCfg, (self.file + "/p300-classifier.cfg"))
copyfile(self.pathSpatialCfg, (self.file + "/p300-spatial-filter.cfg"))

self.changeScreen("StartPage")

#copyfile(self.pathOVFile, self.file)

def setDataset(self):
'''--------------------------------------------------------------------------------------------------
Legt fest welches Datenset fuer das Freestelling genutzt wird
'''

file = self.view.openfiledialog()
print(file)
if not file:
print("nichts ausgewaehlt")
else:
if os.path.exists((file + "/p300-classifier.cfg")):
print("classifier kopiert")
copyfile((file + "/p300-classifier.cfg"), self.pathClassifierCfg)
if os.path.exists((file + "/p300-spatial-filter.cfg")):
print("spatialfilter kopiert")
copyfile((file + "/p300-spatial-filter.cfg"), self.pathSpatialCfg)
if os.path.exists((file + "/p300-xdawn-train.ov")):
print(".ov kopiert")
copyfile((file + "/p300-xdawn-train.ov"), self.pathOVFile)


def test(self):
'''--------------------------------------------------------------------------------------------------
Funktion zum testen von xDawn und ClassifierTraining
'''
self.file = self.view.savefiledialog()
if(self.modi == "taktilesBCI"):
self.model = ModellTaktil(self, dll=self.dll)
elif(self.modi == "visuellesBCI"):
self.model = ModellVisuell(self, dll=self.dll)
self.model.setFunktion(self.model.trainXDawn)
self.model.start()

def commandoCopySpelling(self):
self.view.savefiledialog()

def copyspelling(self, path):
'''--------------------------------------------------------------------------------------------------
Speichert den gewuenschte Pfad und erstellt anschliessend ein Model (als Thread) und fuehrt die
Funktion CopySpelling aus.
'''
self.file = path
print(path)
if self.file == "-1":
print("kein gueltiger Pfad")
self.view.changeFrame("StartPage")
else:
if(self.modi == "taktilesBCI"):
self.model = ModellTaktil(self, dll=self.dll)
elif(self.modi == "visuellesBCI"):
self.model = ModellVisuell(self, dll=self.dll)
self.model.setFunktion(self.model.startCopySpelling)
self.model.start()

def filterXdawn(self):
'''--------------------------------------------------------------------------------------------------
wird nach dem CopySpelling gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
Funktion trainXDawn aus.
'''
print("filterXDawn-Controller -Modi: " + self.modi)
if(self.modi == "taktilesBCI"):
self.model = ModellTaktil(self, dll=self.dll)
elif(self.modi == "visuellesBCI"):
self.model = ModellVisuell(self, dll=self.dll)
self.model.setFunktion(self.model.trainXDawn)
self.model.start()

def filterClassic(self):
'''--------------------------------------------------------------------------------------------------
wird nach dem xDawn-Training gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
Funktion trainClassifier aus.
'''

if(self.modi == "taktilesBCI"):
self.model = ModellTaktil(self, dll=self.dll)
elif(self.modi == "visuellesBCI"):
self.model = ModellVisuell(self, dll=self.dll)
self.model.setFunktion(self.model.trainClassifier)
self.model.start()

def commandFreeSpelling(self):
'''--------------------------------------------------------------------------------------------------
startet nach Benutzeraktion das Freespelling: ie Funktion erstellt ein Model (als Thread) und fuehrt die
Funktion freespelling aus.
'''
print("freespelling")
if(self.modi == "taktilesBCI"):
self.model = ModellTaktil(self, dll=self.dll)
elif(self.modi == "visuellesBCI"):
self.model = ModellVisuell(self, dll=self.dll)
self.model.setFunktion(self.model.freeSpelling)
self.model.start()


def commandStop(self):
'''--------------------------------------------------------------------------------------------------
Wird nach Benutzeraktion aufgerufen und stopt, falls vorhanden, den ablaufenden Thread und schliesst
Openvibe
'''
if(self.model is not None):
self.addInfoText("Aktion: STOP-Befehl\n")
self.model.stop()
self.model.join()
self.model.killProzess()
self.mode = None
def stopAcquisitionServer(self):
'''--------------------------------------------------------------------------------------------------
Wird nur beim schliessen der GUI aufgerufen und stopt und schliesst den Acquisitionserver
'''
self.acquisitionServer.stop()
self.acquisitionServer.join()
self.acquisitionServer.killAcquisitionServer()
self.acquisitionServer = None

def stop(self, next=None):
'''--------------------------------------------------------------------------------------------------
Wird aus dem Modell nach Ablauf oder bei Fehler aufgerufen und stopt den aktuellen Thread.
Anschliessend wird je nach Prozess die naechste Funktion (XDawn-Training oder Classifier) aufgerufen
'''
print("Stop aus Modell")
self.model.stop()
self.model.join()
self.model.killProzess()
self.mode = None
if(next is not None):
func = self.nexts.get(next)
func()


def addInfoText(self,text):
'''--------------------------------------------------------------------------------------------------
Fuegt dem Infotext den Text hinzu und schreibt es in die Ausgabe
'''
self.infotext = self.infotext + text
self.view.setInfoText(self.infotext)

def resetInfo(self):
self.infotext = ""

def setTitle(self,text):
self.view.setTitleText(text)

def changeScreen(self, pageName):
self.view.changeFrame(pageName=pageName)

def getModi(self):
return self.modi

def getWindowSize(self):
return self.view.getWindowSize()




+ 180
- 0
Code/UIModell.py View File

@@ -0,0 +1,180 @@
'''--------------------------------------------------------------------------------------------------
Das Model steuert stellt die Modi unabhaengigen Funktionen bereit
'''

from subprocess import *
from threading import Thread
import time

class Modell(Thread):

def __init__(self,c, dll):
Thread.__init__(self)
self.controller = c
self.dll = dll
self.aktiv= True
def setFunktion(self, func, args=None, kwargs=None):
pass
def startCopySpelling(self):
pass
def trainXDawn(self):
pass

def trainClassifier(self):
pass

def freeSpelling(self):
pass

def stop(self):
'''--------------------------------------------------------------------------------------------------
Die Funktion stop stopt den ablaufenden Thread
'''
print("stop thread")
self.aktiv = False

def run(self):
'''--------------------------------------------------------------------------------------------------
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
'''
print("start thread")
#self.aktiv = True
t = Thread(target=self.startAquisitionServer)
t.setDaemon(True)
t.start()
while self.aktiv:
time.sleep(0.1)

def killProzessParent(self):
'''--------------------------------------------------------------------------------------------------
schliesst OpenVibe-Designer
'''
print('Parent start killing')
pidOV = 0
items = []

prozesse = Popen(["ps", "-e"], stdout=PIPE).communicate()[0].strip()
zeilen = prozesse.split('\n')
for z in zeilen:
if(z.find("openvibe-design") != -1):
z = z.strip()
items = z.split(' ')
pidOV = items[0]
print(pidOV)
if pidOV is not 0:
#kill -TERM veranlasst dem Prozess sich selbst zu beenden (nicht erzwungen)
try:
Popen(["kill", "-TERM", str(pidOV)], stdout=PIPE).communicate()
except:
print("kein killing")


print("killed openvibe-designer")

def killAcquisitionServer(self):
'''--------------------------------------------------------------------------------------------------
schliesst den Acquisitionserver
'''

print('start killing AS')
pid = 0
items = []

prozesse = Popen(["ps", "-e"], stdout=PIPE).communicate()[0].strip()
zeilen = prozesse.split('\n')
for z in zeilen:
if(z.find("openvibe-acquis") != -1):
z = z.strip()
items = z.split(' ')
pid = items[0]
if pid is not 0:
#kill -TERM veranlasst dem Prozess sich selbst zu beenden (nicht erzwungen)
Popen(["kill", "-TERM", str(pid)], stdout=PIPE).communicate()


print("killed openvibe-acquisitionserver")


def startAquisitionServer(self):
'''--------------------------------------------------------------------------------------------------
startet den Acquisitionserver und steuert die Benutzerausgabe
'''

print("start Aquisitionserver")
self.controller.resetInfo()
self.controller.addInfoText('Aquisitionserver -- Bitte starten sie den Server\n')

command = self.dll.getCommandStartAquisitionServer().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
while True:
output = process.stdout.readline()
print(output.strip())
x1 = output.find("Connection succeeded")
x2 = output.find("Now acquiring")
x3 = output.find("Stopping the acquisition")
x4 = output.find("Disconnecting")
init = output.find("Loading plugin: Fiddler")
y = output.find("Error")
if(x1 != -1):
self.controller.addInfoText('Aquisitionserver ist verbunden -- Bitte starten Sie den Server\n')
elif(x2 != -1 ):
self.controller.resetInfo()
self.controller.addInfoText("Aquisitionserver gestartet\n")
self.minimizeWindow("server")
elif(x3 != -1 ):
self.controller.addInfoText("AquisitionServer gestoppt -- Bitte starten Sie den Server\n")
self.positionWindow("server")
elif(x4 != -1 ):
self.controller.addInfoText("Verbindung vom Aquisitionserver getrennt!\n")
self.positionWindow("server")
elif(init != -1 ):
time.sleep(1)
self.positionWindow("server")
elif(y != -1 ):
self.controller.addInfoText("Fehler beim Auisitionserver aufgetaucht\n")
if not self.aktiv:
print("stop")
break

def positionWindow(self, name):
'''--------------------------------------------------------------------------------------------------
positioniert das Fenster auf der GUI
'''
print("calls positionWindow")
parameter = self.controller.getWindowSize()
positionX = int(parameter[0]+ int(parameter[3] * 0.05))
positionY = int(parameter[1]) + int(parameter[2]*0.08)
height = int(parameter[2])*0.55
width = int(parameter[3])*0.9
windowID = Popen(["xdotool", "search", "--onlyvisible", "--name", name], stdout=PIPE).communicate()[0].strip()
try:
print(int(windowID))
Popen(["xdotool", "windowsize", windowID, str(width), str(height)], stdout=PIPE).communicate()
Popen(["xdotool", "windowmove", windowID, str(positionX), str(positionY)], stdout=PIPE).communicate()
Popen(["xdotool", "windowactivate", windowID], stdout=PIPE).communicate()[0].strip()
except:
print("no window")
print(windowID)
self.controller.addInfoText("Fehler: kein Fenster gefunden!")

def minimizeWindow(self, name):
'''--------------------------------------------------------------------------------------------------
minimiert das Fenster
'''
windowID = Popen(["xdotool", "search", "--onlyvisible", "--name", name], stdout=PIPE).communicate()[0].strip()
try:
print(int(windowID))
Popen(["xdotool", "windowminimize", windowID], stdout=PIPE).communicate()
except:
print("no window")
print(windowID)
self.controller.addInfoText("Fehler: kein Fenster gefunden!")


+ 228
- 0
Code/UIModellTaktil.py View File

@@ -0,0 +1,228 @@
'''--------------------------------------------------------------------------------------------------
Das taktile Model steuert den Ablauf der aufrufe der Openvibe Funktionen fuer das taktile BCI
noch nicht implementiert da noch kein Programm dafuer
'''

from subprocess import *
from threading import Thread
import time
from UIModell import *
import re

class ModellTaktil(Modell):

def __init__(self,c, dll):
Thread.__init__(self)
Modell.__init__(self, c, dll)
#self.dll = dll
self.aktiv= True
self.openVibeAktiv = False
def stop(self):
'''--------------------------------------------------------------------------------------------------
Die Funktion stop stopt den ablaufenden Thread
'''
print("stop thread")
self.aktiv = False
def setFunktion(self, func, args=None, kwargs=None):
'''--------------------------------------------------------------------------------------------------
Mittels dieser Funktion kann die im Thread ablaufende Funktion und deren Argumente eingestellt werden
'''
self.func = func
self.args = args or []
self.kwargs = kwargs or {}
def run(self):
'''--------------------------------------------------------------------------------------------------
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
'''
print("start thread")
#self.aktiv = True
t = Thread(target=self.func, args=self.args, kwargs=self.kwargs)
t.setDaemon(True)
t.start()
while self.aktiv:
time.sleep(0.1)
def startCopySpelling(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Librarz die Befehle und startet das Copyspelling. Reagiert auf Error oder
beenden. Bei Beenden startet es das XDawnTraining, bei Error wird der Vorgang gestoppt.
'''
print("start copySpelling")
self.controller.resetInfo()
self.controller.addInfoText('Starten des gefuerten Buchstabierens -- ')

command = self.dll.getCommandCopyspellingTaktil().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
while True:
output = process.stdout.readline()
print(output.strip())
x = output.find("Application terminated")
y = output.find("Error")
if(x != -1):
print("Training finished")
process.terminate()
self.controller.addInfoText('Buchstabieren beendet\n')
self.controller.stop("filterXdawn")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
process.terminate()
self.controller.stop()
break
if not self.aktiv:
print("stop")
break

#self.controller.stop()
def trainXDawn(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das XDawnTraining. Reagiert auf Error oder
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das ClassifierTraining, bei Error wird der Vorgang gestoppt.
'''
print("Start training Xdawn")
self.controller.addInfoText('Starten des xDawn-Trainings -- ')
command = self.dll.getCommandXDawn_taktil() #.split(" ")
print("Command: " + command)
command = command.split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)
self.openVibeAktiv = True
while self.aktiv:
output = process.stdout.readline()
print(output.strip())
x = output.find("Training finished and saved")
y = output.find("Error")
if(x != -1):
print("Training finished")
process.terminate()
self.controller.addInfoText('Training beendet\n')
self.controller.stop("filterClassic")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim XDawn Training aufgetaucht\n")
self.controller.stop()
process.terminate()
break
if not self.aktiv:
print("stop")
break
#self.controller.stop()

#self.controller.filterClassic()


def trainClassifier(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das ClassifierTraining. Reagiert auf Error oder
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das speichern der Daten, bei Error wird der Vorgang gestoppt.
'''
print("start training Classifier")
self.controller.addInfoText("Starten des Classifier-Trainings -- ")

command = self.dll.getCommandClassifier_taktil().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
counter = 0
acc = 0
while True:
output = process.stdout.readline()
print(output.strip())
x = output.find("aka Classifier trainer")
accuracy = output.find("Cross-validation test accuracy is ")
y = output.find("Error")
if(x != -1):
counter = counter +1
#counter = 18
if(counter >= 17):
print("Training finished")
self.controller.addInfoText('Training beendet (' + acc + ')\n')
process.terminate()
self.controller.stop("save")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Classifier Training aufgetaucht\n")
process.terminate()
break
if(accuracy != -1):
#print("Output:")
#print(output)
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
test = output.encode("windows-1252").decode("utf-8")
i = len("Cross-validation test")
#print(output[accuracy:accuracy+i+12])
#print(test[accuracy+i+12:accuracy+i+40].strip())
acc_s = test[accuracy+i:accuracy+i+41].strip()
acc = ansi_escape.sub('', acc_s)
print(acc)

if not self.aktiv:
print("stop")
break

self.controller.changeScreen("StartPage")
self.controller.stop()

def freeSpelling(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das Freespelling. Reagiert auf Error oder
beenden. Daraufhin wird der Vorgang gestoppt.
'''
print("start freeSpelling")
self.controller.resetInfo()
self.controller.addInfoText('Starten des freien Buchstabierens -- ')
command = self.dll.getCommandFreespellingTaktil().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)
self.openVibeAktiv = True
while True:
output = process.stdout.readline()
print(output.strip())
y = output.find("Error")
x = output.find("Application terminated")
if(x != -1):
print("End Spelling")
process.terminate()
self.controller.addInfoText('Buchstabieren beendet\n')
self.controller.changeScreen("StartPage")
self.controller.stop()
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
process.terminate()
self.controller.stop()
break
if not self.aktiv:
print("stop")
break

self.controller.changeScreen("StartPage")
self.controller.stop()

def killProzess(self):
'''--------------------------------------------------------------------------------------------------
Ruft den Parent auf, dass Openvibe falls es noch laeuft geschlossen wird
'''
if(self.openVibeAktiv):
self.openVibeAktiv = False
self.killProzessParent()




+ 230
- 0
Code/UIModellVisuell.py View File

@@ -0,0 +1,230 @@
'''--------------------------------------------------------------------------------------------------
Das Visuelle Model steuert den Ablauf der aufrufe der Openvibe Funktionen fuer das visuelle BCI
'''

from subprocess import *
from threading import Thread
import time
import re

from UIModell import Modell

class ModellVisuell(Modell):

def __init__(self,c, dll):
Thread.__init__(self)
Modell.__init__(self, c, dll)
self.aktiv= True
self.openVibeAktiv = False
def stop(self):
'''--------------------------------------------------------------------------------------------------
Die Funktion stop stopt den ablaufenden Thread
'''
print("stop thread")
self.aktiv = False
def setFunktion(self, func, args=None, kwargs=None):
'''--------------------------------------------------------------------------------------------------
Mittels dieser Funktion kann die im Thread ablaufende Funktion und deren Argumente eingestellt werden
'''
self.func = func
self.args = args or []
self.kwargs = kwargs or {}
def run(self):
'''--------------------------------------------------------------------------------------------------
Wird bei Thread.start() aus dem Controller aufgerufen und laeuft ab sobald der Thread destartet wurde
'''
print("start thread")
#self.aktiv = True
t = Thread(target=self.func, args=self.args, kwargs=self.kwargs)
t.setDaemon(True)
t.start()
while self.aktiv:
time.sleep(0.1)
def startCopySpelling(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Librarz die Befehle und startet das Copyspelling. Reagiert auf Error oder
beenden. Bei Beenden startet es das XDawnTraining, bei Error wird der Vorgang gestoppt.
Positioniert die visuelle Matrix.
'''
print("start copySpelling")
self.controller.resetInfo()
self.controller.addInfoText('Starten des gefuerhten Buchstabierens -- ')
command = self.dll.getCommandCopyspellingVisuell().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
while True:
output = process.stdout.readline()
print(output.strip())
x = output.find("Application terminated")
y = output.find("Error")
z = output.find("Initialization")
if(x != -1):
print("Training finished")
process.terminate()
self.controller.addInfoText('Buchstabieren beendet\n')
self.controller.stop("filterXdawn")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
process.terminate()
self.controller.stop()
break
elif(z != -1):
print("Initiation finisched")
time.sleep(2)
self.positionWindow("p300")
if not self.aktiv:
print("stop")
break
#self.controller.stop()
def trainXDawn(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das XDawnTraining. Reagiert auf Error oder
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das ClassifierTraining, bei Error wird der Vorgang gestoppt.
'''
print("start training Xdawn")
self.controller.addInfoText('Starten des XDawn/Trainings -- ')
command = self.dll.getCommandXDawn_visuell().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
while self.aktiv:
output = process.stdout.readline()
print(output.strip())
x = output.find("Training finished and saved")
y = output.find("Error")
if(x != -1):
print("Training finished")
process.terminate()
self.controller.addInfoText('Beenden des Trainings\n')
self.controller.stop("filterClassic")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim XDawn Training aufgetaucht\n")
self.controller.stop()
process.terminate()
break
if not self.aktiv:
print("stop")
break
#self.controller.stop()

def trainClassifier(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das ClassifierTraining. Reagiert auf Error oder
die Ausgabe das das Training beendet wurde. Bei Beenden startet es das speichern der Daten, bei Error wird der Vorgang gestoppt.
'''
print("start training Classifier")
self.controller.addInfoText("Starten Classifier-Trainings -- ")
command = self.dll.getCommandClassifier_visuell().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
counter = 0
acc = 0
while True:
output = process.stdout.readline()
print(output.strip())
x = output.find("aka Classifier trainer")
accuracy = output.find("Cross-validation test accuracy is ")
y = output.find("Error")
if(x != -1):
counter = counter +1
#counter = 18
if(counter >= 17):
print("Training finished")
self.controller.addInfoText('Beenden des Training (' + acc + ')\n')
process.terminate()
self.controller.stop("save")
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Classifier Training aufgetaucht\n")
process.terminate()
break
if(accuracy != -1):
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
test = output.encode("windows-1252").decode("utf-8")
i = len("Cross-validation test")
acc_s = test[accuracy+i:accuracy+i+41].strip()
acc = ansi_escape.sub('', acc_s)
print(acc)
if not self.aktiv:
print("stop")
break

self.controller.changeScreen("StartPage")
self.controller.stop()

def freeSpelling(self):
'''--------------------------------------------------------------------------------------------------
Holt aus der shared Library die Befehle und startet das Freespelling. Reagiert auf Error oder
beenden. Daraufhin wird der Vorgang gestoppt. Positioniert die visuelle Matrix.
'''
print("start freeSpelling")
self.controller.resetInfo()
self.controller.addInfoText('Starten des freien Buchstabierens -- ')

command = self.dll.getCommandFreespellingVisuell().split(" ")
process = Popen(command, stdout=PIPE, universal_newlines=True)

self.openVibeAktiv = True
while True:
output = process.stdout.readline()
print(output.strip())
y = output.find("Error")
x = output.find("Schlagwort")
z = output.find("Initialization")
if(x != -1):
print("End Spelling")
process.terminate()
self.controller.addInfoText('Buchstabieren beendet\n')
self.controller.changeScreen("StartPage")
self.controller.stop()
break
elif(y != -1 ):
print("Error occured")
self.controller.changeScreen("StartPage")
self.controller.addInfoText("Fehler beim Buchstabieren aufgetaucht\n")
process.terminate()
self.controller.stop()
break
elif(z != -1):
print("Initiation finisched")
time.sleep(2)
self.positionWindow("p300")
if not self.aktiv:
print("stop")
break

self.controller.changeScreen("StartPage")
self.controller.stop()

def killProzess(self):
'''--------------------------------------------------------------------------------------------------
Ruft den Parent auf, dass Openvibe falls es noch laeuft geschlossen wird
'''
if(self.openVibeAktiv):
self.openVibeAktiv = False
self.killProzessParent()





+ 284
- 0
Code/UIViewTKinter.py View File

@@ -0,0 +1,284 @@
'''--------------------------------------------------------------------------------------------------
Die View bildet die Oberflaeche ab.
Sie ist in 3 Sektoren Top, Main und ButtonFrame unterteilt. Der TopFrame beihnahltet die Taskleiste,
der Button Frame gibt Informationen raus. Im Main Frame sind die Buttons yu starten und stoppen der
Buchstabierungen. HIerfuer sind extra Seiten erstellt, die beliebig, je nach Situation ausgetauscht
werden koennen
'''

try:
from Tkinter import * #Fuer Python 2.7
import tkFileDialog as fd
print("python2.7")
except ImportError: #Fuer Python >3
from tkinter import *
from tkinter import filedialog as fd
print("python >3")

from UIController import *



class View(Tk):
def __init__(self, c, path_default, *args, **kwargs):
'''--------------------------------------------------------------------------------------------------
In der Init wird das Lazout gesetyt und die Funktionen yur erstellung der Frames aufgerufen,
zudem wird dem schliesen des Fensters sowie den anpassen der Groesse andere Funktionen hinterlegt
'''
Tk.__init__(self, *args, **kwargs)
img = PhotoImage(file='icon.png')
self.tk.call('wm', 'iconphoto', self._w, img)
self.controller = c
self.PATH_DEFAULT = path_default
self.title("Visuelles Buchstabieren")
self.h = self.winfo_screenheight()
self.w = self.winfo_screenwidth()
self.geometry('{}x{}'.format(self.w,self.h))
self.faktor = [(0.073),(0.727), (0.2)]
#self.resizable(height=False, width= False)
self.layout = {
"background": "#00001E",
"backgroundBtn": "#1C86EE",
"fontColor": "#FFFFFF",
"backgroundBar": "#00002E",
"font": ('Calibri', 20, 'bold'),
"fontSmall": ('Calibri', 14, 'bold'),
"fontInfo": ('Calibri', 25)
}

self.createTopFrame()
self.createMainFrame()
self.createBottomFrame()

self.bind("<Configure>", self.adjustSize)
self.protocol("WM_DELETE_WINDOW", self.onClosing)
def changeFrame(self, pageName):
'''--------------------------------------------------------------------------------------------------
Setzt dem Frame passend zum pageName in den Vordergrund
'''
frame = self.frames[pageName]
frame.tkraise()

def adjustSize(self, event):
'''--------------------------------------------------------------------------------------------------
passt nach Faktoren die einyelnen Seitenteile der jeweiligen Frame Groesse an
'''
if(str(event.widget) =="."):
self.h = event.height
self.w = event.width
self.topFrame.configure(height=(self.h*self.faktor[0]), width=self.w)
self.mainFrame.configure(height=(self.h*self.faktor[1]), width=self.w)
self.bottomFrame.configure(height=(self.h*self.faktor[2]), width=self.w)
self.container.configure(height=(self.h*self.faktor[1]), width=self.w)
for f in self.frames:
self.frames[f].configure(height=(self.h*self.faktor[1]), width=self.w)
self.frames[f].adjustSize(height=(self.h*self.faktor[1]), width=self.w)


def onClosing(self):
'''--------------------------------------------------------------------------------------------------
Stoppt alle laufenden Threads und schliesst OpenVibe und den Aquisitionserver bevor sich das Fenster
schliesst
'''
try:
print("closing")
self.controller.commandStop()
self.controller.stopAcquisitionServer()
print("destroy")
self.dialog.destroy()
except:
pass
self.destroy()
def createTopFrame(self):
'''--------------------------------------------------------------------------------------------------
Erstellt die Buttons und Textfelder fuer die Taskleiste und positionier diese im Frame
'''
self.topFrame = Frame(self, bg=self.layout["backgroundBar"], height=50, width=500)
self.changeBtn = Button(self.topFrame, text="Wechsel zu taktilen BCI", command=lambda: self.controller.actionPerformed("wechsel"), height=3, width = 30, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
self.saveBtn = Button(self.topFrame, text="Auswaehlen der Datei", command=lambda: self.controller.actionPerformed("speicherort"), height=3, width = 30, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
#self.setBtn = Button(self.topFrame, text="Auswaehlen der Datei", command=lambda: self.controller.actionPerformed("setFile"), height=2, width = 25, font=self.layout["fontSmall"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
self.toplabel = Label(self.topFrame, text="visuelles BCI", font=self.layout["font"], bg=self.layout["backgroundBar"], fg=self.layout["fontColor"], )

self.topFrame.grid(column=0, row=0)
self.topFrame.grid_propagate(0)
self.topFrame.pack_propagate(0)

self.changeBtn.grid(column=0, row=0, padx=10,pady=5)
self.saveBtn.grid(column=1, row=0, padx=10, pady=5)
#self.setBtn.grid(column=2, row=0, padx=10, pady=5)
self.toplabel.grid(column=2, row=0, padx=100, pady=2)

def createMainFrame(self):
'''--------------------------------------------------------------------------------------------------
Erstellt und postioniert einen Container als Platzhalter fuer die verschiedenen Seiten. Anscliessend
erstellt es die verschiedenen Seiten und speicher diese in eine Liste
'''
self.mainFrame = Frame(self, bg=self.layout["background"], height=250, width=500)
self.mainFrame.grid(column=0, row=1)
self.mainFrame.pack_propagate(0)
self.container = Frame(self.mainFrame, bg=self.layout["background"], height=250, width=500)
self.container.pack(side="top", fill="both", expand = True)
self.container.pack_propagate(0)
self.container.grid_propagate(0)
self.frames = {}
for F in (StartPage, WorkingPageTaktil, WorkingPageVisuell):
page_name = F.__name__
frame = F(parent=self.container, controller=self.controller, layout=self.layout)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.changeFrame("StartPage")
def createBottomFrame(self):
'''--------------------------------------------------------------------------------------------------
Erstellt und positioniert ein Label fuer die ganzen Informationen
'''
self.bottomFrame = Frame(self, bg=self.layout["backgroundBar"], height=100, width=500)
self.bottomlabel = Label(self.bottomFrame, text="Hier stehen Infos\nGanz viele", justify='left', font=self.layout["fontInfo"], bg=self.layout["backgroundBar"], fg=self.layout["fontColor"])

self.bottomFrame.grid(column=0, row=2)
self.bottomFrame.pack_propagate(0)
self.bottomFrame.grid_propagate(0)

self.bottomlabel.grid(padx=5,pady=5)

def setInfoText(self, text):
self.bottomlabel['text'] = text

def setTitleText(self,text):
self.title(text)
self.toplabel["text"] = text

def setChangeBtnText(self,text):
self.changeBtn["text"] = text

def setDefaultPath(self, path):
self.PATH_DEFAULT = path

def openfiledialog(self):
path = self.PATH_DEFAULT
#file = fd.askopenfilename(initialdir=path)
file = fd.askdirectory(initialdir=path)
return file

def savefiledialog(self):
self.dialog = Tk()

self.dialog.title("Visuelles Buchstabieren")
h = 100
w = 400
self.dialog.geometry('{}x{}'.format(w,h))
self.dialog.geometry("+{}+{}".format(100,200))
l = Label(self.dialog, text="Bitte geben Sie einen Speichernamen ein:")
eingabefeld = Entry(self.dialog)
okBtn = Button(self.dialog, text="OK", command=lambda:self.okBtn(eingabefeld.get()))
l.pack()
eingabefeld.pack()
okBtn.pack()

self.dialog.protocol("WM_DELETE_WINDOW", self.closeDialog)
self.dialog.mainloop()

def okBtn(self, text):
path = self.PATH_DEFAULT + "/" + text
print(path)
self.controller.copyspelling(path)
self.dialog.destroy()

def closeDialog(self):
self.controller.copyspelling("-1")
self.dialog.destroy()
def getWindowSize(self):
return [self.winfo_x(), self.winfo_y(), self.winfo_height(), self.winfo_width()]


class StartPage(Frame):
'''--------------------------------------------------------------------------------------------------
Bildet die Seite in der die Aktionen ausgesucht werden koennen. Beihaltet 2 Buttons einen zum starten
des freien Buchstabierens und einen yum starten des gefuerten Buchstabierens
'''
def __init__(self, parent, controller, layout):
self.layout = layout

Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
self.grid_propagate(0)
self.pack_propagate(0)
self.controller = controller

self.container = Frame(self, bg=self.layout["background"], height=250, width=500)
self.btnFrame = Frame(self.container, bg=self.layout["background"], height=250, width=250)

self.container.columnconfigure(0, weight=1) # Set weight to row and
self.container.rowconfigure(0, weight=1) # column where the widget is
self.container.grid_propagate(0)
self.container.pack_propagate(0)

self.container.pack()
self.btnFrame.grid()

testBtn = Button(self.btnFrame, text="gefuehrtes Buchstabieren", command=lambda: self.controller.actionPerformed("copySpelling"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
#testBtn = Button(self.btnFrame, text="copySpelling", command=lambda: self.controller.actionPerformed("test"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
testBtn.grid(row=0,column=0, padx=25,pady=25)

freeSpellingBtn = Button(self.btnFrame, text="freies Buchstabieren", command=lambda: self.controller.actionPerformed("freeSpelling"), height=6, width = 20, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
freeSpellingBtn.grid(row=0, column=1, padx=25,pady=25)

def adjustSize(self, height, width):
self.container.configure(height=height, width= width)
self.btnFrame.configure(height=(height*4)/5, width= width/2)

class WorkingPageTaktil(Frame):
'''--------------------------------------------------------------------------------------------------
Bildet die Seite nach Auswahl einer Aktion. Beihaltet einen mittig plazierten Buttons zum stoppen
des ablaufenden Vorgang
'''
def __init__(self, parent, controller, layout):
self.layout = layout

Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
self.controller = controller


self.columnconfigure(0, weight=1) # Set weight to row and
self.rowconfigure(0, weight=1) # column where the widget is

stopBtn = Button(self, text="stop", command=lambda: self.controller.actionPerformed("stop"), height=4, width = 15, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
stopBtn.grid()

def adjustSize(self, height, width):
pass

class WorkingPageVisuell(Frame):
'''--------------------------------------------------------------------------------------------------
Bildet die Seite nach Auswahl einer Aktion. Beihaltet einen mittig unten plazierten Buttons zum
stoppen des ablaufenden Vorgang
'''
def __init__(self, parent, controller, layout):
self.layout = layout

Frame.__init__(self, parent, height=250, width=500, bg=self.layout["background"])
self.controller = controller
self.grid_propagate(0)
self.pack_propagate(0)

self.windowFrame = Frame(self, height=200, width=500, bg=self.layout["background"])
self.windowFrame.grid(column=0, row=0)

self.buttonFrame = Frame(self, height=50, width=500, bg=self.layout["background"])
self.buttonFrame.grid(column=0, row=1)
self.buttonFrame.columnconfigure(0, weight=1) # Set weight to row and
self.buttonFrame.rowconfigure(0, weight=1) # column where the widget is

stopBtn = Button(self.buttonFrame, text="stop", command=lambda: self.controller.actionPerformed("stop"), height=1, width = 15, font=self.layout["font"], bg=self.layout["backgroundBtn"], fg=self.layout["fontColor"])
stopBtn.grid()

def adjustSize(self, height, width):
self.windowFrame.configure(height=(height*9)/10, width= width)
self.buttonFrame.configure(height=(height)/10, width= width)

+ 227
- 0
Code/dll.cpp View File

@@ -0,0 +1,227 @@
#include <iostream>
#include <cstring>
using namespace std;

extern "C"{

//allgemein
//-------------------------------------------------------------------------------------------------------------------------------------
string PATH_OV = "meta/dist/Release/openvibe-designer.sh";
string PATH_AquisitionServer = "meta/dist/Release/openvibe-acquisition-server.sh";


//visuell
//-------------------------------------------------------------------------------------------------------------------------------------
string PATH_FILES_Visual = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/";
string pathOVFile_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/signals/p300-xdawn-train.ov";
string pathClassifierCFG_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/cfg/p300-classifier.cfg";
string pathSpatialCFG_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/cfg/p300-spatial-filter.cfg";
string PATH_DEFAULT_visuell = "Projekte/OpenVibe_THN-p300-bci-main/p300-visual/datasets";

string fileCopySpellingVisuell = "p300-xdawn-1-acquisition.xml";
string filefreeSpellingVisuell = "p300-xdawn-4-online.xml";
string fileXDawnTrainingVisuell = "p300-xdawn-2-train-xDAWN.xml";
string fileClassifierTrainingVisuell = "p300-xdawn-3-train-classifier.xml";

//taktil
//------------------------------------------------------------------------------------------------------------------------------------
string fileCopySpellingTaktil = "p300-tactile-1-acquisition.xml";
string filefreeSpellingTaktil = "p300-tactile-4-online.xml";
string fileXDawnTrainingTaktil = "p300-tactile-2-train-xDAWN.xml";
string fileClassifierTrainingTaktil = "p300-tactile-3-train-classifier.xml";

string PATH_FILES_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/";
string pathOVFile_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/signals/p300-xdawn-train.ov";
string pathClassifierCFG_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/cfg/p300-classifier.cfg";
string pathSpatialCFG_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/cfg/p300-spatial-filter.cfg";
string PATH_DEFAULT_taktil = "Projekte/OpenVibe_THN-p300-bci-main/p300-tactile/datasets";

string PATH_FILES_ConfigFile = "Projekte/OpenVibe_THN-p300-bci-main/cfg/OV_TACTILE_PANDA.conf";

//Befehle
//-------------------------------------------------------------------------------------------------------------------------------------
string command = "bash";
string nogui = "--no-gui";
string play = "--play";
string playFast = "--play-fast";
string config = "--config";


char* getCommandPS(){
string s = "";
s = s.append("ps").append(" ").append("-e");
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandFreespellingTaktil()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( play).append(" ").append(PATH_FILES_taktil).append(filefreeSpellingTaktil).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandFreespellingVisuell()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES_Visual).append(filefreeSpellingVisuell).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandCopyspellingTaktil()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( play).append(" ").append(PATH_FILES_taktil).append(fileCopySpellingTaktil).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandCopyspellingVisuell()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES_Visual).append(fileCopySpellingVisuell).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandXDawn_taktil()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( playFast).append(" ").append(PATH_FILES_taktil).append(fileXDawnTrainingTaktil).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandXDawn_visuell()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( playFast).append(" ").append(PATH_FILES_Visual).append(fileXDawnTrainingVisuell).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandClassifier_visuell()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( playFast).append(" ").append(PATH_FILES_Visual).append(fileClassifierTrainingVisuell).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandClassifier_taktil()
{
string s = "";
s = s.append(command).append(" ").append(PATH_OV).append(" ").append(config).append(" ").append(PATH_FILES_ConfigFile).append(" ").append( playFast).append(" ").append(PATH_FILES_taktil).append(fileClassifierTrainingTaktil).append(" ").append(nogui);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getCommandStartAquisitionServer()
{
string s = "";
s = s.append(command).append(" ").append(PATH_AquisitionServer);
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getDefaultPath_visuell()
{
string s = PATH_DEFAULT_visuell;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getDefaultPath_taktil()
{
string s = PATH_DEFAULT_taktil;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getPathOVFile_visuell()
{
string s = pathOVFile_visuell;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getSpatialCFGFile_visuell()
{
string s = pathSpatialCFG_visuell;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getClassifierCFGFile_visuell()
{
string s = pathClassifierCFG_visuell;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getPathOVFile_taktil()
{
string s = pathOVFile_taktil;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getSpatialCFGFile_taktil()
{
string s = pathSpatialCFG_taktil;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}

char* getClassifierCFGFile_taktil()
{
string s = pathClassifierCFG_taktil;
char char_array[s.length()+1];
strcpy(char_array, s.c_str());
char* s_convert = char_array;
return s_convert;
}
}






+ 8
- 0
Code/gui.py View File

@@ -0,0 +1,8 @@
'''--------------------------------------------------------------------------------------------------
In dem File wird eine Instany des Controllers erstellt. Der Controller ist die Schnittstelle
zwischen GUI und Modell und koordiniert den Ablauf und die Erstellung der GUI
'''

from UIController import *

controller = Controller()

BIN
Ordnerstruktur.PNG View File


+ 5
- 0
Projekte/OpenVibe_THN-p300-bci-main/README.md View File

@@ -0,0 +1,5 @@
# OpenVibe_THN-p300-bci

Die Szenarien für das Taktile und das Visuelle BCI, basieren auf dem OpenVibeSzenrio p300-speller-xDAWN.

In die jeweiligen Ordner können die aktuellen OpenVibe-Dateien für das taktile und visuelle Buchstabieren eingefügt werden. Die Dateien können im EFI-Git gefunden werden.

+ 36
- 1
README.md View File

@@ -1 +1,36 @@
Bitte in dem Repository nur Code und keine EEG-Signaldaten hochladen.
<h1>Grafische Oberfläche:</h1>

Die grafische Oberfläche wurde in Python geschrieben. Die Pfade von den OpenVibe Programmen sind in einer Shared Library hinterlegt (dll.so, bzw. ddl.cpp). Alle Python Dateien wurden in der Datei "gui" in eine ausführbare Datei zusammengefasst. Die Oberfläche kann durch ausführen dieser gestartet werden. Hierfür werden die Dateien "gui", "dll.so" und "icon.png" benötigt. Diese in den Ordner über meta kopieren.

Falls zusätzlich eine Desktop Applikation erstellt worden ist, wird noch die "BCI.desktop" und die "start.sh" Datei benötigt. Mittels der "BCI.desktop" Datei kann die Applikation installiert werden. Anschließend wird mit klick auf das Icon die "start.sh" Datei ausgeführt. Diese startet die "gui" und schreibt die logs in eine Textdatei.

<h2>Nutzungsanleitung</h2>

* Installation von xdotool und python-tkinter, falls noch nicht installiert (siehe script.sh)

* Einfügen der taktilen und visuellen OpenVibe Programme

* Anpassen der Defaultpfade in der dll.cpp Datei (Default-Ordnerstruktur ist im Ordnerstruktur.PNG hinterlegt)
-> erstellen einer shared library mit g++ dll.cpp --shared -fPIC -o dll.so

* Fuer den Ablauf werden dann nur die Datei gui, dll.so und das icon (icon.png) benoetigt. Alle Dateien bitte im selben Ordner verschieben (Default im gleichen Ordner wie der Ordner meta).

* Das Programm kann nun mit den Kommandozeilenaufruf ./gui gestartet werden. (Hier darauf achten das die notwendigen Rechte vergeben wurden)

<h2>Zusätzlich für Desktop Applikation </h2>
Fuer den Aufruf ueber ein Desktop Icon werden die Dateien BCI.desktop und start.sh benoetigt:

* Ggf. die Pfade zur start.sh datei und zum Icon in der "BCI.desktop" - Datei angepassen

* Pfade in der start.sh Datei anpassen

* BCI.desktop in den home folder legen und installiert werden
(sudo desktop-file-install BCI.desktop)
* start.sh wird mit dem Icon aufgerufen

<h2>Bei Änderungen der Python Dateien </h2>

Wurde die Python Dateien verändert muss die "gui" Datei neu erstellt werden. Dies kann im Code Ordner mittels pyinstaller –onefile gui.py durchgeführt werden.



BIN
dll.so View File


BIN
gui View File


BIN
icon.png View File


+ 7
- 0
script.sh View File

@@ -0,0 +1,7 @@
sudo apt-get install python-tk
sudo apt-get install xdotool

sudo apt-get install python-setuptools
sudo apt-get install python-pip

pip install pyinstaller==3.6

+ 9
- 0
start.sh View File

@@ -0,0 +1,9 @@
#!/bin/bash


cd ~/bci/
> log.txt
chmod +rw log.txt
./gui >> log.txt



Loading…
Cancel
Save