Skip to content

Commit

Permalink
publication of pursuit tracks chase
Browse files Browse the repository at this point in the history
  • Loading branch information
matus committed Sep 7, 2015
1 parent 6af37f2 commit db1a3ae
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 572 deletions.
4 changes: 1 addition & 3 deletions code/Coord.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,6 @@ def plotAgdist():
plt.savefig(figpath+'trackAgdist')

def computeTrackInfo():
''' '''
def _hlpfun(atraj,gaze,phiold,tphi,ttraj):
dchv=np.int32(np.linalg.norm(np.diff(atraj,2,axis=0),axis=1)>0.0001)
atraj-=gaze[:atraj.shape[0],:]
Expand Down Expand Up @@ -745,8 +744,6 @@ def analyze(dat):
print ndarray2latextable(np.array(out))

if __name__ == '__main__':
codingComparison()
bla
for event in range(0,3)+range(96,100):
for vpl in range(1,5):
initVP(vpl=vpl,evl=event)
Expand All @@ -760,3 +757,4 @@ def analyze(dat):
computeMeanPF()
computeTrackInfo()
createIdealObserver()
codingComparison()
58 changes: 22 additions & 36 deletions code/FiguresMoviesTables.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,50 +934,36 @@ def svmComparison():
plt.ylabel('Time to Saccade in Sec.')
plt.savefig(figpath+'svmComparison',dpi=DPI,bbox_inches='tight')



if __name__=='__main__':
#plotScore(999,1,pcs=4,scs=0)
#plotTrack(MOVIE=False)
#plotPCvp(999,1)
#plotBTpc()
#tabLatent(97,pcs=5)
#plotPC1rail()
plotPCvp(999,1)
bla


# to create figures run
plotPC1rail()
plotBehData()
plotPC1rail()
svmComparison()
plotBTpc()
plotTrack(MOVIE=False)
plotVel()
plotPCvp(999,1)
# generation of figure 1 was not automated
plotBehData()# figures 2, 3
plotBTpc()# figure 4
plotPC1rail()# figure 5
svmComparison() # figure 6
plotTrack(MOVIE=False)# figures 7, 8
plotVel() # figure 9
plotPCvp(999,1) # figure 10

from ReplayData import compareCoding
compareCoding(vp=2,block=18,cids=[0,1,2,4])

# to create movies run
pcAddition()
plotBTmean()
plotCoeff(97)
plotCoeff(0)
plotCoeff(1)
plotTrack()
svmPlotExtrema()
plotScore(999,1,pcs=4,scs=0)
plotCoeff(97) # movie 3
pcAddition() # movie 4
plotCoeff(0)# movie 5
plotCoeff(1) # movie 6
svmPlotExtrema() # movie 7
plotTrack() # movies 8, 9
plotScore(999,1,pcs=4,scs=0) # movie 11

from ReplayData import replayTrial
#note the following trials will be displayed but not saved as movies
replayTrial(vp =1,block=11,trial=7,tlag=0.0,coderid=4)#mov01
replayTrial(vp =2,block=2,trial=19,tlag=0.0,coderid=4)#mov02
replayTrial(vp =1,block=10,trial=9,tlag=0.0,coderid=4)#mov10
replayTrial(vp =3,block=1,trial=12,tlag=0.0,coderid=4)#mov11
replayTrial(vp =3,block=1,trial=7,tlag=0.0,coderid=4)#mov12
# to create tables run
replayTrial(vp =1,block=11,trial=7,tlag=0.0,coderid=4)#movie 1
replayTrial(vp =2,block=2,trial=19,tlag=0.0,coderid=4)#movie 2
replayTrial(vp =1,block=10,trial=9,tlag=0.0,coderid=4)#movie 10
replayTrial(vp =3,block=1,trial=12,tlag=0.0,coderid=4)#movie 12
replayTrial(vp =3,block=1,trial=7,tlag=0.0,coderid=4)#movie 13

# to compute values for the tables run
si2tex()
tabLatent(0,pcs=5)
tabLatent(1,pcs=5)
Expand Down
199 changes: 0 additions & 199 deletions code/Preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,198 +175,6 @@ def readEyelink(vp,block):
data= _discardInvalidTrials(data)
return data


def readSMI(vp,block):
''' reads SMI text file (.txt) of subject VP and block BLOCK
the file should be at /smiOutput/VP<VP>B<BLOCK>.asc
requires the corresponding input files on the input path
vp - subject id
block - experiment block
returns ETData instance
NOTE: this code is experimental
TODO blinks?, latency during the transport of messages?
'''
path = os.getcwd()
path = path.rstrip('code')
f=open(path+'smiOutput/VP%03dB%d Samples.txt'%(vp,block),'r')
Qexp=Settings.load(Q.inputPath+'vp%03d'%vp+Q.delim+'SettingsExp.pkl' )
ms= Qexp.monitor.getSizePix()
try:
line=f.readline()
data=[]
PHASE= -1 # 0-DCORR, 1-TRIAL, 2-DECISION, 4-CALIB
etdat=[]
t0=[0,0,0]
calib=[]
i=0;fr=0;t=0;ftriggers=[]
while True:
words=f.readline().split()

#if i%100==0: print i
#if i<200: print i, words
#if i>1300: break
i+=1
if len(words)>2 and words[2]=='Rate:':
hz=float(words[3]);
if len(words)>2 and words[2]=='Area:':
cent=(float(words[3])/2.0,float(words[4])/2.0)
if len(words)>5 and words[5]=='MONITORDISTANCE':
distance=float(words[6])
if len(words)==0: break
# todo
## if len(words)>2 and words[2]=='!CAL':
## if len(words)==3: PHASE=4
## elif words[3]=='VALIDATION' and not (words[5]=='ABORTED'):
## if words[6] == 'RIGHT':
## calib[-1].append([t,float(words[9]),float(words[11]),RIGHTEYE])
## PHASE= -1
## else:
## calib.append([])
## calib[-1].append([t,float(words[9]),float(words[11]),LEFTEYE])
if len(words)>5 and words[5]=='FRAME':
ftriggers.append([fr,float(words[0])/1000.0,float(words[7])])
fr=int(words[6])+1
if len(words)>5 and words[5]=='TRIALID':
eye='BOTH';t=int(words[6])
PHASE=0;t0[0]=float(words[0])/1000.0
if len(words)>5 and words[5]=='START':
PHASE=1;t0[1]=float(words[0])/1000.0
if len(words)>5 and (words[5]=='DETECTION'):
PHASE=2; t0[2]= float(words[0])/1000.0
#if len(words)>2 and words[2]=='POSTTRIAL':
if len(words)>5 and (words[5]=='POSTTRIAL' or words[5]=='OMISSION'):
etdat = _reformat(etdat,t0[0],Qexp)
ftriggers=np.array(ftriggers)
print ftriggers.shape
if ftriggers.size>0: ftriggers[:,1] -= t0[1]
if etdat.size>0:
et=ETData(etdat,calib,t0,
[vp,block,t,hz,eye],fs=ftriggers)
data.append(et)

etdat=[];t0=[0,0,0];ftriggers=[];fr=0
calib=[];PHASE= -1
#LBLINK=False; RBLINK=False
if PHASE== -1 or PHASE==4: continue
if len(words)>2 and words[1]=='SMP':
# we check whether the data gaze position is on the screen
if words[7]=='.': xleft=np.nan; yleft=np.nan
else:
xleft=float(words[7]); yleft=float(words[8])
#if xleft>ms[0] or xleft<0 or yleft>ms[1] or yleft<0:
if yleft==0 or xleft==0:
xleft=np.nan; yleft=np.nan;
if words[9]=='.': xright=np.nan; yright=np.nan
else:
xright=float(words[9]); yright=float(words[10])
#if xright>ms[0] or xright<=0 or yright<=0 or yright>ms[1]:
if xright==0 or yright==0:
xright=np.nan; yright=np.nan;
meas=(float(words[0])/1000.0,xleft,yleft,
float(words[3]),xright,yright,float(words[5]))
etdat.append(meas)
f.close()
except: f.close(); raise
data=_discardInvalidTrials(data)
return data

def readTobii(vp,block,path,lagged=False,verbose=False):
'''
reads Tobii controller output of subject VP and block BLOCK
the file should be at <PATH>/VP<VP>B<BLOCK>.csv
requires the corresponding input files on the input path
vp - subject id
block - experiment block
path - path to the eyetracking data
lagged - log time stamp when the data was made available
(ca. 30 ms time lag), useful for replay
verbose - print info
returns ETData instance
Each trial starts with line '[time]\tTrial\t[nr]'
and ends with line '[time]\tOmission'
'''
from Settings import Qexp
if verbose: print 'Reading Tobii Data'
#path = os.getcwd()
#path = path.rstrip('code')
f=open(path+'VP%03dB%d.csv'%(vp,block),'r')
#Qexp=Settings.load(Q.inputPath+'vp%03d'%vp+Q.delim+'SettingsExp.pkl' )

#f=open('tobiiOutput/VP%03dB%d.csv'%(vp,block),'r')
ms= Qexp.monitor.getSizePix()
try:
data=[];trial=[]; theta=[];t=0;msgs=[]; t0=[0,0,0];reward=[]
on=False
while True:
words=f.readline()
if len(words)==0: break
words=words.strip('\n').strip('\r').split('\t')
if len(words)==2: # collect header information
if words[0]=='Recording time:':
recTime=words[1]; t0[0]=0; on=True
if words[0]=='Subject: ':on=False
if words[0]=='Recording refresh rate: ':
hz=float(words[1])
elif len(words)==4 and words[2]=='Trial':
t0[1]=trial[-1][0] # perturb
elif len(words)==4 and words[2]=='Phase':
phase=int(words[3])
elif len(words)>=11 and on: # record data
# we check whether the data gaze position is on the screen
xleft=float(words[2]); yleft=float(words[3])
if xleft>ms[0] or xleft<0 or yleft>ms[1] or yleft<0:
xleft=np.nan; yleft=np.nan;
xright=float(words[5]); yright=float(words[6])
if xright>ms[0] or xright<0 or yright<0 or yright>ms[1]:
xright=np.nan; yright=np.nan;
if lagged: tm =float(words[0])+float(words[8]);ff=int(words[1])
else: tm=float(words[0]);ff=int(words[1])-2
tdata=(tm,xleft,yleft,float(words[9]),
xright,yright,float(words[10]),ff)
trial.append(tdata)
elif len(words)>2 and (words[2]=='Detection' or words[2]=='Omission'):
# we have all data for this trial, transform to deg and append
on=False;t0[2]=trial[-1][0]
trial=np.array(trial)
trial[trial==-1]=np.nan # TODO consider validity instead of coordinates
trial=_reformat(trial,t0[0],Qexp)
#print t0, trial.shape, trial[0,0]
et=ETData(trial[:,:-1],[],t0,
[vp,block,t,hz,'BOTH'],fs=np.array([np.nan,np.nan]),recTime=recTime,msgs=msgs)
fs=trial[et.ts:et.te,[-1,0]]
fs[:,1]-=t0[1]
for fff in range(fs.shape[0]-2,-1,-1):
if fs[fff+1,0]<fs[fff,0]:
fs[fff,0]=fs[fff+1,0]
et.fs=np.zeros((fs[-1,0],3))
et.fs[:,0]=range(int(fs[-1,0]))
et.fs[:,1]=interpRange(fs[:,0],fs[:,1],et.fs[:,0])
et.fs[:,2]=interpRange(fs[:,1],range(fs.shape[0]),et.fs[:,1])
et.fs[:,2]=np.round(et.fs[:,2])
for msg in et.msgs:
if msg[2]=='Omission': msg[0]=float(msg[0]);msg[1]=float(msg[1])
if msg[2]=='Drift Correction':
msg[1]=int(round(msg[0]*75/1000.))
msg.append(msg[0]*et.hz/1000.)
elif msg[1]-et.fs.shape[0]>0:
val=(msg[1]-et.fs.shape[0])*75/et.hz+et.fs[-1,2]
msg.append(int(round(val)))
else: msg.append(int(et.fs[int(msg[1]),2]))
#et.extractBasicEvents(trial[:,:-1]);
et.phase=phase;et.reward=reward
data.append(et)
t+=1;trial=[];msgs=[];reward=[]
elif on and len(words)==6:
msgs.append([float(words[0])-t0[1],words[2]+' '+words[5]])
elif on and len(words)>2:
msgs.append([float(words[0])-t0[1],int(words[1]),words[2]])
if words[2]=='Reward On': reward=[float(words[0])-t0[1]]
if words[2]=='Reward Off': reward.append(float(words[0])-t0[1])
except: f.close(); print 'Words: ',words; raise
f.close()
if verbose:print 'Finished Reading Data'
return data

#######################################
def saveETinfo(vp=1,coderid=4,suf=''):
Expand Down Expand Up @@ -484,13 +292,6 @@ def saveETinfo(vp=1,coderid=4,suf=''):

if __name__ == '__main__':
import sys
saveTrackedAgs(vp=2,coderid=4)
bla
vp=int(sys.argv[1])
coder=int(sys.argv[2])
saveETinfo(vp=vp,coderid=coder,suf='coder%d'%coder)


#print np.int32(np.isnan(data[0].gaze[:1000,1]))
#data[0].extractBasicEvents()
#for dat in data: dat.extractBasicEvents()
10 changes: 5 additions & 5 deletions code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ Dependencies

* [PyStan](http://pystan.readthedocs.org/en/latest/) for statistical inference

* [Eyelink routines](http://github.com/simkovic/eyetracking/blob/master/Eyelink.py) to run eyetracking experiment
* [Eyelink routines](http://github.com/simkovic/eyetracking/releases/tag/pursuittrackschase) to run eyetracking experiment

* [matustools](https://github.com/simkovic/matustools) to reproduce the figures
* [matustools](http://github.com/simkovic/matustools/releases/tag/pursuittrackschase) to reproduce the figures

* [Libsvm](http://www.csie.ntu.edu.tw/~cjlin/libsvm/)

Expand All @@ -49,8 +49,8 @@ Looking to Reuse Code?

The code in this repository is meant as an documentation for the published research. The code has not been developed since the publication and may no longer work with the latest versions of its dependencies (such as Psychopy or PyStan). If you are interested in an maintained and (hopefully) up-to-date version of my code please have a look at the following repositories:

* [goal-directed motion toolkit](https://github.com/simkovic/GoaldirectedMotionPsychoexperiments) to create Stimuli and run Experiments
* [goal-directed motion toolkit](http://github.com/simkovic/GoaldirectedMotionPsychoexperiments) to create Stimuli and run Experiments

* [eyetracker](https://github.com/simkovic/eyetracking) to run Eyetracking experiments with Psychopy
* [eyetracker](http://github.com/simkovic/eyetracking) to run Eyetracking experiments with Psychopy

* [matusplotlib](https://github.com/simkovic/matusplotlib/) to plot figures
* [matusplotlib](http://github.com/simkovic/matusplotlib/) to plot figures
Loading

0 comments on commit db1a3ae

Please sign in to comment.