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