Search code examples
pythonloopstimetrialpsychopy

Trialhandler and time measuring in psychopy


For a go-NoGo Task I want to organize pictures with the data.TrialHandler class from psychopy:

trials = data.TrialHandler(ImageList, nReps=1, method='random')

Now I want to code a loop in which psychopy is going into the dictionary, is presenting the first set of pictures (e.g. A_n) and afterwards is going to the second set until the sixth set. I tried the following:

import glob, os, random, sys, time
import numpy.random as rnd
from psychopy import visual, core, event, monitors, gui, logging, data
im_a = glob.glob('./a*')   # upload pictures of the a-type, gives out a List of .jpg-files
im_n = glob.glob('./n*')   # n-type
im_e = glob.glob('./e*')   # e-type

# combining Lists of Pictures
A_n = im_a + im_n
N_a = im_n + im_a
A_e = im_a + im_e
E_a = im_e + im_a
E_n = im_e + im_n
N_e = im_n + im_e

# making a Dictionary of Pictures and Conditions
PicList = [A_n, N_a, A_e, E_a, E_n, N_e]   # just the six Combinations
CondList = [im_a,im_n,im_a,im_e,im_e,im_n] # images that are in the GO-Condition
ImageList = []
for imagelist, condition in zip(PicList, CondList):
    ImageList.append({'imagelist':imagelist,'condition':condition}) # to associate the picturelist with the GO Conditionlist

for the header I ask an extra question: Combining and associating multiple dictionaries

# Set Experiment
win = visual.Window(color='white',units='pix', fullscr=False)
fixCross=visual.TextStim(win,text='+',color='black',pos=(0.0,0.0), height=40)
corrFb = visual.TextStim(win,text='O',height=40,color='green',pos=[0,0])
incorrFb = visual.TextStim(win,text='X',height=40, color='red',pos=[0,0])


# Start Experiement
trials = data.TrialHandler(ImageList, nReps=1, method='random')
rt_clock = core.Clock()
bitmap = visual.ImageStim(win)
for liste in ImageList[0:5]: # to loop through all 6 conditions
     keys = []   
     for i,Pictures in enumerate(liste): # to loop through all pictures in each condition
           bitmap.setImage(Pictures) # attribute error occurs, not if I use Pictures[0][0], even though in this case every pictures is the same
           bitmap.draw() 
           win.flip()
           rt_clock.reset()
           resp = False
           while rt_clock.getTime() < 2.0: # timelimit is defined 2 s
                if not resp:
                      resp = event.getKeys(keyList=['space'])
                      rt = rt_clock.getTime()
           if bool(resp) is (Pictures in CondList):  # at this point python should have access to the Dictionary in which the associated GO Pictures are saved
                corrFb.draw()
                accu=1 # doesn't work yet
           else:
                incorrFb.draw() 
                accu=0
           win.flip()
           core.wait(0.5)
           trials.addData('rt_'+str(i), rt) # is working well when loop: if trial in trials: ...; in this case trialHAndler is not used, therefor trials.addData is not working
           trials.addData('accu_'+str(i), accu)
trials.saveAsExcel(datanames)
core.quit()

There are a few problems in this code: first it only presents one pictuere for six times, but not six different pictures [1]

and secondly a totally different problem [2] ist the time measuring and the saving of the accuracy which the trialhandler is doing, but for each trial. So it adds up all the RT's for each trial. I want to get the RT's for each image. I tried a few things like an extra stimulus.trialhandler for the stimuli and an extraloop in the end which gives me the last RT but not each. --> is answered below!!!

for stimuli in stimulus: stimulus.addData('rt', rt) 

I know these four questions are a lot for one question, but maybe somebody can give me some good ideas of how I can solve these... Thanks everybody!


Solution

  • (A) This isn't relevant to your question but will improve performance. The line:

    bitmap = visual.ImageStim(win)
    

    Shouldn't occur within the loop. i.e. you should initialise each stimulus only once, then within a loop you just update that the properties of that stimulus, e.g. with bitmap.setImage(…). So shift this initialisation line to the top, where you create the TextStims.

    (B) [deleted: I hadn't paid attention to the first code block.]

    (C)

    bitmap.draw(pictures)
    

    This line doesn't take any arguments. It should just be bitmap.draw(). And anyway, it isn't clear what 'pictures' refers to. Remember that Python is case sensitive. This isn't the same thing as 'Pictures' defined in the loop above. I'm guessing that you want to update what picture is being shown? In that case, then you need to be doing the bitmap.setImage(…) line within this loop, not above, where you will always be drawing a fixed picture as that is the only one that gets set on each trial.

    (D) Re the RTs, you are saving this only once per trial (check the indentation). If you want to save one per image, you need to indent these lines again. Also, you only get one line per trial in the data output. If you want to record multiple RTs per trial, you will need to give them unique names, e.g. rt_1, rt_2, …, rt_6 so they each appear in a separate column. e.g. you could use an enumerator for this loop:

    for i, picture in enumerate(Piclist)
        # lots of code
        # then save data:
         trials.addData('rt_'+str(i), rt)