233 lines
9.6 KiB
Python
233 lines
9.6 KiB
Python
# -*- 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
|
|
|
|
# TODO Eventuell updatefunktion über git pull mit einbauen!
|
|
|
|
__version__ = 0.41
|
|
|
|
class PythonBCIgui:
|
|
|
|
def __init__(self, master):
|
|
# Einstellung der Button Größe
|
|
textH = 4
|
|
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
|
|
|
|
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.BtacFree = makeBtn(self, "Freies Buchstabieren", "lightblue", self.btn_tacFree)
|
|
self.BvisFree = makeBtn(self, "Freies Buchstabieren", "lightblue", self.btn_visFree)
|
|
|
|
self.pack_layout()
|
|
|
|
# FILTER ###################################
|
|
def btn_tacFilter(self):
|
|
subprocess.Popen(config['PATH']['tactilebcifilter'] + r'\TactileBCIFilter.exe')
|
|
|
|
# KALIBRIERUNGEN ###########################
|
|
def btn_tacCal(self):
|
|
if config['SETTINGS']['tactilemode'] == 'Motors':
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileCalibration.prm'])
|
|
elif config['SETTINGS']['tactilemode'] == 'Nested':
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileCalibrationNested.prm'])
|
|
# TODO Throw error if else
|
|
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):
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE gUSBampVisualCalibration.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'])
|
|
|
|
# P300 Classifier #########################
|
|
def btn_p300(self):
|
|
subprocess.Popen(config['PATH']['bci2000'] + r'\tools\P300Classifier\P300Classifier.exe')
|
|
|
|
# FREESPELL ###############################
|
|
def btn_tacFree(self):
|
|
if config['SETTINGS']['tactilemode'] == 'Motors':
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileFree.prm'])
|
|
elif config['SETTINGS']['tactilemode'] == 'Nested':
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE TactileFreeNested.prm'])
|
|
# TODO throw error if else
|
|
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_visFree(self):
|
|
subprocess.Popen([config['PATH']['bci2000'] + r'\prog\Operator.exe', '--OnConnect', '-LOAD PARAMETERFILE gUSBampVisualFree.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'])
|
|
|
|
# This Function packs all the Buttons into the Layout
|
|
def pack_layout(self):
|
|
if config['SETTINGS']['paradigm'] == 'Tactile':
|
|
self.BtacFilter.pack()
|
|
self.BtacCal.pack()
|
|
self.Bp300.pack()
|
|
self.BtacFree.pack()
|
|
elif config['SETTINGS']['paradigm'] == 'Visual':
|
|
self.BvisCal.pack()
|
|
self.Bp300.pack()
|
|
self.BvisFree.pack()
|
|
|
|
# This Function removes all the Buttons from the Layout
|
|
def unpack_layout(self):
|
|
# Add ALL your Buttons here
|
|
self.BtacFilter.pack_forget()
|
|
self.BtacCal.pack_forget()
|
|
self.BvisCal.pack_forget()
|
|
self.Bp300.pack_forget()
|
|
self.BtacFree.pack_forget()
|
|
self.BvisFree.pack_forget()
|
|
|
|
# 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)
|
|
|
|
# This Function sets the Paradigm to 'Visual'
|
|
def setVisual():
|
|
if config['SETTINGS']['paradigm'] == 'Visual':
|
|
return
|
|
else:
|
|
config['SETTINGS']['paradigm'] = 'Visual'
|
|
config.write(open(configPath,'w'))
|
|
app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI')
|
|
app.unpack_layout()
|
|
app.pack_layout()
|
|
|
|
# This Function sets the Paradigm to 'Tactile'
|
|
def setTactile():
|
|
if config['SETTINGS']['paradigm'] == 'Tactile':
|
|
return
|
|
else:
|
|
config['SETTINGS']['paradigm'] = 'Tactile'
|
|
config.write(open(configPath,'w'))
|
|
app.Lparadigm.config(text = config['SETTINGS']['paradigm'] + ' BCI')
|
|
app.unpack_layout()
|
|
app.pack_layout()
|
|
|
|
def setTactileModeMotors():
|
|
if config['SETTINGS']['tactilemode'] == 'Motors':
|
|
return
|
|
else:
|
|
config['SETTINGS']['tactilemode'] = 'Motors'
|
|
config.write(open(configPath,'w'))
|
|
|
|
def setTactileModeNested():
|
|
if config['SETTINGS']['tactilemode'] == 'Nested':
|
|
return
|
|
else:
|
|
config['SETTINGS']['tactilemode'] = 'Nested'
|
|
config.write(open(configPath,'w'))
|
|
|
|
# This Function sets the BCI2000 Path
|
|
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'))
|
|
|
|
# This Function sets the TactileBCIFilter Path
|
|
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'))
|
|
|
|
# This Function resets the config
|
|
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']['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['SETTINGS']['paradigm'] = r'Visual'
|
|
config['SETTINGS']['hardware'] = r'gUSBamp' # TODO Add gNautilus parameters
|
|
config['SETTINGS']['tactilemode'] = r'Motors'
|
|
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)
|
|
root.destroy()
|
|
# root.quit()
|
|
|
|
root = tkinter.Tk()
|
|
root.title('PythonBCIgui v' + str(__version__))
|
|
|
|
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)
|
|
|
|
tactileModeMenu = tkinter.Menu(leistenMenu)
|
|
leistenMenu.add_cascade(label="Taktiler Modus", menu=tactileModeMenu)
|
|
tactileModeMenu.add_command(label="Motoren", command=setTactileModeMotors)
|
|
tactileModeMenu.add_command(label="Kategorien", command=setTactileModeNested)
|
|
|
|
root.config(menu = leistenMenu)
|
|
|
|
app = PythonBCIgui(root)
|
|
root.mainloop()
|
|
#root.destroy() # optional;
|