Skip to content

Commit

Permalink
Adding new code
Browse files Browse the repository at this point in the history
  • Loading branch information
Gian Perrone authored and Gian Perrone committed Jan 21, 2013
1 parent 4bb5e8d commit f996f15
Show file tree
Hide file tree
Showing 11 changed files with 534 additions and 15 deletions.
2 changes: 1 addition & 1 deletion detect/dispersion.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def next(self):

else:
# Remove the first element
self.window.pop(0)
self.window = self.window[1:]
# Recurse.
return self.next()

Expand Down
3 changes: 3 additions & 0 deletions detect/eventstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def centroid(self,window):
"""Compute a centroid for a window of points."""
xs = 0
ys = 0

if len(window) == 0:
raise StopIteration

for p in window:
xs = xs + p.x
Expand Down
1 change: 0 additions & 1 deletion detect/hmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ def next(self):

for curr in self.input:
v = self.intersampleVelocity(self.prev,curr)

obs.append(v)
inp.append(self.prev)
self.prev = curr
Expand Down
21 changes: 21 additions & 0 deletions detect/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,25 @@ def next(self):

return self.data.pop(0)

class FileSampleStream(SampleStream):
def __init__(self,filename):
self.handle = open(filename, 'r')
self.handle.readline() # skip header
self.index = 0

def next(self):
line = self.handle.readline()
if line == '':
raise StopIteration

f = line.split('\t')

self.index = self.index + 1

t = float(f[0]) / 1000000.0 # Microseconds to seconds

s = Sample(self.index, int(f[0]), int(f[1]), int(f[2]))
s.eventType = int(f[3][:-1])

return s

124 changes: 124 additions & 0 deletions detect/srr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
###############################################################################
# Event Detection Algorithm Suite
# Copyright (C) 2012 Gian Perrone (http://github.com/gian)
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both the copyright notice and this permission notice and warranty
# disclaimer appear in supporting documentation, and that the name of
# the above copyright holders, or their entities, not be used in
# advertising or publicity pertaining to distribution of the software
# without specific, written prior permission.
#
# The above copyright holders disclaim all warranties with regard to
# this software, including all implied warranties of merchantability and
# fitness. In no event shall the above copyright holders be liable for
# any special, indirect or consequential damages or any damages
# whatsoever resulting from loss of use, data or profits, whether in an
# action of contract, negligence or other tortious action, arising out
# of or in connection with the use or performance of this software.
###############################################################################

from . import eventstream
from eventstream import EventStream
from eventstream import EFixation
import math

class SRR(EventStream):
"""A velocity and acceleration threshold-based algorithm,
based on the descriptions given in the SR Research EyeLink manual (1.3.0)
and default parameters given by Holmqvist et al. in
Eye Tracking: A comprehensive guide to methods and measures (2011).
The EyeLink algorithm parameters are usually given in terms of
degrees/s and degrees/s^2. Our inputs are consistently based upon
pixels/s and pixels/s^2. The DegreesOfVision class contains translation
calculators for converting between these.
This algorithm by default does no filtering of input streams. Use one of the other
filter modules to provide custom filtering behaviour prior to applying this event
detector.
Parameters:
windowSize: the size of the window (in samples).
velThresh (pixels/s) The velocity above which to detect a saccade.
accelThresh (pixels/s^2) The acceleration threshold above which to detect a saccade.
"""
def __init__(self, sampleStream, windowSize, velThresh, accelThresh):
super(SRR, self).__init__(sampleStream)
self.windowSize = windowSize
self.velThresh = velThresh
self.accelThresh = accelThresh
self.window = []
self.prevVelocity = 0.0
self.prevTime = 0

def fillWindow(self):
try:
while len(self.window) < self.windowSize:
self.window.append(self.input.next())
except StopIteration:
return

def windowVelocity(self):
""" Compute average inter-sample velocity over a window of samples. """
prev = self.window[0]

dsum = 0
interval = 0

for curr in self.window[1:]:

dx = curr.x - prev.x
dy = curr.y - prev.y
dt = curr.time - prev.time

if dt <= 0:
dt = 1

dsum = dsum + math.sqrt(dx * dx + dy * dy)
interval = interval + dt

if interval == 0:
interval = 1

return dsum / float(interval)

def windowAccel(self):
""" Compute instantaneous acceleration over a window of samples. """
# We use the self.prevVelocity

currTime = self.window[0].time
currVelocity = self.windowVelocity()
dt = currTime - self.prevTime
dv = currVelocity - self.prevVelocity

self.prevVelocity = currVelocity
self.prevTime = currTime

if dt == 0.0:
dt = 1.0

return dv / float(dt)


def next(self):
# Fill the window with samples.
self.fillWindow()

if len(self.window) == 0:
raise StopIteration

ac = self.windowAccel()
vc = self.windowVelocity()

self.window = self.window[1:]

print "AC: " + str(ac) + " V: " + str(vc)

return 0




1 change: 0 additions & 1 deletion detect/velocity.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def next(self):

for curr in self.input:
v = self.intersampleVelocity(self.prev,curr)

if v < self.threshold:
fixation.append(self.prev)
self.prev = curr
Expand Down
4 changes: 2 additions & 2 deletions detect/weightedfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ def intersampleVelocity(self,prev,curr):

if dt <= 0:
# We can't work with a zero or negative time interval, so we
# return an arbitrary velocity above the threshold.
return 10000.0 + self.threshold
# return an arbitrary large velocity
return 10000.0

d = math.sqrt(dx * dx + dy * dy)

Expand Down
130 changes: 130 additions & 0 deletions hmmTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
###############################################################################
# Event Detection Algorithm Suite
# Copyright (C) 2012 Gian Perrone (http://github.com/gian)
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both the copyright notice and this permission notice and warranty
# disclaimer appear in supporting documentation, and that the name of
# the above copyright holders, or their entities, not be used in
# advertising or publicity pertaining to distribution of the software
# without specific, written prior permission.
#
# The above copyright holders disclaim all warranties with regard to
# this software, including all implied warranties of merchantability and
# fitness. In no event shall the above copyright holders be liable for
# any special, indirect or consequential damages or any damages
# whatsoever resulting from loss of use, data or profits, whether in an
# action of contract, negligence or other tortious action, arising out
# of or in connection with the use or performance of this software.
###############################################################################

from detect.sample import Sample
from detect.sample import FileSampleStream

from detect.dispersion import *
from detect.velocity import *
from detect.hmm import *
from detect.prefix import *
from detect.aoi import *
from detect.movingaverage import *
from detect.srr import *

print "============= I-VT test ==============="

stream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt')

fstream = MovingAverageFilter(stream,9)

idt = HMM(fstream, 0.001, 0.001, 0.005, 0.5, 0.95, 0.05, 0.95, 0.05)

fixations = []

for i in idt:
print i
fixations.append(i)

verifStream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt')

taggedEvents = []
cfix = []
eventType = []
for i in verifStream:
if i.eventType == 1:
cfix.append(i)
eventType.append(1)
else:
eventType.append(0)
if len(cfix) == 0:
continue
print ("Fixation of length: " + str(len(cfix)) + " starting at sample " + str(cfix[0].index))
p = idt.centroid(cfix)

f = EFixation(p, len(cfix), cfix[0], cfix[-1])
taggedEvents.append(f)
cfix = []

verifStream = FileSampleStream('testData/UH27_img_vy_labelled_MN.txt')

saccEvents = []
csacc = []
saccEventType = []
for i in verifStream:
if i.eventType == 2:
csacc.append(i)
saccEventType.append(1)
else:
saccEventType.append(0)
if len(csacc) == 0:
continue
print ("Saccade of length: " + str(len(csacc)) + " starting at sample " + str(csacc[0].index))

f = ESaccade(len(csacc), csacc[0], csacc[-1])
saccEvents.append(f)
csacc = []


matchedSamples = 0
errorSamples = 0
fixCount = 0
for f in fixations:
if f.type != 'fixation':
continue
s = f.start.index
for i in range(s,s+f.length):
fixCount = fixCount + 1
if eventType[i] == 1:
matchedSamples = matchedSamples + 1
else:
errorSamples = errorSamples + 1

mPct = matchedSamples / float(fixCount)
ePct = errorSamples / float(fixCount)

print "Fixations:"
print "Matched Samples: " + str(matchedSamples) + " (" + str(mPct * 100) + "%)"
print "Error Samples: " + str(errorSamples) + " (" + str(ePct * 100) + "%)"

matchedSamples = 0
errorSamples = 0
saccCount = 0

for f in fixations:
if f.type != 'saccade':
continue
s = f.start.index
for i in range(s,s+f.length):
if saccEventType[i] == 1:
saccCount = saccCount + 1
matchedSamples = matchedSamples + 1
else:
errorSamples = errorSamples + 1

mPct = matchedSamples / float(saccCount)
ePct = errorSamples / float(saccCount)
print "Saccades:"
print "Matched Samples: " + str(matchedSamples) + " (" + str(mPct * 100) + "%)"
print "Error Samples: " + str(errorSamples) + " (" + str(ePct * 100) + "%)"


Loading

0 comments on commit f996f15

Please sign in to comment.