'''-------------------------------------------------------------------------------------------------- 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()