Package pype :: Module lzones
[frames] | no frames]

Source Code for Module pype.lzones

  1  # -*- Mode: Python; tab-width: 4; py-indent-offset: 4; -*- 
  2   
  3  """Pure python/pype landing zone (aka fixwin) implementation. 
  4   
  5  Not really for public consumption. 
  6   
  7  Author -- James A. Mazer (mazerj@gmail.com) 
  8   
  9  """ 
 10   
 11  import sys 
 12  import imp 
 13  import math 
 14   
 15  from pype import * 
 16   
 17  import filebox 
 18   
19 -class LandingZone(object):
20 """ 21 Circular Landing zone detector -- this is sort of like a FixWin, 22 but all done in pype (vs comedi_server subproc). A landing 23 zone is circular region located at (x,y) with a radius of size 24 pixels. Once the eyes enter the landing zone, a counter is 25 started. If the eyes are still in the landing zone after fixtime, 26 then it's considered a landing event the .inside() method returns 27 one. 28 29 This depends on the .inside() method being in some sort of 30 tight loop and called over and over again until something 31 happens, otherwise you might miss exit/entry events.. 32 33 Eyes must stay inside the zone for fixtime_ms before it's 34 considered a fixation insize the zone. Use fixtime_ms=0 if 35 you want to accept pass throughs w/o fixations. 36 37 """ 38
39 - def __init__(self, x, y, size, fixtime, app):
40 self.app = app 41 self.icon = None 42 self.x, self.y, self.size = x, y, size 43 self.size2 = size**2 44 self.fixtime = fixtime 45 self.entered_at = None
46
47 - def __del__(self):
48 self.clear()
49
50 - def inside(self, t=None, x=None, y=None):
51 """ 52 If you have multiple landing zones, you can sit in a loop, use 53 app.eye_txy() to query time and eye position ONCE, and then apply 54 it to multiple landing zones by passing in (x,y) values 55 56 """ 57 if t is None: 58 (t, x, y) = self.app.eye_txy() 59 if ((self.x-x)**2 + (self.y-y)**2) < self.size2: 60 if self.entered_at is None: 61 self.entered_at = t 62 if (t - self.entered_at) >= self.fixtime: 63 return 1 64 return 0 65 else: 66 self.entered_at = None 67 return 0
68
69 - def draw(self, color='grey', dash=None, text=None):
70 self.clear() 71 self.icon = self.app.udpy.icon(self.x, self.y, 72 2*self.size, 2*self.size*self.vbias, 73 color=color, type=2, dash=dash)
74
75 - def clear(self):
76 if self.icon: 77 self.app.udpy.icon(self.icon) 78 self.icon = None
79
80 -class SectorLandingZone(object):
81 """ 82 Sector-style Landing zone detector -- landing zone is defined 83 as an angular sector of an annular zone around a fixation 84 spot (xo, yo). Annular sector runs from inner_pix to outer_pix 85 and has an angular subtense of angle_deg +- subtense_deg. 86 87 Eyes must stay inside the zone for fixtime_ms before it's 88 considered a fixation insize the zone. Use fixtime_ms=0 if 89 you want to accept pass throughs w/o fixations. 90 91 See LandingZone for additional details about usage. 92 93 """ 94
95 - def __init__(self, xo, yo, 96 inner_pix, outer_pix, angle_deg, subtense_deg, 97 fixtime_ms, app):
98 self.app = app 99 self.icon = None 100 self.xo, self.yo = xo, yo 101 self.inner = inner_pix 102 self.outer = outer_pix 103 self.angle = math.pi * angle_deg / 180.0 104 self.subtense = math.pi * subtense_deg / 180.0 105 self.fixtime = fixtime_ms 106 self.entered_at = None
107
108 - def __del__(self):
109 self.clear()
110
111 - def inside(self, t=None, x=None, y=None):
112 """ 113 If you have multiple landing zones, you can sit in a loop, use 114 app.eye_txy() to query time and eye position ONCE, and then apply 115 it to multiple landing zones by passing in (x,y) values 116 117 """ 118 if t is None: 119 (t, x, y) = self.app.eye_txy() 120 121 x, y = x - self.xo, y - self.yo 122 r = (x**2 + y**2)**0.5 123 if (r > self.inner) and (r < self.outer): 124 d = abs(math.pi * math.atan2(y, x) - self.angle) 125 if d > pi: 126 d = (2 * math.pi) - d 127 if d < self.subtense: 128 # inside sector 129 if self.entered_at is None: 130 self.entered_at = t 131 if (t - self.entered_at) >= self.fixtime: 132 return 1 133 return 0 134 else: 135 self.entered_at = None 136 return 0
137
138 - def draw(self, color='grey', dash=None, text=None):
139 x = self.xo + (self.inner+self.outer)/2.0 + math.cos(self.angle) 140 y = self.xo + (self.inner+self.outer)/2.0 + math.sin(self.angle) 141 self.clear() 142 self.icon = self.app.udpy.icon(x, y, 143 self.outer-self.inter, 144 self.outer-self.inter, 145 color=color, type=1, dash=dash)
146
147 - def clear(self):
148 if self.icon: 149 self.app.udpy.icon(self.icon) 150 self.icon = None
151 152 if __name__ == '__main__': 153 sys.stderr.write('%s should never be loaded as main.\n' % __file__) 154 sys.exit(1) 155