source: trunk/Puzzlebox/Synapse/Session.py @ 374

Last change on this file since 374 was 374, checked in by sc, 8 years ago
  • reset session time issue fixed
File size: 16.9 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.01
10"""
11
12__todo__ = """
13"""
14
15### IMPORTS ###
16import os, sys, time
17
18import Puzzlebox.Synapse.Configuration as configuration
19
20if configuration.ENABLE_PYSIDE:
21        try:
22                import PySide as PyQt4
23                from PySide import QtCore, QtGui
24        except Exception, e:
25                print "ERROR: [Synapse:Session] Exception importing PySide:",
26                print e
27                configuration.ENABLE_PYSIDE = False
28        else:
29                print "INFO: [Synapse:Session] Using PySide module"
30
31if not configuration.ENABLE_PYSIDE:
32        print "INFO: [Synapse:Session] Using PyQt4 module"
33        from PyQt4 import QtCore, QtGui
34
35
36try:
37        import cPickle as pickle
38except:
39        import pickle
40
41
42#####################################################################
43# Globals
44#####################################################################
45
46DEBUG = configuration.DEBUG
47
48
49#####################################################################
50# Classes
51#####################################################################
52
53class puzzlebox_synapse_session(QtGui.QWidget):
54       
55        def __init__(self, log, \
56                     DEBUG=DEBUG, \
57                     parent=None, \
58                     ):
59               
60                self.log = log
61                self.DEBUG = DEBUG
62                self.parent=parent
63               
64                if self.parent == None:
65                        QtGui.QWidget.__init__(self, parent)
66                        #self.setupUi(self)
67               
68                        self.configureSettings()
69                        self.connectWidgets()
70               
71                self.name = "Synapse:Session"
72               
73               
74                if (sys.platform == 'win32'):
75                        self.homepath = os.path.join( \
76                           os.environ['HOMEDRIVE'], \
77                           os.environ['HOMEPATH'], \
78                           'Desktop')
79                elif (sys.platform == 'darwin'):
80                        desktop = os.path.join(os.environ['HOME'], 'Documents')
81                        if os.path.exists(desktop):
82                                self.homepath = desktop
83                        else:
84                                self.homepath = os.environ['HOME']
85                else:
86                        desktop = os.path.join(os.environ['HOME'], 'Desktop')
87                        if os.path.exists(desktop):
88                                self.homepath = desktop
89                        else:
90                                self.homepath = os.environ['HOME']
91               
92               
93                if not os.path.exists(self.homepath):
94                        if self.DEBUG:
95                                print "DEBUG: User default path not found"
96                        self.homepath = os.getcwd()
97       
98       
99        ##################################################################
100       
101        def configureSettings(self):
102               
103                pass
104       
105       
106        ##################################################################
107       
108        def connectWidgets(self):
109               
110                pass
111       
112       
113        ##################################################################
114       
115        def updateProfileSessionStatus(self, source=None, target=None):
116               
117                session_time = self.calculateSessionTime()
118               
119                if source == None:
120                        if self.parent == None:
121                                source = self
122                        else:
123                                source = self.parent
124               
125                if target == None:
126                        if self.parent == None:
127                                target = self
128                        else:
129                                target = self.parent
130               
131                target.textLabelSessionTime.setText(session_time)
132               
133                try:
134                        target.textLabelPacketsReceived.setText( "%i" % \
135                                source.synapseServer.protocol.packet_count)
136                except:
137                        pass
138               
139                try:
140                        target.textLabelPacketsDropped.setText( "%i" % \
141                                source.synapseServer.protocol.bad_packets)
142                except:
143                        pass
144       
145       
146        ##################################################################
147       
148        def calculateSessionTime(self):
149               
150                if self.parent == None:
151                        server = self.synapseServer
152                else:
153                        server = self.parent.synapseServer
154               
155                session_time = time.time() - \
156                        server.session_start_timestamp
157                        #server.protocol.session_start_timestamp
158               
159                session_time = int(session_time)
160               
161                session_time = self.convert_seconds_to_datetime(session_time)
162               
163                return(session_time)
164       
165       
166        ##################################################################
167       
168        def collectData(self, source=None, target=None):
169               
170                if source == None:
171                        if self.parent == None:
172                                source = self
173                        else:
174                                source = self.parent
175               
176                if target == None:
177                        if self.parent == None:
178                                target = self
179                        else:
180                                target = self.parent
181               
182                data = {}
183               
184                data['rawEeg'] = source.packets['rawEeg']
185                data['signals'] = source.packets['signals']
186               
187                data['sessionTime'] = self.calculateSessionTime()
188               
189                data['profileName'] = str(target.lineEditSessionProfile.text())
190               
191                return(data)
192       
193       
194        ##################################################################
195       
196        def parseTimeStamp(self, timestamp, local_version=False, truncate_time_zone=False):
197               
198                try:
199                        decimal = '%f' % timestamp
200                        decimal = decimal.split('.')[1]
201                except:
202                        decimal = '0'
203               
204                localtime = time.localtime(timestamp)
205               
206                if local_version:
207                        date = time.strftime('%x', localtime)
208                        localtime = time.strftime('%X', localtime)
209               
210                elif truncate_time_zone:
211                        date = time.strftime('%Y-%m-%d', localtime)
212                        localtime = time.strftime('%H:%M:%S', localtime)
213                        localtime = '%s.%s' % (localtime, decimal[:3])
214               
215                else:
216                        date = time.strftime('%Y-%m-%d', localtime)
217                        localtime = time.strftime('%H:%M:%S', localtime)
218                        localtime = '%s.%s %s' % (localtime, decimal, \
219                                       time.strftime('%Z', time.localtime(timestamp)))
220               
221               
222                return(date, localtime)
223       
224       
225        ##################################################################
226       
227        def saveData(self, source=None, target=None, output_file=None, use_default=False):
228               
229                if source == None:
230                        if self.parent == None:
231                                source = self
232                        else:
233                                source = self.parent
234               
235                if target == None:
236                        if self.parent == None:
237                                target = self
238                        else:
239                                target = self.parent
240               
241                data = self.collectData(source=source, target=target)
242               
243                (date, localtime) = self.parseTimeStamp(time.time())
244               
245                default_filename = '%s %s.synapse' % (date, \
246                                      target.lineEditSessionProfile.text())
247                                     
248                default_filename = os.path.join(self.homepath, default_filename)
249               
250                if output_file == None:
251                       
252                        # use_default controls whether or not a file is automatically saves using the
253                        # default name and path (as opposed to raising a GUI file selection menu)
254                        # whenever an explicit filepath is not defined
255                        if use_default:
256                                       
257                                        output_file = default_filename
258                       
259                        else:
260                       
261                                output_file = QtGui.QFileDialog.getSaveFileName(parent=target, \
262                                                 caption="Save Session Data to File", \
263                                                 dir=default_filename, \
264                                                 filter="Puzzlebox Synapse Data File (*.synapse)")
265                               
266                                try:
267                                        output_file = output_file[0]
268                                except:
269                                        output_file = ''
270               
271               
272                if output_file == '':
273                        return
274               
275                file = open(str(output_file), 'w')
276                pickle.dump(data, file)
277                file.close()
278       
279       
280        ##################################################################
281       
282        def exportData(self, parent=None, source=None, target=None, output_file=None, use_default=False):
283               
284                if parent == None:
285                        if self.parent == None:
286                                parent = self
287                        else:
288                                parent = self.parent
289               
290                if source == None:
291                        if self.parent == None:
292                                source = self
293                        else:
294                                source = self.parent
295               
296                if target == None:
297                        if self.parent == None:
298                                target = self
299                        else:
300                                target = self.parent
301               
302               
303                (date, localtime) = self.parseTimeStamp(time.time())
304               
305                default_filename = '%s %s.csv' % (date, \
306                                      target.lineEditSessionProfile.text())
307               
308                default_filename = os.path.join(target.homepath, default_filename)
309               
310               
311                if output_file == None:
312                       
313                        # use_default controls whether or not a file is automatically saves using the
314                        # default name and path (as opposed to raising a GUI file selection menu)
315                        # whenever an explicit filepath is not defined
316                        if use_default:
317                                       
318                                        output_file = default_filename
319                       
320                        else:
321                                output_file = QtGui.QFileDialog.getSaveFileName(parent=target, \
322                                                 caption="Export Session Data to File", \
323                                                 dir=default_filename, \
324                                                 filter="CSV File (*.csv);;Text File (*.txt)")
325                               
326                                try:
327                                        output_file = output_file[0]
328                                except:
329                                        output_file = ''
330               
331               
332                if output_file == '':
333                        return
334               
335               
336                if str(output_file).endswith('.csv'):
337                       
338                        outputData = self.exportDataToCSV(parent=parent, source=source, target=target)
339               
340               
341                else:
342                       
343                        try:
344                                outputData = self.textEditDebugConsole.toPlainText()
345                        except:
346                                outputData = self.exportDataToCSV()
347               
348               
349                file = open(str(output_file), 'w')
350                file.write(outputData)
351                file.close()
352       
353       
354        ##################################################################
355       
356        def exportDataToCSV(self, parent=None, source=None, target=None):
357               
358                if parent == None:
359                        if self.parent == None:
360                                parent = self
361                        else:
362                                parent = self.parent
363               
364                if source == None:
365                        if self.parent == None:
366                                source = self
367                        else:
368                                source = self.parent
369               
370                if target == None:
371                        if self.parent == None:
372                                target = self
373                        else:
374                                target = self.parent
375               
376                try:
377                        truncate_csv_timezone = target.configuration.EXPORT_CSV_TRUNCATE_TIMEZONE
378                except:
379                        truncate_csv_timezone = False
380               
381                try:
382                        scrub_data = target.configuration.EXPORT_CSV_SCRUB_DATA
383                except:
384                        scrub_data = False
385               
386               
387                headers = 'Date,Time,Attention,Meditation,Signal Level,Delta,Theta,Low Alpha,High Alpha,Low Beta,High Beta,Low Gamma,Mid Gamma'
388               
389                customDataHeaders = []
390                for header in parent.customDataHeaders:
391                        customDataHeaders.append(header)
392                for plugin in parent.activePlugins:
393                        for header in plugin.customDataHeaders:
394                                customDataHeaders.append(header)
395               
396                for each in customDataHeaders:
397                        headers = headers + ',%s' % each
398               
399                headers = headers + '\n'
400               
401                csv = {}
402               
403                for packet in source.packets['signals']:
404                       
405                       
406                        if 'rawEeg' in packet.keys():
407                                continue
408                       
409                        if packet['timestamp'] not in csv.keys():
410                               
411                                if 'blinkStrength' in packet.keys():
412                                        # Skip any blink packets from log
413                                        continue
414                               
415                               
416                                #print packet
417                                timestamp = packet['timestamp']
418                                (date, localtime) = self.parseTimeStamp(timestamp, \
419                                                    truncate_time_zone=truncate_csv_timezone)
420                               
421                                csv[timestamp] = {}
422                                csv[timestamp]['Date'] = date
423                                csv[timestamp]['Time'] = localtime
424                                csv[timestamp]['Attention'] = ''
425                                csv[timestamp]['Meditation'] = ''
426                                csv[timestamp]['Signal Level'] = ''
427                                csv[timestamp]['Delta'] = ''
428                                csv[timestamp]['Theta'] = ''
429                                csv[timestamp]['Low Alpha'] = ''
430                                csv[timestamp]['High Alpha'] = ''
431                                csv[timestamp]['Low Beta'] = ''
432                                csv[timestamp]['High Beta'] = ''
433                                csv[timestamp]['Low Gamma'] = ''
434                                csv[timestamp]['Mid Gamma'] = ''
435                               
436                                for header in customDataHeaders:
437                                        csv[timestamp][header] = ''
438                       
439                       
440                        if 'eSense' in packet.keys():
441                                if 'attention' in packet['eSense'].keys():
442                                        csv[timestamp]['Attention'] = packet['eSense']['attention']
443                                if 'meditation' in packet['eSense'].keys():
444                                        csv[timestamp]['Meditation'] = packet['eSense']['meditation']
445                       
446                        if 'eegPower' in packet.keys():
447                                if 'delta' in packet['eegPower'].keys():
448                                        csv[timestamp]['Delta'] = packet['eegPower']['delta']
449                                if 'theta' in packet['eegPower'].keys():
450                                        csv[timestamp]['Theta'] = packet['eegPower']['theta']
451                                if 'lowAlpha' in packet['eegPower'].keys():
452                                        csv[timestamp]['Low Alpha'] = packet['eegPower']['lowAlpha']
453                                if 'highAlpha' in packet['eegPower'].keys():
454                                        csv[timestamp]['High Alpha'] = packet['eegPower']['highAlpha']
455                                if 'lowBeta' in packet['eegPower'].keys():
456                                        csv[timestamp]['Low Beta'] = packet['eegPower']['lowBeta']
457                                if 'highBeta' in packet['eegPower'].keys():
458                                        csv[timestamp]['High Beta'] = packet['eegPower']['highBeta']
459                                if 'lowGamma' in packet['eegPower'].keys():
460                                        csv[timestamp]['Low Gamma'] = packet['eegPower']['lowGamma']
461                                if 'highGamma' in packet['eegPower'].keys():
462                                        csv[timestamp]['Mid Gamma'] = packet['eegPower']['highGamma']
463                       
464                        if 'poorSignalLevel' in packet.keys():
465                                csv[timestamp]['Signal Level'] = packet['poorSignalLevel']
466                       
467                        for header in customDataHeaders:
468                                if 'custom' in packet.keys() and \
469                                   header in packet['custom'].keys():
470                                        csv[timestamp][header] = packet['custom'][header]
471               
472               
473                if scrub_data:
474                        csv = self.scrubData(csv, truncate_csv_timezone)
475               
476               
477                output = headers
478               
479                csv_keys = csv.keys()
480                csv_keys.sort()
481               
482                for key in csv_keys:
483                       
484                        row = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % \
485                              (csv[key]['Date'], \
486                               csv[key]['Time'], \
487                               csv[key]['Attention'], \
488                               csv[key]['Meditation'], \
489                               csv[key]['Signal Level'], \
490                               csv[key]['Delta'], \
491                               csv[key]['Theta'], \
492                               csv[key]['Low Alpha'], \
493                               csv[key]['High Alpha'], \
494                               csv[key]['Low Beta'], \
495                               csv[key]['High Beta'], \
496                               csv[key]['Low Gamma'], \
497                               csv[key]['Mid Gamma'])
498                       
499                        for header in customDataHeaders:
500                                row = row + ',%s' % csv[key][header]
501                       
502                        row = row + '\n'
503                       
504                        output = output + row
505               
506               
507                return(output)
508       
509       
510        ##################################################################
511       
512        def scrubData(self, csv, truncate_csv_timezone=False):
513               
514                # If there are missing packets, repeat a given packet once per missing
515                # second until there is a gap between 1 and 2 seconds, in which case
516                # produce a final duplicate packet at the mid-point between the packets
517
518                if self.DEBUG:
519                        print "INFO: Scrubbing Data"
520               
521                last_time = None
522                last_recorded_time = None
523               
524                output = {}
525               
526                csv_keys = csv.keys()
527                csv_keys.sort()
528               
529                for key in csv_keys:
530                       
531                        timestamp = key
532
533                        if csv[key]['Attention'] == '':
534                                continue
535                       
536                        if last_time == None:
537                                # First entry in log
538                                last_time = timestamp
539                                last_recorded_time = timestamp
540                                output[key] = csv[key]
541                                continue
542                       
543                        else:
544                               
545                                #time_difference = timestamp - last_time
546                                time_difference = timestamp - last_recorded_time
547                               
548                                if (time_difference <= 1) and \
549                                   (time_difference >= PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD):
550                                        # Skip packets within the correct time threshold
551                                        last_time = timestamp
552                                        last_recorded_time = timestamp
553                                        output[key] = csv[key]
554                                        continue
555                               
556                                else:
557                                       
558                                        if self.DEBUG > 1:
559                                                print "time_difference:",
560                                                print time_difference
561                                                print "timestamp:",
562                                                print self.parseTimeStamp(timestamp)[-1].split(' ')[0]
563                                                print "last_time:",
564                                                print self.parseTimeStamp(last_time)[-1].split(' ')[0]
565                                                print "last_recorded_time:",
566                                                print self.parseTimeStamp(last_recorded_time)[-1].split(' ')[0]
567                                       
568                                       
569                                        new_packet = csv[key].copy()
570                                       
571                                        if time_difference >= 2:
572                                               
573                                                ##new_time = last_time + 1
574                                                #new_time = last_recorded_time + 1
575                                               
576                                                count = int(time_difference)
577                                                while count >= 1:
578                                                        new_packet = csv[key].copy()
579                                                        new_time = last_recorded_time + 1
580                                                        (date, formatted_new_time) = self.parseTimeStamp(new_time, \
581                                                         truncate_time_zone=truncate_csv_timezone)
582                                                        new_packet['Time'] = formatted_new_time
583                                                        last_recorded_time = new_time
584                                                        last_time = timestamp
585                                                        output[new_time] = new_packet
586                                                        count = count - 1
587                                                continue
588                                               
589                                        elif time_difference < PACKET_MINIMUM_TIME_DIFFERENCE_THRESHOLD:
590                                                # Spread out "bunched up" packets
591                                                #new_time = last_time + 1
592                                                new_time = last_recorded_time + 1
593                                       
594                                       
595                                        elif (time_difference < 2) and (time_difference > 1):
596                                               
597                                                #new_time = last_time + ((last_time - timestamp) / 2)
598                                                #new_time = last_recorded_time + ((last_recorded_time - timestamp) / 2)
599                                                #new_time = last_time + 1
600                                                new_time = last_recorded_time + 1
601                                       
602                                       
603                                        (date, formatted_new_time) = self.parseTimeStamp(new_time, \
604                                           truncate_time_zone=truncate_csv_timezone)
605                                       
606                                        new_packet['Time'] = formatted_new_time
607                                       
608                                        #last_time = new_time
609                                        last_recorded_time = new_time
610                                        last_time = timestamp
611                                        output[new_time] = new_packet
612                                       
613                                        if self.DEBUG > 1:
614                                                print "WARN: Scrubbing new packet:",
615                                                print new_packet
616                                                print
617               
618               
619                return(output)
620       
621       
622        ##################################################################
623       
624        def resetData(self, source=None):
625               
626                if source == None:
627                        if self.parent == None:
628                                source = self
629                        else:
630                                source = self.parent
631               
632                source.packets['rawEeg'] = []
633                source.packets['signals'] = []
634               
635                #source.synapseServer.protocol.session_start_timestamp = \
636                        #time.time()
637                self.synapseServer.protocol.resetSessionStartTime()
638               
639                source.synapseServer.protocol.packet_count = 0
640                source.synapseServer.protocol.bad_packets = 0
641               
642                self.updateProfileSessionStatus()
643               
644                try:
645                        source.textEditDebugConsole.setText("")
646                except:
647                        pass
648       
649       
650        #####################################################################
651       
652        def convert_seconds_to_datetime(self, duration):
653               
654                duration_hours = duration / (60 * 60)
655                duration_minutes = (duration - (duration_hours * (60 * 60))) / 60
656                duration_seconds = (duration - (duration_hours * (60 * 60)) - (duration_minutes * 60))
657               
658                duration_hours = '%i' % duration_hours
659                if (len(duration_hours) == 1):
660                        duration_hours = "0%s" % duration_hours
661               
662                duration_minutes = '%i' % duration_minutes
663                if (len(duration_minutes) == 1):
664                        duration_minutes = "0%s" % duration_minutes
665               
666                duration_seconds = '%i' % duration_seconds
667                if (len(duration_seconds) == 1):
668                        duration_seconds = "0%s" % duration_seconds
669               
670                datetime = '%s:%s:%s' % (duration_hours, duration_minutes, duration_seconds)
671               
672                return(datetime)
673
Note: See TracBrowser for help on using the repository browser.