|
|
|
|
|
|
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
import tkinter |
|
|
import tkinter |
|
|
|
|
|
import tkinter.font |
|
|
|
|
|
import tkinter.filedialog |
|
|
import subprocess |
|
|
import subprocess |
|
|
import configparser |
|
|
import configparser |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__version__ = 0.3 |
|
|
__version__ = 0.3 |
|
|
|
|
|
|
|
|
class App: |
|
|
|
|
|
|
|
|
class PythonBCIgui: |
|
|
|
|
|
|
|
|
def __init__(self, master): |
|
|
def __init__(self, master): |
|
|
self.paradigmText = tkinter.sys.argv[1] |
|
|
|
|
|
# App.paradigmText = sys.argv[1] |
|
|
|
|
|
# pathOrigin = os.path.dirname(os.path.realpath(__file__)) |
|
|
|
|
|
|
|
|
#pathOrigin = os.path.dirname(os.path.realpath(__file__)) |
|
|
|
|
|
#print(pathOrigin) |
|
|
|
|
|
|
|
|
# TODO current working directory auf root von dieser file setzen |
|
|
# TODO current working directory auf root von dieser file setzen |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# pathSave = "\\questions\\" + self.paradigmText |
|
|
# pathSave = "\\questions\\" + self.paradigmText |
|
|
# pathSave = os.getcwd() + pathSave |
|
|
# pathSave = os.getcwd() + pathSave |
|
|
|
|
|
|
|
|
config.read('config.ini') |
|
|
|
|
|
|
|
|
|
|
|
# Einstellung der GUI Größe |
|
|
|
|
|
|
|
|
# Einstellung der Button Größe |
|
|
textH = 4 |
|
|
textH = 4 |
|
|
textHsmall = 2 |
|
|
textHsmall = 2 |
|
|
textW = 20 |
|
|
textW = 20 |
|
|
|
|
|
|
|
|
def makeBtn(self, text, bg, command, side): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def makeBtn(self, text, bg, command): |
|
|
self.button = tkinter.Button(frame, text=text, bg=bg, command=command) |
|
|
self.button = tkinter.Button(frame, text=text, bg=bg, command=command) |
|
|
self.button.config( height = textH, width = textW ) |
|
|
self.button.config( height = textH, width = textW ) |
|
|
self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') |
|
|
self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') |
|
|
self.button.pack(side=side) |
|
|
|
|
|
return self.button |
|
|
return self.button |
|
|
|
|
|
|
|
|
def makeBtnSmall(self, text, bg, command, side): |
|
|
|
|
|
|
|
|
def makeBtnSmall(self, text, bg, command): |
|
|
self.button = tkinter.Button(frame, text=text, bg=bg, command=command) |
|
|
self.button = tkinter.Button(frame, text=text, bg=bg, command=command) |
|
|
self.button.config( height = textHsmall, width = textW ) |
|
|
self.button.config( height = textHsmall, width = textW ) |
|
|
self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') |
|
|
self.button['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') |
|
|
self.button.pack(side=side) |
|
|
|
|
|
return self.button |
|
|
return self.button |
|
|
|
|
|
|
|
|
frame = tkinter.Frame(master) |
|
|
frame = tkinter.Frame(master) |
|
|
frame.pack() |
|
|
frame.pack() |
|
|
|
|
|
|
|
|
# label generation |
|
|
# label generation |
|
|
headerText = 'PythonBCIgui V' + str(__version__) + '\n\n' + self.paradigmText + ' BCI' |
|
|
|
|
|
|
|
|
headerText = config['SETTINGS']['paradigm'] + ' BCI' |
|
|
self.Lparadigm = tkinter.Label(frame, text = headerText, height = 4, width = 20) |
|
|
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['font'] = tkinter.font.Font(family='Helvetica', size=16, weight='bold') |
|
|
self.Lparadigm.pack() |
|
|
self.Lparadigm.pack() |
|
|
|
|
|
|
|
|
# button generation |
|
|
# button generation |
|
|
if self.paradigmText == 'Tactile': |
|
|
|
|
|
self.Bfilter = makeBtn(self, "1. Filter", "lightyellow", self.btn_filter, tkinter.TOP) |
|
|
|
|
|
self.BtacCal = makeBtn(self, "2. Kalibrierung", "lightgreen", self.btn_tacCal, tkinter.TOP) |
|
|
|
|
|
self.Bp300 = makeBtn(self, "3. P300 Klassifizierung", "orange", self.btn_p300, tkinter.TOP) |
|
|
|
|
|
self.BtacCopy = makeBtn(self, "4. Freies Buchstabieren", "lightblue", self.btn_tacCopy, tkinter.TOP) |
|
|
|
|
|
self.BtacSimul = makeBtn(self, "5. Rollstuhlsimulator", "pink", self.btn_tacSimul, tkinter.TOP) |
|
|
|
|
|
elif self.paradigmText == 'Visual': |
|
|
|
|
|
self.Bfilter = makeBtn(self, "1. Filter", "lightyellow", self.btn_filter, tkinter.TOP) |
|
|
|
|
|
self.BvisCal = makeBtn(self, "2. Kalibrierung", "lightgreen", self.btn_visCal, tkinter.TOP) |
|
|
|
|
|
self.Bp300 = makeBtn(self, "3. P300 Klassifizierung", "orange", self.btn_p300, tkinter.TOP) |
|
|
|
|
|
self.BvisCopy = makeBtn(self, "4. Freies Buchstabieren", "lightblue", self.btn_visCopy, tkinter.TOP) |
|
|
|
|
|
elif self.paradigmText == 'Test': # TODO Remove |
|
|
|
|
|
self.Bfilter = makeBtn(self, "1. Filter", "lightyellow", self.btn_filter, tkinter.TOP) |
|
|
|
|
|
self.BvisCal = makeBtn(self, "2. Kalibrierung", "lightgreen", self.btn_visCal, tkinter.TOP) |
|
|
|
|
|
self.Bp300 = makeBtn(self, "3. P300 Klassifizierung", "orange", self.btn_p300, tkinter.TOP) |
|
|
|
|
|
self.BvisCopy = makeBtn(self, "4. Freies Buchstabieren", "lightblue", self.btn_visCopy, tkinter.TOP) |
|
|
|
|
|
self.Btest = makeBtnSmall(self, "TEST", "green", self.btn_test, tkinter.TOP) # TODO Remove |
|
|
|
|
|
else: |
|
|
|
|
|
print('Fehler: Bitte wählen Sie "Tactile" oder "Visual" als Argument') |
|
|
|
|
|
raise ValueError |
|
|
|
|
|
|
|
|
|
|
|
# self.Bquest = makeBtnSmall(self, "6. Fragebogen", "green", self.btn_quest, TOP) |
|
|
|
|
|
self.BtacConfig = makeBtnSmall(self, "Konfiguration", "gray", self.btn_config, tkinter.TOP) |
|
|
|
|
|
|
|
|
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.rowconfigure((0,1), weight=1) # make buttons stretch when |
|
|
frame.columnconfigure((0,2), weight=1) # when window is resized |
|
|
frame.columnconfigure((0,2), weight=1) # when window is resized |
|
|
# TODO Hilfestellung nach jedem Button aufploppen lassen: |
|
|
# TODO Hilfestellung nach jedem Button aufploppen lassen: |
|
|
# Was tun? Wo klicken? Welche File wo laden? |
|
|
# Was tun? Wo klicken? Welche File wo laden? |
|
|
|
|
|
|
|
|
|
|
|
self.pack_layout() |
|
|
|
|
|
|
|
|
# 1. FILTER ################################## |
|
|
# 1. FILTER ################################## |
|
|
def btn_filter(self): |
|
|
|
|
|
|
|
|
def btn_tacFilter(self): |
|
|
print('Starte TactileBCIFilter.exe') |
|
|
print('Starte TactileBCIFilter.exe') |
|
|
subprocess.Popen(config['PATH']['tactilebcifilter'] + '\TactileBCIFilter.exe') |
|
|
subprocess.Popen(config['PATH']['tactilebcifilter'] + '\TactileBCIFilter.exe') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\gUSBampSource.exe', '127.0.0.1']) |
|
|
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\P3SignalProcessing.exe', '127.0.0.1']) |
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\P3Speller.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 |
|
|
|
|
|
|
|
|
# TODO Lock einführen und bei Returnwert Lock öffnen mit tkinter.Button.config(state = tkinter.DISABLED) |
|
|
def btn_visCal(self): |
|
|
def btn_visCal(self): |
|
|
print('starte visuelle Kalibrierung') |
|
|
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\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE gUSBamp_visual_copySpeller.prm']) |
|
|
|
|
|
|
|
|
# q.qSubjControl() |
|
|
# q.qSubjControl() |
|
|
# q.qCtrlChange() |
|
|
# q.qCtrlChange() |
|
|
# q.save() |
|
|
# q.save() |
|
|
|
|
|
|
|
|
# X. Settings ######################### |
|
|
|
|
|
def btn_config(self): |
|
|
|
|
|
print('Konfiguration') |
|
|
|
|
|
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.') |
|
|
|
|
|
config['PATH']['bci2000'] = tkinter.filedialog.askdirectory() |
|
|
|
|
|
tkinter.messagebox.showinfo('Konfiguration', 'Bitte wählen Sie nun den Ordner aus, in dem sich die TactileBCIfilter.exe befindet.') |
|
|
|
|
|
config['PATH']['tactilebcifilter'] = tkinter.filedialog.askdirectory() |
|
|
|
|
|
config.write(open('config.ini','w')) |
|
|
|
|
|
# TODO Catch errors falls falsche Ordner gewählt wurden |
|
|
|
|
|
|
|
|
|
|
|
def btn_test(self): # TODO Remove |
|
|
|
|
|
print('TEST') |
|
|
|
|
|
print(self.paradigmText) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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): |
|
|
def global_close(self, window): |
|
|
print('Beenden') |
|
|
print('Beenden') |
|
|
window.destroy() |
|
|
window.destroy() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
config = configparser.ConfigParser() |
|
|
config = configparser.ConfigParser() |
|
|
|
|
|
config.read('config.ini') |
|
|
|
|
|
|
|
|
|
|
|
def setVisual(): |
|
|
|
|
|
config['SETTINGS']['paradigm'] = 'Visual' |
|
|
|
|
|
config.write(open('config.ini','w')) |
|
|
|
|
|
app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') |
|
|
|
|
|
app.unpack_layout() |
|
|
|
|
|
app.pack_layout() |
|
|
|
|
|
|
|
|
|
|
|
def setTactile(): |
|
|
|
|
|
config['SETTINGS']['paradigm'] = 'Tactile' |
|
|
|
|
|
config.write(open('config.ini','w')) |
|
|
|
|
|
app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') |
|
|
|
|
|
app.unpack_layout() |
|
|
|
|
|
app.pack_layout() |
|
|
|
|
|
|
|
|
root = tkinter.Tk() |
|
|
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('config.ini','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('config.ini','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['SETTINGS']['paradigm'] = r'Visual' |
|
|
|
|
|
config['SETTINGS']['hardware'] = r'gUSBamp' |
|
|
|
|
|
config.write(open('config.ini','w')) |
|
|
|
|
|
app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI') |
|
|
|
|
|
app.unpack_layout() |
|
|
|
|
|
app.pack_layout() |
|
|
|
|
|
|
|
|
def on_closing(): |
|
|
def on_closing(): |
|
|
#self.global_close(root) |
|
|
#self.global_close(root) |
|
|
print('Beenden') |
|
|
print('Beenden') |
|
|
root.destroy() |
|
|
root.destroy() |
|
|
|
|
|
# root.quit() |
|
|
|
|
|
|
|
|
root.protocol("WM_DELETE_WINDOW", on_closing) |
|
|
root.protocol("WM_DELETE_WINDOW", on_closing) |
|
|
app = App(root) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
root.config(menu = leistenMenu) |
|
|
|
|
|
|
|
|
|
|
|
app = PythonBCIgui(root) |
|
|
root.mainloop() |
|
|
root.mainloop() |
|
|
#root.destroy() # optional; |
|
|
#root.destroy() # optional; |
|
|
|
|
|
|
|
|
|
|
|
# TODO Remove prints before deployment |