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

Last change on this file since 223 was 223, checked in by sc, 10 years ago

synapse/Puzzlebox/Synapse/Interface.py:

  • removed unecessary debug output

synapse/Puzzlebox/Synapse/Server.py:

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