Oddball paradigm - How to set probabilities of oddball or common stimulus

Hello Suddha,

I didn’t know about this in-built method. I’ve now created my oddball paradigm in a different way. For anyone interested in doing it my way. This code randomises single (oddball) and pair stimulation but ensures that there can never be two continuous single stimulations in a row:

#begin experiment
import random
import serial
from psychopy import sound
import serial
import psychtoolbox as ptb
from psychopy.core import StaticPeriod

#loads the sound file and plays sound for 0.2 seconds
tactors1 = sound.Sound('experiment_audio.wav', name='$tactors1', stereo = True, secs = 0.2)
tactors1.setVolume(1)
tactors1.playing = False
tactors1.waiting = False


tactors2 = sound.Sound('experiment_audio.wav', name='$tactors2', stereo = True, secs = 0.2)
tactors2.setVolume(1)
tactors2.playing = False
tactors2.waiting = False
first_tactor_start_time = core.getTime()
first_tactor_stop_time = core.getTime()

first_tactor_played = False


#this is serial port of the tactors. Change COM8 to another number if 'USB Serial Port' in Ports in Device manager has changed COM number
##port_tactors = serial.Serial('COM8',57600)
##port_tactors.write([0x1b, 0x54, 0x31, 0x4c, 0x44])
##port_tactors.write([0x1b, 0x54, 0x32, 0x52, 0x44])

##port_trigger_eeg = serial.Serial('COM5')
##port_trigger_eeg.write([0x00])


tactors1_on_times = 0
tactors2_on_times = 0

#array approach

import random

stimulation_array = []
one_indices = set()

while len(one_indices) != 15:
    # set 2nd integer to however many total stimulations you'd like to deliver in total -1
    idx = random.randint(0, 39)
    if not {idx, idx+1, idx-1} & one_indices:
        one_indices.add(idx)
# range should be total number of stimulations but not total -1
for idx in range(40):
    if idx in one_indices:
        stimulation_array.append(1)
    else:
        stimulation_array.append(2)

print(stimulation_array)
length = len(stimulation_array)
array_position_number = 0
value = stimulation_array[array_position_number]


#begin routine

tactors1Onsets=[]
tactors1ISIs=[]

tactors2Onsets=[]
tactors2ISIs=[]


pulse_started_tactors1 = False
pulse_ended_tactors1 = False

pulse_started_tactors2 = False
pulse_ended_tactors2 = False

pulse_started_trigger = False
pulse_ended_trigger = False


tactors1.playing = False
tactors2.playing = False

trial_ended = True

#each frame

# we want to present the tone every
# 5 - 9 seconds for the duration of the trial
# if the sound is not currently playing
if not tactors1.playing and not tactors1.waiting:
    if trial_ended == True:
        # pick how long we will wait for
        tactors1ISI = randint(5, 9)
        print('tactorISI', tactors1ISI)
        tactors1ISIs.append(tactors1ISI)
        tactors1Onset = t +tactors1ISI
        #we are waiting for the sound to play
        tactors1.waiting = True
        tactors2.waiting = False

        # If Loop to iterate through list:
        if array_position_number < length and tactors1_on_times >5:
                value = stimulation_array[array_position_number]
                array_position_number += 1
                print('array position number is ',array_position_number)
        
        #reset trial variables
        pulse_started_tactors1 = False
        pulse_ended_tactors1 = False
        pulse_started_tactors2 = False
        pulse_ended_tactors2 = False
        trial_ended = False
elif not tactors1.playing and tactors1.waiting:
    if t >= tactors1Onset:
        print('playing 1st tactor')
        tactors1.play()
        tactors1_on_times +=1
        tactors1Onsets.append(t)
        tactors1.playing = True
        tactors1.waiting = False
        first_tactor_start_time = core.getTime() # Gets a timestamp of the start of the first vibration       
        ##port_tactors.write([0x1b, 0x54, 0x31,0x45])
        ##port_tactors.write([0x1b, 0x54, 0x32,0x45])
        ##port_trigger_eeg.write([0x01])
        

if tactors1.playing:
    if t >= tactors1Onset + tactors1.secs:
            tactors1.stop()
            ##port_tactors.write([0x1b, 0x54, 0x31,0x44])
            ##port_tactors.write([0x1b, 0x54, 0x32,0x44])
            tactors1.playing = False
            first_tactor_played = True
            first_tactor_stop_time = core.getTime()


if tactors1.playing == True and not pulse_started_tactors1:
    pulse_start_time_tactors1 = globalClock.getTime()
    pulse_started_tactors1 = True
    print("tactor1 has played",tactors1_on_times,"times.")


if pulse_started_tactors1 and not pulse_ended_tactors1:
    if globalClock.getTime() - pulse_start_time_tactors1 >= 0.01:
        ##port_trigger_eeg.write([0x00])
        pulse_ended_tactors1 = True

#2nd vibration

if not tactors2.playing and not tactors2.waiting:
    if first_tactor_played == True:
            # pick how long we will wait for
            tactors2ISI = 0.7
            print('tactor2ISI', tactors2ISI)
            tactors2ISIs.append(tactors2ISI)
            tactors2Onset = t +tactors2ISI
            #we are waiting for the sound to play
            tactors2.waiting = True

if not tactors2.playing and tactors2.waiting:
    if first_tactor_played == True and tactors1_on_times <=5:
        if t >= tactors2Onset:
            print('playing 2nd tactor')
            tactors2.play()
            tactors2_on_times +=1
            tactors2Onsets.append(t)
            print("tactor2 has played ",tactors2_on_times,"times.")
            ##port_tactors.write([0x1b, 0x54, 0x31,0x45])
            ##port_tactors.write([0x1b, 0x54, 0x32,0x45])
            ##port_trigger_eeg.write([0x02])
            tactors2.playing = True
            tactors2.waiting = False
            
    elif first_tactor_played == True and tactors1_on_times >5:
        if value>1 and t >= tactors2Onset:
            print('playing 2nd tactor')
            tactors2.play()
            tactors2_on_times +=1
            tactors2Onsets.append(t)
            print("tactor2 has played ",tactors2_on_times,"times.")
            ##port_tactors.write([0x1b, 0x54, 0x31,0x45])
            ##port_tactors.write([0x1b, 0x54, 0x32,0x45])
            ##port_trigger_eeg.write([0x02])
            tactors2.playing = True
            tactors2.waiting = False
   
        elif value <= 1:
            trial_ended = True
            first_tactor_played == False


if tactors2.playing:
    if t >= tactors2Onset + tactors2.secs:
            tactors2.stop()
            tactors2.playing = False
            ##port_tactors.write([0x1b, 0x54, 0x31,0x44])
            ##port_tactors.write([0x1b, 0x54, 0x32,0x44])
            first_tactor_played = False
            
if tactors2.playing == True and not pulse_started_tactors2:
    pulse_start_time_tactors2 = globalClock.getTime()
    pulse_started_tactors2 = True
    pulse_ended_tactors2 = False
    print("tactor2 has played",tactors2_on_times,"times.")


if pulse_started_tactors2 and not pulse_ended_tactors2:
    if globalClock.getTime() - pulse_start_time_tactors2 >= 0.01:
        ##port_trigger_eeg.write([0x00])
        pulse_ended_tactors2 = True
        trial_ended = True


Hopefully others trying to create oddball experiments will find this code useful :slight_smile: