# -*- coding: utf-8 -*- """ Created on Fri Sep 4 11:36:24 2020 @author: Igor Beloschapkin """ import tkinter import tkinter.font import tkinter.filedialog import subprocess import configparser import os # import queue # own code: # from questionnaire import quest # from wheelchairAdapter import BCI2000ReceiverThread # TODO Eventuell updatefunktion über git pull mit einbauen! __version__ = 0.4 class PythonBCIgui: def __init__(self, master): # Einstellung der Button Größe textH = 4 textHsmall = 2 textW = 20 def makeBtn(self, text, bg, command): self.button = tkinter.Button(frame, text=text, bg=bg, command=command) self.button.config( height = textH, width = textW ) self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') return self.button def makeBtnSmall(self, text, bg, command): self.button = tkinter.Button(frame, text=text, bg=bg, command=command) self.button.config( height = textHsmall, width = textW ) self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') return self.button frame = tkinter.Frame(master) frame.pack() # label generation headerText = config['SETTINGS']['paradigm'] + ' BCI' self.Lparadigm = tkinter.Label(frame, text = headerText, height = 4, width = 20) self.Lparadigm['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') self.Lparadigm.pack() # button generation self.BtacFilter = makeBtn(self, "Filter", "pink", self.btn_tacFilter) self.BtacCal = makeBtn(self, "Kalibrierung", "lightgreen", self.btn_tacCal) self.BvisCal = makeBtn(self, "Kalibrierung", "lightgreen", self.btn_visCal) self.Bp300 = makeBtn(self, "P300 Klassifizierung", "orange", self.btn_p300) self.BtacCopy = makeBtn(self, "Freies Buchstabieren", "lightblue", self.btn_tacCopy) self.BvisCopy = makeBtn(self, "Freies Buchstabieren", "lightblue", self.btn_visCopy) self.BtacSimul = makeBtn(self, "Rollstuhlsimulator", "lightyellow", self.btn_tacSimul) # self.Bquest = makeBtnSmall(self, "Fragebogen", "green", self.btn_quest, TOP) frame.rowconfigure((0,1), weight=1) # make buttons stretch when frame.columnconfigure((0,2), weight=1) # when window is resized # TODO Hilfestellung nach jedem Button aufploppen lassen: # Was tun? Wo klicken? Welche File wo laden? self.pack_layout() # 1. FILTER ################################## def btn_tacFilter(self): print('Starte TactileBCIFilter.exe') subprocess.Popen(config['PATH']['tactilebcifilter'] + r'\TactileBCIFilter.exe') # 2. KALIBIERUNGEN ########################### def btn_tacCal(self): print('starte taktile Kalibrierung') subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileCalibration.prm']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3SignalProcessing.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.exe', '127.0.0.1']) # TODO Lock einführen und bei Returnwert Lock öffnen mit tkinter.Button.config(state = tkinter.DISABLED) def btn_visCal(self): print('starte visuelle Kalibrierung') subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE gUSBamp_visual_copySpeller.prm']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3SignalProcessing.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.exe', '127.0.0.1']) # 3. P300 Classifier ######################### def btn_p300(self): print('Starte P300Classifier.exe') subprocess.Popen(config['PATH']['bci2000'] + r'\tools\P300Classifier\P300Classifier.exe') # 4. COPYSPELL ########################### def btn_tacCopy(self): print('Starte taktilen Speller') subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileCopy.prm']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3SignalProcessing.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.exe', '127.0.0.1']) def btn_visCopy(self): print('Starte visuellen Speller') subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE gUSBamp_visual_freeSpeller.prm']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3SignalProcessing.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.exe', '127.0.0.1']) # 5. WHEELCHAIR SIMULATOR ########################### def btn_tacSimul(self): print('Starte Wheelchair Simulator') # BCI2000ReceiverThread1.start() subprocess.Popen(config['PATH']['wheelchairsimulator'] + r'\Wheels_Occlusion_AutoLog.exe') subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileDrive.prm']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3SignalProcessing.exe', '127.0.0.1']) subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.exe', '127.0.0.1']) # QUESTIONNAIRE PROMPT ########################### # def btn_quest(self): #root.destroy() # self.startQuestions(self.paradigmText) # def startQuestions(self, para): # print('Starte Fragebogen') # q = quest(para) # q.qSatisfaction() # q.qExhaustion() # q.qSubjControl() # q.qCtrlChange() # q.save() def pack_layout(self): # This Function packs all the Buttons into the Layout if config['SETTINGS']['paradigm'] == 'Tactile': self.BtacFilter.pack() self.BtacCal.pack() elif config['SETTINGS']['paradigm'] == 'Visual': self.BvisCal.pack() self.Bp300.pack() if config['SETTINGS']['paradigm'] == 'Tactile': self.BtacCopy.pack() self.BtacSimul.pack() elif config['SETTINGS']['paradigm'] == 'Visual': self.BvisCopy.pack() def unpack_layout(self): # This Function removes all the Buttons from the Layout # Add ALL your Buttons here self.BtacFilter.pack_forget() self.BtacCal.pack_forget() self.BvisCal.pack_forget() self.Bp300.pack_forget() self.BtacCopy.pack_forget() self.BtacSimul.pack_forget() self.BvisCopy.pack_forget() def global_close(self, window): print('Beenden') window.destroy() # set paths pathOrigin = os.path.dirname(os.path.realpath(__file__)) # set pathOrigin to directory of this file os.chdir(pathOrigin) config = configparser.ConfigParser() configPath = pathOrigin + '/config.ini' config.read(configPath) def setVisual(): config['SETTINGS']['paradigm'] = 'Visual' config.write(open(configPath,'w')) app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') app.unpack_layout() app.pack_layout() def setTactile(): config['SETTINGS']['paradigm'] = 'Tactile' config.write(open(configPath,'w')) app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') app.unpack_layout() app.pack_layout() root = tkinter.Tk() root.title('PythonBCIgui v' + str(__version__)) def setPathBci2000(): tkinter.messagebox.showinfo('Konfiguration', 'Bitte wählen Sie nun den BCI2000 Ordner aus, in dem sich die Ordner "batch", "data", "icons", "parms", "prog" und "tools" befinden.') tmpPath = tkinter.filedialog.askdirectory() if not tmpPath: pass else: config['PATH']['bci2000'] = tmpPath config.write(open(configPath,'w')) def setPathTactileBCIFilter(): tkinter.messagebox.showinfo('Konfiguration', 'Bitte wählen Sie nun den Ordner aus, in dem sich die TactileBCIfilter.exe befindet.') tmpPath = tkinter.filedialog.askdirectory() if not tmpPath: pass else: config['PATH']['tactilebcifilter'] = tmpPath config.write(open(configPath,'w')) def setPathWheelchair(): tkinter.messagebox.showinfo('Konfiguration', 'Bitte wählen Sie nun den Ordner aus, in dem sich die Wheels_Occlusion_AutoLog.exe befindet.') tmpPath = tkinter.filedialog.askdirectory() if not tmpPath: pass else: config['PATH']['wheelchairsimulator'] = tmpPath config.write(open(configPath,'w')) def setConfigDefault(): # config['PATH']['tactilebcifilter'] = r'C:/Users/bci/Desktop/Qt Filter Program/build-TactileBCIFilter-Desktop_Qt_5_15_0_MinGW_32_bit-Release/release' # config['PATH']['bci2000'] = r'C:/BCI2000/BCI2000 v3.6.beta.R5570/BCI2000.x64' # config['PATH']['wheelchairsimulator'] = r'C:\Users\bci\Desktop\Wheelchair' config['PATH']['tactilebcifilter'] = r'C:\Users\EEG-Gruppe\Desktop\Arduino\Qt Tactile BCI Filter App\Executable' config['PATH']['bci2000'] = r'C:\Users\EEG-Gruppe\Desktop\BCI Paket\Paradigmen\Tactile\BCI2000\BCI2000-06-13\BCI2000src' config['PATH']['wheelchairsimulator'] = r'C:\Users\EEG-Gruppe\Desktop\Wheelchair' config['SETTINGS']['paradigm'] = r'Visual' config['SETTINGS']['hardware'] = r'gUSBamp' config.write(open(configPath,'w')) app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') app.unpack_layout() app.pack_layout() def on_closing(): #self.global_close(root) print('Beenden') root.destroy() # root.quit() root.protocol("WM_DELETE_WINDOW", on_closing) leistenMenu = tkinter.Menu(root) fileMenu = tkinter.Menu(leistenMenu) leistenMenu.add_cascade(label="Datei", menu=fileMenu) fileMenu.add_command(label="Einstellungen Zurücksetzen", command=setConfigDefault) fileMenu.add_command(label="Beenden", command=on_closing) paradigmMenu = tkinter.Menu(leistenMenu) leistenMenu.add_cascade(label="Paradigmen", menu=paradigmMenu) paradigmMenu.add_command(label="Visual", command=setVisual) paradigmMenu.add_separator() paradigmMenu.add_command(label="Tactile", command=setTactile) pathMenu = tkinter.Menu(leistenMenu) leistenMenu.add_cascade(label="Pfade", menu=pathMenu) pathMenu.add_command(label="BCI2000", command=setPathBci2000) pathMenu.add_separator() pathMenu.add_command(label="TactileBCIFilter", command=setPathTactileBCIFilter) pathMenu.add_separator() pathMenu.add_command(label="Wheelchair Simulator", command=setPathWheelchair) root.config(menu = leistenMenu) # # initialize queue for wheelchairadapter # phaseInSequenceQueue = queue.Queue() # StimulusCodeQueue = queue.Queue() # RunApplication = True # # initialize BCI2000ReceiverThread for wheelchairadapter # BCI2000ReceiverThread1 = BCI2000ReceiverThread(1, phaseInSequenceQueue, StimulusCodeQueue) app = PythonBCIgui(root) root.mainloop() #root.destroy() # optional; # TODO Remove prints before deployment