Stair one button.py

From PsyPad
Jump to navigation Jump to search
<nowiki>
  1. Process single button staircase log files from PsyPad to produce
  2. "readable" output.
  3. Andrew Turpin
  4. Fri 21 Mar 2014 10:53:51 EST

import re import json import time import datetime import sys

global rev_values # list of [list of reversal values] per staircase global mins # list of min dB value per staircase global maxs # list of max dB value per staircase global seen_max # count of number of times max dB seen per staircase global not_seen_min # count of number of times min dB not seen per staircase global hits_to_finish # number of times min dB not seen or max dB seen per staircase global start_time # time of first question global end_time # time of test end

  1. Print a line for a single presentation
  2. If caused a reversal add a *
  3. If it is a min or max value,
  4. record in seen_max or not_seen_min if appropriate
  5. INPUTS
  6. date - date in seconds since epoc
  7. reversal - True or False
  8. currentStair - number of this staircase
  9. stim_level - stimulus level presented
  10. button - True if button pressed
  11. OUTPUTS:
  12. Nothing
  13. SIDEFFECTS:
  14. Prints line of text describing presentation

def printIt(date, reversal, currentStair, stim_level, button):

   if reversal:
       rev_values[currentStair] = rev_values[currentStair] + [stim_level]
       flag = "*"
   else:
       flag = ""
        
   if button == -1:
       but = " Not seen"
   else:
       but = str(button)
   t = time.strftime("%a, %d %b %Y %H:%M:%S",time.localtime(float(date)))
   print "# " + t + " stair= " + str(currentStair) + " stim= " + str(stim_level) + " button= " + but + flag
   if button and stim_level == maxs[currentStair]:
       seen_max[currentStair] = seen_max[currentStair] + 1
   if not button and stim_level == mins[currentStair]:
       not_seen_min[currentStair] = not_seen_min[currentStair] + 1
  1. Get information from JSON header in log
  2. and initialise global variables accordingly
  3. INPUTS:
  4. inData - string of data that is in 3rd field of 1st line of logfiles
  5. OUTPUTS:
  6. Nothing
  7. SIDEFFECTS:
  8. Prints max and min stim values

def extract_test_info(inData):

   global rev_values, mins, maxs, seen_max, not_seen_min, hits_to_finish 
   d = json.loads(inData)
   
   if d['use_staircase_method'] != 1:
       print "This script only works on staircases, not MOCS"
       sys.exit()
   
   mins = [ 36-int(x[-2:]) for x in d['staircase_max_level'].split("/")]  # note db inverts image name
   maxs = [ 36-int(x[-2:]) for x in d['staircase_min_level'].split("/")]  # note db inverts image name
   rev_values   = [[] for i in range(d['number_of_staircases']) ]  # set up a list of empty lists, one per staircase
   seen_max     = [0 for i in range(d['number_of_staircases']) ]  # set up a list of empty lists, one per staircase
   not_seen_min = [0 for i in range(d['number_of_staircases']) ]  # set up a list of empty lists, one per staircase
   hits_to_finish = [ int(x) for x in d['hits_to_finish'].split("/")]
   
   print "# Maxs: {0}".format(maxs)
   print "# Mins: {0}".format(mins)
   
  1. Process log to get and print information about each presentation
  2. INPUTS:
  3. f - file handle
  4. OUTPUTS:
  5. None
  6. SIDEFFECTS:
  7. Prints stuff

def get_presentations(f):

   global start_time, end_time
   firstTime = True
   for line in f:
       fields = line.split("|")    # each line has 3 parts
       date = fields[0]            # date in first part
       type = fields[1]            # type/code in second part
       inData = fields[2]          # inData in third part
       if type == "test_begin":
           extract_test_info(inData)
       if type == "currentStaircase":
           currentStair = int(inData.strip())
       
       if type == "reversal":
           reversal = True
       
       if type == "next_question":
           if firstTime:
               firstTime = False
               start_time = date
           else:
               printIt(date, reversal, currentStair, stim_level, button)
           reversal = False
           button = -1
       
       if type == "presented_image":
           A = inData.split("/")       # inData is of format q/b_xxx
           stim_level = int(A[0])      # sitm level is the last two chars before / (qq)
           corr_button = A[1][0]       # button that should be pressed is first char (b) (most likely 1)
       
       if type == "button_press":
           button = inData[0] == corr_button   # button number is first char of inData
   
       if type == "test_finished":
           end_time = date
       # print final presentation once all lines read
   printIt(date, reversal, currentStair, stim_level, button)
  1. Open file and process each line

def main():

   global start_time, end_time
   if len(sys.argv) != 2:
       print("Usage: python {0} logfile_name".format(sys.argv[0]))
       sys.exit(1)
   f = open(sys.argv[1])
   get_presentations(f)
   #####################################
   # print the means of rev_values
   #####################################
   for s in range(len(rev_values)):
       if seen_max[s] == hits_to_finish[s]:
           print "Staircase {0}: Maxed    {1} Seen     {2} times".format(s, maxs[s], seen_max[s])
   
       if not_seen_min[s] == hits_to_finish[s]:
           print "Staircase {0}: Minned   {1} Not_seen {2} times".format(s, mins[s], not_seen_min[s])
   
       if len(rev_values[s]) > 0:
           print "Staircase {0}: Mean_rev {1} Last_rev {2}".format(s, sum(rev_values[s])/len(rev_values[s]), rev_values[s][-1])
   #####################################
   # print the time elapsed
   #####################################
   st = time.localtime(float(start_time))
   et = time.localtime(float(end_time))
   print "Start time " + time.strftime("%a, %d %b %Y %H:%M:%S",st)
   print "End   time " + time.strftime("%a, %d %b %Y %H:%M:%S",et)
   print "Elapsed: " + str(datetime.timedelta(seconds=(int(end_time) - int(start_time))))

if __name__ == '__main__':

   main()