PDA

View Full Version : motion tracker changes Vizard timing


jelly
06-07-2016, 01:29 PM
Hello!

I am having very weird timing problems when running my script with the Polhemus motion tracker as opposed to without.

It only happens when I uncomment the section of the code that writes an output file with the position data of the tracker markers. It does not matter if Polhemus is running in parallel, as long as the Vizard script is not using the data.

Has anyone ever had anything similar and knows how to solve this problem? :confused:

Thanks in advance!

J

Jeff
06-09-2016, 02:10 AM
Can you explain further what you mean by timing problems? It would probably help if you post example code that shows the issue.

jelly
06-09-2016, 04:53 AM
Dear Jeff,

I will try to post some code later this evening, the script is so large by now, it really is difficult to tell what is causing it. So I will need to try and create a simpler version.

In principle, I think it could be related to frequency or sampling. I've had a colleague who has told me that she had sounds in her script (like me) and they did not play at exactly the same time from one execution to the next. Another one had a countdown timer clock that was sometimes skipping the display of seconds. And another who had a beep sound that played three times at the end of a trial. There was supposed to be a 1s gap between each beep but sometimes the gaps were audibly uneven and the timer on screen was a bit slow. While for them this was not crucial, the timing of the sounds in my experiment is! All of us were/are using the Polhemus motion tracker.

I will follow this up later with a less complex code version that hopefully still illustrates the problem!

jelly
06-09-2016, 12:17 PM
Dear Jeff,

I have some code below, which is also writing an output file. It only requires a sound .wav file as a cue, otherwise it should run on the spot and illustrate the issue.

When running it, you can see on the screen display that the sampling will freeze and skip seconds. Mostly it seems as if it balances itself out, meaning that if one second froze for too long, then another second at another time will be skipped.

Another thing I am thinking is (because my other colleagues also had similar problem when using sound) that maybe the sampling is faster than the sound and this interaction somehow causes some problems. But running the code with all the sound related things commented still has the problem...:confused:


import time
import viztask
import numpy as np
import random
import vizact
import itertools

viz.go()

###########################
## GENERAL SETUP
###########################


viz.MainView.setPosition(0,1.8,0)
viz.MainView.setEuler(0,0,0)
viz.mouse.setVisible(viz.OFF) #Stops the mouse appearing on the screen.
viz.mouse.setOverride(viz.ON) #Stops Vizard navigation using the mouse.

#Set background colour
viz.clearcolor(viz.BLACK) #Set background colour to black

ID = input('Participant ID: ') #This is the unique ID number to identify the participant.
suffix = input('Suffix: ') #This is the suffix to the participant's ID number, used for not overwriting data files.
#Create a data ID and data header for the participant:
dataID = str(ID) + '_' + str(suffix) #Adds a suffix to the session number so that files can't be overwritten.
#Create a first line to write to data files:
firstLine = 'Study Data \n'


####~~~~~~~Make Windows for Textures~~~~~~~####

#make box for clock
timeBox = viz.addText('', viz.SCREEN)
timeBox.setPosition(0.5,0.5)
timeBox.setScale([0.4, 0.4, 0.4])
timeBox.alignment(viz.ALIGN_CENTER_CENTER)
timeBox.color([1,1,1])

###########################
## OUTPUT FILE
###########################

####~~~~~~~OUTPUT~~~~~~~####
Data = open(str(dataID) + '_Data3.txt','w')
DataHeaders = 'ID\tPic\tTimeNow\tPicstate\tBeepstate\n'
Data.write(firstLine)
Data.close()

####~~~~~~~Create fuction for saving data~~~~~~~####

def saveData():

global picstateString, beepstateString, timeNow

Data = open(str(dataID) + '_Data3.txt','a', 1) # 'a' means append the file rather than overwrite

vars = "%s\t%s\t%s\t%s\t%s\n" %(
ID, hno, timeNow, picstateString, beepstateString)

Data.write(vars)


###########################
## STIMULI
###########################

### Cue sound
cue = viz.addAudio('cues\dong.wav')
cueDuration = cue.getDuration()

picList = np.arange(1, 59, 1) # this is in the real experiment an actual list of jpegs


### Timings ###

beeptimes = []
otimes2 = []
ctimes2 = []
otimes_short2 = []
otimes_long2 = []
ctimes_short2 = []
ctimes_long2 = []


def uniform_min_range(a, b, n, min_dist):
while True:
atimes = np.random.uniform(a, b, size=n)
np.sort(atimes)
if np.all(np.diff(atimes) >= min_dist):
return atimes

def timings():
global condition, beeptimes, otimes, ctimes, otimes2, ctimes2, otimes_short2, otimes_long2, ctimes_short2, ctimes_long2, ctimes2String, otimes2String, beeptimesString

beeptimes = uniform_min_range(0, 20, 5, 1.0)
print 'beep times: ', beeptimes
beeptimesString = 'BeepTimes: '+','.join(map(str,beeptimes)) + '\n'
num_to_select = 4

otimes = random.sample(beeptimes, num_to_select)
ctimes = list(set(beeptimes) - set(otimes))

otimes1 = [oo + 0.8 for oo in otimes]
otimes2 = np.sort(otimes1)
print 'otimes short', otimes2
ctimes2 = [ctimes[0] + 0.8]
print 'ctimes short', ctimes2

otimes2String = 'S1 Times: ' + ',' .join(map(str,otimes2)) +'\n'
ctimes2String = 'S2 Times: ' + ','.join(map(str,ctimes2)) +'\n'

### Picture state

hno = 30

def setup_pics(): # at 0 nothing happens; at 1 (or -1) something happens (a beep, a pic) --> this sets it up
global tt, picstate, beepstate, picstateString, beepstateString, beeptimesString, otimes2String, ctimes2String

global beeptimes, otimes, ctimes, otimes_short2, otimes_long2, ctimes_short2, ctimes_long2
timings()

Data = open(str(dataID) + '_Data3.txt','a',1)
Data.write(beeptimesString)
Data.write(otimes2String)
Data.write(ctimes2String)
Data.write(DataHeaders)


tt =[]
dt = 0.04 #seconds for increment
tt.append(0) #first elem in tt is 0

picstate = []
picstate.append(0) #first elem in picstate is 0

beepstate = []
beepstate.append(0)

n=0
done = 0
while not done: #keep adding elements to the picstate list
n=n+1 #elem by elem
picstate.append(0)
beepstate.append(0)
tt.append(tt[n-1]+dt) #keep adding time elements to time list, by adding dt = 0.04 s to the one b4


for oo in otimes2: # for each elem in the otimes
if (oo - tt[n]<0.5 and oo-tt[n]>0): #if the element in the otimes minus the current element in tt is lower than 0.5 and bigger than 0 (basically between 0 and 0,5) than choose action 1
picstate[n] = 1
for pp in ctimes2: #if the element in the closing times minus the current element in tt is lower than 0.5 and bigger than 0 (basically between 0 and 0,5) than choose action 2
if (pp - tt[n]<0.5 and pp-tt[n]>0):
picstate[n] = -1
for bs in beeptimes:
if (bs - tt[n]<0.5 and bs-tt[n]>0):
beepstate[n] = 1
if tt[n] > 25: # if the current element in tt is bigger than 20 then stop the loop to add to the list, it's over
done = 1

print 'tt', tt
print 'picstate', picstate
print 'beepstate', beepstate

def choose_pic():
global picstate, beepstate, picstateString, beepstateString, timeNow
global hno
global tt, start, ntt


ntt = viz.tick()-start # get time NOW since start of trial (can be made to be since start of experiment)
nn = np.searchsorted(tt,ntt,side='left')

thispic = picstate[nn]
thisbeep = beepstate[nn]

if thisbeep == 1 and thisbeep-1 == 0:
def cueplay():
cue.play()
#yield viztask.waitTime(cueDuration)
#cue.stop()
cueplay()


picstateString = str(picstate[nn])
beepstateString = str(beepstate[nn])
timeNow = str(round(ntt,2)) # string of time Now ntt (rounded) to print in output file

### DEFAULT - random walk
if thispic==0:
prob = [0.05, 0.95] # Probability to move up or down
rr = np.random.random(1)
if hno<27:
hno = hno+2
elif hno>35:
hno = hno-2
else:
if rr < prob[0] and hno>27:
hno = hno-1
elif rr > prob[1] and hno<35:
hno = hno+1

### STATE1
elif thispic==1: ## state for triggering action 1
if hno<54:
hno = hno+5

### STATE2
elif thispic==-1: ## state for triggering action 1
if hno>4:
hno = hno-5

##save stuff
saveData()

## DISPLAY
time_left = round(20-ntt,0)

timeBox.message('Time: '+str(int(round(ntt)))+' - '+'PictureNo: '+ str(picstate[nn])+ ' - '+ 'Beep: '+str(beepstate[nn])+' - ' + str(nn))


###########################
## TRIAL
###########################

def mainTrial():
global start, nn
nn = 1
setup_pics()
start = viz.tick()
vizact.ontimer2(0.035,500,choose_pic)
yield viztask.waitTime(25)


viztask.schedule(mainTrial())





The problem with the tracker may be more complex but it is possible that not the tracker is the problem after all. The code I have embedded below, ignores the motion tracker altogether and still I have some timing issues. I guess it is better to understand/solve these first, before moving on.

Any help or ideas are very welcome and I would be very grateful for them!

jelly
06-13-2016, 11:34 AM
For now, I think I have found the problem! It explains why I had the issue with the motion tracker on or off. The cause was not the tracker itself but the way the function which was writing the output was implemented. It was messing up the sampling, slowing it down, since the output file had to be opened, data saved and written each time.

Now that I am only saving data at each timepoint and writing it only once at the very end, the issue seems to be gone.