source: trunk/synapse/Puzzlebox/Synapse/Interface.py @ 275

Last change on this file since 275 was 275, checked in by sc, 11 years ago

trunk/synapse/Puzzlebox/Synapse/Interface.py:

  • try/except added around parsing timestamps for emulation

trunk/synapse/Puzzlebox/Synapse/Protocol.py:

  • try/except added around data parsing error
  • read_buffer_check_timer disabled

puzzlebox_synapse_configuration.ini:

  • THINKGEAR_BLINK_FREQUENCY_TIMER added and set to 1

trunk/brainstorms/Puzzlebox/Brainstorms/Wheelchair_Control.py:

  • whitespace cleanup
  • Property svn:executable set to *
File size: 27.6 KB
Line 
1# -*- coding: utf-8 -*-
2
3# Copyright Puzzlebox Productions, LLC (2010)
4#
5# This code is released under the GNU Pulic License (GPL) version 2
6# For more information please refer to http://www.gnu.org/copyleft/gpl.html
7
8# Old Class Names:
9#       puzzlebox_synapse_interface = QtUI
10
11__changelog__ = """\
12Last Update: 2011.03.01
13
14"""
15
16__todo__ = """
17- update configuration.ini file with settings entered into interface
18
19"""
20
21### IMPORTS ###
22import os, sys, time
23import simplejson as json
24
25try:
26        from Interface_Plot import *
27        MATPLOTLIB_AVAILABLE = True
28except:
29        MATPLOTLIB_AVAILABLE = False
30
31if (sys.platform != 'win32'):
32        import bluetooth
33        DEFAULT_IMAGE_PATH = '/usr/share/puzzlebox_synapse/images'
34else:
35        import _winreg as winreg
36        import itertools
37        import re
38        import serial
39        DEFAULT_IMAGE_PATH = 'images'
40
41try:
42        import PySide as PyQt4
43        from PySide import QtCore, QtGui
44except:
45        print "Using PyQt4 module"
46        from PyQt4 import QtCore, QtGui
47else:
48        print "Using PySide module"
49
50try:
51        import cPickle as pickle
52except:
53        import pickle
54
55# from puzzlebox_synapse_interface_design import Ui_Form
56from Interface_Design import Ui_Form as Design
57
58import Configuration as configuration
59import Server as synapse_server
60import Client as thinkgear_client
61#import puzzlebox_logger
62
63### GLOBALS ###
64
65DEBUG = 1
66
67THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
68THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
69
70THINKGEAR_EEG_POWER_BAND_ORDER = configuration.THINKGEAR_EEG_POWER_BAND_ORDER
71
72THINKGEAR_EMULATION_MAX_ESENSE_VALUE = \
73        configuration.THINKGEAR_EMULATION_MAX_ESENSE_VALUE
74THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE = \
75        configuration.THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE
76
77PATH_TO_HCITOOL = '/usr/bin/hcitool'
78
79#UPDATE_INTERFACE_VIA_TIMER = True # Alternative is to establish a
80                                  ## ThinkGear Connect client which
81                                  ## updates the interface on demand
82                                  ## as packets are received
83
84UPDATE_INTERFACE_VIA_TIMER = False
85
86#INTERFACE_UPDATE_FREQUENCY = (1 / 512) * 1000 # ms (512 Hz)
87INTERFACE_UPDATE_FREQUENCY = 1000 # ms
88
89INTERFACE_RAW_EEG_UPDATE_FREQUENCY = 512
90
91### CLASSES ###
92
93class QtUI(QtGui.QWidget, Design):
94       
95        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
96               
97                self.log = log
98                self.DEBUG = DEBUG
99               
100                QtGui.QWidget.__init__(self, parent)
101                self.setupUi(self)
102               
103                self.configureSettings()
104                self.connectWidgets()
105               
106                self.name = "Synapse Interface"
107               
108                self.thinkGearConnectServer = None
109                self.thinkgearConnectClient = None
110               
111                self.maxEEGPower = THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE
112               
113                self.debug_console_buffer = ''
114               
115                self.packets = {}
116                self.packets['rawEeg'] = []
117                self.packets['signals'] = []
118               
119                if UPDATE_INTERFACE_VIA_TIMER:
120                        self.updateInterfaceTimer = QtCore.QTimer()
121                        QtCore.QObject.connect(self.updateInterfaceTimer, \
122                                                    QtCore.SIGNAL("timeout()"), \
123                                                    self.updateInterface)
124       
125       
126        ##################################################################
127       
128        def configureSettings(self):
129               
130                # Synapse Interface
131                image_path = "puzzlebox.ico"
132                if not os.path.exists(image_path):
133                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
134               
135                if os.path.exists(image_path):
136                        icon = QtGui.QIcon()
137                        icon.addPixmap(QtGui.QPixmap(image_path), \
138                                            QtGui.QIcon.Normal, \
139                                            QtGui.QIcon.Off)
140                        self.setWindowIcon(icon)
141               
142                image_path = "puzzlebox_logo.png"
143                if not os.path.exists(image_path):
144                        image_path = os.path.join(DEFAULT_IMAGE_PATH, image_path)
145                if os.path.exists(image_path):
146                        self.labelPuzzleboxIcon.setPixmap(QtGui.QPixmap(image_path))
147               
148               
149                if configuration.INTERFACE_TAB_POSITION == 'South':
150                        self.tabWidget.setTabPosition(QtGui.QTabWidget.South)
151                else:
152                        self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
153               
154               
155                # ThinkGear Device
156                self.searchForThinkGearDevices()
157               
158               
159                # ThinkGear Connect Server
160                self.textLabelBluetoothStatus.setText("Status: Disconnected")
161               
162                # Display Host for ThinkGear Connect Socket Server
163                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
164               
165                # Display Port for ThinkGear Connect Socket Server
166                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
167               
168               
169                # ThinkgGear Progress Bars
170                self.progressBarEEGDelta.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
171                self.progressBarEEGTheta.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
172                self.progressBarEEGLowAlpha.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
173                self.progressBarEEGHighAlpha.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
174                self.progressBarEEGLowBeta.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
175                self.progressBarEEGHighBeta.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
176                self.progressBarEEGLowGamma.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
177                self.progressBarEEGMidGamma.setMaximum(THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE)
178               
179                self.progressBarAttention.setMaximum(THINKGEAR_EMULATION_MAX_ESENSE_VALUE)
180                self.progressBarMeditation.setMaximum(THINKGEAR_EMULATION_MAX_ESENSE_VALUE)
181               
182                self.progressBarSignalContactQuality.setMaximum(200)
183               
184               
185                if MATPLOTLIB_AVAILABLE:
186                        self.rawEEGMatplot = rawEEGMatplotlibCanvas( \
187                                                self.tabEEGSignals, \
188                                                width=8, \
189                                                height=4, \
190                                                dpi=100, \
191                                                title='Raw EEG Waves')
192                        self.chartEEGMatplot = chartEEGMatplotlibCanvas( \
193                                                self.tabCharts, \
194                                                width=8, \
195                                                height=4, \
196                                                dpi=100, \
197                                                title='EEG Brain Signals')
198               
199                else:
200                        self.tabWidget.removeTab(self.tabWidget.indexOf(self.tabEEGSignals))
201                        self.tabWidget.removeTab(self.tabWidget.indexOf(self.tabCharts))
202       
203       
204        ##################################################################
205       
206        def connectWidgets(self):
207               
208                self.connect(self.pushButtonBluetoothSearch, \
209                                  QtCore.SIGNAL("clicked()"), \
210                                  self.searchForThinkGearDevices)
211               
212                self.connect(self.pushButtonBluetoothConnect, \
213                                  QtCore.SIGNAL("clicked()"), \
214                                  self.connectToThinkGearDevice)
215               
216                self.connect(self.pushButtonThinkGearConnect, \
217                                  QtCore.SIGNAL("clicked()"), \
218                                  self.startThinkGearConnectServer)
219               
220                self.connect(self.pushButtonSave, \
221                                  QtCore.SIGNAL("clicked()"), \
222                                  self.saveData)
223               
224                self.connect(self.pushButtonExport, \
225                                  QtCore.SIGNAL("clicked()"), \
226                                  self.exportData)
227               
228                self.connect(self.pushButtonReset, \
229                                  QtCore.SIGNAL("clicked()"), \
230                                  self.resetData)
231       
232       
233        ##################################################################
234       
235        def connectToThinkGearDevice(self):
236               
237                device_selection = self.comboBoxDeviceSelect.currentText()
238               
239                self.disconnect(self.pushButtonBluetoothConnect, \
240                                     QtCore.SIGNAL("clicked()"), \
241                                     self.connectToThinkGearDevice)
242               
243                self.connect(self.pushButtonBluetoothConnect, \
244                                  QtCore.SIGNAL("clicked()"), \
245                                  self.disconnectFromThinkGearDevice)
246               
247                self.textLabelBluetoothStatus.setText("Status: Connected")
248               
249                self.pushButtonBluetoothSearch.setEnabled(False)
250               
251                self.pushButtonBluetoothConnect.setText('Disconnect')
252                self.pushButtonBluetoothConnect.setChecked(True)
253               
254                self.comboBoxDeviceSelect.setEnabled(False)
255       
256       
257        ##################################################################
258       
259        def disconnectFromThinkGearDevice(self):
260               
261                self.disconnect(self.pushButtonBluetoothConnect, \
262                                     QtCore.SIGNAL("clicked()"), \
263                                     self.disconnectFromThinkGearDevice)
264               
265                self.connect(self.pushButtonBluetoothConnect, \
266                                  QtCore.SIGNAL("clicked()"), \
267                                  self.connectToThinkGearDevice)
268               
269                self.textLabelBluetoothStatus.setText("Status: Disconnected")
270               
271                self.pushButtonBluetoothSearch.setEnabled(True)
272               
273                self.pushButtonBluetoothConnect.setText('Connect')
274                self.pushButtonBluetoothConnect.setChecked(False)
275               
276                self.comboBoxDeviceSelect.setEnabled(True)
277               
278               
279                self.progressBarEEGDelta.setValue(0)
280                self.progressBarEEGTheta.setValue(0)
281                self.progressBarEEGLowAlpha.setValue(0)
282                self.progressBarEEGHighAlpha.setValue(0)
283                self.progressBarEEGLowBeta.setValue(0)
284                self.progressBarEEGHighBeta.setValue(0)
285                self.progressBarEEGLowGamma.setValue(0)
286                self.progressBarEEGMidGamma.setValue(0)
287               
288                self.progressBarAttention.setValue(0)
289                self.progressBarMeditation.setValue(0)
290               
291                self.progressBarSignalContactQuality.setValue(0)
292               
293                self.maxEEGPower = THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE
294               
295                # In case the user connects to a MindSet, then disconnects
296                # and re-connects to a MindSet Emulator,
297                # we need to reset the max power values
298                self.progressBarEEGDelta.setMaximum(self.maxEEGPower)
299                self.progressBarEEGTheta.setMaximum(self.maxEEGPower)
300                self.progressBarEEGLowAlpha.setMaximum(self.maxEEGPower)
301                self.progressBarEEGHighAlpha.setMaximum(self.maxEEGPower)
302                self.progressBarEEGLowBeta.setMaximum(self.maxEEGPower)
303                self.progressBarEEGHighBeta.setMaximum(self.maxEEGPower)
304                self.progressBarEEGLowGamma.setMaximum(self.maxEEGPower)
305                self.progressBarEEGMidGamma.setMaximum(self.maxEEGPower)
306       
307       
308        ##################################################################
309       
310        def startThinkGearConnectServer(self):
311               
312                # Ensure EEG device is connected first
313               
314                if not self.pushButtonBluetoothConnect.isChecked():
315                        self.connectToThinkGearDevice()
316               
317               
318                self.pushButtonBluetoothSearch.setEnabled(False)
319                self.pushButtonBluetoothConnect.setEnabled(False)
320               
321                server_interface = str(self.lineEditThinkGearHost.text())
322                server_port = int(self.lineEditThinkGearPort.text())
323                device_address = str(self.comboBoxDeviceSelect.currentText())
324                emulate_headset_data = (device_address == 'MindSet Emulator')
325               
326               
327                self.thinkGearConnectServer = \
328                        synapse_server.ThinkgearServer( \
329                                self.log, \
330                                server_interface=server_interface, \
331                                server_port=server_port, \
332                                device_address=device_address, \
333                                emulate_headset_data=emulate_headset_data, \
334                                DEBUG=DEBUG, \
335                                parent=self)
336               
337                self.thinkGearConnectServer.start()
338               
339               
340                if UPDATE_INTERFACE_VIA_TIMER:
341                        self.updateInterfaceTimer.start(INTERFACE_UPDATE_FREQUENCY)
342               
343                else:
344                        self.thinkgearConnectClient = \
345                                thinkgear_client.QtClient( \
346                                        self.log, \
347                                        server_host=server_interface, \
348                                        server_port=server_port, \
349                                        DEBUG=0, \
350                                        parent=self)
351                       
352                        self.thinkgearConnectClient.start()
353               
354               
355                self.disconnect(self.pushButtonThinkGearConnect, \
356                                     QtCore.SIGNAL("clicked()"), \
357                                     self.startThinkGearConnectServer)
358               
359                self.connect(self.pushButtonThinkGearConnect, \
360                                  QtCore.SIGNAL("clicked()"), \
361                                  self.stopThinkGearConnectServer)
362               
363                self.lineEditThinkGearHost.setEnabled(False)
364                self.lineEditThinkGearPort.setEnabled(False)
365               
366                self.pushButtonThinkGearConnect.setText('Stop')
367       
368       
369        ##################################################################
370       
371        def stopThinkGearConnectServer(self):
372               
373                if UPDATE_INTERFACE_VIA_TIMER:
374                        self.updateInterfaceTimer.stop()
375                else:
376                        try:
377                                self.thinkgearConnectClient.disconnectFromHost()
378                        except Exception, e:
379                                if self.DEBUG:
380                                        print "Call failed to self.thinkgearConnectClient.disconnectFromHost():",
381                                        print e
382                       
383                        try:
384                                self.thinkGearConnectServer.exitThread()
385                        except Exception, e:
386                                if self.DEBUG:
387                                        print "Call failed to self.thinkGearConnectServer.exitThread():",
388                                        print e
389               
390                self.disconnect(self.pushButtonThinkGearConnect, \
391                                QtCore.SIGNAL("clicked()"), \
392                                self.stopThinkGearConnectServer)
393               
394                self.connect(self.pushButtonThinkGearConnect, \
395                                  QtCore.SIGNAL("clicked()"), \
396                                  self.startThinkGearConnectServer)
397               
398                self.lineEditThinkGearHost.setEnabled(True)
399                self.lineEditThinkGearPort.setEnabled(True)
400               
401                self.pushButtonThinkGearConnect.setText('Start')
402               
403                #self.pushButtonBluetoothSearch.setEnabled(True)
404                self.pushButtonBluetoothConnect.setEnabled(True)
405               
406                self.pushButtonThinkGearConnect.setChecked(False)
407       
408       
409        ##################################################################
410       
411        def updateInterface(self):
412               
413                if not self.thinkGearConnectServer.emulate_headset_data:
414                        self.processPacketThinkGear( \
415                                self.thinkGearConnectServer.protocol.data_packet)
416       
417       
418        ##################################################################
419       
420        def parseTimeStamp(self, timestamp, local_version=False):
421               
422                try:
423                        decimal = '%f' % timestamp
424                        decimal = decimal.split('.')[1]
425                except:
426                        decimal = '0'
427               
428                localtime = time.localtime(timestamp)
429               
430                if local_version:
431                        date = time.strftime('%x', localtime)
432                        localtime = time.strftime('%X', localtime)
433               
434                else:
435                        date = time.strftime('%Y-%m-%d', localtime)
436                        localtime = time.strftime('%H:%M:%S', localtime)
437                        localtime = '%s.%s %s' % (localtime, decimal, \
438                                       time.strftime('%Z', time.localtime(timestamp)))
439               
440               
441                return(date, localtime)
442       
443       
444        ##################################################################
445       
446        def processPacketThinkGear(self, packet):
447               
448                if self.DEBUG > 2:
449                        print packet
450               
451               
452                if ('rawEeg' in packet.keys()):
453                        self.packets['rawEeg'].append(packet['rawEeg'])
454                        value = packet['rawEeg']
455                        if MATPLOTLIB_AVAILABLE and \
456                                (self.tabWidget.currentIndex() == \
457                                 self.tabWidget.indexOf(self.tabEEGSignals)):
458                                self.rawEEGMatplot.update_figure(value)
459                else:
460                        self.packets['signals'].append(packet)
461               
462               
463                if ('poorSignalLevel' in packet.keys()):
464                        value = 200 - packet['poorSignalLevel']
465                        self.progressBarSignalContactQuality.setValue(value)
466                        self.textEditDebugConsole.append("")
467                        try:
468                                (date, localtime) = self.parseTimeStamp(packet['timestamp'])
469                                self.textEditDebugConsole.append("Timestamp: %s %s" % (date, localtime))
470                        except:
471                                pass
472                        self.textEditDebugConsole.append("poorSignalLevel: %i" % \
473                                                         packet['poorSignalLevel'])
474               
475               
476                if ('eSense' in packet.keys()):
477                       
478                        if ('attention' in packet['eSense'].keys()):
479                                value = packet['eSense']['attention']
480                                self.progressBarAttention.setValue(value)
481                                self.textEditDebugConsole.append("eSense attention: %i" % value)
482                       
483                        if ('meditation' in packet['eSense'].keys()):
484                                value = packet['eSense']['meditation']
485                                self.progressBarMeditation.setValue(value)
486                                self.textEditDebugConsole.append("eSense meditation: %i" % value)
487                       
488                       
489                        if MATPLOTLIB_AVAILABLE:
490                                self.chartEEGMatplot.update_values('eSense', packet['eSense'])
491                                if (self.tabWidget.currentIndex() == \
492                                    self.tabWidget.indexOf(self.tabCharts)):
493                                        self.chartEEGMatplot.update_figure('eSense', packet['eSense'])
494               
495               
496                if ('eegPower' in packet.keys()):
497                       
498                        # If we are not emulating packets we'll set the maximum EEG Power value
499                        # threshold to the default (or maximum value found within this packet)
500                        if not self.thinkGearConnectServer.emulate_headset_data:
501                                self.maxEEGPower = THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE
502                       
503                        for value in packet['eegPower'].keys():
504                                if packet['eegPower'][value] > self.maxEEGPower:
505                                        self.maxEEGPower = packet['eegPower'][value]
506                       
507                       
508                        if ('delta' in packet['eegPower'].keys()):
509                                value = packet['eegPower']['delta']
510                                self.progressBarEEGDelta.setMaximum(self.maxEEGPower)
511                                self.progressBarEEGDelta.setValue(value)
512                                self.textEditDebugConsole.append("delta: %i" % value)
513                       
514                        if ('theta' in packet['eegPower'].keys()):
515                                value = packet['eegPower']['theta']
516                                self.progressBarEEGTheta.setMaximum(self.maxEEGPower)
517                                self.progressBarEEGTheta.setValue(value)
518                                self.textEditDebugConsole.append("theta: %i" % value)
519                       
520                        if ('lowAlpha' in packet['eegPower'].keys()):
521                                value = packet['eegPower']['lowAlpha']
522                                self.progressBarEEGLowAlpha.setMaximum(self.maxEEGPower)
523                                self.progressBarEEGLowAlpha.setValue(value)
524                                self.textEditDebugConsole.append("lowAlpha: %i" % value)
525                       
526                        if ('highAlpha' in packet['eegPower'].keys()):
527                                value = packet['eegPower']['highAlpha']
528                                self.progressBarEEGHighAlpha.setMaximum(self.maxEEGPower)
529                                self.progressBarEEGHighAlpha.setValue(value)
530                                self.textEditDebugConsole.append("highAlpha: %i" % value)
531                       
532                        if ('lowBeta' in packet['eegPower'].keys()):
533                                value = packet['eegPower']['lowBeta']
534                                self.progressBarEEGLowBeta.setMaximum(self.maxEEGPower)
535                                self.progressBarEEGLowBeta.setValue(value)
536                                self.textEditDebugConsole.append("lowBeta: %i" % value)
537                       
538                        if ('highBeta' in packet['eegPower'].keys()):
539                                value = packet['eegPower']['highBeta']
540                                self.progressBarEEGHighBeta.setMaximum(self.maxEEGPower)
541                                self.progressBarEEGHighBeta.setValue(value)
542                                self.textEditDebugConsole.append("highBeta: %i" % value)
543                       
544                        if ('lowGamma' in packet['eegPower'].keys()):
545                                value = packet['eegPower']['lowGamma']
546                                self.progressBarEEGLowGamma.setMaximum(self.maxEEGPower)
547                                self.progressBarEEGLowGamma.setValue(value)
548                                self.textEditDebugConsole.append("lowGamma: %i" % value)
549                       
550                        if ('highGamma' in packet['eegPower'].keys()):
551                                value = packet['eegPower']['highGamma']
552                                self.progressBarEEGMidGamma.setMaximum(self.maxEEGPower)
553                                self.progressBarEEGMidGamma.setValue(value)
554                                self.textEditDebugConsole.append("highGamma: %i" % value)
555                       
556                       
557                        if MATPLOTLIB_AVAILABLE:
558                                self.chartEEGMatplot.update_values('eegPower', packet['eegPower'])
559                                if (self.tabWidget.currentIndex() == \
560                                    self.tabWidget.indexOf(self.tabCharts)):
561                                        self.chartEEGMatplot.update_figure('eegPower', packet['eegPower'])
562               
563               
564                if ((self.thinkGearConnectServer.protocol != None) and
565                    (self.tabWidget.currentIndex() == \
566                     self.tabWidget.indexOf(self.tabControlPanel))):
567                       
568                        self.updateProfileSessionStatus()
569       
570       
571        ##################################################################
572       
573        def updateProfileSessionStatus(self):
574               
575                session_time = self.calculateSessionTime()
576               
577                self.textLabelSessionTime.setText(session_time)
578               
579                self.textLabelPacketsReceived.setText( "%i" % \
580                        self.thinkGearConnectServer.protocol.packet_count)
581                self.textLabelPacketsDropped.setText( "%i" % \
582                        self.thinkGearConnectServer.protocol.bad_packets)
583       
584       
585        ##################################################################
586       
587        def calculateSessionTime(self):
588               
589                session_time = time.time() - \
590                        self.thinkGearConnectServer.protocol.session_start_timestamp
591               
592                session_time = int(session_time)
593               
594                session_time = self.convert_seconds_to_datetime(session_time)
595               
596                return(session_time)
597       
598       
599        ##################################################################
600       
601        def enumerateSerialPorts(self):
602               
603                """ Uses the Win32 registry to return an
604                iterator of serial (COM) ports
605                existing on this computer.
606               
607                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
608                """
609         
610                path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
611                try:
612                        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
613                except WindowsError:
614                        #raise IterationError
615                        return
616               
617                for i in itertools.count():
618                        try:
619                                val = winreg.EnumValue(key, i)
620                                yield str(val[1])
621                        except EnvironmentError:
622                                break
623       
624       
625        ##################################################################
626       
627        def fullPortName(self, portname):
628               
629                """ Given a port-name (of the form COM7,
630                COM12, CNCA0, etc.) returns a full
631                name suitable for opening with the
632                Serial class.
633                """
634               
635                m = re.match('^COM(\d+)$', portname)
636                if m and int(m.group(1)) < 10:
637                        return portname
638               
639                return '\\\\.\\' + portname
640       
641       
642        ##################################################################
643       
644        def searchForThinkGearDevices(self):
645               
646                #self.pushButtonBluetoothSearch.setText('Searching')
647               
648                mindset_devices = []
649               
650                if (sys.platform == 'win32'):
651                       
652                        for portname in self.enumerateSerialPorts():
653                               
654                                if portname not in mindset_devices:
655                                        #portname = self.fullPortName(portname)
656                                        mindset_devices.append(portname)
657               
658               
659                else:
660                       
661                        # Bluetooth module doesn't compile properly under Windows
662                       
663                        bluetooth_devices = []
664                       
665                        #bluetooth_devices = bluetooth.discover_devices( \
666                                                    #duration=5, \
667                                                    #flush_cache=True, \
668                                                    #lookup_names=True)
669                       
670                        command = '%s con' % PATH_TO_HCITOOL
671                       
672                        output = os.popen(command, 'r')
673                       
674                        for line in output.readlines():
675                                try:
676                                        address = line.split(' ')[2]
677                                except:
678                                        pass
679                                else:
680                                        bluetooth_devices.append(address)
681                       
682                        for address in bluetooth_devices:
683                                device_name = bluetooth.lookup_name(address)
684                                if ((device_name == 'MindSet') and \
685                                    (address not in mindset_devices)):
686                                        mindset_devices.append(address)
687                       
688                       
689                        if self.DEBUG:
690                                print "Bluetooth MindSet devices found:",
691                                print mindset_devices
692                       
693                       
694                        self.comboBoxDeviceSelect.clear()
695                       
696                        self.comboBoxDeviceSelect.addItem('MindSet Emulator')
697                       
698                        if os.path.exists('/dev/ttyUSB0'):
699                                self.comboBoxDeviceSelect.addItem('/dev/ttyUSB0')
700                        if os.path.exists('/dev/ttyUSB1'):
701                                self.comboBoxDeviceSelect.addItem('/dev/ttyUSB1')
702                        if os.path.exists('/dev/ttyUSB2'):
703                                self.comboBoxDeviceSelect.addItem('/dev/ttyUSB2')
704                        if os.path.exists('/dev/ttyUSB3'):
705                                self.comboBoxDeviceSelect.addItem('/dev/ttyUSB3')
706                        if os.path.exists('/dev/ttyUSB4'):
707                                self.comboBoxDeviceSelect.addItem('/dev/ttyUSB4')
708               
709               
710                for mindset_device in mindset_devices:
711                        self.comboBoxDeviceSelect.addItem(mindset_device)
712               
713               
714                #self.pushButtonBluetoothSearch.setText('Search')
715       
716       
717        ##################################################################
718       
719        def collectData(self):
720               
721                data = {}
722               
723                data['rawEeg'] = self.packets['rawEeg']
724                data['signals'] = self.packets['signals']
725               
726                data['sessionTime'] = self.calculateSessionTime()
727               
728                data['profileName'] = str(self.lineEditSessionProfile.text())
729               
730                return(data)
731       
732       
733        ##################################################################
734       
735        def saveData(self):
736               
737                data = self.collectData()
738               
739                #output_file = 'data.synapse'
740               
741                (date, localtime) = self.parseTimeStamp(time.time())
742               
743                default_filename = '%s %s.synapse' % (date, \
744                                      self.lineEditSessionProfile.text())
745               
746                output_file = QtGui.QFileDialog.getSaveFileName(self, \
747                                 "Save Synapse Data File", \
748                                 default_filename, \
749                                 "Synapse Data File (*.synapse)")
750               
751               
752                file = open(output_file, 'w')
753                pickle.dump(data, file)
754                file.close()
755       
756       
757        ##################################################################
758       
759        def exportData(self):
760               
761                #output_file = 'text.synapse'
762               
763                (date, localtime) = self.parseTimeStamp(time.time())
764               
765                default_filename = '%s %s.csv' % (date, \
766                                      self.lineEditSessionProfile.text())
767               
768                output_file = QtGui.QFileDialog.getSaveFileName(self, \
769                                 "Export Synapse Data to File", \
770                                 default_filename, \
771                                 "CSV File (*.csv);;Text File (*.txt)")
772               
773                print output_file
774               
775                if str(output_file).endswith('.csv'):
776                       
777                        outputData = self.exportDataToCSV()
778               
779               
780                else:
781                       
782                        outputData = self.textEditDebugConsole.toPlainText()
783                       
784                       
785                file = open(output_file, 'w')
786                file.write(outputData)
787                file.close()
788       
789       
790        ##################################################################
791       
792        def exportDataToCSV(self):
793               
794                header = 'Date,Time,Delta,Theta,Low Alpha,High Alpha,Low Beta,High Beta,Low Gamma,Mid Gamma,Attention,Meditation,Signal Level\n'
795               
796                csv = {}
797               
798                for packet in self.packets['signals']:
799                       
800                        if 'rawEeg' in packet.keys():
801                                continue
802                       
803                        if packet['timestamp'] not in csv.keys():
804                               
805                                print packet
806                                timestamp = packet['timestamp']
807                                (date, localtime) = self.parseTimeStamp(timestamp)
808                               
809                                csv[timestamp] = {}
810                                csv[timestamp]['Date'] = date
811                                csv[timestamp]['Time'] = localtime
812                                csv[timestamp]['Delta'] = ''
813                                csv[timestamp]['Theta'] = ''
814                                csv[timestamp]['Low Alpha'] = ''
815                                csv[timestamp]['High Alpha'] = ''
816                                csv[timestamp]['Low Beta'] = ''
817                                csv[timestamp]['High Beta'] = ''
818                                csv[timestamp]['Low Gamma'] = ''
819                                csv[timestamp]['Mid Gamma'] = ''
820                                csv[timestamp]['Attention'] = ''
821                                csv[timestamp]['Meditation'] = ''
822                                csv[timestamp]['Signal Level'] = ''
823                       
824                       
825                        if 'eSense' in packet.keys():
826                                if 'attention' in packet['eSense'].keys():
827                                        csv[timestamp]['Attention'] = packet['eSense']['attention']
828                                if 'meditation' in packet['eSense'].keys():
829                                        csv[timestamp]['Meditation'] = packet['eSense']['meditation']
830                       
831                        if 'eegPower' in packet.keys():
832                                if 'delta' in packet['eegPower'].keys():
833                                        csv[timestamp]['Delta'] = packet['eegPower']['delta']
834                                if 'theta' in packet['eegPower'].keys():
835                                        csv[timestamp]['Theta'] = packet['eegPower']['theta']
836                                if 'lowAlpha' in packet['eegPower'].keys():
837                                        csv[timestamp]['Low Alpha'] = packet['eegPower']['lowAlpha']
838                                if 'highAlpha' in packet['eegPower'].keys():
839                                        csv[timestamp]['High Alpha'] = packet['eegPower']['highAlpha']
840                                if 'lowBeta' in packet['eegPower'].keys():
841                                        csv[timestamp]['Low Beta'] = packet['eegPower']['lowBeta']
842                                if 'highBeta' in packet['eegPower'].keys():
843                                        csv[timestamp]['High Beta'] = packet['eegPower']['highBeta']
844                                if 'lowGamma' in packet['eegPower'].keys():
845                                        csv[timestamp]['Low Gamma'] = packet['eegPower']['lowGamma']
846                                if 'highGamma' in packet['eegPower'].keys():
847                                        csv[timestamp]['Mid Gamma'] = packet['eegPower']['highGamma']
848                       
849                        if 'poorSignalLevel' in packet.keys():
850                                csv[timestamp]['Signal Level'] = packet['poorSignalLevel']
851               
852               
853                output = header
854               
855                csv_keys = csv.keys()
856                csv_keys.sort()
857               
858                for key in csv_keys:
859                       
860                        row = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % \
861                              (csv[key]['Date'], \
862                               csv[key]['Time'], \
863                               csv[key]['Delta'], \
864                               csv[key]['Theta'], \
865                               csv[key]['Low Alpha'], \
866                               csv[key]['High Alpha'], \
867                               csv[key]['Low Beta'], \
868                               csv[key]['High Beta'], \
869                               csv[key]['Low Gamma'], \
870                               csv[key]['Mid Gamma'], \
871                               csv[key]['Attention'], \
872                               csv[key]['Meditation'], \
873                               csv[key]['Signal Level'])
874                       
875                       
876                        output = output + row
877               
878               
879                return(output)
880       
881       
882        ##################################################################
883       
884        def resetData(self):
885               
886                self.packets['rawEeg'] = []
887                self.packets['signals'] = []
888               
889                self.thinkGearConnectServer.protocol.session_start_timestamp = \
890                        time.time()
891               
892                self.thinkGearConnectServer.protocol.packet_count = 0
893                self.thinkGearConnectServer.protocol.bad_packets = 0
894               
895                self.updateProfileSessionStatus()
896               
897                self.textEditDebugConsole.setText("")
898       
899       
900        #####################################################################
901       
902        def convert_seconds_to_datetime(self, duration):
903               
904                duration_hours = duration / (60 * 60)
905                duration_minutes = (duration - (duration_hours * (60 * 60))) / 60
906                duration_seconds = (duration - (duration_hours * (60 * 60)) - (duration_minutes * 60))
907               
908                duration_hours = '%i' % duration_hours
909                if (len(duration_hours) == 1):
910                        duration_hours = "0%s" % duration_hours
911               
912                duration_minutes = '%i' % duration_minutes
913                if (len(duration_minutes) == 1):
914                        duration_minutes = "0%s" % duration_minutes
915               
916                duration_seconds = '%i' % duration_seconds
917                if (len(duration_seconds) == 1):
918                        duration_seconds = "0%s" % duration_seconds
919               
920                datetime = '%s:%s:%s' % (duration_hours, duration_minutes, duration_seconds)
921               
922                return(datetime)
923       
924       
925        ##################################################################
926       
927        def closeEvent(self, event):
928               
929                quit_message = "Are you sure you want to exit the program?"
930               
931                reply = QtGui.QMessageBox.question( \
932                           self, \
933                          'Message', \
934                           quit_message, \
935                           QtGui.QMessageBox.Yes, \
936                           QtGui.QMessageBox.No)
937               
938                if reply == QtGui.QMessageBox.Yes:
939                       
940                        if UPDATE_INTERFACE_VIA_TIMER:
941                                self.updateInterfaceTimer.stop()
942                        else:
943                                if self.thinkgearConnectClient != None:
944                                        self.thinkgearConnectClient.disconnectFromHost()
945                       
946                        if self.thinkGearConnectServer != None:
947                                self.thinkGearConnectServer.exitThread()
948                       
949                        event.accept()
950               
951                else:
952                        event.ignore()
Note: See TracBrowser for help on using the repository browser.