# Used to process PsychoPy logfiles to generate onset times, durations, and accuracy. Firat Soylu 2017 - University of Alabama
import csv
import re
import os
import fnmatch

combLogf = [] #will include all logfiles


for filename in os.listdir("log-files"): #takes all logfiles calculates corrected time values, inserts subject info and combines all logfiles
        logFile = list(csv.reader(open('log-files/' + filename,'rU'), delimiter='\t', dialect=csv.excel_tab))
        i = 0
        expBeginRow = 'empty'
        expBeginTime = 'empty'
        for row in logFile: #Find the point when experiment starts
                if row[1]=='DATA ' and row[2].startswith('Keypress: quoteleft') and expBeginTime == 'empty':
                        expBeginTime=row[0]
                        # print (expBeginTime)
                        expBeginRow = i
                i = i + 1

        for k in range(expBeginRow): #delete everything above the point when experiment starts
                logFile.pop(0)

        for row in logFile:
                subtractedTime = float(row[0]) - float(expBeginTime) #this is the time value that will be used for onsets. 
                row.insert(1,subtractedTime)
                row.insert(0,filename[0:2])

        #print(logFile[0])

        for row in logFile:
                combLogf.append(row)

outputFile = open('allLogfiles.output','wt')
#outputFile = open('processed.output','wt')
writer = csv.writer(outputFile, delimiter="\t", dialect='excel')
for row in combLogf:
        writer.writerow(row)


# Now start going through each row to get the 'Subject','Condition','Stimulus','State','Response','Accuracy','Duration' info
i = 0
dataSheet = []
dataSheet.append(['Subject','Diff','Oper','Prob','probAns','corrResp','Keyp1','Response','Accuracy','onset1','onset2','rt1','rt2'])

for row in combLogf:
        keyp1 = 'empty'
        response = 'empty'
        accuracy = 'na'
        rt1 = 'empty'
        rt2 = 'empty'
        onset1 = 'empty'
        onset2 = 'empty'

        if row[4].startswith('New trial (rep=') and row[4].find('probAns') != -1:
                rowData = row[4].split(',')
                #print(rowData)
                subj = row[0]
                #diff = rowData[3].split('\'')[1] #the logfiles for the fingersense study marks all trials as easy addition. if it wasn't so this would have worked.
                #oper = rowData[4].split('\'')[1] #the logfiles for the fingersense study marks all trials as easy addition. if it wasn't so this would have worked.
                prob = rowData[5].split('\'')[3]
                probAns  =  rowData[2].split('\'')[3]
                corrResp = rowData[1].split('\'')[2][2]


                if prob.find('-') != -1:
                        oper = "subtraction"
                        if int(prob.split('-')[0]) < 6: #for subtraction if the first operand is bigger than 5 than hard, otherwise easy
                                diff = 'easy'
                        elif int(prob.split('-')[0]) > 5:
                                diff = 'hard'
                        else:
                                print("error: prob info")
                                break

                elif prob.find('+') != -1:
                        oper = "addition"
                        if int(probAns.split('=')[1]) < 11: #for addition if the sum is less than 11 than easy, otherwise hard
                                diff = 'easy'
                        elif int(probAns.split('=')[1]) > 10:
                                diff = 'hard'
                        else:
                                print("error: probAns info")
                                break
                else:
                        print("error: no operation info")
                        break

                
                k = i + 1 #start from the beginning of the current trial and go down to find the stimuli and key presses   
                while not combLogf[k][4].startswith('New trial ('):
                        if combLogf[k][4].startswith('text: text = u'):
                                if onset1 != 'empty':
                                        print ('error onset1 already set')
                                        break
                                onset1 = round(combLogf[k][2],4)
                        elif combLogf[k][4].startswith('text_2: text = u'):
                                if onset2 != 'empty':
                                        print ('error onset2 already set')
                                        break
                                onset2 = round(combLogf[k][2],4)


                        if combLogf[k][4].startswith('Keypress:') and keyp1 == 'empty' and onset1 != 'empty' and onset2 == 'empty' and rt1 == 'empty' and combLogf[k][4].find('quoteleft') == -1:
                                        keyp1 = combLogf[k][4].split(':')[1][1:]
                                        rt1 = round(combLogf[k][2] - onset1,4)
                        elif combLogf[k][4].startswith('Keypress:') and onset2 != 'empty' and rt2 == 'empty'and combLogf[k][4].find('quoteleft') == -1:
                                        response = combLogf[k][4].split(':')[1][1:]
                                        rt2 = round(combLogf[k][2] - onset2,4)
                        k = k + 1


                if keyp1 == 'empty' and rt1 == 'empty': #this means the participant did not click on a button to skip to the response, but responded to validation
                        keyp1 = "skipped" #did the participant click on a button to skip the problem? 
                        rt1 = round(onset2 - onset1, 4)

                if keyp1 in ['1','4']:
                        keyp1 = '2'
                elif keyp1 in ['6','8']:
                        keyp1 = '7'

                if response in ['1','4']:
                        response = '2'
                elif response in ['6','8']:
                        response = '7'


                if response != 'empty': #calculate accuracy
                        if response == corrResp:
                                accuracy = 1
                        else:
                                accuracy = 0
                else: #no response
                        response = "noResp"
                        accuracy = " "
                        rt2 = " "


                # print(subj,diff,oper,prob,probAns,corrResp,keyp1,response,accuracy,onset1,onset2,rt1,rt2)
                if keyp1 not in ['escape','lshift','space'] and response not in ['escape','lshift','space']: #the question terminates at the end of the block
                        dataSheet.append([subj,diff,oper,prob,probAns,corrResp,keyp1,response,accuracy,onset1,onset2,rt1,rt2])

        i = i + 1;

outputFile = open('processedData.output','wt')
writer = csv.writer(outputFile, delimiter="\t", dialect='excel')
for row in dataSheet:
        writer.writerow(row)



#This part creates the vector files (.txt later to be converted to .mat) to input the onset and duration information for all conditions (multiple conditions in Level1)
#################

name_dic1 = dict(zip(('add','sub','fix'),(0,1,2,3,4)))
name_dic2 = dict(zip((0,1,2,3,4),('add','sub','fix')))

fixations = list(csv.reader(open('fixations.txt','rU'), delimiter='\t', dialect=csv.excel_tab)) #fixation values are stored in fixations.txt

def condmatch(trialstring):
        condno = name_dic1.get(trialstring)
        return condno

def writetrial(defj, defoutputf, deffilename): #this is used to create the output file, later to be used by SPM
    global name_dic2
    defname = name_dic2.get(defj)
    outputf.write('names{'+str(defj+1)+'} = \'' + defname+'\'; \nonsets{'+str(defj+1)+'} = ['+ " ".join(onsets[defj])+']; \
    \ndurations{'+str(defj+1)+'} = [' + " ".join(durations[defj]) + '];\n\n')

onsets = [[],[],[]]
durations = [[],[],[]]
skippers = (2, 6, 8, 11, 12, 23, 24, 25, 30, 31, 33, 35) #these subjects did not click to pass the question, their durations will be set to 4sec

dataSheet.pop(0) #get rid of the labels on the top of the sheet
i = 0
while i < len(dataSheet):
        row = dataSheet[i] #so that i don't have to write dataSheet[i] everytime 
        subj = row[0]

        if row[8] == 1: #if the repsonse is correct, otherwise don't include 
                cond = row[2][0:3]  #name of operation
                print(cond)
                
                onsets[condmatch(cond)].append(str(row[9]))
                durations[condmatch(cond)].append(str(row[11]))
                

        if i==0 or (i!=0 and i != len(dataSheet) - 1 and subj!=dataSheet[i+1][0]) or i == len(dataSheet) - 1: #end of current subject. get fixation value, write stuff in the file & continue with the new subj
                for fixRow in fixations:
                        if fixRow[0] == subj:
                                onsets[2] = [fixRow[1]]
                                durations[2] = [fixRow[2]]

                outputf = open('vector_files/m/vector_'+subj+'.m','w')
                outputf.write('names = cell(1,3); \nonsets = cell(1,3); \ndurations = cell(1,3);\n\n')

                for j in range(0,3):
                        writetrial(j, outputf, filename)
                outputf.close()

                onsets = [[],[],[]]
                durations = [[],[],[]]

        i += 1