0

I am using the PsychoPy Builder and have used the code only rudimentary. Now I'm having a problem for which I think coding is inevitable, but I have no idea how to do it and so far, I didn't find helpful answers in the net.

I have an experiment with pictures of 3 valences (negative, neutral, positive). In one of the corners of the pictures, additional pictures (letters and numbers) can appear (randomly in one of the 4 positions) in random latencies.

All in all, with all combinations (taken the identity of the letters/numbers into account), I have more than 2000 trial possibilities. But I only need 72 trials, with the condition that each valence appears 24 times (or: each of the 36 pictures 2 times) and each latency 36 times. Thus, the valence and latency should be counterbalanced, but the positions and the identities of the letters and numbers can be random. However, in a specific rate, (in 25% of the trials) no letters/ numbers should apear in the corners.

Is there a way to do it?

Sarah
  • 35
  • 6

2 Answers2

0

Here is a strategy you could try, but as I don't use builder I can't integrate it into that work flow.

Prepare a list that has the types of trials you want in the write numbers. You could type this by hand if needed. For example mytrials = ['a','a',...'d','d'] where those letters represent some label for the combination of trial types you want.

Then open up the console and permute that list (i.e. shuffle it).

import random
random.shuffle(mytrials)

That will shift the mytrials around. You can see that by just printing that. When you are happy with that paste that into your code with some sort of loop like

t in mytrials:
   if t == 'a':
      <grab a picture of type 'a'>
   elseif t == 'b':
      <grab a picture of type 'b'>
   else:
      <grab a picture of type 'c'>
   <then show the picture you grabbed>

There are programmatic ways to build the list with the right number of repeats, but for what you are doing it may be easier to just get going with a hand written list, and then worry about making it fancier once that works.

brittAnderson
  • 1,428
  • 11
  • 25
0

Adding a pretty simple code component in builder will do this for you. I'm a bit confused about the conditions, but you'll probably get the general idea. Let's assume that you have your 72 "fixed" conditions in a conditions file and a loop with a routine that runs for each of these conditions.

I assume that you have a TextStim in your stimulus routine. Let's say that you called it 'letternumber'. Then the general strategy is to pre-compute a list of randomized characters and positions for each of the 72 trials and then just display them as we move through the experiment. To do this, add a code component to the top of your stimulus routine and add under "begin experiment":

import random  # we'll use this module to pick random elements from below
# Indicator sequence, specifying whether letter/number should be shown. False= do not show. True = do show.
show_letternumber = [False] * 18 + [True] * 54  # 18/72=25%, 54/72=75%.
random.shuffle(show_letternumber)

# Sets of letters and numbers to present
char_set = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g']  # ... and so on.
char_trial = [random.choice(char_set) if show_char else '' for show_char in char_set]  # list with characters

# List of positions
pos_set = [(0.5, 0.5),(-0.5, 0.5),(-0.5,-0.5),(0.5, -0.5)]  # coordinates of your four corners
pos_trial = [random.choice(pos_set) for char in char_trial]

Then under "begin routine" in the code component, set the lettersnumbers to show the value of character_trial for that trial and at the position in pos_trial.

letternumbers.pos = pos_trial[trials.thisN]  # set position. trials.thisN is the current trial number
letternumbers.text = char_trial[trials.thisN]  # set text

# Save to data/log
trials.addData('pos', pos_trial[trials.thisN])
trials.addData('char', char_trial[trials.thisN])

You may need to tick "set every repeat" for the lettersnumbers component in Builder for the text to actually show.

Jonas Lindeløv
  • 5,442
  • 6
  • 31
  • 54
  • As I'm really new to this, it took me a while to find out that in the "each trial" (whis is called "each frame" in my version) code component the "trials" stands for the name of the loop. But now it seems to work. Thank you! – Sarah Jun 04 '15 at 12:01
  • Ah, sorry, it's "begin routine". And insert the second code snippet in "begin routine". You only need to do this once per routine so this would save a bit of performance, but more importantly, make more sense. Updated the answer accordingly. – Jonas Lindeløv Jun 04 '15 at 19:55
  • Unfortunately, after a couple of trials, I get an error feedback and the program stops. The error feedback is: ... letternumbers.pos=pos_trial[trials.thisN] IndexError: list index out of range – Sarah Jun 10 '15 at 13:02