Randomizing stimulus presentation in visual search

1,436 views
Skip to first unread message

jacobz

unread,
Jan 18, 2012, 11:46:11 PM1/18/12
to psychopy-users
Hi PsychoPy community,

I could certainly use your help! I'm trying to create a visual search
screen with randomized objects in one of four fixed locations, but I'm
having some trouble figuring out how to do it.

The problem is this: I have 4 fixed object locations and 12 objects to
be displayed. 2 of the objects are targets (T1 and T2) and 10 of the
objects are distractors (D1-D10). In each search array, one (but not
both) of the targets and three targets must be presented. I've been
trying to come up with a good way to do this, but I haven't had any
luck. The only way I can think of is to create a conditions file with
every possible permutation and use a random loop type, but that seems
a horribly inefficient way to do this. Is there a better way to
achieve this?

Thanks!

Gary Lupyan

unread,
Jan 19, 2012, 12:02:32 AM1/19/12
to psychop...@googlegroups.com
Horribly inefficient indeed!
It sounds like you're using the builder which I am not familiar with,
but in basic python code, you'd just do

import(random)

targets = range(2)
distractors = range(10)
locations = range(4)

for each trial, you can then do:
curTargets = random.sample(targets,1)
curDistractors = random.sample(distractors,3)

now you have a random sample (without replacement) of 1 target and 3 distractors
If you want to distribute them randomly to the locations, shuffle the
locations like so:
random.shuffle(locations)


See Exercises 3 and 4 here:
http://sapir.psych.wisc.edu/wiki/index.php/Psych711


-----------------------------------------------------
Gary Lupyan - lup...@wisc.edu
Assistant Professor of Psychology
University of Wisconsin, Madison
http://sapir.psych.wisc.edu
-----------------------------------------------------

> --
> You received this message because you are subscribed to the Google Groups "psychopy-users" group.
> To post to this group, send email to psychop...@googlegroups.com.
> To unsubscribe from this group, send email to psychopy-user...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/psychopy-users?hl=en.
>

Message has been deleted

jacobz

unread,
Jan 19, 2012, 10:20:06 PM1/19/12
to psychopy-users
Thanks Gary! This is very helpful (as are the rest of
your demonstrations!). I've been trying to work on integrating this
code into my experiment (which, as you correctly guessed was coded in
the builder) by using a code component. I went through the examples
on your site, but I'm still a bit confused with a couple of aspects.

I'm struggling to understand how to define the "source bank" for
the objects (where the targets should be drawing from). My
understanding is that I can't define a variable as containing multiple
objects (e.g., "targets = [t1.jpg, t2.jpg]"). Is there another way to
specify where the random samples are drawn from?

In a similar vein, I'm not sure how to define the locations that the
randomly selected objects should be placed in. Again, I'm not sure if
I can define "locations = ([-300, 300], [300, 300], etc)".


I'm really sorry if some of these questions are seemingly obvious,
but I'm new to programming and trying to push through the hurdles!
I sincerely appreciate your help, and also the help that you've
provided by making your course publicly accessible.

On Jan 18, 11:02 pm, Gary Lupyan <glup...@gmail.com> wrote:
> Horribly inefficient indeed!
> It sounds like you're using the builder which I am not familiar with,
> but in basic python code, you'd just do
>
> import(random)
>
> targets = range(2)
> distractors = range(10)
> locations = range(4)
>
> for each trial, you can then do:
> curTargets = random.sample(targets,1)
> curDistractors = random.sample(distractors,3)
>
> now you have a random sample (without replacement) of 1 target and 3 distractors
> If you want to distribute them randomly to the locations, shuffle the
> locations like so:
> random.shuffle(locations)
>
> See Exercises 3 and 4 here:http://sapir.psych.wisc.edu/wiki/index.php/Psych711
>
> -----------------------------------------------------
> Gary Lupyan - lup...@wisc.edu
> Assistant Professor of Psychology
> University of Wisconsin, Madisonhttp://sapir.psych.wisc.edu

Yaroslav Halchenko

unread,
Jan 20, 2012, 9:56:34 AM1/20/12
to psychop...@googlegroups.com
just keep in mind that sequence

AAAABBBB is as random as ABBABAAB to the pseudorandom numbers
generator so you might like to QA random sequences regarding
present undesired trial-orders and simply choose the one which is ok for
your purposes. You might also like to look into
http://neuro.debian.net/pkgs/debruijn.html and alike for perfect counter
balancing

Cheers

> > import(random)

> > > Thanks!

--
=------------------------------------------------------------------=
Keep in touch www.onerussian.com
Yaroslav Halchenko www.ohloh.net/accounts/yarikoptic

jacobz

unread,
Jan 25, 2012, 10:24:45 AM1/25/12
to psychopy-users
Hi Everyone - I wanted to post an update as I'm getting close to a
solution. I really appreciate all of the help that you guys have
offered as it's been instrumental to getting me this far! The main
problem that I'm having now is how to use a dynamically changing
stimulus position as a variable in the "pos" spot on my object. I've
tried setting a variable (e.g., distractor0pos = [400,400]) and then
using $distractor0pos as the position, but that doesn't seem to work.
Does anyone have any suggestions?

Here's the code I have so far:

alldistractors = ["d1.jpg", "d2.jpg", "d3.jpg", "d4.jpg", "d5.jpg",
"d6.jpg", "d7.jpg", "d8.jpg", "d9.jpg", "d10.jpg"]
distractors = random.sample(alldistractors, 3)
distractor0 = distractors[0]
distractor1 = distractors[1]
distractor2 = distractors[2]

randtarget = random.randint(1, 2)
if randtarget == 1:
targetobject= "t1.jpg" #top left
if randtarget == 2:
targetobject= "t2.jpg" #top left

randposition = random.randint(1,4)
if randposition == 1:
targetPos=[-400, 400] #top left
searchcorrAns = 4
distractor0Pos=[400, -400]
distractor1Pos=[-400, -400]
distractor2Pos=[400, 400]
if randposition == 2:
targetPos=[400, 400] #top right
searchcorrAns = 5
distractor0Pos=[-400, 400]
distractor1Pos=[-400, -400]
distractor2Pos=[400, -400]
if randposition == 3:
targetPos=[-400, -400] #bottom left
searchcorrAns = 1
distractor0Pos=[-400, 400]
distractor1Pos=[400, -400]
distractor2Pos=[400, -400]
if randposition == 4:
targetPos=[400, -400] #bottom right
searchcorrAns = 2
distractor0Pos=[-400, 400]
distractor1Pos=[400, 400]
distractor2Pos=[-400, -400]

On Jan 20, 8:56 am, Yaroslav Halchenko <yarikop...@gmail.com> wrote:
> just keep in mind that sequence
>
> AAAABBBB  is as random as ABBABAAB  to the pseudorandom numbers
> generator so you might like to QA random sequences regarding
> present undesired trial-orders and simply choose the one which is ok for
> your purposes.  You might also like to look intohttp://neuro.debian.net/pkgs/debruijn.htmland alike for perfect counter

Chris Cox

unread,
Jan 25, 2012, 11:17:47 AM1/25/12
to psychop...@googlegroups.com
Hey Jacob,

If all you want to do is generate a display of 4 stimuli, which are always filling the same 4 "slots" on the screen, all you need to do is select 4 stimuli and set their positions appropriately. This can be done with two lists. The function you should be looking into is random.shuffle(). It will shuffle a list in place (which means that you don't create a new, shuffled version of the list, you just literally shuffle the list). For the sake of example, let's assume you have all of your stimuli in a directory called STIMULI and you can safely load them all at the same time:

import os

stimDir = 'path/to/STIMULI'
fileList = [os.path.join(stimDir,file) for file in os.listdir(stimDir)]
stimList = [visual.PatchStim(win=win,tex=file) for file in fileList] # Google "List Comprehension Python" to help understand these two lines
posList = [(400,400),(-400,400),(400,-400),(-400,-400)]

numberOfTrials = 12
for trial in range(numberOfTrials):
random.shuffle(stimList):
pick4stimuli = stimList[0:4]
for stim,pos in zip(pick4stimuli,posList):
stim.setPos(pos)
stim.draw()
win.flip()

To handle including your targets, you could just make a list of targets, pick one on each iteration, and insert it into the list display list in a controlled way:

distDir = 'path/to/STIMULI/DISTRACTORS'
targDir = 'path/to/STIMULI/TARGETS'
distFileList = [os.path.join(distDir,file) for file in os.listdir(distDir)]
targFileList = [os.path.join(targDir,file) for file in os.listdir(targDir)]

distList = [visual.PatchStim(win=win,tex=file) for file in distFileList]
targList = [visual.PatchStim(win=win,tex=file) for file in targFileList]
posList = [(400,400),(-400,400),(400,-400),(-400,-400)]

targPos = range(4) * 3
random.shuffle(targPos)

numberOfTrials = 12
for trial in range(numberOfTrials):
random.shuffle(stimList):
stimToDisplay = distList[0:3]
stimToDisplay.insert(targPos[trial],targList[trial])
for stim,pos in zip(stimToDisplay,posList):
stim.setPos(pos)
stim.draw()
win.flip()

I'm also sticking the second block of code on pastebin, so it's a little easier to read. There might be some things here that don't make sense, but try to work through this code, and feel free to shoot me questions to clarify. Also, I hope there aren't typos, because I didn't test this code...

http://pastebin.com/XU2q8cB4

Chris

Reply all
Reply to author
Forward
0 new messages