def wait_for_fixation_start(self): print("wait_for_fixation_start", flush=True) # function assumes a 'fixation' has started when gaze position # remains reasonably stable for self.fixtimetresh # get starting position spos = self.sample() while not self.is_valid_sample(spos): spos = self.sample() # get starting time t0 = clock.get_time() # wait for reasonably stable position moving = True while moving: # get new sample npos = self.sample() # check if sample is valid if self.is_valid_sample(npos): # check if new sample is too far from starting position if (npos[0]-spos[0])**2 + (npos[1]-spos[1])**2 > self.pxfixtresh**2: # Pythagoras # if not, reset starting position and time spos = copy.copy(npos) t0 = clock.get_time() # if new sample is close to starting sample else: # get timestamp t1 = clock.get_time() # check if fixation time threshold has been surpassed if t1 - t0 >= self.fixtimetresh: # return time and starting position return t1, spos
def get_key(self, keylist='default', timeout='default', flush=False): # See _keyboard.basekeyboard.BaseKeyboard # set keylist and timeout if keylist == 'default': keylist = self.klist if timeout == 'default': timeout = self.timeout # flush if necessary if flush: pygame.event.get(pygame.KEYDOWN) # starttime starttime = clock.get_time() time = clock.get_time() # wait for input while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.KEYDOWN: time = clock.get_time() key = pygame.key.name(event.key) if keylist == None or key in keylist: return key, time # in case of timeout return None, time
def get_key(self, keylist='default', timeout='default', flush=False): # See _keyboard.basekeyboard.BaseKeyboard # set keylist and timeout if keylist == 'default': keylist = self.klist if timeout == 'default': timeout = self.timeout # flush if necessary if flush: psychopy.event.clearEvents(eventType='keyboard') # starttime starttime = clock.get_time() time = clock.get_time() # wait for input while timeout == None or time - starttime <= timeout: keys = psychopy.event.getKeys(keyList=keylist,timeStamped=False) for key in keys: if keylist == None or key in keylist: return key, clock.get_time() time = clock.get_time() return None, time
def wait_for_blink_start(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': t, d = self.wait_for_event(pylink.STARTBLINK) return t, d.getTime() # # # # # # PyGaze method else: blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if not self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed 150 ms if clock.get_time() - t0 >= 150: # return timestamp of blink start return t0
def wait_for_fixation_start(self): """Returns starting time and position when a fixation is started; function assumes a 'fixation' has started when gaze position remains reasonably stable (i.e. when most deviant samples are within self.pxfixtresh) for five samples in a row (self.pxfixtresh is created in self.calibration, based on self.fixtresh, a property defined in self.__init__) arguments None returns time, gazepos -- time is the starting time in milliseconds (from expstart), gazepos is a (x,y) gaze position tuple of the position from which the fixation was initiated """ # # # # # # Native method if self.eventdetection == 'native': print("WARNING! 'native' event detection not implemented") # # # # # # PyGaze method # function assumes a 'fixation' has started when gaze position # remains reasonably stable for self.fixtimetresh # get starting position spos = self.sample() while not self.is_valid_sample(spos): spos = self.sample() # get starting time t0 = clock.get_time() # wait for reasonably stable position moving = True while moving: # get new sample npos = self.sample() # check if sample is valid if self.is_valid_sample(npos): # check if new sample is too far from starting position if (npos[0]-spos[0])**2 + (npos[1]-spos[1])**2 > self.pxfixtresh**2: # Pythagoras # if not, reset starting position and time spos = copy.copy(npos) t0 = clock.get_time() # if new sample is close to starting sample else: # get timestamp t1 = clock.get_time() # check if fixation time threshold has been surpassed if t1 - t0 >= self.fixtimetresh: # return time and starting position return t1, spos
def wait_for_blink_start(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': t, d = self.wait_for_event(pylink.STARTBLINK) return t, d.getTime() # # # # # # PyGaze method else: blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if not self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed 150 ms if clock.get_time() - t0 >= self.blink_threshold: # return timestamp of blink start return t0
def wait_for_saccade_start(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': t, d = self.wait_for_event(pylink.STARTSACC) return t, d.getStartGaze() # # # # # # PyGaze method else: # get starting position (no blinks) newpos = self.sample() while not self.is_valid_sample(newpos): newpos = self.sample() # get starting time, position, intersampledistance, and velocity t0 = clock.get_time() prevpos = newpos[:] s = 0 v0 = 0 # get samples saccadic = False while not saccadic: # get new sample newpos = self.sample() t1 = clock.get_time() if self.is_valid_sample(newpos) and newpos != prevpos: # check if distance is larger than precision error sx = newpos[0] - prevpos[0] sy = newpos[1] - prevpos[1] # weigthed distance: (sx/tx)**2 + (sy/ty)**2 > 1 means # movement larger than RMS noise if (sx/self.pxdsttresh[0])**2 + (sy/self.pxdsttresh[1])**2 \ > self.weightdist: # calculate distance # intersampledistance = speed in pixels/ms s = ((sx)**2 + (sy)**2)**0.5 # calculate velocity v1 = s / (t1 - t0) # calculate acceleration a = (v1 - v0) / (t1 - t0 ) # acceleration in pixels/ms**2 # check if either velocity or acceleration are above # threshold values if v1 > self.pxspdtresh or a > self.pxacctresh: saccadic = True spos = prevpos[:] stime = clock.get_time() # update previous values t0 = copy.copy(t1) v0 = copy.copy(v1) # udate previous sample prevpos = newpos[:] return stime, spos
def wait_for_saccade_end(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': d = self.wait_for_event(pylink.ENDSACC) return d.getTime(), d.getStartGaze(), d.getEndGaze() # # # # # # PyGaze method else: # get starting position (no blinks) t0, spos = self.wait_for_saccade_start() # get valid sample prevpos = self.sample() while not self.is_valid_sample(prevpos): prevpos = self.sample() # get starting time, intersample distance, and velocity t1 = clock.get_time() # = intersample distance = speed in px/sample s = ((prevpos[0]-spos[0])**2 + (prevpos[1]-spos[1])**2)**0.5 v0 = s / (t1-t0) # run until velocity and acceleration go below threshold saccadic = True while saccadic: # get new sample newpos = self.sample() t1 = clock.get_time() if self.is_valid_sample(newpos) and newpos != prevpos: # calculate distance # = speed in pixels/sample s = ((newpos[0]-prevpos[0])**2 + \ (newpos[1]-prevpos[1])**2)**0.5 # calculate velocity v1 = s / (t1-t0) # calculate acceleration # acceleration in pixels/sample**2 (actually is # v1-v0 / t1-t0; but t1-t0 = 1 sample) a = (v1-v0) / (t1-t0) # check if velocity and acceleration are below threshold if v1 < self.pxspdtresh and (a > -1*self.pxacctresh and \ a < 0): saccadic = False epos = newpos[:] etime = clock.get_time() # update previous values t0 = copy.copy(t1) v0 = copy.copy(v1) # udate previous sample prevpos = newpos[:] return etime, spos, epos
def wait_for_fixation_start(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': d = self.wait_for_event(pylink.STARTFIX) return d.getTime(), d.getStartGaze() # # # # # # PyGaze method else: # function assumes a 'fixation' has started when gaze position # remains reasonably stable for self.fixtimetresh # get starting position spos = self.sample() while not self.is_valid_sample(spos): spos = self.sample() # get starting time t0 = clock.get_time() # wait for reasonably stable position moving = True while moving: # get new sample npos = self.sample() # check if sample is valid if self.is_valid_sample(npos): # check if new sample is too far from starting position if (npos[0]-spos[0])**2 + (npos[1]-spos[1])**2 > \ self.pxfixtresh**2: # Pythagoras # if not, reset starting position and time spos = copy.copy(npos) t0 = clock.get_time() # if new sample is close to starting sample else: # get timestamp t1 = clock.get_time() # check if fixation time threshold has been surpassed if t1 - t0 >= self.fixtimetresh: # return time and starting position return t1, spos
def wait_for_blink_start(self): """Waits for a blink start and returns the blink starting time arguments None returns timestamp -- blink starting time in milliseconds, as measured from experiment begin time """ # # # # # # Tobii method if self.eventdetection == 'native': # print warning, since Tobii does not have a blink detection # built into their API print("WARNING! 'native' event detection has been selected, \ but Tobii does not offer blink detection; PyGaze algorithm \ will be used") # # # # # # PyGaze method # start recording if recording has not yet started if not self.recording: self.start_recording() stoprec = True else: stoprec = False blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed BLINKTHRESH if clock.get_time() - t0 >= self.blinkthresh: if stoprec: self.stop_recording() # return timestamp of blink start return t0
def wait_for_fixation_start(self): """Returns starting time and position when a simulated fixation is started""" # function assumes a 'fixation' has started when 'gaze' position remains reasonably # stable for five samples in a row (same as saccade end) maxerr = 3 # pixels # wait for reasonably stable position xl = [] # list for last five samples (x coordinate) yl = [] # list for last five samples (y coordinate) moving = True while moving: npos = self.sample() xl.append(npos[0]) # add newest sample yl.append(npos[1]) # add newest sample if len(xl) == 5: # check if deviation is small enough if max(xl)-min(xl) < maxerr and max(yl)-min(yl) < maxerr: moving = False # remove oldest sample xl.pop(0); yl.pop(0) # wait for a bit, to avoid immediately returning (runs go faster than mouse moves) clock.pause(10) return clock.get_time(), (xl[len(xl)-1],yl[len(yl)-1])
def wait_for_saccade_end(self): """Returns ending time, starting and end position when a simulated saccade is ended""" # function assumes that a 'saccade' has ended when 'gaze' position remains reasonably # (i.e.: within maxerr) stable for five samples # for saccade start algorithm, see wait_for_fixation_start stime, spos = self.wait_for_saccade_start() maxerr = 3 # pixels # wait for reasonably stable position xl = [] # list for last five samples (x coordinate) yl = [] # list for last five samples (y coordinate) moving = True while moving: # check positions npos = self.sample() xl.append(npos[0]) # add newest sample yl.append(npos[1]) # add newest sample if len(xl) == 5: # check if deviation is small enough if max(xl)-min(xl) < maxerr and max(yl)-min(yl) < maxerr: moving = False # remove oldest sample xl.pop(0); yl.pop(0) # wait for a bit, to avoid immediately returning (runs go faster than mouse moves) clock.pause(10) return clock.get_time(), spos, (xl[len(xl)-1],yl[len(yl)-1])
def show_part(self, rect, screen=None): # See _display.basedisplay.BaseDisplay for documentation if len(rect) > 1: for r in rect: pygaze.expdisplay.set_clip(r) if screen: pygaze.expdisplay.blit(screen.screen, (0, 0)) pygame.display.update(r) pygaze.expdisplay.set_clip(None) elif len(rect) == 1: pygaze.expdisplay.clip(rect) if screen: pygaze.expdisplay.blit(screen.screen, (0, 0)) pygame.display.update(rect) pygaze.expdisplay.set_clip(None) else: raise Exception( "Error in libscreen.Display.show_part: rect should be a single rect (i.e. a (x,y,w,h) tuple) or a list of rects!" ) return clock.get_time()
def wait_for_blink_end(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': t, d = self.wait_for_event(pylink.ENDBLINK) return t # # # # # # PyGaze method else: blinking = True # loop while there is a blink while blinking: # get newest sample gazepos = self.sample() # check if it's valid if self.is_valid_sample(gazepos): # if it is a valid sample, blinking has stopped blinking = False # return timestamp of blink end return clock.get_time()
def wait_for_fixation_start(self): """Returns starting time and position when a simulated fixation is started""" # function assumes a 'fixation' has started when 'gaze' position remains reasonably # stable for five samples in a row (same as saccade end) maxerr = 3 # pixels # wait for reasonably stable position xl = [] # list for last five samples (x coordinate) yl = [] # list for last five samples (y coordinate) moving = True while moving: npos = self.sample() xl.append(npos[0]) # add newest sample yl.append(npos[1]) # add newest sample if len(xl) == 5: # check if deviation is small enough if max(xl) - min(xl) < maxerr and max(yl) - min(yl) < maxerr: moving = False # remove oldest sample xl.pop(0) yl.pop(0) # wait for a bit, to avoid immediately returning (runs go faster than mouse moves) clock.pause(10) return clock.get_time(), (xl[len(xl) - 1], yl[len(yl) - 1])
def wait_for_saccade_end(self): """Returns ending time, starting and end position when a simulated saccade is ended""" # function assumes that a 'saccade' has ended when 'gaze' position remains reasonably # (i.e.: within maxerr) stable for five samples # for saccade start algorithm, see wait_for_fixation_start stime, spos = self.wait_for_saccade_start() maxerr = 3 # pixels # wait for reasonably stable position xl = [] # list for last five samples (x coordinate) yl = [] # list for last five samples (y coordinate) moving = True while moving: # check positions npos = self.sample() xl.append(npos[0]) # add newest sample yl.append(npos[1]) # add newest sample if len(xl) == 5: # check if deviation is small enough if max(xl) - min(xl) < maxerr and max(yl) - min(yl) < maxerr: moving = False # remove oldest sample xl.pop(0) yl.pop(0) # wait for a bit, to avoid immediately returning (runs go faster than mouse moves) clock.pause(10) return clock.get_time(), spos, (xl[len(xl) - 1], yl[len(yl) - 1])
def wait_for_fixation_end(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" # # # # # # EyeLink method if self.eventdetection == 'native': t, d = self.wait_for_event(pylink.ENDFIX) return t, d.getTime(), d.getStartGaze() # # # # # # PyGaze method else: # function assumes that a 'fixation' has ended when a deviation of # more than fixtresh from the initial 'fixation' position has been # detected # get starting time and position stime, spos = self.wait_for_fixation_start() # loop until fixation has ended while True: # get new sample npos = self.sample() # get newest sample # check if sample is valid if self.is_valid_sample(npos): # check if sample deviates to much from starting position if (npos[0]-spos[0])**2 + (npos[1]-spos[1])**2 > \ self.pxfixtresh**2: # Pythagoras # break loop if deviation is too high break return clock.get_time(), spos
def wait_for_blink_end(self): """Waits for a blink end and returns the blink ending time arguments None returns timestamp -- blink ending time in milliseconds, as measured from experiment begin time """ # # # # # # Native method if self.eventdetection == 'native': print("WARNING! 'native' event detection not implemented") # # # # # # PyGaze method blinking = True # loop while there is a blink while blinking: # get newest sample gazepos = self.sample() # check if it's valid if self.is_valid_sample(gazepos): # if it is a valid sample, blinking has stopped blinking = False # return timestamp of blink end return clock.get_time()
def wait_for_fixation_end(self): """Returns time and gaze position when a simulated fixation is ended""" stime, spos = self.wait_for_fixation_start() return clock.get_time(), spos
def start_recording(self): self.gaze_data = [] self.eyetracker.subscribe_to(tr.EYETRACKER_GAZE_DATA, self._on_gaze_data, as_dictionary=True) time.sleep(1) self.recording = True self.t0 = clock.get_time()
def wait_for_blink_start(self): blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if not self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed BLINKTHRESH if clock.get_time()-t0 >= self.blinkthresh: # return timestamp of blink start return t0
def get_joybutton(self, joybuttonlist='default', timeout='default'): """Waits for joystick buttonpress arguments None keyword arguments joybuttonlist -- list of buttons that are allowed (e.g. [0,2,4]), None to allow all buttons or 'default' to use jbuttonlist property (default = 'default') timeout -- time in milliseconds after which None is returned when no buttonpress is registered; None for no timeout or 'default' to use the timeout property (default = 'default') returns button, presstime -- button is an integer, indicating which button has been pressed or None when no button has been pressed presstime is the time (measured from expbegintime) a buttonpress or a timeout occured """ # set joybuttonlist and timeout if joybuttonlist == 'default': joybuttonlist = self.jbuttonlist if timeout == 'default': timeout = self.timeout # register start time starttime = clock.get_time() time = starttime # wait for button press while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.JOYBUTTONDOWN: time = clock.get_time() if joybuttonlist == None or event.button in joybuttonlist: pressed = event.button return pressed, time # in case of timeout return None, time
def show_part(self, rect, screen=None): # See _display.basedisplay.BaseDisplay for documentation self.fill(screen) self.show() print("WARNING! screen.Display.show_part not available for PsychoPy display type; fill() and show() are used instead") return clock.get_time()
def stop_recording(self): """Dummy for stopping recording, prints what would have been the recording end""" self.simulator.set_visible(visible=False) dumrectime = clock.get_time() self.recording = False print("Recording would have stopped at: " + str(dumrectime))
def close(self): """Dummy for closing connection with eyetracker, prints what would have been connection closing time""" if self.recording: self.stop_recording() closetime = clock.get_time() print("eyetracker connection would have closed at: " + str(closetime))
def wait_for_fixation_end(self): """Returns time and gaze position when a fixation has ended; function assumes that a 'fixation' has ended when a deviation of more than self.pxfixtresh from the initial fixation position has been detected (self.pxfixtresh is created in self.calibration, based on self.fixtresh, a property defined in self.__init__) arguments None returns time, gazepos -- time is the starting time in milliseconds (from expstart), gazepos is a (x,y) gaze position tuple of the position from which the fixation was initiated """ # # # # # # Tobii method if self.eventdetection == 'native': # print warning, since Tobii does not have a fixation detection # built into their API print("WARNING! 'native' event detection has been selected, \ but Tobii does not offer fixation detection; PyGaze algorithm \ will be used") # # # # # # PyGaze method # function assumes that a 'fixation' has ended when a deviation of more than fixtresh # from the initial 'fixation' position has been detected # get starting time and position stime, spos = self.wait_for_fixation_start() # start recording if recording has not yet started if not self.recording: self.start_recording() stoprec = True else: stoprec = False # loop until fixation has ended while True: # get new sample npos = self.sample() # get newest sample # check if sample is valid if self.is_valid_sample(npos): # check if sample deviates to much from starting position if (npos[0] - spos[0])**2 + (npos[1] - spos[1])**2 > self.pxfixtresh**2: # break loop if deviation is too high break if stoprec: self.stop_recording() return clock.get_time(), spos
def start_recording(self): """Dummy for starting recording, prints what would have been the recording start""" self.simulator.set_visible(visible=True) dumrectime = clock.get_time() self.recording = True print("Recording would have started at: " + str(dumrectime))
def wait_for_blink_start(self): """Returns starting time and position of a simulated blink (mousebuttondown)""" # blinks are simulated with mouseclicks: a right mouseclick simulates the closing # of the eyes, a mousebuttonup the opening. while not self.blinking: pos = self.sample() return clock.get_time(), pos
def wait_for_blink_start(self): """Waits for a blink start and returns the blink starting time arguments None returns timestamp -- blink starting time in milliseconds, as measured from experiment begin time """ # # # # # # SMI method if self.eventdetection == 'native': # print warning, since SMI does not have a blink detection # built into their API print("WARNING! 'native' event detection has been selected, \ but SMI does not offer blink detection; PyGaze algorithm \ will be used") # # # # # # PyGaze method blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if not self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed 150 ms if clock.get_time()-t0 >= 150: # return timestamp of blink start return t0
def wait_for_blink_start(self): """Waits for a blink start and returns the blink starting time arguments None returns timestamp -- blink starting time in milliseconds, as measured from experiment begin time """ # # # # # # EyeTribe method if self.eventdetection == 'native': # print warning, since EyeTribe does not have a blink detection # built into their API print("WARNING! 'native' event detection has been selected, \ but EyeTribe does not offer blink detection; PyGaze algorithm \ will be used") # # # # # # PyGaze method blinking = False # loop until there is a blink while not blinking: # get newest sample gazepos = self.sample() # check if it's a valid sample if not self.is_valid_sample(gazepos): # get timestamp for possible blink start t0 = clock.get_time() # loop until a blink is determined, or a valid sample occurs while not self.is_valid_sample(self.sample()): # check if time has surpassed 150 ms if clock.get_time()-t0 >= 150: # return timestamp of blink start return t0
def wait_for_saccade_end(self): """Returns ending time, starting and end position when a simulated saccade is ended""" # function assumes that a 'saccade' has ended when 'gaze' position remains reasonably # (i.e.: within maxerr) stable for five samples # for saccade start algorithm, see wait_for_fixation_start stime, spos = self.wait_for_saccade_start() return clock.get_time(), spos, (190, 190)
def wait_for_saccade_end(self): """Returns ending time, starting and end position when a simulated saccade is ended""" # function assumes that a 'saccade' has ended when 'gaze' position remains reasonably # (i.e.: within maxerr) stable for five samples # for saccade start algorithm, see wait_for_fixation_start stime, spos = self.wait_for_saccade_start() return clock.get_time(), spos, (190,190)
def wait_for_saccade_start(self): # get starting position (no blinks) newpos = self.sample() while not self.is_valid_sample(newpos): newpos = self.sample() # get starting time, position, intersampledistance, and velocity t0 = clock.get_time() prevpos = newpos[:] s = 0 v0 = 0 # get samples saccadic = False while not saccadic: # get new sample newpos = self.sample() t1 = clock.get_time() if self.is_valid_sample(newpos) and newpos != prevpos: # check if distance is larger than precision error sx = newpos[0]-prevpos[0]; sy = newpos[1]-prevpos[1] if (sx/self.pxdsttresh[0])**2 + (sy/self.pxdsttresh[1])**2 > self.weightdist: # weigthed distance = (sx/tx)**2 + (sy/ty)**2 > 1 means movement larger than RMS noise # calculate distance s = ((sx)**2 + (sy)**2)**0.5 # intersampledistance = speed in pixels/ms # calculate velocity v1 = s / (t1-t0) # calculate acceleration a = (v1-v0) / (t1-t0) # acceleration in pixels/ms**2 # check if either velocity or acceleration are above threshold values if v1 > self.pxspdtresh or a > self.pxacctresh: saccadic = True spos = prevpos[:] stime = clock.get_time() # update previous values t0 = copy.copy(t1) v0 = copy.copy(v1) # udate previous sample prevpos = newpos[:] return stime, spos
def get_joyhats(self, timeout='default'): """Waits for joystick hat movement arguments None keyword arguments timeout -- time in milliseconds after which None is returned when no buttonpress is registered; None for no timeout or 'default' to use the timeout property (default = 'default') returns hatpos, time -- hatpos is a [hat1,hat2,...,hatN] position list for the positions of the joystick hats; each hat position is a (x,y) tuple time is the time (measured from expbegintime) a hatmovement or a timeout occured """ # set timeout if timeout == 'default': timeout = self.timeout # start time and pos hatpos = [] starttime = clock.get_time() time = starttime # wait for axis movement while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.JOYHATMOTION: time = clock.get_time() for hat in range(self.js.get_numhats()): hatpos.append(self.js.get_hat(hat)) return hatpos, time # in case of timeout return None, time
def _get_eyelink_clock_async(self): """ Retrieve time differenece between tracker timestamps and current clock time upheld in the pygaze environment. Note that this is not guaranteed to be a static time difference, the clocks might run at different speeds. Therefore you should consider running this function every time you utilize on this time difference. Returns: The tracker time minus the clock time """ return pylink.getEYELINK().trackerTime() - clock.get_time()
def get_joyaxes(self, timeout='default'): """Waits for joystick axis movement arguments None keyword arguments timeout -- time in milliseconds after which None is returned when no buttonpress is registered; None for no timeout or 'default' to use the timeout property (default = 'default') returns axespos, time -- axespos is a [x,y,z] position list for the positions of the joystick axes (usually [x,y,z] for the main stick); x, y and z are floats time is the time (measured from expbegintime) an axismovement or a timeout occured """ # set timeout if timeout == 'default': timeout = self.timeout # start time and pos pos = [] starttime = clock.get_time() time = starttime # wait for axis movement while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.JOYAXISMOTION: time = clock.get_time() for axis in range(self.js.get_numaxes()): pos.append(self.js.get_axis(axis)) return pos, time # in case of timeout return None, time
def get_joyballs(self, timeout='default'): """Waits for joystick trackball movement arguments None keyword arguments timeout -- time in milliseconds after which None is returned when no buttonpress is registered; None for no timeout or 'default' to use the timeout property (default = 'default') returns ballpos, time -- ballpos is a [ball1,ball2,...,ballN] position list for the positions of the joystick balls; each ball position is a (x,y) tuple time is the time (measured from expbegintime) a ballmovement or a timeout occured """ # set timeout if timeout == 'default': timeout = self.timeout # start time and pos ballpos = [] starttime = clock.get_time() time = starttime # wait for axis movement while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.JOYBALLMOTION: time = clock.get_time() for ball in range(self.js.get_numballs()): ballpos.append(self.js.get_ball(ball)) return ballpos, time # in case of timeout return None, time
def wait_for_fixation_end(self): """Returns time and gaze position when a fixation has ended; function assumes that a 'fixation' has ended when a deviation of more than self.pxfixtresh from the initial fixation position has been detected (self.pxfixtresh is created in self.calibration, based on self.fixtresh, a property defined in self.__init__) arguments None returns time, gazepos -- time is the starting time in milliseconds (from expstart), gazepos is a (x,y) gaze position tuple of the position from which the fixation was initiated """ # # # # # # EyeTribe method if self.eventdetection == 'native': # print warning, since EyeTribe does not have a blink detection # built into their API print("WARNING! 'native' event detection has been selected, \ but EyeTribe does not offer fixation detection; \ PyGaze algorithm will be used") # # # # # # PyGaze method # function assumes that a 'fixation' has ended when a deviation of more than fixtresh # from the initial 'fixation' position has been detected # get starting time and position stime, spos = self.wait_for_fixation_start() # loop until fixation has ended while True: # get new sample npos = self.sample() # get newest sample # check if sample is valid if self.is_valid_sample(npos): # check if sample deviates to much from starting position if (npos[0]-spos[0])**2 + (npos[1]-spos[1])**2 > self.pxfixtresh**2: # Pythagoras # break loop if deviation is too high break return clock.get_time(), spos
def get_clicked(self, mousebuttonlist='default', timeout='default'): # See _mouse.basemouse.BaseMouse # set buttonlist and timeout if mousebuttonlist == 'default': mousebuttonlist = self.mbuttonlist if timeout == 'default': timeout = self.timeout # starttime starttime = clock.get_time() time = clock.get_time() # wait for mouse clicks while timeout == None or time - starttime <= timeout: time = clock.get_time() pressed = self.mouse.getPressed() if sum(pressed) > 0: for b in range(0,len(pressed)): if pressed[b] == 1: if mousebuttonlist == None or b+1 in mousebuttonlist: return b+1, self.get_pos(), time # in case of timeout return None, None, time
def wait_for_blink_end(self): """Returns ending time and position of a simulated blink (mousebuttonup)""" # blinks are simulated with mouseclicks: a right mouseclick simulates the closing # of the eyes, a mousebuttonup the opening. # wait for blink start while not self.blinking: spos = self.sample() # wait for blink end while self.blinking: epos = self.sample() return clock.get_time(), epos
def get_clicked(self, mousebuttonlist='default', timeout='default'): # See _mouse.basemouse.BaseMouse # set buttonlist and timeout if mousebuttonlist == 'default': mousebuttonlist = self.mbuttonlist if timeout == 'default': timeout = self.timeout # starttime starttime = clock.get_time() time = clock.get_time() # wait for mouse clicks while timeout == None or time - starttime <= timeout: time = clock.get_time() for event in pygame.event.get(): if event.type == pygame.MOUSEBUTTONDOWN: time = clock.get_time() clickpos = self.get_pos() if mousebuttonlist == None or event.button in mousebuttonlist: pressed = event.button return pressed, clickpos, time # in case of timeout return None, None, time
def wait_for_saccade_start(self): """Returns starting time and starting position when a simulated saccade is started""" # function assumes that a 'saccade' has been started when a deviation of more than # maxerr from the initial 'gaze' position has been detected (using Pythagoras, ofcourse) spos = self.sample() # starting position maxerr = 3 # pixels while True: npos = self.sample() # get newest sample if ((spos[0]-npos[0])**2 + (spos[1]-npos[1])**2)**0.5 > maxerr: # Pythagoras break return clock.get_time(), spos
def wait_for_fixation_end(self): """Returns time and gaze position when a simulated fixation is ended""" # function assumes that a 'fixation' has ended when a deviation of more than maxerr # from the initial 'fixation' position has been detected (using Pythagoras, ofcourse) stime, spos = self.wait_for_fixation_start() maxerr = 3 # pixels while True: npos = self.sample() # get newest sample if ((spos[0]-npos[0])**2 + (spos[1]-npos[1])**2)**0.5 > maxerr: # Pythagoras break return clock.get_time(), spos