kiapGUIToolBox.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. import datetime
  2. import glob
  3. import inspect
  4. import logging
  5. import os
  6. import sys
  7. import time
  8. from queue import Queue
  9. from PyQt5 import Qt, QtCore, QtGui, QtWidgets
  10. from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
  11. from PyQt5.QtWidgets import QApplication, QGridLayout, QLabel, QWidget
  12. from modules import bci
  13. class kiapGUI(QWidget):
  14. lstvModelFiles = None
  15. txbExpLogWin = None
  16. btnExpStart = None
  17. cmbExpParadigms = None
  18. lblDeviceConfigFile = None
  19. tab1GbxDevice = None
  20. tab1GbxPatient = None
  21. btnSetConfigFile = None
  22. btnLoadConfigFile = None
  23. cmbPatients = None
  24. lblExpSessionInfo = None
  25. lblExpPatienName = None
  26. txbExpSelectedString = None
  27. selectedPatient = None
  28. selectedConfigFile = None
  29. lblExpTime = None
  30. selectedParadigm = None
  31. __app = None
  32. __mainWindow = None
  33. # recording_signal = pyqtSignal(int)
  34. def __init__(self, recording_status, log, params, decoder_decision, parent_conn, parent_conn2, parent_conn3, block_phase, audio_feedback_run, audio_fb_target):
  35. super().__init__()
  36. self.log = log
  37. self.bci = bci.Bci()
  38. self.bci.init(params, recording_status, decoder_decision, parent_conn, parent_conn2, parent_conn3, block_phase, audio_feedback_run, audio_fb_target)
  39. self.thread = QThread() # no parent!
  40. self.bci.moveToThread(self.thread)
  41. self.thread.started.connect(self.bci.start_session)
  42. self.thread.finished.connect(self.quit_thread)
  43. # 4 - Connect Worker Signals to the Thread slots
  44. self.bci.finished_block.connect(self.thread.quit)
  45. self.bci.finished_block.connect(self.block_done)
  46. self.bci.history.connect(self.get_message)
  47. # 5 - Connect Thread started signal to Worker operational slot method
  48. # self.thread.start()
  49. # self.thread.started.connect(self.bci.start_trial)
  50. # * - Thread finished signal will close the app if you want!
  51. # self.thread.finished.connect(sys.exit)
  52. # 6 - Start the thread
  53. self.__InitUI()
  54. def onIntReady(self, i):
  55. self.log.debug('got {} from thread'.format(i))
  56. def __btnAddFilesClicked(self):
  57. options = QtWidgets.QFileDialog.Options()
  58. options |= QtWidgets.QFileDialog.DontUseNativeDialog
  59. selectedFile, _ = QtWidgets.QFileDialog.getOpenFileName(None,"QFileDialog.getOpenFileName()", "","All Files (*);;Python Files (*.py)")
  60. if selectedFile:
  61. #fileName = Qt.QUrl().fromLocalFile(selectedFile).fileName()
  62. self.lstModelFiles.append(selectedFile)
  63. listModel = Qt.QStandardItemModel(self.lstvModelFiles)
  64. for file in self.lstModelFiles:
  65. f = Qt.QStandardItem(file)
  66. listModel.appendRow(f)
  67. self.lstvModelFiles.setModel(listModel)
  68. self.lstvModelFiles.show()
  69. print('Clicked')
  70. def __btnRemoveFilesClicked(self):
  71. a = 1
  72. self.lstModelFiles.remove(self.lstvModelFiles.currentIndex().data())
  73. listModel = Qt.QStandardItemModel(self.lstvModelFiles)
  74. for file in self.lstModelFiles:
  75. f = Qt.QStandardItem(file)
  76. listModel.appendRow(f)
  77. self.lstvModelFiles.setModel(listModel)
  78. self.lstvModelFiles.show()
  79. print('Clicked')
  80. def __btnStartClicked(self):
  81. if(self.btnExpStart.text() == 'Start'):
  82. self.btnExpStart.setText('Stop')
  83. self.cmbExpParadigms.setEnabled(False)
  84. selectedParadigm = self.cmbExpParadigms.currentText()
  85. self.ShowMessage(selectedParadigm + 'Block start.')
  86. self.StartClicked()
  87. else:
  88. self.btnExpStart.setText('Start')
  89. self.cmbExpParadigms.setEnabled(True)
  90. self.ShowMessage(self.cmbExpParadigms.currentText() + ' Stopped by operator')
  91. self.StopClicked()
  92. time.sleep(1)
  93. return None
  94. # def __btnSaveLogClicked(self):
  95. # fileName = Qt.QFileDialog.getSaveFileName(None,'Save Log',sys.path[0] + os.sep + 'Patients' + os.sep + self.selectedPatient + os.sep,'Log Files (*.html)')
  96. # if(fileName[0] != ''):
  97. # f = open(fileName[0],'w+')
  98. # f.write(self.txbExpLogWin.toHtml())
  99. # f.close()
  100. # self.txbExpLogWin.clear()
  101. # self.ShowMessageBox('Saving Data','Data Saved Successfully')
  102. # print('save log')
  103. def __btnLoadConfigFileClicked(self):
  104. options = QtWidgets.QFileDialog.Options()
  105. options |= QtWidgets.QFileDialog.DontUseNativeDialog
  106. self.selectedConfigFile, _ = QtWidgets.QFileDialog.getOpenFileName(None,"QFileDialog.getOpenFileName()", "","Config Files (*.yaml)")
  107. if self.selectedConfigFile:
  108. self.lblDeviceConfigFile.setText('Config File: ' + self.selectedConfigFile)
  109. else:
  110. self.lblDeviceConfigFile.setText('Config File: ')
  111. def __btnSetConfigFileClicked(self):
  112. pass
  113. # self.bci.load_config()
  114. # self.log.info('Config file reloaded!')
  115. # tbPallet = QtGui.QPalette()
  116. # if(self.btnSetConfigFile.text() == 'Set'):
  117. # if self.selectedConfigFile:
  118. # self.btnLoadConfigFile.setEnabled(False)
  119. # self.lblDeviceConfigFile.setEnabled(False)
  120. # self.btnSetConfigFile.setText('Unset')
  121. # tbPallet.setColor(QtGui.QPalette.Background,QtGui.QColor(50,205,50))
  122. # else:
  123. # self.ShowMessageBox('Error','Config File Not Selected')
  124. # else:
  125. # self.btnLoadConfigFile.setEnabled(True)
  126. # self.lblDeviceConfigFile.setEnabled(True)
  127. # self.btnSetConfigFile.setText('Set')
  128. # tbPallet.setColor(QtGui.QPalette.Background,QtGui.QColor(255,69,0))
  129. # self.tab1GbxDevice.setPalette(tbPallet)
  130. # self.tab1GbxDevice.show()
  131. def __btnSetPatientClicked(self):
  132. tbPallet = QtGui.QPalette()
  133. if(self.btnSetPatient.text() == 'Set'):
  134. self.cmbPatients.setEnabled(False)
  135. self.btnSetPatient.setText('Unset')
  136. tbPallet.setColor(QtGui.QPalette.Background,QtGui.QColor(50,205,50))
  137. self.selectedPatient = self.cmbPatients.currentText()
  138. self.lblExpPatienName.setText('Patient: ' + self.selectedPatient)
  139. else:
  140. self.cmbPatients.setEnabled(True)
  141. self.btnSetPatient.setText('Set')
  142. tbPallet.setColor(QtGui.QPalette.Background,QtGui.QColor(255,69,0))
  143. self.selectedPatient = None
  144. self.lblExpPatienName.setText('Patient: ')
  145. self.tab1GbxPatient.setPalette(tbPallet)
  146. self.tab1GbxPatient.show()
  147. def __UpdateTime(self):
  148. self.lblExpTime.setText(datetime.datetime.now().strftime('%H:%M:%S'))
  149. def __InitUI(self):
  150. self.__app = QtWidgets.QApplication([])
  151. self.__mainWindow = QtWidgets.QMainWindow()
  152. self.__mainWindow.setWindowTitle('KIAP - Speller V 0.1')
  153. self.__mainWindow.setFixedSize(600,600)
  154. self.__mainWindow.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
  155. self.__mainWindow.closeEvent = self.__WindowClosed
  156. tbMain = QtWidgets.QTabWidget()
  157. tbMain.setAutoFillBackground(True)
  158. #tbPallet = QtGui.QPalette()
  159. #tbPallet.setColor(QtGui.QPalette.Background,QtGui.QColor(255,0,0))
  160. #tbMain.setPalette(tbPallet)
  161. # tab1 = QtWidgets.QWidget()
  162. # tbMain.addTab(tab1,'Configuration')
  163. # tab1GrdMain = QtWidgets.QGridLayout()
  164. # tab1GrdMain.setRowStretch(0,1)
  165. # tab1GrdMain.setRowStretch(1,1)
  166. # tab1GrdMain.setRowStretch(2,1)
  167. # self.tab1GbxDevice = QtWidgets.QGroupBox('Device')
  168. # self.tab1GbxDevice.setAutoFillBackground(True)
  169. # grdDeviceConfig = QtWidgets.QGridLayout()
  170. # grdDeviceConfig.setColumnStretch(0,7)
  171. # grdDeviceConfig.setColumnStretch(0,1)
  172. # grdDeviceConfig.setRowStretch(0,1)
  173. # grdDeviceConfig.setRowStretch(0,1)
  174. # grdDeviceConfig.setRowStretch(0,1)
  175. # grdDeviceConfig.setRowStretch(0,1)
  176. # self.lblDeviceConfigFile = QtWidgets.QLabel('Selected Config File :')
  177. # grdDeviceConfig.addWidget(self.lblDeviceConfigFile,0,0,QtCore.Qt.AlignTop)
  178. # self.btnLoadConfigFile = QtWidgets.QPushButton('Load')
  179. # self.btnLoadConfigFile.clicked.connect(self.__btnLoadConfigFileClicked)
  180. # grdDeviceConfig.addWidget(self.btnLoadConfigFile,2,1)
  181. # self.btnSetConfigFile = QtWidgets.QPushButton('Set')
  182. # self.btnSetConfigFile.clicked.connect(self.__btnSetConfigFileClicked)
  183. # grdDeviceConfig.addWidget(self.btnSetConfigFile,3,1)
  184. # self.tab1GbxDevice.setLayout(grdDeviceConfig)
  185. # tab1GbxModel = QtWidgets.QGroupBox('Model')
  186. # tab1GbxModel.setEnabled(False)
  187. # tab1GbxModelMainLayout = QtWidgets.QHBoxLayout()
  188. # tab1GbxModelMainLayout.setStretch(0,1)
  189. # tab1GbxModelMainLayout.setStretch(1,1)
  190. # grdModelFileSection = QtWidgets.QGridLayout()
  191. # grdModelFileSection.setRowStretch(0,1)
  192. # grdModelFileSection.setRowStretch(1,1)
  193. # grdModelFileSection.setRowStretch(2,1)
  194. # grdModelFileSection.setRowStretch(3,1)
  195. # grdModelFileSection.setRowStretch(4,1)
  196. # grdModelFileSection.setRowStretch(5,1)
  197. # grdModelFileSection.setColumnStretch(0,1)
  198. # grdModelFileSection.setColumnStretch(1,1)
  199. # grdModelFileSection.setColumnStretch(2,1)
  200. # grdModelFileSection.setColumnStretch(3,1)
  201. # self.lstvModelFiles = QtWidgets.QListView()
  202. # self.lstvModelFiles.setWindowTitle('Files')
  203. # grdModelFileSection.addWidget(self.lstvModelFiles,0,0,5,2)
  204. # #lstvModelFiles.setModel()
  205. # btnModelRemoveFile = QtWidgets.QPushButton('Remove')
  206. # btnModelRemoveFile.setToolTip('Remove selected file from list')
  207. # btnModelRemoveFile.clicked.connect(self.__btnRemoveFilesClicked)
  208. # grdModelFileSection.addWidget(btnModelRemoveFile,5,0)
  209. # btnModelAddFile = QtWidgets.QPushButton('Add')
  210. # btnModelAddFile.setToolTip('Add files for building a model')
  211. # btnModelAddFile.clicked.connect(self.__btnAddFilesClicked)
  212. # grdModelFileSection.addWidget(btnModelAddFile,5,1)
  213. # txbModelBuildReport = QtWidgets.QTextEdit()
  214. # txbModelBuildReport.setEnabled(False)
  215. # grdModelFileSection.addWidget(txbModelBuildReport,0,2,3,2)
  216. # rbtModelFileSVM = QtWidgets.QRadioButton('SVM')
  217. # grdModelFileSection.addWidget(rbtModelFileSVM,3,2)
  218. # rbtModelFileGLM = QtWidgets.QRadioButton('GLM')
  219. # grdModelFileSection.addWidget(rbtModelFileGLM,3,3)
  220. # txbModelFileNewModelName = QtWidgets.QTextEdit('ModelName')
  221. # #grdModelFileSection.addWidget(txbModelFileNewModelName,4,2,1,2)
  222. # btnModelFileBuildModel = QtWidgets.QPushButton('Build New Model')
  223. # grdModelFileSection.addWidget(btnModelFileBuildModel,5,2,1,2)
  224. # grdModelSelection = QtWidgets.QGridLayout()
  225. # grdModelSelection.setRowStretch(0,1)
  226. # grdModelSelection.setRowStretch(1,1)
  227. # grdModelSelection.setRowStretch(2,1)
  228. # grdModelSelection.setRowStretch(3,1)
  229. # grdModelSelection.setRowStretch(4,1)
  230. # grdModelSelection.setRowStretch(5,1)
  231. # grdModelSelection.setColumnStretch(0,1)
  232. # grdModelSelection.setColumnStretch(1,1)
  233. # btnSetModel = QtWidgets.QPushButton('Set')
  234. # grdModelSelection.addWidget(btnSetModel,5,1)
  235. # tab1GbxModelMainLayout.addLayout(grdModelFileSection)
  236. # tab1GbxModelMainLayout.addLayout(grdModelSelection)
  237. # tab1GbxModel.setLayout(tab1GbxModelMainLayout)
  238. # self.tab1GbxPatient = QtWidgets.QGroupBox('Patient')
  239. # self.tab1GbxPatient.setAutoFillBackground(True)
  240. # grdPatientInfo = QtWidgets.QGridLayout()
  241. # grdPatientInfo.setColumnStretch(0,7)
  242. # grdPatientInfo.setColumnStretch(0,1)
  243. # grdPatientInfo.setRowStretch(0,1)
  244. # grdPatientInfo.setRowStretch(0,1)
  245. # grdPatientInfo.setRowStretch(0,1)
  246. # grdPatientInfo.setRowStretch(0,1)
  247. # self.cmbPatients = QtWidgets.QComboBox()
  248. # for p in glob.glob(sys.path[0] + '\\Patients\\*\\'):
  249. # self.cmbPatients.addItem(os.path.basename(p[:-1]))
  250. # grdPatientInfo.addWidget(self.cmbPatients,0,0,alignment=QtCore.Qt.AlignTop)
  251. # self.btnSetPatient = QtWidgets.QPushButton('Set')
  252. # self.btnSetPatient.clicked.connect(self.__btnSetPatientClicked)
  253. # grdPatientInfo.addWidget(self.btnSetPatient,3,2)
  254. # self.tab1GbxPatient.setLayout(grdPatientInfo)
  255. # tab1GrdMain.addWidget(self.tab1GbxDevice,0,0)
  256. # tab1GrdMain.addWidget(tab1GbxModel,1,0)
  257. # tab1GrdMain.addWidget(self.tab1GbxPatient,2,0)
  258. # tab1.layout = tab1GrdMain
  259. # tab1.setLayout(tab1.layout)
  260. tab2 = QtWidgets.QWidget()
  261. tbMain.addTab(tab2,'Experiment')
  262. grdExperimentTab = QtWidgets.QGridLayout()
  263. grdExperimentTab.setRowStretch(0,1)
  264. grdExperimentTab.setRowStretch(1,1)
  265. grdExperimentTab.setRowStretch(2,1)
  266. grdExperimentTab.setRowStretch(3,1)
  267. grdExperimentTab.setRowStretch(4,12)
  268. grdExperimentTab.setRowStretch(3,1)
  269. grdExperimentTab.setColumnStretch(0,1)
  270. grdExperimentTab.setColumnStretch(1,1)
  271. grdExperimentTab.setColumnStretch(2,1)
  272. grdExperimentTab.setColumnStretch(3,1)
  273. grdExperimentTab.setColumnStretch(4,1)
  274. grdExperimentTab.setColumnStretch(5,1)
  275. grdExperimentTab.setColumnStretch(6,1)
  276. grdExperimentTab.setColumnStretch(7,1)
  277. self.lblExpPatienName = QtWidgets.QLabel('Patient Name:')
  278. grdExperimentTab.addWidget(self.lblExpPatienName,0,0)
  279. self.lblExpSessionInfo = QtWidgets.QLabel('Session Info:')
  280. grdExperimentTab.addWidget(self.lblExpSessionInfo,1,0)
  281. self.lblExpTime = QtWidgets.QLabel()
  282. grdExperimentTab.addWidget(self.lblExpTime,0,6,QtCore.Qt.AlignBottom)
  283. self.label_update_timer = QtCore.QTimer()
  284. self.label_update_timer.setSingleShot(False)
  285. self.label_update_timer.timeout.connect(self.__UpdateTime)
  286. self.label_update_timer.start(1000)
  287. lblDate = QtWidgets.QLabel(datetime.datetime.now().strftime('%B %d, %Y'))
  288. grdExperimentTab.addWidget(lblDate,1,6,QtCore.Qt.AlignTop)
  289. sepLine = QtWidgets.QFrame()
  290. sepLine.setLineWidth(2)
  291. sepLine.setMidLineWidth(1)
  292. sepLine.setFrameShape(Qt.QFrame.HLine)
  293. sepLine.setFrameShadow(Qt.QFrame.Raised)
  294. grdExperimentTab.addWidget(sepLine,1,0,1,8,QtCore.Qt.AlignBottom)
  295. self.txbExpSelectedString = QtWidgets.QLabel('Selected String:')
  296. grdExperimentTab.addWidget(self.txbExpSelectedString,2,0,2,7)
  297. self.cmbExpParadigms = QtWidgets.QComboBox()
  298. for p in glob.glob(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + '\\paradigms\\*.py'):
  299. self.cmbExpParadigms.addItem(os.path.basename(p[:-3]))
  300. #self.cmbExpParadigms.addItem('Speller')
  301. #self.cmbExpParadigms.addItem('Yes / No')
  302. #self.cmbExpParadigms.addItem('Free Recording')
  303. #self.cmbExpParadigms.addItem('Motor Paradigm')
  304. grdExperimentTab.addWidget(self.cmbExpParadigms,2,6,1,2)
  305. self.btnExpStart = QtWidgets.QPushButton('Start')
  306. self.btnExpStart.clicked.connect(self.__btnStartClicked)
  307. grdExperimentTab.addWidget(self.btnExpStart,3,6,1,2)
  308. self.txbExpLogWin = QtWidgets.QTextBrowser()
  309. grdExperimentTab.addWidget(self.txbExpLogWin,4,0,2,8)
  310. # btnExpSaveLog = QtWidgets.QPushButton('Save Log')
  311. # btnExpSaveLog.clicked.connect(self.__btnSaveLogClicked)
  312. # grdExperimentTab.addWidget(btnExpSaveLog,9,7)
  313. tab2.layout = grdExperimentTab
  314. tab2.setLayout(tab2.layout)
  315. self.__mainWindow.setCentralWidget(tbMain)
  316. def __WindowClosed(self, evt):
  317. pass
  318. def StartGUI(self):
  319. self.__mainWindow.show()
  320. # self.__mainWindow.move(800, 100)
  321. self.__mainWindow.move(2400, 600)
  322. self.__app.exec()
  323. def SetSelectedSentensce(slef,sentence):
  324. self.txbExpSelectedString.SetText('Selected String: ' + sentence)
  325. @pyqtSlot(str)
  326. def get_message(self, msg):
  327. # print(msg)
  328. # self.log.error(f'HISTORY {msg}')
  329. self.ShowMessage(msg)
  330. def ShowMessage(self, msg):
  331. self.txbExpLogWin.append(str(datetime.datetime.now()) + ' | ' + msg )
  332. def ShowMessageBox(self,title,msg):
  333. msgbx = QtWidgets.QMessageBox()
  334. msgbx.setText(msg)
  335. msgbx.setWindowTitle(title)
  336. #msgbx.standardButton(QtWidgets.QMessageBox.Ok)
  337. msgbx.exec()
  338. def StartClicked(self):
  339. res = self.bci.load_config()
  340. if res > 0:
  341. self.__btnStartClicked()
  342. self.log.warning('Block not started')
  343. else:
  344. self.log.info('Config file reloaded!')
  345. self.thread.start()
  346. return None
  347. def StopClicked(self):
  348. self.bci.recording_status.value = 0
  349. return None
  350. def quit_thread(self):
  351. self.log.debug('Quitting thread, data_recording_status: {}\n'.format(self.bci.recording_status.value))
  352. self.thread.quit()
  353. return None
  354. def block_done(self):
  355. # self.bci.recording_status.value = 0
  356. self.btnExpStart.setText('Start')
  357. self.cmbExpParadigms.setEnabled(True)
  358. self.ShowMessage(self.cmbExpParadigms.currentText() + 'Block end.\n')
  359. return None