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

Last change on this file since 389 was 389, checked in by sc, 9 years ago
  • work underway to shift session data management from Synapse:ThinkGear:Protocol to Synapse:Session
File size: 22.3 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.04.09
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
132PACKET_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               
183               
184                self.configureEEG()
185               
186                self.configureNetwork()
187               
188               
189                if (self.emulate_headset_data):
190                        self.emulationTimer = QtCore.QTimer()
191                        QtCore.QObject.connect(self.emulationTimer, \
192                                                    QtCore.SIGNAL("timeout()"), \
193                                                    self.emulationEvent)
194                        self.emulationTimer.start(MESSAGE_FREQUENCY_TIMER)
195       
196       
197        ##################################################################
198       
199        def configureEEG(self):
200               
201                if not self.emulate_headset_data:
202                       
203                        self.serial_device = \
204                                thinkgear_protocol.SerialDevice( \
205                                        self.log, \
206                                        device_address=self.device_address, \
207                                        DEBUG=self.DEBUG, \
208                                        parent=self)
209                       
210                        self.serial_device.start()
211               
212                else:
213                        self.serial_device = None
214               
215               
216                self.protocol = \
217                        thinkgear_protocol.puzzlebox_synapse_protocol_thinkgear( \
218                                self.log, \
219                                self.serial_device, \
220                                device_model=self.device_model, \
221                                DEBUG=self.DEBUG, \
222                                parent=self)
223               
224                #self.plugin_session = self.parent.plugin_session # for Jigsaw compatability
225               
226                self.protocol.start()
227       
228       
229        ##################################################################
230       
231        def emulationEvent(self):
232               
233                self.updateStatus()
234               
235                if COMMUNICATION_MODE == 'Emit Signal':
236                        self.emitSendPacketSignal()
237                else:
238                        self.sendPacketQueue()
239       
240       
241        ##################################################################
242       
243        def processData(self, data):
244               
245                response = None
246               
247                # Special socket handling for Flash applications
248                if (data == FLASH_POLICY_FILE_REQUEST):
249                       
250                        response = FLASH_SOCKET_POLICY_FILE
251                       
252                        #self.packet_queue.insert(0, FLASH_SOCKET_POLICY_FILE)
253               
254               
255                elif (type(data) == type({}) and \
256                      data.has_key('appName') and \
257                      data.has_key('appKey')):
258                       
259                        authorized = self.authorizeClient(data)
260                       
261                        response = {}
262                        response['isAuthorized'] = authorized
263                       
264                        #self.packet_queue.insert(0, response)
265               
266               
267                return(response)
268       
269       
270        ##################################################################
271       
272        def validateChecksum(self, checksum):
273               
274                '''The key used by the client application to identify
275itself. This must be 40 hexadecimal characters, ideally generated
276using an SHA-1 digest. The appKey is an identifier that is unique
277to each application, rather than each instance of an application.
278It is used by the server to bypass the authorization process if a
279user had previously authorized the requesting client. To reduce
280the chance of overlap with the appKey of other applications,
281the appKey should be generated using an SHA-1 digest.'''
282               
283                is_valid = True
284               
285                hexadecimal_characters = '0123456789abcdef'
286               
287                if len(checksum) != 40:
288                        is_valid = False
289                else:
290                        for character in checksum:
291                                if character not in hexadecimal_characters:
292                                        is_valid = False
293               
294                return(is_valid)
295       
296       
297        ##################################################################
298       
299        def authorizeClient(self, data):
300       
301                '''The client must initiate an authorization request
302and the server must authorize the client before the
303server will start transmitting any headset data.'''
304               
305                is_authorized = self.validateChecksum(data['appKey'])
306               
307                # A human-readable name identifying the client
308                # application. This can be a maximum of 255 characters.
309               
310                if len(data['appName']) > 255:
311                        is_authorized = False
312               
313               
314                return(is_authorized)
315       
316       
317        ##################################################################
318       
319        def calculateWavePoint(self, x, max_height=100, wave_length=10):
320               
321                # start at 0, increase to max value at half of one
322                # wavelength, decrease to 0 by end of wavelength
323                y = ( (max_height/2) * \
324                      math.sin ((x-1) * ( math.pi / (wave_length / 2)))) + \
325                      (max_height/2)
326               
327                # start at max value, decrease to 0 at half of one
328                # wavelegnth, increase to max by end of wavelength
329                #y = ( (max_height/2) * \
330                      #math.cos (x * ( math.pi / (wave_length / 2)))) + \
331                      #(max_height/2)
332               
333               
334                return(y)
335       
336       
337        ##################################################################
338       
339        def simulateHeadsetData(self):
340               
341                response = DEFAULT_PACKET
342               
343                response['timestamp'] = time.time()
344               
345                time_value = self.connection_timestamp - time.time()
346               
347                for key in response.keys():
348                       
349                        if key == 'poorSignalLevel':
350                                pass
351                       
352                        elif key == 'eSense':
353                               
354                                plot_attention = self.calculateWavePoint( \
355                                        time_value, \
356                                        max_height=100, \
357                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
358                               
359                                plot_meditation = self.calculateWavePoint( \
360                                        time_value + THINKGEAR_MEDITATION_PLOT_OFFSET, \
361                                        max_height=100, \
362                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
363                               
364                                for each in response[key].keys():
365                                       
366                                        if ((each == 'attention') and \
367                                                 (THINKGEAR_ATTENTION_MULTIPLIER != None)):
368                                                value = plot_attention * \
369                                                   THINKGEAR_ATTENTION_MULTIPLIER
370                                       
371                                        elif ((each == 'meditation') and \
372                                                   (THINKGEAR_MEDITATION_MULTIPLIER != None)):
373                                                value = plot_meditation * \
374                                                   THINKGEAR_MEDITATION_MULTIPLIER
375                                       
376                                       
377                                        value = int(value)
378                                       
379                                       
380                                        if value < 0:
381                                                value = 0
382                                        elif value > 100:
383                                                value = 100
384                                       
385                                        response[key][each] = value
386                       
387                       
388                        elif key == 'eegPower':
389                                plot = self.calculateWavePoint( \
390                                        time_value, \
391                                        max_height=65535, \
392                                        wave_length=DEFAULT_SAMPLE_WAVELENGTH)
393                               
394                                for each in response[key].keys():
395                                        if ((THINKGEAR_EEG_POWER_MULTIPLIERS != None) and \
396                                                 (each in THINKGEAR_EEG_POWER_MULTIPLIERS.keys())):
397                                                value = THINKGEAR_EEG_POWER_MULTIPLIERS[each] * plot
398                                        else:
399                                                value = plot
400                                        response[key][each] = value
401               
402               
403                return(response)
404       
405       
406        ##################################################################
407       
408        def processPacketThinkGear(self, packet):
409               
410                if self.DEBUG > 2:
411                        print packet
412               
413                if (packet != {}):
414                        self.packet_queue.append(packet)
415                       
416                        if COMMUNICATION_MODE == 'Emit Signal':
417                                self.emitSendPacketSignal()
418                       
419                        else:
420                                self.sendPacketQueue()
421                               
422                                if (self.parent != None):
423                                        #self.parent.processPacketThinkGear(packet)
424                                        self.parent.processPacketEEG(packet)
425       
426       
427        ##################################################################
428       
429        def updateStatus(self):
430               
431                # Craft a simulated data packet
432                packet = self.simulateHeadsetData()
433               
434                self.packet_queue.append(packet)
435               
436                # Include simulated blinks at desired frequency
437                if ((self.blink_frequency_timer != None) and \
438                                (self.blink_frequency_timer > 0) and \
439                                (time.time() - self.blink_timestamp > \
440                                self.blink_frequency_timer)):
441                       
442                        self.blink_timestamp = time.time()
443                       
444                        packet = DEFAULT_BLINK_MESSAGE
445                       
446                        packet['timestamp'] = self.blink_timestamp
447                       
448                        self.packet_queue.append(packet)
449       
450       
451        ##################################################################
452       
453        #def updateSessionStartTime(self, session_start_timestamp):
454               
455                #if self.parent != None:
456                        #self.parent.updateSessionStartTime(session_start_timestamp)
457
458       
459        ##################################################################
460       
461        def resetDevice(self):
462               
463                if self.serial_device != None:
464                        self.serial_device.exitThread()
465               
466                if self.protocol != None:
467                        self.protocol.exitThread()
468               
469                self.configureEEG()
470       
471       
472        ##################################################################
473       
474        def exportDataToCSV(self, parent=None, source=None, target=None):
475               
476                # handle importing class from multiple sources
477                if parent == None:
478                        if self.parent == None:
479                                parent = self
480                        else:
481                                parent = self.parent
482               
483                if source == None:
484                        if self.parent == None:
485                                source = self
486                        else:
487                                source = self.parent
488               
489                if target == None:
490                        if self.parent == None:
491                                target = self
492                        else:
493                                target = self.parent
494               
495                try:
496                        truncate_csv_timezone = target.configuration.EXPORT_CSV_TRUNCATE_TIMEZONE
497                except:
498                        truncate_csv_timezone = False
499               
500               
501                if not self.emulate_headset_data:
502                        # NOTE: no need to scrub emulated data
503                        try:
504                                scrub_data = target.configuration.EXPORT_CSV_SCRUB_DATA
505                        except:
506                                scrub_data = False
507                else:
508                        scrub_data = False
509               
510                #headers = 'Date,Time'
511                headers = 'Date,Time,Attention,Meditation,Signal Level,Delta,Theta,Low Alpha,High Alpha,Low Beta,High Beta,Low Gamma,Mid Gamma'
512                #headers = self.customDataHeaders
513               
514                customDataHeaders = []
515                for header in parent.customDataHeaders:
516                        customDataHeaders.append(header)
517                for plugin in parent.activePlugins:
518                        for header in plugin.customDataHeaders:
519                                customDataHeaders.append(header)
520               
521                for each in customDataHeaders:
522                        headers = headers + ',%s' % each
523               
524                headers = headers + '\n'
525               
526               
527                csv = {}
528               
529                for packet in source.packets['signals']:
530                       
531                       
532                        if 'rawEeg' in packet.keys():
533                                continue
534                       
535                        if packet['timestamp'] not in csv.keys():
536                               
537                                if 'blinkStrength' in packet.keys():
538                                        # Skip any blink packets from log
539                                        continue
540                               
541                               
542                                timestamp = packet['timestamp']
543                                #(date, localtime) = self.parseTimeStamp(timestamp, \
544                                                    #truncate_time_zone=truncate_csv_timezone)
545                                (date, localtime) = source.parseTimeStamp(timestamp, \
546                                                    truncate_time_zone=truncate_csv_timezone)
547                               
548                                csv[timestamp] = {}
549                                csv[timestamp]['Date'] = date
550                                csv[timestamp]['Time'] = localtime
551                                csv[timestamp]['Attention'] = ''
552                                csv[timestamp]['Meditation'] = ''
553                                csv[timestamp]['Signal Level'] = ''
554                                csv[timestamp]['Delta'] = ''
555                                csv[timestamp]['Theta'] = ''
556                                csv[timestamp]['Low Alpha'] = ''
557                                csv[timestamp]['High Alpha'] = ''
558                                csv[timestamp]['Low Beta'] = ''
559                                csv[timestamp]['High Beta'] = ''
560                                csv[timestamp]['Low Gamma'] = ''
561                                csv[timestamp]['Mid Gamma'] = ''
562                               
563                                for header in customDataHeaders:
564                                        csv[timestamp][header] = ''
565                       
566                       
567                        if 'eSense' in packet.keys():
568                                if 'attention' in packet['eSense'].keys():
569                                        csv[timestamp]['Attention'] = packet['eSense']['attention']
570                                if 'meditation' in packet['eSense'].keys():
571                                        csv[timestamp]['Meditation'] = packet['eSense']['meditation']
572                       
573                        if 'poorSignalLevel' in packet.keys():
574                                csv[timestamp]['Signal Level'] = packet['poorSignalLevel']
575                       
576                        if 'eegPower' in packet.keys():
577                                if 'delta' in packet['eegPower'].keys():
578                                        csv[timestamp]['Delta'] = packet['eegPower']['delta']
579                                if 'theta' in packet['eegPower'].keys():
580                                        csv[timestamp]['Theta'] = packet['eegPower']['theta']
581                                if 'lowAlpha' in packet['eegPower'].keys():
582                                        csv[timestamp]['Low Alpha'] = packet['eegPower']['lowAlpha']
583                                if 'highAlpha' in packet['eegPower'].keys():
584                                        csv[timestamp]['High Alpha'] = packet['eegPower']['highAlpha']
585                                if 'lowBeta' in packet['eegPower'].keys():
586                                        csv[timestamp]['Low Beta'] = packet['eegPower']['lowBeta']
587                                if 'highBeta' in packet['eegPower'].keys():
588                                        csv[timestamp]['High Beta'] = packet['eegPower']['highBeta']
589                                if 'lowGamma' in packet['eegPower'].keys():
590                                        csv[timestamp]['Low Gamma'] = packet['eegPower']['lowGamma']
591                                if 'highGamma' in packet['eegPower'].keys():
592                                        csv[timestamp]['Mid Gamma'] = packet['eegPower']['highGamma']
593                       
594                        for header in customDataHeaders:
595                                if 'custom' in packet.keys() and \
596                                   header in packet['custom'].keys():
597                                        csv[timestamp][header] = packet['custom'][header]
598               
599               
600                if scrub_data:
601                        csv = self.scrubData(csv, truncate_csv_timezone, source=source)
602               
603               
604                output = headers
605               
606                csv_keys = csv.keys()
607                csv_keys.sort()
608               
609                for key in csv_keys:
610                       
611                        row = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % \
612                              (csv[key]['Date'], \
613                               csv[key]['Time'], \
614                               csv[key]['Attention'], \
615                               csv[key]['Meditation'], \
616                               csv[key]['Signal Level'], \
617                               csv[key]['Delta'], \
618                               csv[key]['Theta'], \
619                               csv[key]['Low Alpha'], \
620                               csv[key]['High Alpha'], \
621                               csv[key]['Low Beta'], \
622                               csv[key]['High Beta'], \
623                               csv[key]['Low Gamma'], \
624                               csv[key]['Mid Gamma'])
625                       
626                        for header in customDataHeaders:
627                                row = row + ',%s' % csv[key][header]
628                       
629                        row = row + '\n'
630                       
631                        output = output + row
632               
633               
634                return(output)
635       
636       
637        ##################################################################
638       
639        def scrubData(self, csv, truncate_csv_timezone=False, source=None):
640               
641                # If there are missing packets, repeat a given packet once per missing
642                # second until there is a gap between 1 and 2 seconds, in which case
643                # produce a final duplicate packet at the mid-point between the packets
644               
645                if self.DEBUG:
646                        print "INFO: Scrubbing Data"
647               
648                if source == None:
649                        if self.parent == None:
650                                source = self
651                        else:
652                                source = self.parent
653               
654                last_time = None
655                last_recorded_time = None
656               
657                output = {}
658               
659                csv_keys = csv.keys()
660                csv_keys.sort()
661               
662                for key in csv_keys:
663                       
664                        timestamp = key
665
666                        if csv[key]['Attention'] == '':
667                                continue
668                       
669                        if last_time == None:
670                                # First entry in log
671                                last_time = timestamp
672                                last_recorded_time = timestamp
673                                output[key] = csv[key]
674                                continue
675                       
676                        else:
677                               
678                                #time_difference = timestamp - last_time
679                                time_difference = timestamp - last_recorded_time
680                               
681                                if (time_difference <= 1) and \
682                                   (time_difference >= PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD):
683                                        # Skip packets within the correct time threshold
684                                        last_time = timestamp
685                                        last_recorded_time = timestamp
686                                        output[key] = csv[key]
687                                        continue
688                               
689                                else:
690                                       
691                                        if self.DEBUG > 1:
692                                                print "time_difference:",
693                                                print time_difference
694                                                print "timestamp:",
695                                                print source.parseTimeStamp(timestamp)[-1].split(' ')[0]
696                                                print "last_time:",
697                                                print source.parseTimeStamp(last_time)[-1].split(' ')[0]
698                                                print "last_recorded_time:",
699                                                print source.parseTimeStamp(last_recorded_time)[-1].split(' ')[0]
700                                       
701                                       
702                                        new_packet = csv[key].copy()
703                                       
704                                        if time_difference >= 2:
705                                               
706                                                ##new_time = last_time + 1
707                                                #new_time = last_recorded_time + 1
708                                               
709                                                count = int(time_difference)
710                                                while count >= 1:
711                                                        new_packet = csv[key].copy()
712                                                        new_time = last_recorded_time + 1
713                                                        (date, formatted_new_time) = source.parseTimeStamp(new_time, \
714                                                         truncate_time_zone=truncate_csv_timezone)
715                                                        new_packet['Time'] = formatted_new_time
716                                                        last_recorded_time = new_time
717                                                        last_time = timestamp
718                                                        output[new_time] = new_packet
719                                                        count = count - 1
720                                                continue
721                                               
722                                        elif time_difference < PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD:
723                                                # Spread out "bunched up" packets
724                                                #new_time = last_time + 1
725                                                new_time = last_recorded_time + 1
726                                       
727                                       
728                                        elif (time_difference < 2) and (time_difference > 1):
729                                               
730                                                #new_time = last_time + ((last_time - timestamp) / 2)
731                                                #new_time = last_recorded_time + ((last_recorded_time - timestamp) / 2)
732                                                #new_time = last_time + 1
733                                                new_time = last_recorded_time + 1
734                                       
735                                       
736                                        (date, formatted_new_time) = source.parseTimeStamp(new_time, \
737                                           truncate_time_zone=truncate_csv_timezone)
738                                       
739                                        new_packet['Time'] = formatted_new_time
740                                       
741                                        #last_time = new_time
742                                        last_recorded_time = new_time
743                                        last_time = timestamp
744                                        output[new_time] = new_packet
745                                       
746                                        if self.DEBUG > 1:
747                                                print "WARN: Scrubbing new packet:",
748                                                print new_packet
749                                                print
750               
751               
752                return(output)
753       
754       
755        ##################################################################
756       
757        def setPacketCount(self, value):
758               
759                self.parent.setPacketCount(value)
760       
761       
762        ##################################################################
763       
764        def setBadPackets(self, value):
765               
766                self.parent.setBadPackets(value)
767       
768       
769        ##################################################################
770       
771        def incrementPacketCount(self):
772               
773                self.parent.incrementPacketCount()
774       
775       
776        ##################################################################
777       
778        def incrementBadPackets(self):
779               
780                self.parent.incrementBadPackets()
781       
782       
783        ##################################################################
784       
785        def resetSessionStartTime(self):
786               
787                self.parent.resetSessionStartTime()
788       
789       
790        ##################################################################
791       
792        #def run(self):
793               
794                #if self.DEBUG:
795                        #print "<---- [%s] Main thread running" % self.name
796               
797                #self.exec_()
798       
799       
800        ##################################################################
801       
802        def exitThread(self, callThreadQuit=True):
803               
804                if (self.emulate_headset_data):
805                        try:
806                                self.emulationTimer.stop()
807                        except Exception, e:
808                                if self.DEBUG:
809                                        print "ERROR: Exception when stopping emulation timer:",
810                                        print e
811               
812                # Calling exitThread() on protocol first seems to occassionally
813                # create the following error:
814                # RuntimeError: Internal C++ object (PySide.QtNetwork.QTcpSocket) already deleted.
815                # Segmentation fault
816                # ...when program is closed without pressing "Stop" button for EEG
817                #if self.protocol != None:
818                        #self.protocol.exitThread()
819               
820                # Call disconnect block in protocol first due to above error
821                self.protocol.disconnectHardware()
822               
823                if self.serial_device != None:
824                        self.serial_device.exitThread()
825               
826                if self.protocol != None:
827                        self.protocol.exitThread()
828               
829                self.socket.close()
830               
831                if callThreadQuit:
832                        QtCore.QThread.quit(self)
833               
834                if self.parent == None:
835                        sys.exit()
836       
837       
838        ##################################################################
839       
840        #def stop(self):
841               
842                #self.exitThread()
843
Note: See TracBrowser for help on using the repository browser.