psychopy.org | Reference | Downloads | Github

How to ensure randomised sound is 50/50 across trials

It’s currently set as

if soundFlag < 6:
    soundFlag = 0
else:
    soundFlag = 1

sound_5.setVolume(soundFlag, log=False)

We don’t know what soundFlag is or how it was generated.

To get useful responses on forums like this, first ask yourself "could someone answer this question, knowing nothing other than what I wrote down for them?

I’m sorry I didn’t realise the question was vague. The sound is an auditory beep and soundFlag is set for the volume whether it is mute or sound is on. The sound has been randomised using the code above whether sound is mute or on. However, I would like the sound to be on for half the trial and mute for the other half (whilst still being random).

soundFlag = 0;

You still haven’t answered this. If the issue is how to balance the trials 50:50, then that requires that you take that constraint into account when generating this variable on a trial-by-trial basis. We don’t know how you have done that to date, so we can’t suggest improvements.

But starting from scratch, and without knowing anything else about your design (e.g. the number of trials), would suggest two approaches:

  • Set the sound volume variable from your conditions file, such that 50% of rows have a value of 0 and 50% a value of 1.
  • If for some reason that approach won’t work for you, then generate a balanced but randomised list of values and extract one value from the list on each trial:

Insert a code component. In its “Begin experiment” tab, put something like:

number_of_trials = 50 # use the real value

# create a balanced list of volumes:
sound_volumes = [0, 1] * (number_of_trials/2)

# randomise its order:
shuffle(sound_volumes)

Then in the “Begin routine” tab, select the next value:

current_volume = sound_volumes.pop()
thisExp.addData('volume', current_volume) # make sure to record it in the data

and then use current_volume to control the volume of your sound stimulus. Make sure the code component is above the sound component, so that the latter gets to refer to the latest version of the variable.

Thank you for your suggestions. I have tried the first suggestion of setting the sound volume from the conditions file so that 50% have the value of 0 and the others 1. However, the sound is not playing in any trials when uploaded on Pavlovia.
I set the duration to 0.05 because need the sound (a beep) to only play for 50ms.

This is the link to the study

https://run.pavlovia.org/smoha005/soundy/html

OK, so time to do some problem-solving. First remove the soundFlag variable and just replace it with a constant value of 1. Does it work then? If not, the problem lies elsewhere.

Thank you, it’s working now, however, I now keep getting an unspecified javascript error message

link: https://run.pavlovia.org/smoha005/cirso/html/

https://run.pavlovia.org/smoha005/cirso/html

The only JS code i’ve got are code are the following (code_8)

    var foo = [];
    for (var i = start; i < end; i++) {
        foo.push(i);
    }
    return foo;
}

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1)); 
    [array[i], array[j]] = [array[j], array[i]];
  }
}

var trialListCatA = range(2,6);
var trialListCatB = range(6,8);
var trialListCatC = range(8,20);
var trialListCatD = range(20,26);
var trialListCatE = range(26,38);
var trialListCatF = range(38,42);
var trialListCatG = range(42,68);

shuffle(trialListCatA);
var catAsliceBL2 = trialListCatA.slice(0,3);
var catAsliceBL3 = trialListCatA.slice(3,4);

shuffle(trialListCatG);
var catGsliceBL2 = trialListCatG.slice(0,15);
var catGsliceBL3 = trialListCatG.slice(15,26);

trialListBlock1 = trialListCatA.concat(trialListCatB);
trialListBlock2 = trialListCatC.concat(trialListCatD, catGsliceBL2, catAsliceBL2);
trialListBlock3 = trialListCatE.concat(trialListCatD, trialListCatB, trialListCatF, catGsliceBL3, catAsliceBL3);
trialListBlock4 = trialListCatA.concat(trialListCatB);```

And code_5 
```// Begin Routine
function getRandomIntInclusive(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive 
}

jitter = getRandomIntInclusive(100, 500)  // Gives random value between 100 and 500, inclusive
// This value can be passed to your blank component for providing
// a random gap between sound and stimulus```

which are both syntactically valid so I am not sure where the problem lies

@dvbridges Could you please help me. The problem is that it doesn’t say where the problem lies, I just keep getting an ‘unspecified javascript error’ whenever I try to run the experimment on Pavlovia

@dvbridges I have attached a link to the study: https://run.pavlovia.org/smoha005/jenin/html

The error message 'unspecified javascript error occurs between some trials and not others.

Hello,
I have a similar issue with randomizing the position of two text components. I’ve used ‘shuffle’ and it works well to randomize the positions, but it’s not 50/50. I think I may be setting the parameter the wrong way in the text components.

Positions = [(-.5, 0), (.5, 0)]
shuffle(Positions)

Then in one text component (target_text) I set the position to Positions[0], and for the other (competitor_text) Positions[1]. I’m not sure about the [0]/[1], but I have to specify something otherwise I get an error.

I don’t know how I could apply the “current_volume” to my situation since I have two simultaneous components. I’ll have 160 trials in total but am working with a reduced example of only 10 trials.
Any idea what I’m doing wrong?
Thanks a lot!

Yes, because it looks like you’re just randomising the choice between two options on on each trial, which will give an average close to 50% of each in the long run, but is certainly not guaranteed to be balanced. It’s the equivalent of tossing a coin on each trial.

You need to follow the above approach:

i.e. make a balanced list of 160 entries (i.e. one per trial, 80 of each position), shuffle it just once (at the start of the experiment), and then pop out an entry once per trial.

i.e. the set-up code belongs in the “begin experiment” tab, and the getting of a value for each trial (and recording it in the data) happens in the “begin routine” tab.

This will give you a random order on each session but also a guarantee of being balanced 50:50.

Begin experiment:

# balanced list of 160 values for the target:
target_positions = [0.5, -0.5] * 80

# randomised order per session:
shuffle(target_positions)

Begin routine:


target_x = target_positions.pop() # select target position for this trial
competitor_x = target_x * -0.5 # the other is on the opposite side

# record them:
thisExp.addData('target_x', target_x)
thisExp.addData('competitor_x', competitor_x)

Then in your text stimuli, specify their positions like this:

[target_x, 0]

and

[competitor_x, 0]

respectively.

Amazing, thanks a lot @Michael !
I just changed the multiplier to
competitor_x = target_x * -1
instead of -0.5, otherwise the two words were not centered.