You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UIController.py 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. '''--------------------------------------------------------------------------------------------------
  2. Im Controller wird in der Init eine View erstellt und gestartet. Zudem wird der Acquisitionserver
  3. gestartet, die shared Librarz geladen, die Konstanten Initialtisiert.
  4. Mittels der Funktion Action Performed wird die jeweilige Reaktion auf die Benutyeraktion ausgeloest.
  5. Hierfuer stehen die verschiedenen eigenen Funktionen die die Reaktion in der richtigen reihenfolge
  6. an ein neu instanizieertes Modell weitergibt.
  7. Zudem stehen einige Funktionen zur Informationsuebergabe an die View oder das Modell zur Verfuegung
  8. '''
  9. from UIModellVisuell import *
  10. from UIModellTaktil import *
  11. from UIModell import *
  12. import UIViewTKinter as viewTkinter
  13. from shutil import copyfile
  14. import ctypes
  15. import os
  16. class Controller():
  17. def __init__(self):
  18. '''--------------------------------------------------------------------------------------------------
  19. In der Init wird die shared Library geladen, die View erstellt und geoeffnet und die verschiedenen
  20. Konstanten gesetzt
  21. '''
  22. self.getSharedLibrary()
  23. self.view = viewTkinter.View(self, self.dll.getDefaultPath_visuell())
  24. self.modi = "visuellesBCI"
  25. self.pathOVFile = self.dll.getPathOVFile_visuell()
  26. self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
  27. self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
  28. self.infotext = ""
  29. self.commands = {
  30. "copySpelling": self.commandoCopySpelling,
  31. "stop": self.commandStop,
  32. "freeSpelling": self.commandFreeSpelling,
  33. "test": self.test,
  34. "wechsel": self.wechsel,
  35. "speicherort": self.setDataset
  36. }
  37. self.nexts = {
  38. "filterXdawn" : self.filterXdawn,
  39. "filterClassic": self.filterClassic,
  40. "save": self.speichern
  41. }
  42. self.pagesTaktil = {
  43. "stop": "StartPage",
  44. "copySpelling": "WorkingPageTaktil",
  45. "freeSpelling": "WorkingPageTaktil",
  46. "test": "WorkingPageTaktil"
  47. }
  48. self.pagesVisuell = {
  49. "stop": "StartPage",
  50. "copySpelling": "WorkingPageVisuell",
  51. "freeSpelling": "WorkingPageVisuell",
  52. "test": "WorkingPageVisuell"
  53. }
  54. self.acquisitionServer = Modell(self, self.dll)
  55. self.acquisitionServer.start()
  56. self.model = None
  57. self.view.mainloop()
  58. def getSharedLibrary(self):
  59. '''--------------------------------------------------------------------------------------------------
  60. Laedt die shared Library (diese muss sich im gleichen Ordner wie die ausfuehrunde Datei befinden)
  61. und setzt die Eingabe und Rueckgabewerte.
  62. '''
  63. path = os.path.abspath(".")
  64. path = path + "/dll.so"
  65. self.dll = ctypes.CDLL(path)
  66. self.dll.getCommandFreespellingTaktil.argtypes = []
  67. self.dll.getCommandFreespellingTaktil.restype = ctypes.c_char_p
  68. self.dll.getCommandFreespellingVisuell.argtypes = []
  69. self.dll.getCommandFreespellingVisuell.restype = ctypes.c_char_p
  70. self.dll.getCommandCopyspellingTaktil.argtypes = []
  71. self.dll.getCommandCopyspellingTaktil.restype = ctypes.c_char_p
  72. self.dll.getCommandCopyspellingVisuell.argtypes = []
  73. self.dll.getCommandCopyspellingVisuell.restype = ctypes.c_char_p
  74. self.dll.getCommandXDawn_taktil.argtypes = []
  75. self.dll.getCommandXDawn_taktil.restype = ctypes.c_char_p
  76. self.dll.getCommandXDawn_visuell.argtypes = []
  77. self.dll.getCommandXDawn_visuell.restype = ctypes.c_char_p
  78. self.dll.getCommandClassifier_visuell.argtypes = []
  79. self.dll.getCommandClassifier_visuell.restype = ctypes.c_char_p
  80. self.dll.getCommandClassifier_taktil.argtypes = []
  81. self.dll.getCommandClassifier_taktil.restype = ctypes.c_char_p
  82. self.dll.getDefaultPath_visuell.argtypes = []
  83. self.dll.getDefaultPath_visuell.restype = ctypes.c_char_p
  84. self.dll.getDefaultPath_taktil.argtypes = []
  85. self.dll.getDefaultPath_taktil.restype = ctypes.c_char_p
  86. self.dll.getPathOVFile_visuell.argtypes = []
  87. self.dll.getPathOVFile_visuell.restype = ctypes.c_char_p
  88. self.dll.getSpatialCFGFile_visuell.argtypes = []
  89. self.dll.getSpatialCFGFile_visuell.restype = ctypes.c_char_p
  90. self.dll.getClassifierCFGFile_visuell.argtypes = []
  91. self.dll.getClassifierCFGFile_visuell.restype = ctypes.c_char_p
  92. self.dll.getPathOVFile_taktil.argtypes = []
  93. self.dll.getPathOVFile_taktil.restype = ctypes.c_char_p
  94. self.dll.getSpatialCFGFile_taktil.argtypes = []
  95. self.dll.getSpatialCFGFile_taktil.restype = ctypes.c_char_p
  96. self.dll.getClassifierCFGFile_taktil.argtypes = []
  97. self.dll.getClassifierCFGFile_taktil.restype = ctypes.c_char_p
  98. self.dll.getCommandStartAquisitionServer.argtypes = []
  99. self.dll.getCommandStartAquisitionServer.restype = ctypes.c_char_p
  100. def actionPerformed(self, action):
  101. '''--------------------------------------------------------------------------------------------------
  102. Wird aufgerufen wenn ein Button in der Init gedrueckt wird zuerst wird kontrolliert ob die Seite
  103. gewechselt werden muss, dann nach dem Buttonnamen die Funktion zugeordnert. Der Funktion zum
  104. Buttomnamen wird in der Init festgelegt
  105. '''
  106. self.changePage(action)
  107. func = self.commands.get(action)
  108. if(func is not None):
  109. func()
  110. else:
  111. print("Kommado existiert nicht")
  112. def changePage(self,action):
  113. '''--------------------------------------------------------------------------------------------------
  114. Change Page ruft je nach Aktion und Modi die jeweilige Seite auf
  115. '''
  116. if(self.modi == "taktilesBCI"):
  117. page = self.pagesTaktil.get(action)
  118. elif(self.modi == "visuellesBCI"):
  119. page = self.pagesVisuell.get(action)
  120. if(page is not None):
  121. self.view.changeFrame(page)
  122. def wechsel(self):
  123. '''--------------------------------------------------------------------------------------------------
  124. Wechsel aendert den Modi. Dafuer wird zuerst der aktuelle Modi ueberprueft und dann auf den anderen
  125. Modi gesetzt.
  126. '''
  127. self.resetInfo()
  128. self.addInfoText("")
  129. if(self.modi == "taktilesBCI"):
  130. self.view.setChangeBtnText("Wechsel zu taktilen BCI")
  131. self.view.setTitleText("visuelles BCI")
  132. self.view.setDefaultPath(self.dll.getDefaultPath_visuell())
  133. self.pathOVFile = self.dll.getPathOVFile_visuell()
  134. self.pathSpatialCfg = self.dll.getSpatialCFGFile_visuell()
  135. self.pathClassifierCfg = self.dll.getClassifierCFGFile_visuell()
  136. self.modi = "visuellesBCI"
  137. elif(self.modi == "visuellesBCI"):
  138. self.setTitle("taktiles BCI")
  139. self.view.setChangeBtnText("Wechsel zu visuellen BCI")
  140. self.view.setDefaultPath(self.dll.getDefaultPath_taktil())
  141. self.pathOVFile = self.dll.getPathOVFile_taktil()
  142. self.pathSpatialCfg = self.dll.getSpatialCFGFile_taktil()
  143. self.pathClassifierCfg = self.dll.getClassifierCFGFile_taktil()
  144. self.modi = "taktilesBCI"
  145. def speichern(self):
  146. '''--------------------------------------------------------------------------------------------------
  147. wird nach dem Classifier Training aufgerufen und speichert die erstellte .ov Datei und die
  148. spatial.cfg, classifier.cgf-Dateine unter dem ausgewaehlten Ordnername.
  149. (Ordnername wird zu Beginn des CopySpellings festgelegt)
  150. '''
  151. print("saveFile")
  152. print(self.file)
  153. if not os.path.exists(self.file):
  154. os.mkdir(self.file)
  155. copyfile(self.pathOVFile, (self.file + "/p300-xdawn-train.ov"))
  156. copyfile(self.pathClassifierCfg, (self.file + "/p300-classifier.cfg"))
  157. copyfile(self.pathSpatialCfg, (self.file + "/p300-spatial-filter.cfg"))
  158. self.changeScreen("StartPage")
  159. #copyfile(self.pathOVFile, self.file)
  160. def setDataset(self):
  161. '''--------------------------------------------------------------------------------------------------
  162. Legt fest welches Datenset fuer das Freestelling genutzt wird
  163. '''
  164. file = self.view.openfiledialog()
  165. print(file)
  166. if not file:
  167. print("nichts ausgewaehlt")
  168. else:
  169. if os.path.exists((file + "/p300-classifier.cfg")):
  170. print("classifier kopiert")
  171. copyfile((file + "/p300-classifier.cfg"), self.pathClassifierCfg)
  172. if os.path.exists((file + "/p300-spatial-filter.cfg")):
  173. print("spatialfilter kopiert")
  174. copyfile((file + "/p300-spatial-filter.cfg"), self.pathSpatialCfg)
  175. if os.path.exists((file + "/p300-xdawn-train.ov")):
  176. print(".ov kopiert")
  177. copyfile((file + "/p300-xdawn-train.ov"), self.pathOVFile)
  178. def test(self):
  179. '''--------------------------------------------------------------------------------------------------
  180. Funktion zum testen von xDawn und ClassifierTraining
  181. '''
  182. self.file = self.view.savefiledialog()
  183. if(self.modi == "taktilesBCI"):
  184. self.model = ModellTaktil(self, dll=self.dll)
  185. elif(self.modi == "visuellesBCI"):
  186. self.model = ModellVisuell(self, dll=self.dll)
  187. self.model.setFunktion(self.model.trainXDawn)
  188. self.model.start()
  189. def commandoCopySpelling(self):
  190. self.view.savefiledialog()
  191. def copyspelling(self, path):
  192. '''--------------------------------------------------------------------------------------------------
  193. Speichert den gewuenschte Pfad und erstellt anschliessend ein Model (als Thread) und fuehrt die
  194. Funktion CopySpelling aus.
  195. '''
  196. self.file = path
  197. print(path)
  198. if self.file == "-1":
  199. print("kein gueltiger Pfad")
  200. self.view.changeFrame("StartPage")
  201. else:
  202. if(self.modi == "taktilesBCI"):
  203. self.model = ModellTaktil(self, dll=self.dll)
  204. elif(self.modi == "visuellesBCI"):
  205. self.model = ModellVisuell(self, dll=self.dll)
  206. self.model.setFunktion(self.model.startCopySpelling)
  207. self.model.start()
  208. def filterXdawn(self):
  209. '''--------------------------------------------------------------------------------------------------
  210. wird nach dem CopySpelling gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
  211. Funktion trainXDawn aus.
  212. '''
  213. if(self.modi == "taktilesBCI"):
  214. self.model = ModellTaktil(self, dll=self.dll)
  215. elif(self.modi == "visuellesBCI"):
  216. self.model = ModellVisuell(self, dll=self.dll)
  217. self.model.setFunktion(self.model.trainXDawn)
  218. self.model.start()
  219. def filterClassic(self):
  220. '''--------------------------------------------------------------------------------------------------
  221. wird nach dem xDawn-Training gestartet. Die Funktion erstellt ein Model (als Thread) und fuehrt die
  222. Funktion trainClassifier aus.
  223. '''
  224. if(self.modi == "taktilesBCI"):
  225. self.model = ModellTaktil(self, dll=self.dll)
  226. elif(self.modi == "visuellesBCI"):
  227. self.model = ModellVisuell(self, dll=self.dll)
  228. self.model.setFunktion(self.model.trainClassifier)
  229. self.model.start()
  230. def commandFreeSpelling(self):
  231. '''--------------------------------------------------------------------------------------------------
  232. startet nach Benutzeraktion das Freespelling: ie Funktion erstellt ein Model (als Thread) und fuehrt die
  233. Funktion freespelling aus.
  234. '''
  235. print("freespelling")
  236. if(self.modi == "taktilesBCI"):
  237. self.model = ModellTaktil(self, dll=self.dll)
  238. elif(self.modi == "visuellesBCI"):
  239. self.model = ModellVisuell(self, dll=self.dll)
  240. self.model.setFunktion(self.model.freeSpelling)
  241. self.model.start()
  242. def commandStop(self):
  243. '''--------------------------------------------------------------------------------------------------
  244. Wird nach Benutzeraktion aufgerufen und stopt, falls vorhanden, den ablaufenden Thread und schliesst
  245. Openvibe
  246. '''
  247. if(self.model is not None):
  248. self.addInfoText("Aktion: STOP-Befehl\n")
  249. self.model.stop()
  250. self.model.join()
  251. self.model.killProzess()
  252. self.mode = None
  253. def stopAcquisitionServer(self):
  254. '''--------------------------------------------------------------------------------------------------
  255. Wird nur beim schliessen der GUI aufgerufen und stopt und schliesst den Acquisitionserver
  256. '''
  257. self.acquisitionServer.stop()
  258. self.acquisitionServer.join()
  259. self.acquisitionServer.killAcquisitionServer()
  260. self.acquisitionServer = None
  261. def stop(self, next=None):
  262. '''--------------------------------------------------------------------------------------------------
  263. Wird aus dem Modell nach Ablauf oder bei Fehler aufgerufen und stopt den aktuellen Thread.
  264. Anschliessend wird je nach Prozess die naechste Funktion (XDawn-Training oder Classifier) aufgerufen
  265. '''
  266. print("Stop aus Modell")
  267. self.model.stop()
  268. self.model.join()
  269. self.model.killProzess()
  270. self.mode = None
  271. if(next is not None):
  272. func = self.nexts.get(next)
  273. func()
  274. def addInfoText(self,text):
  275. '''--------------------------------------------------------------------------------------------------
  276. Fuegt dem Infotext den Text hinzu und schreibt es in die Ausgabe
  277. '''
  278. self.infotext = self.infotext + text
  279. self.view.setInfoText(self.infotext)
  280. def resetInfo(self):
  281. self.infotext = ""
  282. def setTitle(self,text):
  283. self.view.setTitleText(text)
  284. def changeScreen(self, pageName):
  285. self.view.changeFrame(pageName=pageName)
  286. def getModi(self):
  287. return self.modi
  288. def getWindowSize(self):
  289. return self.view.getWindowSize()