source: trunk/Puzzlebox/Synapse/ThinkGear/Server.py @ 393

Last change on this file since 393 was 393, checked in by sc, 8 years ago
  • updates for exporting ThinkGear? and Emotiv custom data headers
File size: 24.8 KB
Line 
1# -*- coding: utf-8 -*-
2
3# Copyright Puzzlebox Productions, LLC (2010-2012)
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__changelog__ = """\
9Last Update: 2012.05.11
10"""
11
12### IMPORTS ###
13
14import os, sys, time
15import math
16
17import simplejson as json
18
19import Puzzlebox.Synapse.Configuration as configuration
20
21if configuration.ENABLE_PYSIDE:
22        try:
23                import PySide as PyQt4
24                from PySide import QtCore, QtGui, QtNetwork
25        except Exception, e:
26                print "ERROR: Exception importing PySide:",
27                print e
28                configuration.ENABLE_PYSIDE = False
29        else:
30                print "INFO: [Synapse:ThinkGear:Server] Using PySide module"
31
32if not configuration.ENABLE_PYSIDE:
33        print "INFO: [Synapse:ThinkGear:Server] Using PyQt4 module"
34        from PyQt4 import QtCore, QtGui, QtNetwork
35
36import Puzzlebox.Synapse.Server as synapse_server
37import Puzzlebox.Synapse.ThinkGear.Protocol as thinkgear_protocol
38
39#####################################################################
40# Globals
41#####################################################################
42
43DEBUG = configuration.DEBUG
44
45COMMUNICATION_MODE = 'Emit Signal'
46#COMMUNICATION_MODE = 'Call Parent'
47
48SERVER_INTERFACE = configuration.THINKGEAR_SERVER_INTERFACE
49SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
50DEFAULT_DEVICE_MODEL = 'NeuroSky MindWave'
51THINKGEAR_DEVICE_SERIAL_PORT = configuration.THINKGEAR_DEVICE_SERIAL_PORT
52
53CLIENT_NO_REPLY_WAIT = configuration.CLIENT_NO_REPLY_WAIT * 1000
54
55FLASH_POLICY_FILE_REQUEST = configuration.FLASH_POLICY_FILE_REQUEST
56FLASH_SOCKET_POLICY_FILE = configuration.FLASH_SOCKET_POLICY_FILE
57
58DELIMITER = configuration.THINKGEAR_DELIMITER
59
60MESSAGE_FREQUENCY_TIMER = 1 * 1000 # 1 Hz (1000 ms)
61
62ENABLE_SIMULATE_HEADSET_DATA = configuration.THINKGEAR_ENABLE_SIMULATE_HEADSET_DATA
63
64BLINK_FREQUENCY_TIMER = configuration.THINKGEAR_BLINK_FREQUENCY_TIMER
65
66DEFAULT_SAMPLE_WAVELENGTH = configuration.THINKGEAR_DEFAULT_SAMPLE_WAVELENGTH
67
68THINKGEAR_EMULATION_MAX_ESENSE_VALUE = \
69        configuration.THINKGEAR_EMULATION_MAX_ESENSE_VALUE
70THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE = \
71        configuration.THINKGEAR_EMULATION_MAX_EEG_POWER_VALUE
72
73THINKGEAR_ATTENTION_MULTIPLIER = configuration.THINKGEAR_ATTENTION_MULTIPLIER
74THINKGEAR_MEDITATION_MULTIPLIER = configuration.THINKGEAR_MEDITATION_MULTIPLIER
75THINKGEAR_MEDITATION_PLOT_OFFSET = configuration.THINKGEAR_MEDITATION_PLOT_OFFSET
76
77THINKGEAR_EEG_POWER_MULTIPLIERS = configuration.THINKGEAR_EEG_POWER_MULTIPLIERS
78
79DEFAULT_AUTHORIZATION_MESSAGE = \
80        {"isAuthorized": True}
81                # Tells the client whether the server has authorized
82                # access to the user's headset data. The value is
83                # either true or false.
84
85DEFAULT_SIGNAL_LEVEL_MESSAGE = \
86        {"poorSignalLevel": 0}
87                # A quantifier of the quality of the brainwave signal.
88                # This is an integer value that is generally in the
89                # range of 0 to 200, with 0 indicating a
90                # good signal and 200 indicating an off-head state.
91
92DEFAULT_EEG_POWER_MESSAGE = \
93        {"eegPower": { \
94                'delta': 0, \
95                'theta': 0, \
96                'lowAlpha': 0, \
97                'highAlpha': 0, \
98                'lowBeta': 0, \
99                'highBeta': 0, \
100                'lowGamma': 0, \
101                'highGamma': 0, \
102                }, \
103        } # A container for the EEG powers. These may
104          # be either integer or floating-point values.
105          # Maximum values are undocumented but assumed to be 65535
106
107DEFAULT_ESENSE_MESSAGE = \
108        {"eSense": { \
109                'attention': 0, \
110                'meditation': 0, \
111                }, \
112        } # A container for the eSense™ attributes.
113          # These are integer values between 0 and 100,
114          # where 0 is perceived as a lack of that attribute
115          # and 100 is an excess of that attribute.
116
117DEFAULT_BLINK_MESSAGE = {"blinkStrength": 255}
118        # The strength of a detected blink. This is
119        # an integer in the range of 0-255.
120
121DEFAULT_RAWEEG_MESSAGE = {"rawEeg": 255}
122        # The raw data reading off the forehead sensor.
123        # This may be either an integer or a floating-point value.
124
125DEFAULT_PACKET = {}
126DEFAULT_PACKET.update(DEFAULT_EEG_POWER_MESSAGE)
127DEFAULT_PACKET.update(DEFAULT_SIGNAL_LEVEL_MESSAGE)
128DEFAULT_PACKET.update(DEFAULT_ESENSE_MESSAGE)
129
130DEFAULT_RESPONSE_MESSAGE = DEFAULT_SIGNAL_LEVEL_MESSAGE
131
132#PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD = 0.75
133
134#####################################################################
135# Classes
136#####################################################################
137
138class puzzlebox_synapse_server_thinkgear(synapse_server.puzzlebox_synapse_server):
139       
140        def __init__(self, log, \
141                          server_interface=SERVER_INTERFACE, \
142                          server_port=SERVER_PORT, \
143                          device_model=None, \
144                          device_address=THINKGEAR_DEVICE_SERIAL_PORT, \
145                          emulate_headset_data=ENABLE_SIMULATE_HEADSET_DATA, \
146                          DEBUG=DEBUG, \
147                          parent=None):
148               
149                QtCore.QThread.__init__(self,parent)
150               
151                self.log = log
152                self.DEBUG = DEBUG
153                self.parent = parent
154               
155                self.server_interface = server_interface
156                self.server_port = server_port
157                self.device_address = device_address
158                self.device_model = device_model
159                self.emulate_headset_data = emulate_headset_data
160               
161                self.name = 'Synapse:ThinkGear:Server'
162               
163                self.connection_timestamp = time.time()
164                self.session_start_timestamp = time.time()
165               
166                self.connections = []
167                self.packet_queue = []
168               
169                self.serial_device = None
170                self.protocol = None
171               
172                self.connect(self, \
173                             QtCore.SIGNAL("sendPacket()"), \
174                             self.sendPacketQueue)
175               
176                self.message_frequency_timer = MESSAGE_FREQUENCY_TIMER
177                self.blink_frequency_timer = BLINK_FREQUENCY_TIMER
178                self.blink_timestamp = time.time()
179               
180               
181                #self.customDataHeaders = 'Attention,Meditation,Signal Level,Delta,Theta,Low Alpha,High Alpha,Low Beta,High Beta,Low Gamma,Mid Gamma'
182                self.customDataHeaders = ['Attention', \
183                                          'Meditation', \
184                                          'Signal Level', \
185                                          'Delta', \
186                                          'Theta', \
187                                          'Low Alpha', \
188                                          'High Alpha', \
189                                          'Low Beta', \
190                                          'High Beta', \
191                                          'Low Gamma', \
192                                          'Mid Gamma', \
193                                         ]
194               
195               
196                self.configureEEG()
197               
198                self.configureNetwork()
199               
200               
201                if (self.emulate_headset_data):
202                        self.emulationTimer = QtCore.QTimer()
203                        QtCore.QObject.connect(self.emulationTimer, \
204                                                    QtCore.SIGNAL("timeout()"), \
205                                                    self.emulationEvent)
206                        self.emulationTimer.start(MESSAGE_FREQUENCY_TIMER)
207       
208       
209        ##################################################################
210       
211        def configureEEG(self):
212               
213                if not self.emulate_headset_data:
214                       
215                        self.serial_device = \
216                                thinkgear_protocol.SerialDevice( \
217                                        self.log, \
218                                        device_address=self.device_address, \
219                                        DEBUG=self.DEBUG, \
220                                        parent=self)
221                       
222                        self.serial_device.start()
223               
224                else:
225                        self.serial_device = None
226               
227               
228                self.protocol = \
229                        thinkgear_protocol.puzzlebox_synapse_protocol_thinkgear( \
230                                self.log, \
231                                self.serial_device, \
232                                device_model=self.device_model, \
233                                DEBUG=self.DEBUG, \
234                                parent=self)
235               
236                #self.plugin_session = self.parent.plugin_session # for Jigsaw compatability
237               
238                self.protocol.start()
239       
240       
241        ##################################################################
242       
243        def emulationEvent(self):
244               
245                self.updateStatus()
246               
247                if COMMUNICATION_MODE == 'Emit Signal':
248                        self.emitSendPacketSignal()
249                else:
250                        self.sendPacketQueue()
251       
252       
253        ##################################################################
254       
255        def processData(self, data):
256               
257                response = None
258               
259                # Special socket handling for Flash applications
260                if (data == FLASH_POLICY_FILE_REQUEST):
261                       
262                        response = FLASH_SOCKET_POLICY_FILE
263                       
264                        #self.packet_queue.insert(0, FLASH_SOCKET_POLICY_FILE)
265               
266               
267                elif (type(data) == type({}) and \
268                      data.has_key('appName') and \
269                      data.has_key('appKey')):
270                       
271                        authorized = self.authorizeClient(data)
272                       
273                        response = {}
274                        response['isAuthorized'] = authorized
275                       
276                        #self.packet_queue.insert(0, response)
277               
278               
279                return(response)
280       
281       
282        ##################################################################
283       
284        def validateChecksum(self, checksum):
285               
286                '''The key used by the client application to identify
287itself. This must be 40 hexadecimal characters, ideally generated
288using an SHA-1 digest. The appKey is an identifier that is unique
289to each application, rather than each instance of an application.
290It is used by the server to bypass the authorization process if a
291user had previously authorized the requesting client. To reduce
292the chance of overlap with the appKey of other applications,
293the appKey should be generated using an SHA-1 digest.'''
294               
295                is_valid = True
296               
297                hexadecimal_characters = '0123456789abcdef'
298               
299                if len(checksum) != 40:
300                        is_valid = False
301                else:
302                        for character in checksum:
303                                if character not in hexadecimal_characters:
304                                        is_valid = False
305               
306                return(is_valid)
307       
308       
309        ##################################################################
310       
311        def authorizeClient(self, data):
312       
313                '''The client must initiate an authorization request
314and the server must authorize the client before the
315server will start transmitting any headset data.'''
316               
317                is_authorized = self.validateChecksum(data['appKey'])
318               
319                # A human-readable name identifying the client
320                # application. This can be a maximum of 255 characters.
321               
322                if len(data['appName']) > 255:
323                        is_authorized = False
324               
325               
326                return(is_authorized)
327       
328       
329        ##################################################################
330       
331        def calculateWavePoint(self, x, max_height=100, wave_length=10):
332               
333                # start at 0, increase to max value at half of one
334                # wavelength, decrease to 0 by end of wavelength
335                y = ( (max_height/2) * \
336                      math.sin ((x-1) * ( math.pi / (wave_length / 2)))) + \
337                      (max_height/2)
338               
339                # start at max value, decrease to 0 at half of one
340                # wavelegnth, increase to max by end of wavelength
341                #y = ( (max_height/2) * \
342                      #math.cos (x * ( math.pi / (wave_length / 2)))) + \
343                      #(max_height/2)
344               
345               
346                return(y)
347       
348       
349        ##################################################################
350       
351        def simulateHeadsetData(self):
352               
353                response = DEFAULT_PACKET
354               
355                response['timestamp'] = time.time()
356               
357                time_value = self.connection_timestamp - time.time()
358               
359                for key in response.keys():
360                       
361                        if key == 'poorSignalLevel':
362                                pass
363                       
364                        elif key == 'eSense':
365                               
366                                plot_attention = self.calculateWavePoint( \
367                                        time_value, \
368                                        max_height=100, \
369                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
370                               
371                                plot_meditation = self.calculateWavePoint( \
372                                        time_value + THINKGEAR_MEDITATION_PLOT_OFFSET, \
373                                        max_height=100, \
374                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
375                               
376                                for each in response[key].keys():
377                                       
378                                        if ((each == 'attention') and \
379                                                 (THINKGEAR_ATTENTION_MULTIPLIER != None)):
380                                                value = plot_attention * \
381                                                   THINKGEAR_ATTENTION_MULTIPLIER
382                                       
383                                        elif ((each == 'meditation') and \
384                                                   (THINKGEAR_MEDITATION_MULTIPLIER != None)):
385                                                value = plot_meditation * \
386                                                   THINKGEAR_MEDITATION_MULTIPLIER
387                                       
388                                       
389                                        value = int(value)
390                                       
391                                       
392                                        if value < 0:
393                                                value = 0
394                                        elif value > 100:
395                                                value = 100
396                                       
397                                        response[key][each] = value
398                       
399                       
400                        elif key == 'eegPower':
401                                plot = self.calculateWavePoint( \
402                                        time_value, \
403                                        max_height=65535, \
404                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
405                               
406                                for each in response[key].keys():
407                                        if ((THINKGEAR_EEG_POWER_MULTIPLIERS != None) and \
408                                                 (each in THINKGEAR_EEG_POWER_MULTIPLIERS.keys())):
409                                                value = int(THINKGEAR_EEG_POWER_MULTIPLIERS[each] * plot)
410                                        else:
411                                                value = plot
412                                        response[key][each] = value
413               
414               
415                return(response)
416       
417       
418        ##################################################################
419       
420        def processPacketThinkGear(self, packet):
421               
422                if self.DEBUG > 2:
423                        print packet
424               
425                if (packet != {}):
426                        self.packet_queue.append(packet)
427                       
428                        if COMMUNICATION_MODE == 'Emit Signal':
429                                self.emitSendPacketSignal()
430                       
431                        else:
432                                self.sendPacketQueue()
433                               
434                                if (self.parent != None):
435                                        #self.parent.processPacketThinkGear(packet)
436                                        self.parent.processPacketEEG(packet)
437       
438       
439        ##################################################################
440       
441        def updateStatus(self):
442               
443                # Craft a simulated data packet
444                packet = self.simulateHeadsetData()
445               
446                self.packet_queue.append(packet)
447               
448                # Include simulated blinks at desired frequency
449                if ((self.blink_frequency_timer != None) and \
450                                (self.blink_frequency_timer > 0) and \
451                                (time.time() - self.blink_timestamp > \
452                                self.blink_frequency_timer)):
453                       
454                        self.blink_timestamp = time.time()
455                       
456                        packet = DEFAULT_BLINK_MESSAGE
457                       
458                        packet['timestamp'] = self.blink_timestamp
459                       
460                        self.packet_queue.append(packet)
461       
462       
463        ##################################################################
464       
465        #def updateSessionStartTime(self, session_start_timestamp):
466               
467                #if self.parent != None:
468                        #self.parent.updateSessionStartTime(session_start_timestamp)
469
470       
471        ##################################################################
472       
473        def resetDevice(self):
474               
475                if self.serial_device != None:
476                        self.serial_device.exitThread()
477               
478                if self.protocol != None:
479                        self.protocol.exitThread()
480               
481                self.configureEEG()
482       
483       
484        ##################################################################
485       
486        def processPacketForExport(self, packet={}, output={}):
487               
488                if 'blinkStrength' in packet.keys():
489                        # Skip any blink packets from log
490                        #continue
491                        return(output)
492               
493                #output['Attention'] = ''
494                #output['Meditation'] = ''
495                #output['Signal Level'] = ''
496                #output['Delta'] = ''
497                #output['Theta'] = ''
498                #output['Low Alpha'] = ''
499                #output['High Alpha'] = ''
500                #output['Low Beta'] = ''
501                #output['High Beta'] = ''
502                #output['Low Gamma'] = ''
503                #output['Mid Gamma'] = ''
504               
505                for header in self.customDataHeaders:
506                        output[header] = ''
507               
508                if 'eSense' in packet.keys():
509                        if 'attention' in packet['eSense'].keys():
510                                output['Attention'] = packet['eSense']['attention']
511                        if 'meditation' in packet['eSense'].keys():
512                                output['Meditation'] = packet['eSense']['meditation']
513               
514                if 'poorSignalLevel' in packet.keys():
515                        output['Signal Level'] = packet['poorSignalLevel']
516               
517                if 'eegPower' in packet.keys():
518                        if 'delta' in packet['eegPower'].keys():
519                                output['Delta'] = packet['eegPower']['delta']
520                        if 'theta' in packet['eegPower'].keys():
521                                output['Theta'] = packet['eegPower']['theta']
522                        if 'lowAlpha' in packet['eegPower'].keys():
523                                output['Low Alpha'] = packet['eegPower']['lowAlpha']
524                        if 'highAlpha' in packet['eegPower'].keys():
525                                output['High Alpha'] = packet['eegPower']['highAlpha']
526                        if 'lowBeta' in packet['eegPower'].keys():
527                                output['Low Beta'] = packet['eegPower']['lowBeta']
528                        if 'highBeta' in packet['eegPower'].keys():
529                                output['High Beta'] = packet['eegPower']['highBeta']
530                        if 'lowGamma' in packet['eegPower'].keys():
531                                output['Low Gamma'] = packet['eegPower']['lowGamma']
532                        if 'highGamma' in packet['eegPower'].keys():
533                                output['Mid Gamma'] = packet['eegPower']['highGamma']
534               
535               
536                return(output)
537       
538       
539        ##################################################################
540       
541        #def exportDataToCSV(self, parent=None, source=None, target=None):
542               
543                ## handle importing class from multiple sources
544                #if parent == None:
545                        #if self.parent == None:
546                                #parent = self
547                        #else:
548                                #parent = self.parent
549               
550                #if source == None:
551                        #if self.parent == None:
552                                #source = self
553                        #else:
554                                #source = self.parent
555               
556                #if target == None:
557                        #if self.parent == None:
558                                #target = self
559                        #else:
560                                #target = self.parent
561               
562                #try:
563                        #truncate_csv_timezone = target.configuration.EXPORT_CSV_TRUNCATE_TIMEZONE
564                #except:
565                        #truncate_csv_timezone = False
566               
567               
568                #if not self.emulate_headset_data:
569                        ## NOTE: no need to scrub emulated data
570                        #try:
571                                #scrub_data = target.configuration.EXPORT_CSV_SCRUB_DATA
572                        #except:
573                                #scrub_data = False
574                #else:
575                        #scrub_data = False
576               
577                ##headers = 'Date,Time'
578                #headers = 'Date,Time,Attention,Meditation,Signal Level,Delta,Theta,Low Alpha,High Alpha,Low Beta,High Beta,Low Gamma,Mid Gamma'
579                ##headers = self.customDataHeaders
580               
581                #customDataHeaders = []
582                #for header in parent.customDataHeaders:
583                        #customDataHeaders.append(header)
584                #for plugin in parent.activePlugins:
585                        #for header in plugin.customDataHeaders:
586                                #customDataHeaders.append(header)
587               
588                #for each in customDataHeaders:
589                        #headers = headers + ',%s' % each
590               
591                #headers = headers + '\n'
592               
593               
594                #csv = {}
595               
596                #for packet in source.packets['signals']:
597                       
598                       
599                        #if 'rawEeg' in packet.keys():
600                                #continue
601                       
602                        #if packet['timestamp'] not in csv.keys():
603                               
604                                #if 'blinkStrength' in packet.keys():
605                                        ## Skip any blink packets from log
606                                        #continue
607                               
608                               
609                                #timestamp = packet['timestamp']
610                                ##(date, localtime) = self.parseTimeStamp(timestamp, \
611                                                    ##truncate_time_zone=truncate_csv_timezone)
612                                #(date, localtime) = source.parseTimeStamp(timestamp, \
613                                                    #truncate_time_zone=truncate_csv_timezone)
614                               
615                                #csv[timestamp] = {}
616                                #csv[timestamp]['Date'] = date
617                                #csv[timestamp]['Time'] = localtime
618                                #csv[timestamp]['Attention'] = ''
619                                #csv[timestamp]['Meditation'] = ''
620                                #csv[timestamp]['Signal Level'] = ''
621                                #csv[timestamp]['Delta'] = ''
622                                #csv[timestamp]['Theta'] = ''
623                                #csv[timestamp]['Low Alpha'] = ''
624                                #csv[timestamp]['High Alpha'] = ''
625                                #csv[timestamp]['Low Beta'] = ''
626                                #csv[timestamp]['High Beta'] = ''
627                                #csv[timestamp]['Low Gamma'] = ''
628                                #csv[timestamp]['Mid Gamma'] = ''
629                               
630                                #for header in customDataHeaders:
631                                        #csv[timestamp][header] = ''
632                       
633                       
634                        #if 'eSense' in packet.keys():
635                                #if 'attention' in packet['eSense'].keys():
636                                        #csv[timestamp]['Attention'] = packet['eSense']['attention']
637                                #if 'meditation' in packet['eSense'].keys():
638                                        #csv[timestamp]['Meditation'] = packet['eSense']['meditation']
639                       
640                        #if 'poorSignalLevel' in packet.keys():
641                                #csv[timestamp]['Signal Level'] = packet['poorSignalLevel']
642                       
643                        #if 'eegPower' in packet.keys():
644                                #if 'delta' in packet['eegPower'].keys():
645                                        #csv[timestamp]['Delta'] = packet['eegPower']['delta']
646                                #if 'theta' in packet['eegPower'].keys():
647                                        #csv[timestamp]['Theta'] = packet['eegPower']['theta']
648                                #if 'lowAlpha' in packet['eegPower'].keys():
649                                        #csv[timestamp]['Low Alpha'] = packet['eegPower']['lowAlpha']
650                                #if 'highAlpha' in packet['eegPower'].keys():
651                                        #csv[timestamp]['High Alpha'] = packet['eegPower']['highAlpha']
652                                #if 'lowBeta' in packet['eegPower'].keys():
653                                        #csv[timestamp]['Low Beta'] = packet['eegPower']['lowBeta']
654                                #if 'highBeta' in packet['eegPower'].keys():
655                                        #csv[timestamp]['High Beta'] = packet['eegPower']['highBeta']
656                                #if 'lowGamma' in packet['eegPower'].keys():
657                                        #csv[timestamp]['Low Gamma'] = packet['eegPower']['lowGamma']
658                                #if 'highGamma' in packet['eegPower'].keys():
659                                        #csv[timestamp]['Mid Gamma'] = packet['eegPower']['highGamma']
660                       
661                        #for header in customDataHeaders:
662                                #if 'custom' in packet.keys() and \
663                                   #header in packet['custom'].keys():
664                                        #csv[timestamp][header] = packet['custom'][header]
665               
666               
667                #if scrub_data:
668                        #csv = self.scrubData(csv, truncate_csv_timezone, source=source)
669               
670               
671                #output = headers
672               
673                #csv_keys = csv.keys()
674                #csv_keys.sort()
675               
676                #for key in csv_keys:
677                       
678                        #row = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % \
679                              #(csv[key]['Date'], \
680                               #csv[key]['Time'], \
681                               #csv[key]['Attention'], \
682                               #csv[key]['Meditation'], \
683                               #csv[key]['Signal Level'], \
684                               #csv[key]['Delta'], \
685                               #csv[key]['Theta'], \
686                               #csv[key]['Low Alpha'], \
687                               #csv[key]['High Alpha'], \
688                               #csv[key]['Low Beta'], \
689                               #csv[key]['High Beta'], \
690                               #csv[key]['Low Gamma'], \
691                               #csv[key]['Mid Gamma'])
692                       
693                        #for header in customDataHeaders:
694                                #row = row + ',%s' % csv[key][header]
695                       
696                        #row = row + '\n'
697                       
698                        #output = output + row
699               
700               
701                #return(output)
702       
703       
704        ##################################################################
705       
706        #def scrubData(self, csv, truncate_csv_timezone=False, source=None):
707               
708                ## If there are missing packets, repeat a given packet once per missing
709                ## second until there is a gap between 1 and 2 seconds, in which case
710                ## produce a final duplicate packet at the mid-point between the packets
711               
712                #if self.DEBUG:
713                        #print "INFO: Scrubbing Data"
714               
715                #if source == None:
716                        #if self.parent == None:
717                                #source = self
718                        #else:
719                                #source = self.parent
720               
721                #last_time = None
722                #last_recorded_time = None
723               
724                #output = {}
725               
726                #csv_keys = csv.keys()
727                #csv_keys.sort()
728               
729                #for key in csv_keys:
730                       
731                        #timestamp = key
732
733                        #if csv[key]['Attention'] == '':
734                                #continue
735                       
736                        #if last_time == None:
737                                ## First entry in log
738                                #last_time = timestamp
739                                #last_recorded_time = timestamp
740                                #output[key] = csv[key]
741                                #continue
742                       
743                        #else:
744                               
745                                ##time_difference = timestamp - last_time
746                                #time_difference = timestamp - last_recorded_time
747                               
748                                #if (time_difference <= 1) and \
749                                   #(time_difference >= PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD):
750                                        ## Skip packets within the correct time threshold
751                                        #last_time = timestamp
752                                        #last_recorded_time = timestamp
753                                        #output[key] = csv[key]
754                                        #continue
755                               
756                                #else:
757                                       
758                                        #if self.DEBUG > 1:
759                                                #print "time_difference:",
760                                                #print time_difference
761                                                #print "timestamp:",
762                                                #print source.parseTimeStamp(timestamp)[-1].split(' ')[0]
763                                                #print "last_time:",
764                                                #print source.parseTimeStamp(last_time)[-1].split(' ')[0]
765                                                #print "last_recorded_time:",
766                                                #print source.parseTimeStamp(last_recorded_time)[-1].split(' ')[0]
767                                       
768                                       
769                                        #new_packet = csv[key].copy()
770                                       
771                                        #if time_difference >= 2:
772                                               
773                                                ###new_time = last_time + 1
774                                                ##new_time = last_recorded_time + 1
775                                               
776                                                #count = int(time_difference)
777                                                #while count >= 1:
778                                                        #new_packet = csv[key].copy()
779                                                        #new_time = last_recorded_time + 1
780                                                        #(date, formatted_new_time) = source.parseTimeStamp(new_time, \
781                                                         #truncate_time_zone=truncate_csv_timezone)
782                                                        #new_packet['Time'] = formatted_new_time
783                                                        #last_recorded_time = new_time
784                                                        #last_time = timestamp
785                                                        #output[new_time] = new_packet
786                                                        #count = count - 1
787                                                #continue
788                                               
789                                        #elif time_difference < PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD:
790                                                ## Spread out "bunched up" packets
791                                                ##new_time = last_time + 1
792                                                #new_time = last_recorded_time + 1
793                                       
794                                       
795                                        #elif (time_difference < 2) and (time_difference > 1):
796                                               
797                                                ##new_time = last_time + ((last_time - timestamp) / 2)
798                                                ##new_time = last_recorded_time + ((last_recorded_time - timestamp) / 2)
799                                                ##new_time = last_time + 1
800                                                #new_time = last_recorded_time + 1
801                                       
802                                       
803                                        #(date, formatted_new_time) = source.parseTimeStamp(new_time, \
804                                           #truncate_time_zone=truncate_csv_timezone)
805                                       
806                                        #new_packet['Time'] = formatted_new_time
807                                       
808                                        ##last_time = new_time
809                                        #last_recorded_time = new_time
810                                        #last_time = timestamp
811                                        #output[new_time] = new_packet
812                                       
813                                        #if self.DEBUG > 1:
814                                                #print "WARN: Scrubbing new packet:",
815                                                #print new_packet
816                                                #print
817               
818               
819                #return(output)
820       
821       
822        ##################################################################
823       
824        def setPacketCount(self, value):
825               
826                self.parent.setPacketCount(value)
827       
828       
829        ##################################################################
830       
831        def setBadPackets(self, value):
832               
833                self.parent.setBadPackets(value)
834       
835       
836        ##################################################################
837       
838        def incrementPacketCount(self):
839               
840                self.parent.incrementPacketCount()
841       
842       
843        ##################################################################
844       
845        def incrementBadPackets(self):
846               
847                self.parent.incrementBadPackets()
848       
849       
850        ##################################################################
851       
852        def resetSessionStartTime(self):
853               
854                self.parent.resetSessionStartTime()
855       
856       
857        ##################################################################
858       
859        #def run(self):
860               
861                #if self.DEBUG:
862                        #print "<---- [%s] Main thread running" % self.name
863               
864                #self.exec_()
865       
866       
867        ##################################################################
868       
869        def exitThread(self, callThreadQuit=True):
870               
871                if (self.emulate_headset_data):
872                        try:
873                                self.emulationTimer.stop()
874                        except Exception, e:
875                                if self.DEBUG:
876                                        print "ERROR: Exception when stopping emulation timer:",
877                                        print e
878               
879                # Calling exitThread() on protocol first seems to occassionally
880                # create the following error:
881                # RuntimeError: Internal C++ object (PySide.QtNetwork.QTcpSocket) already deleted.
882                # Segmentation fault
883                # ...when program is closed without pressing "Stop" button for EEG
884                #if self.protocol != None:
885                        #self.protocol.exitThread()
886               
887                # Call disconnect block in protocol first due to above error
888                self.protocol.disconnectHardware()
889               
890                if self.serial_device != None:
891                        self.serial_device.exitThread()
892               
893                if self.protocol != None:
894                        self.protocol.exitThread()
895               
896                self.socket.close()
897               
898                if callThreadQuit:
899                        QtCore.QThread.quit(self)
900               
901                if self.parent == None:
902                        sys.exit()
903       
904       
905        ##################################################################
906       
907        #def stop(self):
908               
909                #self.exitThread()
910
Note: See TracBrowser for help on using the repository browser.