def generateTrials(myDict, nTestTrials): ''' generates a list of trials to write to csv file supply 3 columns to be factorially combined myDict = {'contrast': [1.0, 0.75, 0.5, 0.25], 'orientation':[225, 315], 'probeMatch':[1, 0], 'correctKey':[1]} ''' columnHeaders = myDict.keys() trialList = data.createFactorialTrialList(myDict) for item in trialList: if item['probeMatch'] == 1: item['correctKey'] = expInfo['sameKey'] else: item['correctKey'] =expInfo['differentKey'] # write trial list for experiment loop: if expInfo['experimentType']=='practise': trialList = rand.sample(trialList, nTestTrials) with open('mainTrials.csv', 'wb') as mainTrialsFile: writer = csv.writer(mainTrialsFile, dialect='excel') writer.writerow(columnHeaders) for row in trialList: writer.writerow(row.values()) if expInfo['experimentType']=='practise': # generate trial list for practise loop: practiseTrialList = rand.sample(trialList, nTestTrials) # write trial list for practise loop: with open('practiseTrials.csv', 'wb') as practiseTrialsFile: writer = csv.writer(practiseTrialsFile, dialect='excel') writer.writerow(columnHeaders) for row in practiseTrialList: writer.writerow(row.values())
def test_default(self): exp = data.ExperimentHandler(name='testExp', version='0.1', extraInfo={ 'participant': 'jwp', 'ori': 45 }, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName=self.tmpDir + 'default') # First loop: Training. conds = data.createFactorialTrialList({ 'faceExpression': ['happy', 'sad'], 'presTime': [0.2, 0.3] }) training = data.TrialHandler( trialList=conds, nReps=3, name='train', method='random', seed=100 # Global seed - so fixed for whole experiment. ) exp.addLoop(training) for trial in training: training.addData('training.rt', random.random() * 0.5 + 0.5) if random.random() > 0.5: training.addData('training.key', 'left') else: training.addData('training.key', 'right') exp.nextEntry() # Then run 3 repeats of a staircase. outerLoop = data.TrialHandler(trialList=[], nReps=3, name='stairBlock', method='random') exp.addLoop(outerLoop) for thisRep in outerLoop: # The outer loop doesn't save any data. staircase = data.StairHandler(startVal=10, name='staircase', nTrials=5) exp.addLoop(staircase) for thisTrial in staircase: id = random.random() if random.random() > 0.5: staircase.addData(1) else: staircase.addData(0) exp.addData('id', id) exp.nextEntry()
def generateTrialsDict(myDict): columnHeaders = myDict.keys() trialList = data.createFactorialTrialList(myDict) for item in trialList: if item['orientation'] > 0: item['correctKey'] = expInfo['rightKey'] elif item['orientation'] < 0: item['correctKey'] =expInfo['leftKey'] return trialList
def test_ExperimentHandler(): exp = data.ExperimentHandler(name='testExp', version='0.1', extraInfo={ 'participant': 'jwp', 'ori': 45 }, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName=tmpFile + 'x') #a first loop (like training?) conds = data.createFactorialTrialList({ 'faceExpression': ['happy', 'sad'], 'presTime': [0.2, 0.3] }) training = data.TrialHandler( trialList=conds, nReps=3, name='train', method='random', seed=100) #this will set the global seed - so fixed for whole exp exp.addLoop(training) #run those trials for trial in training: training.addData('training.rt', random.random() * 0.5 + 0.5) if random.random() > 0.5: training.addData('training.key', 'left') else: training.addData('training.key', 'right') exp.nextEntry() #then run 3 repeats of a staircase outerLoop = data.TrialHandler(trialList=[], nReps=3, name='stairBlock', method='random') exp.addLoop(outerLoop) for thisRep in outerLoop: #the outer loop doesn't save any data staircase = data.StairHandler(startVal=10, name='staircase', nTrials=5) exp.addLoop(staircase) for thisTrial in staircase: id = random.random() if random.random() > 0.5: staircase.addData(1) else: staircase.addData(0) exp.addData('id', id) exp.nextEntry() #exp should then automatically save the pickle and csv data files for e in exp.entries: print e print 'done'
def test_default(self): exp = data.ExperimentHandler( name='testExp', version='0.1', extraInfo={'participant': 'jwp', 'ori': 45}, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName=self.tmpDir + 'default' ) # First loop: Training. conds = data.createFactorialTrialList( {'faceExpression': ['happy', 'sad'], 'presTime': [0.2, 0.3]} ) training = data.TrialHandler( trialList=conds, nReps=3, name='train', method='random', seed=self.random_seed) exp.addLoop(training) rng = np.random.RandomState(seed=self.random_seed) for trial in training: training.addData('training.rt', rng.rand() * 0.5 + 0.5) if rng.rand() > 0.5: training.addData('training.key', 'left') else: training.addData('training.key', 'right') exp.nextEntry() # Then run 3 repeats of a staircase. outerLoop = data.TrialHandler( trialList=[], nReps=3,name='stairBlock', method='random' ) exp.addLoop(outerLoop) for thisRep in outerLoop: # The outer loop doesn't save any data. staircase = data.StairHandler( startVal=10, name='staircase', nTrials=5 ) exp.addLoop(staircase) for thisTrial in staircase: id = rng.rand() if rng.rand() > 0.5: staircase.addData(1) else: staircase.addData(0) exp.addData('id', id) exp.nextEntry()
def sart_block(win, fb, omitNum, reps, bNum, fixed): mouse = event.Mouse(visible=0) xStim = visual.TextStim(win, text="X", height=3.35, color="white", pos=(0, 0)) circleStim = visual.Circle(win, radius=1.50, lineWidth=8, lineColor="white", pos=(0, -.2)) numStim = visual.TextStim(win, font="Arial", color="white", pos=(0, 0)) correctStim = visual.TextStim(win, text="CORRECT", color="green", font="Arial", pos=(0, 0)) incorrectStim = visual.TextStim(win, text="INCORRECT", color="red", font="Arial", pos=(0, 0)) numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] if fb == True: fontSizes=[1.20, 3.00] else: fontSizes=[1.20, 1.80, 2.35, 2.50, 3.00] list= data.createFactorialTrialList({"number" : numbers, "fontSize" : fontSizes}) seqList = [] for i in range(len(fontSizes)): for number in numbers: random.shuffle(list) for trial in list: if trial["number"] == number and trial not in seqList: seqList.append(trial) break if fixed == True: trials = data.TrialHandler(seqList, nReps=reps, method='sequential') else: trials = data.TrialHandler(list, nReps=reps, method='random') clock = core.Clock() tNum = 0 resultList =[] startTime = time.clock() for trial in trials: tNum += 1 resultList.append(sart_trial(win, fb, omitNum, xStim, circleStim, numStim, correctStim, incorrectStim, clock, trials.thisTrial['fontSize'], trials.thisTrial['number'], tNum, bNum, mouse)) endTime = time.clock() totalTime = endTime - startTime for row in resultList: row.append(totalTime/tNum) print ("\n\n#### Block " + str(bNum) + " ####\nDes. Time Per P Trial: " + str(2.05*1000) + " ms\nDes. Time Per Non-P Trial: " + str(1.15*1000) + " ms\nActual Time Per Trial: " + str((totalTime/tNum)*1000) + " ms\n\n") return resultList
def generateTrials(myDict): ''' generates a list of trials to write to csv file supply 3 columns to be factorially combined myDict = {'contrast': [1.0, 0.75, 0.5, 0.25], 'orientation':[225, 315], 'probeMatch':[1, 0]} ''' columnHeaders = myDict.keys() # header = ",".join(columnHeaders) trialList = data.createFactorialTrialList(myDict) with open('mainTrials.csv', 'wb') as mainTrialsFile: writer = csv.writer(mainTrialsFile, dialect='excel') writer.writerow(columnHeaders) for row in trialList: writer.writerow(row.values())
def generateTrialsCSV(myDict): columnHeaders = myDict.keys() trialList = data.createFactorialTrialList(myDict) for item in trialList: if item['orientation'] > 0: item['correctKey'] = 'j' elif item['orientation'] < 0: item['correctKey'] = 'f' with open('ssv_loop.csv', 'wb') as conditionsFile: writer = csv.writer(conditionsFile, dialect='excel') writer.writerow(columnHeaders) for row in trialList: writer.writerow(row.values())
def generateTrials(myDict): ''' generates a list of trials to write to csv file ''' columnHeaders = myDict.keys() trialList = data.createFactorialTrialList(myDict) # write trial list for experiment loop: # if expInfo['experimentType']=='practise': # trialList = rand.sample(trialList, nTestTrials) with open('conditions.csv', 'wb') as conditionsFile: writer = csv.writer(conditionsFile, dialect='excel') writer.writerow(columnHeaders) for row in trialList: writer.writerow(row.values())
def test_ExperimentHandler(): exp = data.ExperimentHandler(name='testExp', version='0.1', extraInfo={'participant':'jwp','ori':45}, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName=tmpFile+'x') #a first loop (like training?) conds = data.createFactorialTrialList({'faceExpression':['happy','sad'],'presTime':[0.2,0.3]}) training=data.TrialHandler(trialList=conds, nReps=3,name='train', method='random', seed=100)#this will set the global seed - so fixed for whole exp exp.addLoop(training) #run those trials for trial in training: training.addData('training.rt',random.random()*0.5+0.5) if random.random()>0.5: training.addData('training.key','left') else: training.addData('training.key','right') exp.nextEntry() #then run 3 repeats of a staircase outerLoop=data.TrialHandler(trialList=[], nReps=3,name='stairBlock', method='random') exp.addLoop(outerLoop) for thisRep in outerLoop:#the outer loop doesn't save any data staircase=data.StairHandler(startVal=10, name='staircase', nTrials=5) exp.addLoop(staircase) for thisTrial in staircase: id=random.random() if random.random()>0.5: staircase.addData(1) else: staircase.addData(0) exp.addData('id',id) exp.nextEntry() #exp should then automatically save the pickle and csv data files for e in exp.entries: print e print 'done'
def rand_trials_sample(self): """ generates a randomized list of trial/stimulus parameters, of length numTrials """ factors = { "ISI_s": self.ISI, "flash_dur_ms": self.flash_dur, "luminance": self.luminance, "wave_freq_Hz": self.wave_freq, #waveFreq = freq of the tone "pulse_dur_ms": self.pulse_dur, #pulseDur = length of time the tone is played "wave_amp_dB": self.wave_amp, #waveAmp = sound levels "stimulus": self.stimulus, "delay_ms": self.delay # delay between presenting A and V } stimList = data.createFactorialTrialList(factors) randSample = random.sample(stimList, self.numTrials) return randSample
from ppc import csvWriter opacities = [0.2, 1.0] images = ['cat.jpg', 'lion.jpg', 'fish.gif'] reps = 2 """ 1. PSYCHOPY VERSION % No ability to save on trial-to-trial basis! (reason enough to discard) + Short and simple i Suitable for simple factorial designs but not much more % Messy output: adds extra columns ("ran" and "order") and floats integers (1 becomes 1.0) """ from psychopy import data conditions = data.createFactorialTrialList({ 'opacity': opacities, 'image': images }) # tuple list of unique trials trials = data.TrialHandler( conditions, reps, method='fullRandom') # as a TrialHandler object with repetitions of trials for trial in trials: trials.addData('answer', random.choice(['left', 'right'])) trials.addData('score', random.randint(0, 1)) trials.saveAsWideText('result_trialHandler (' + time.strftime('%Y-%m-%d %H-%M-%S', time.localtime()) + ').csv', appendFile=False) """ 2. GENERIC PYTHON VERSION
exp = data.ExperimentHandler(name='testExp', version='0.1', extraInfo={ 'participant': 'jwp', 'ori': 45 }, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName='testExp') # a first loop (like training?) conds = data.createFactorialTrialList({ 'faceExpression': ['happy', 'sad'], 'presTime': [0.2, 0.3] }) training = data.TrialHandler( trialList=conds, nReps=3, name='train', method='random', seed=100) # this will set the global seed - for the whole exp exp.addLoop(training) # run those trials for trial in training: training.addData('training.rt', random.random() * 0.5 + 0.5) if random.random() > 0.5: training.addData('training.key', 'left') else: training.addData('training.key', 'right') exp.nextEntry() # then run 3 repeats of a staircase
from psychopy import data, log from numpy import random log.console.setLevel(log.DEBUG) exp = data.ExperimentHandler(name='testExp', version='0.1', extraInfo={'participant':'jwp','ori':45}, runtimeInfo=None, originPath=None, savePickle=True, saveWideText=True, dataFileName='testExp') #a first loop (like training?) conds = data.createFactorialTrialList({'faceExpression':['happy','sad'],'presTime':[0.2,0.3]}) training=data.TrialHandler(trialList=conds, nReps=3,name='train', method='random', seed=100)#this will set the global seed - so fixed for whole exp exp.addLoop(training) #run those trials for trial in training: training.addData('training.rt',random.random()*0.5+0.5) if random.random()>0.5: training.addData('training.key','left') else: training.addData('training.key','right') exp.nextEntry() #then run 3 repeats of a staircase outerLoop=data.TrialHandler(trialList=[], nReps=3,name='stairBlock', method='random')
opacities = [0.2, 1.0] images = ['cat.jpg', 'lion.jpg', 'fish.gif'] reps = 2 """ 1. PSYCHOPY VERSION % No ability to save on trial-to-trial basis! (reason enough to discard) + Short and simple i Suitable for simple factorial designs but not much more % Messy output: adds extra columns ("ran" and "order") and floats integers (1 becomes 1.0) """ from psychopy import data conditions = data.createFactorialTrialList({'opacity': opacities, 'image': images}) # tuple list of unique trials trials = data.TrialHandler(conditions, reps, method='fullRandom') # as a TrialHandler object with repetitions of trials for trial in trials: trials.addData('answer', random.choice(['left', 'right'])) trials.addData('score', random.randint(0,1)) trials.saveAsWideText('result_trialHandler (' + time.strftime('%Y-%m-%d %H-%M-%S', time.localtime()) +').csv', appendFile=False) """ 2. GENERIC PYTHON VERSION + good control + pure core python (occam's razor) % Sensitive to identical keys in all trial-dicts """
""" 3) line orientation judgment trials using the rough SVV estimate as centre for line orientations """ # GO signal for line orientation discrimination trials print("Waiting for 2AFC task to start\n") draw_fixation(color='green') sequence = list(np.linspace(start=svv-RANGE, stop=svv+RANGE, num=N_ORI)) conditions = {'orientation': sequence} trial_list = data.createFactorialTrialList(conditions) trials = data.TrialHandler(trialList=trial_list, nReps=N_REPS, method='random') experiment.addLoop(trials) """ start trial loop """ # initial interval frame_n = 0 while frame_n < ITI_DURATION: frame_n += 1 win.flip()
[i.setTex(noise_texture) for i in noise] [i.draw() for i in noise] win.flip() """ 3) line orientation judgment trials using the rough SVV estimate as centre for line orientations """ # GO signal for line orientation discrimination trials print("Waiting for 2AFC task to start\n") draw_fixation(color='green') sequence = list(np.linspace(start=svv - RANGE, stop=svv + RANGE, num=N_ORI)) conditions = {'orientation': sequence} trial_list = data.createFactorialTrialList(conditions) trials = data.TrialHandler(trialList=trial_list, nReps=N_REPS, method='random') experiment.addLoop(trials) """ start trial loop """ # initial interval frame_n = 0 while frame_n < ITI_DURATION: frame_n += 1 win.flip() # start trial draw_lines(lines, trials)
luminance=0) flash.autoDraw = True #factorially combine the options into a dict. required by psychopy factors = { "ISI": ISI, "flash_dur": flash_dur, "luminance": luminance, "frequency": frequency, #waveFreq "duration": duration, #pulseDur "sound_levels": sound_levels, #waveAmp "auditory_on": auditory_on } #make a randomized stimulus list stimList = data.createFactorialTrialList(factors) randNs = random.sample( range(0, len(stimList) - 1), numTrials) # generate random numbers equal to the # of trials trials_subset = [ None ] * numTrials # to get a subset of values to use for the inputs from the overall massive stimlist for i in range(0, numTrials): randNum = randNs[i] trials_subset[i] = stimList[randNum] #making experimentHandler and trials exp = data.ExperimentHandler(name='testExp',
if infoBox.OK: # this will be True (user hit OK) or False (cancelled) metaData.update(metaData2) # add new metaData to existing metaData else: sys.exit("User cancelled gui.") # set up counterbalancing if metaData['override automated counter-balancing'] == True: # user has chosen to override automated counter-balancing cb = {'sequenceOrder': ['X', 'Y'], 'testOrder': ['A', 'B']} # set up info for infoBox gui infoBox = gui.DlgFromDict(dictionary=cb, title='Choose counter-balancing parameters') # display gui to get info from user sequenceOrder = cb['sequenceOrder'] testOrder = cb['testOrder'] if not infoBox.OK: # if user hit cancel quitExp() # quit else: # otherwise use automated counter-balancing trialList = data.createFactorialTrialList( {'sequenceOrder': ['X', 'Y'], 'testOrder': ['A', 'B']}) # get counter balancing conditions # assign to counter-balanced conditions [the 4 unique arrangements are assigned cyclically] sequenceOrder = trialList[int(metaData['participant']) % 4]['sequenceOrder'] testOrder = trialList[int(metaData['participant']) % 4]['testOrder'] metaData.update({'expName': expName, 'date': date, 'session': session, 'sequenceOrder': sequenceOrder, 'testOrder': testOrder}) # record the counterbalancing info in the metaData # Customise sequences for this participant if sequenceOrder == 'X': oldSequence = '41324' newSequence = '23142' elif sequenceOrder == 'Y': oldSequence = '23142' newSequence = '41324'
originPath=None, savePickle=False, saveWideText=True, autoLog=False, dataFileName=filename) temp_file = codecs.open(filename + '_temp.csv', 'w+', 'utf-8') # number of repetitions for all conditions nReps = 3 condsList = data.createFactorialTrialList({ 'ctpd_prime': [-80, -60, -40, -30, -20, -10, 0, 10, 20, 30, 40, 60, 80], 'dsd_prime': [10], 'dsd_test': [5], 'dtype_prime': ['norm'], 'dtype_test': ['norm'], 'streak_length_prime': [2, 3, 5, 6], 'prime_set_size': [36], 'test_set_size': [36] }) trialsList = [] totBlockN = 0 curTrialN = 0 coordinates_by_trial = {} oris_by_trial = {} colors_by_trial = {} set_sizes = {} totalTrials = 0 ###############################################################################
imList_changed[change_pos].setImage("%s_%s/%03d.png" % tuple(parMatrix[change_pos][0:3])) # print imList[change_pos]._imName screenshot_changed = visual.BufferImageStim(win, stim=imList) return (screenshot, screenshot_changed, parMatrix, imList, imList_changed) probe = visual.Circle(win, 0.2, 96, units="deg", fillColor="#a8a8a8", lineWidth=0) maskTime = 5 showTime = 15 fpTime = 1 # in second change_types = ["shape"] trainingList = data.createFactorialTrialList(factors={"change_type": change_types, "change_pos": range(nImages)}) shuffle(trainingList) fullPosList = range(nImages) shuffle(fullPosList) # mainTrials=[] ecc_list = [x - 0.5 for x in range(1, 8)] angle_list = range(0, 360, 30) # for i in change_types: # print i # print sample(range(nImages),5) factorsList = data.createFactorialTrialList( factors={
iFBT = 0.500 # immediate feedback interval bFBT = 15. # break interval between blocks # parameters of the visual stimuli size = 50 # size of the stimuli (in pixels) XY = [[-size/2,0],[0,size/2],[0,size/4],[size/2,size/4],[size/2,-size/4],[0,-size/4],[0,-size/2]] # basic coordinates of a leftwards-pointing arrow CLRS = ['green', 'red'] # colors of the go and stop arrows, respectively # define response keys (in this case: the arrow keys and esc key) keys = ('left', 'right', 'escape') ### DO NOT CHANGE THE DESIGN (UNLESS YOU REALLY KNOW WHAT YOU ARE DOING) # Specify the design (2 by 4 in this instance) go = [0,1] # left (0) vs. right (1) arrows signal = [0,0,0,1] # 1/4 of the trials are signal (1) trials design = data.createFactorialTrialList({"goStim": go, "signal": signal}) ##################################################################### ### Initialise experiment ##################################################################### # By default, Psychopy changes the working directory based on the # location of the .py file. The output folder will be located here. # The output folder will be created if it does not exist yet. wd = os.getcwd() data_path = wd + "/output" if not os.path.isdir('output'): os.mkdir('output') # Get some user info and use this to determine the file name info = {"Participant": "", "Session": "", "X extra: Gender": "", "X extra: Age": ""} already_exists = True
imList_changed[change_pos].setImage('%s_%s/%03d.png' % tuple(parMatrix[change_pos][0:3])) #print imList[change_pos]._imName screenshot_changed = visual.BufferImageStim(win, stim=imList) return (screenshot, screenshot_changed,parMatrix, imList, imList_changed) probe = visual.Circle(win, 0.2, 96, units='deg', fillColor='#a8a8a8', lineWidth=0) maskTime=5 showTime=15 fpTime=1 #in second change_types=['color','rot','shape'] trainingList = data.createFactorialTrialList(factors={'change_type': change_types,'change_pos':range(nImages)}) shuffle(trainingList) fullPosList=range(nImages) shuffle(fullPosList) mainTrials=[] ecc_list=[x - .5 for x in range(1, 8)] angle_list=range(0,360,30) #for i in change_types: # print i # print sample(range(nImages),5) factorsList = data.createFactorialTrialList(factors={'change_type': change_types, 'trial_probe_ecc':ecc_list, 'trial_probe_angle':angle_list}) #print 'factorsList: %g'%len(factorsList)
def randomize(c_b, block): # Variables and their Parameters bins = ['Bin_1', 'Bin_2', 'Bin_3', 'Bin_4', 'Bin_5'] scaleType = ['Prob', 'Det'] congruency = ['L_Con', 'R_Con', 'L_Incon', 'R_Incon'] # Inserting the parameters into the block design if block != 0: if block % 2 == c_b: Design = data.createFactorialTrialList({ "Bins": bins, "Congruency": congruency }) dataFrame = pandas.DataFrame.from_dict(Design) dataFrame["ScaleType"] = "Prob" else: Design = data.createFactorialTrialList({ "Bins": bins, "Congruency": congruency }) dataFrame = pandas.DataFrame.from_dict(Design) dataFrame["ScaleType"] = "Det" else: Design = data.createFactorialTrialList({ "ScaleType": scaleType, "Bins": bins, "Congruency": congruency }) dataFrame = pandas.DataFrame.from_dict(Design) # Adding in index tags and correct response column via DataFrame() ##adding in index tags dataFrame["Tag"] = range(len(dataFrame)) ##adding in correct responses dataFrame['CorAns'] = dataFrame["Congruency"] dataFrame['CorAns'].replace(['L_Con', 'R_Con', 'L_Incon', 'R_Incon'], [left_key, right_key, left_key, right_key], inplace=True) ##adding in reward magnitude dataFrame['BinSize'] = dataFrame['Bins'] dataFrame['BinSize'].replace(['Bin_1', 'Bin_2', 'Bin_3', 'Bin_4', 'Bin_5'], [0, 20, 50, 80, 100], inplace=True) #Convert dataframe back to list of dictionaries trial_list = pandas.DataFrame.to_dict(dataFrame, orient="records") # TESTRUN # If the experimenter wishes to test-run option, reduced amount of trials are given if int(info["testrun"]) == 1: ## including a practice block if block == 0: trials = data.TrialHandler(trialList=random.sample( trial_list, n_practice_trials), nReps=1, method="random") else: trials = data.TrialHandler(trialList=random.sample( trial_list, n_test_trials), nReps=1, method='random') thisExp.addLoop(trials) else: if block == 0: trials = data.TrialHandler(trialList=random.sample( trial_list, n_practice_trials), nReps=1, method='random') else: trials = data.TrialHandler(trialList=trial_list, nReps=n_trial_rep, method='random') thisExp.addLoop(trials) return trials
opacities = [0.2, 1.0] images = ["cat.jpg", "lion.jpg", "fish.gif"] reps = 2 """ 1. PSYCHOPY VERSION % No ability to save on trial-to-trial basis! (reason enough to discard) + Short and simple i Suitable for simple factorial designs but not much more % Messy output: adds extra columns ("ran" and "order") and floats integers (1 becomes 1.0) """ from psychopy import data conditions = data.createFactorialTrialList({"opacity": opacities, "image": images}) # tuple list of unique trials trials = data.TrialHandler(conditions, reps, method="fullRandom") # as a TrialHandler object with repetitions of trials for trial in trials: trials.addData("answer", random.choice(["left", "right"])) trials.addData("score", random.randint(0, 1)) trials.saveAsWideText( "result_trialHandler (" + time.strftime("%Y-%m-%d %H-%M-%S", time.localtime()) + ").csv", appendFile=False ) """ 2. GENERIC PYTHON VERSION + good control + pure core python (occam's razor)