@@ -0,0 +1,327 @@ | |||
'''-------------------------------------------------------------------------------------------------- | |||
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()) | |||
self.modi = "visuellesBCI" | |||
self.pathOVFile = self.dll.getPathOVFile() | |||
self.pathSpatialCfg = self.dll.getSpatialCFGFile() | |||
self.pathClassifierCfg = self.dll.getClassifierCFGFile() | |||
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.argtypes = [] | |||
self.dll.getCommandXDawn.restype = ctypes.c_char_p | |||
self.dll.getCommandClassifier.argtypes = [] | |||
self.dll.getCommandClassifier.restype = ctypes.c_char_p | |||
self.dll.getDefaultPath.argtypes = [] | |||
self.dll.getDefaultPath.restype = ctypes.c_char_p | |||
self.dll.getPathOVFile.argtypes = [] | |||
self.dll.getPathOVFile.restype = ctypes.c_char_p | |||
self.dll.getSpatialCFGFile.argtypes = [] | |||
self.dll.getSpatialCFGFile.restype = ctypes.c_char_p | |||
self.dll.getClassifierCFGFile.argtypes = [] | |||
self.dll.getClassifierCFGFile.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.modi = "visuellesBCI" | |||
elif(self.modi == "visuellesBCI"): | |||
self.setTitle("taktiles BCI") | |||
self.view.setChangeBtnText("Wechsel zu visuellen BCI") | |||
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) | |||
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")) | |||
#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 | |||
if self.file is "-1": | |||
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. | |||
''' | |||
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() | |||
@@ -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] | |||
#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!") | |||
@@ -0,0 +1,214 @@ | |||
'''-------------------------------------------------------------------------------------------------- | |||
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 * | |||
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.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("schlagwort?") | |||
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().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().split(" ") | |||
process = Popen(command, stdout=PIPE, universal_newlines=True) | |||
self.openVibeAktiv = True | |||
counter = 0 | |||
while True: | |||
output = process.stdout.readline() | |||
print(output.strip()) | |||
x = output.find("aka Classifier trainer") | |||
accuracy = output.find("Training set 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\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 | |||
elif(accuracy != -1): | |||
print("ACCURACY" + output) | |||
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.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") | |||
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() | |||
@@ -0,0 +1,225 @@ | |||
'''-------------------------------------------------------------------------------------------------- | |||
Das Visuelle Model steuert den Ablauf der aufrufe der Openvibe Funktionen fuer das visuelle BCI | |||
''' | |||
from subprocess import * | |||
from threading import Thread | |||
import time | |||
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(1) | |||
self.positionWindow("p300") | |||
self.minimizeWindow("stimulator") | |||
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().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().split(" ") | |||
process = Popen(command, stdout=PIPE, universal_newlines=True) | |||
self.openVibeAktiv = True | |||
counter = 0 | |||
while True: | |||
output = process.stdout.readline() | |||
print(output.strip()) | |||
x = output.find("aka Classifier trainer") | |||
accuracy = output.find("Training set 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\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 | |||
elif(accuracy != -1): | |||
print("ACCURACY" + output) | |||
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(1) | |||
self.positionWindow("p300") | |||
self.minimizeWindow("stimulator") | |||
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() | |||
@@ -0,0 +1,267 @@ | |||
'''-------------------------------------------------------------------------------------------------- | |||
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 | |||
except ImportError: #Fuer Python >3 | |||
from tkinter import * | |||
from tkinter import filedialog as fd | |||
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) | |||
self.controller = c | |||
self.PATH_DEFAULT = path_default | |||
self.title("Visuelles Buchstabieren") | |||
self.h = 1000 | |||
self.w = 2000 | |||
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 | |||
''' | |||
print("closing") | |||
self.controller.commandStop() | |||
self.controller.stopAcquisitionServer() | |||
print("destroy") | |||
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 openfiledialog(self): | |||
path = self.PATH_DEFAULT | |||
#file = fd.askopenfilename(initialdir=path) | |||
file = fd.askdirectory(initialdir=path) | |||
return file | |||
def savefiledialog(self): | |||
self.dialog = Tk() | |||
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=200, 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*4)/5, width= width) | |||
self.buttonFrame.configure(height=(height)/10, width= width) |
@@ -0,0 +1,146 @@ | |||
#include <iostream> | |||
#include <cstring> | |||
using namespace std; | |||
extern "C"{ | |||
string PATH_OV = "meta/dist/Release/openvibe-designer.sh"; | |||
string PATH_AquisitionServer = "meta/dist/Release/openvibe-acquisition-server.sh"; | |||
string PATH_FILES = "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/"; | |||
string pathOVFile = "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/signals/p300-xdawn-train2.ov"; | |||
string pathClassifierCFG = "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/cfg/p300-classifier.cfg"; | |||
string pathSpatialCFG = "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/cfg/p300-spatial-filter.cfg"; | |||
string PATH_DEFAULT = "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/datasets"; | |||
string fileCopySpellingTaktil = "p300-visual-1-acquisition.xml"; | |||
string fileCopySpellingVisuell = "p300-visual-1-acquisition.xml"; | |||
string fileXDawnTraining = "p300-visual-2-train-xDAWN.xml"; | |||
string fileClassifierTraining = "p300-visual-3-train-classifier.xml"; | |||
string filefreeSpellingTaktil = "p300-visual-4-online.xml"; | |||
string filefreeSpellingVisuell = "p300-visual-4-online.xml"; | |||
string command = "bash"; | |||
string nogui = "--no-gui"; | |||
string play = "--play"; | |||
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( play).append(" ").append(PATH_FILES).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).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( play).append(" ").append(PATH_FILES).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).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() | |||
{ | |||
string s = ""; | |||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES).append(fileXDawnTraining).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() | |||
{ | |||
string s = ""; | |||
s = s.append(command).append(" ").append(PATH_OV).append(" ").append( play).append(" ").append(PATH_FILES).append(fileClassifierTraining).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() | |||
{ | |||
string s = PATH_DEFAULT; | |||
char char_array[s.length()+1]; | |||
strcpy(char_array, s.c_str()); | |||
char* s_convert = char_array; | |||
return s_convert; | |||
} | |||
char* getPathOVFile() | |||
{ | |||
string s = pathOVFile; | |||
char char_array[s.length()+1]; | |||
strcpy(char_array, s.c_str()); | |||
char* s_convert = char_array; | |||
return s_convert; | |||
} | |||
char* getSpatialCFGFile() | |||
{ | |||
string s = pathSpatialCFG; | |||
char char_array[s.length()+1]; | |||
strcpy(char_array, s.c_str()); | |||
char* s_convert = char_array; | |||
return s_convert; | |||
} | |||
char* getClassifierCFGFile() | |||
{ | |||
string s = pathClassifierCFG; | |||
char char_array[s.length()+1]; | |||
strcpy(char_array, s.c_str()); | |||
char* s_convert = char_array; | |||
return s_convert; | |||
} | |||
} | |||
@@ -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() |
@@ -0,0 +1,33 @@ | |||
# -*- mode: python ; coding: utf-8 -*- | |||
block_cipher = None | |||
a = Analysis(['gui.py'], | |||
pathex=['/home/ubuntu/Desktop/BCIProjekt'], | |||
binaries=[], | |||
datas=[], | |||
hiddenimports=[], | |||
hookspath=[], | |||
runtime_hooks=[], | |||
excludes=[], | |||
win_no_prefer_redirects=False, | |||
win_private_assemblies=False, | |||
cipher=block_cipher, | |||
noarchive=False) | |||
pyz = PYZ(a.pure, a.zipped_data, | |||
cipher=block_cipher) | |||
exe = EXE(pyz, | |||
a.scripts, | |||
a.binaries, | |||
a.zipfiles, | |||
a.datas, | |||
[], | |||
name='gui', | |||
debug=False, | |||
bootloader_ignore_signals=False, | |||
strip=False, | |||
upx=True, | |||
upx_exclude=[], | |||
runtime_tmpdir=None, | |||
console=True ) |
@@ -0,0 +1,2 @@ | |||
sudo apt-get install python-tk | |||
sudo apt-get install xdotool |
@@ -0,0 +1,80 @@ | |||
from subprocess import * | |||
from threading import Thread | |||
import time | |||
class Modell(Thread): | |||
def __init__(self): | |||
Thread.__init__(self) | |||
self.aktiv= True | |||
self.aktiv2 = True | |||
def stop(self): | |||
print("stop thread") | |||
self.aktiv = False | |||
def setFunktion(self, func, args=None, kwargs=None): | |||
self.func = func | |||
self.args = args or [] | |||
self.kwargs = kwargs or {} | |||
def run(self): | |||
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 counter(self): | |||
n = 0 | |||
while self.aktiv2: | |||
print(n) | |||
time.sleep(0.1) | |||
n = n+1 | |||
if not self.aktiv2: | |||
print("stop") | |||
break | |||
def stop2(self): | |||
self.aktiv2 = False | |||
#self.aktiv = False | |||
def test(self): | |||
command = ["bash", "meta/dist/Release/openvibe-designer.sh", "--play", "Projekte/OpenViBE_visual_BCI-master/openvibe_visual_bci/p300-visual-1-acquisition.xml", "--no-gui"] | |||
process = Popen(command, stdout=PIPE, universal_newlines=True) | |||
while self.aktiv2: | |||
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() | |||
break | |||
elif(y != -1 ): | |||
process.terminate() | |||
break | |||
if not self.aktiv: | |||
print("stop") | |||
break | |||
m = Modell() | |||
m.setFunktion(m.test) | |||
m.start() | |||
time.sleep(2) | |||
m.stop() | |||
m.join() | |||
while True: | |||
pass | |||