def __init__(self, disptype=settings.DISPTYPE, pos="centre", dist=125, \ size=200): """Initializes FRL object arguments None keyword arguments disptype -- display type, either "psychopy" or "pygame" (default = DISPTYPE) pos -- a string indicating the FRL position in relation to gaze position; allowed are "centre", "top", "topright", "right", "bottomright", "bottom", "bottomleft", "left", "topleft" (default = "centre") dist -- distance between gaze position and FRL center in pixels (default = 125) size -- FRL diameter in pixels (default = 200) """ # FRL characteristics self.pos = pos self.dist = dist self.size = size # FRL distance # horizontal distance between gaze position and FRL-centre self.frlxdis = ((self.dist**2) / 2)**0.5 # vertical distance between gaze position and FRL-centre self.frlydis = ((self.dist**2) / 2)**0.5 # FRL position if pos in ["center", "centre"]: self.frlcor = (0, 0) elif pos == "top": self.frlcor = (0, -self.dist) elif pos == "topright": self.frlcor = (-self.frlxdis, self.frlydis) elif pos == "right": self.frlcor = (self.dist, 0) elif pos == "bottomright": self.frlcor = (-self.frlxdis, -self.frlydis) elif pos == "bottom": self.frlcor = (0, self.dist) elif pos == "bottomleft": self.frlcor = (self.frlxdis, -self.frlydis) elif pos == "left": self.frlcor = (-self.dist, 0) elif pos == "topleft": self.frlcor = (self.frlxdis, self.frlydis) else: print( "WARNING! plugins.frl.__init__: FRL position argument '{}' not recognized; FRL position set to 'centre'." .format(pos)) self.frlcor = (0, 0) if disptype in ["pygame", "psychopy"]: self.disptype = disptype else: raise Exception( "Error in plugins.frl.__init__: disptype '{}' not recognized". format(disptype)) if self.disptype == "pygame": self.__class__ = PyGameFRL elif self.disptype == "psychopy": self.__class__ = PsychoPyFRL self.frl = Aperture(pygaze.expdisplay, self.size, \ pos=pos2psychopos(self.frlcor), shape="circle", units="pix")
class frl(item.item): """A plug-in to limit stimulus visibility using a forced retinal location""" def __init__(self, name, experiment, string=None): """ Constructor Arguments: name -- item name experiment -- an experiment object Keyword arguments: string -- a definitional string (default=None) """ self.item_type = u"frl" self.sketchpad = u"" self.timeout = 50000 self.size = 150 self.dist = 100 self.angle = 45 self.frltype = u'circle' # possibly add Gauss and raised cosine in future self.description = \ u"Limits canvas visibility using a forced retinal location, until a key is pressed, or a timeout is reached" item.item.__init__(self, name, experiment, string) def prepare(self): """ Prepare the plug-in Returns: True """ item.item.prepare(self) # check for eyetracker if not hasattr(self.experiment, "eyetracker"): raise exceptions.runtime_error( \ u"Please connect to the eyetracker using the the eyetracker_calibrate plugin before using the FRL plugin") # canvas self.cv = canvas(self.experiment) self.cv.copy(self.experiment.items[self.get(u'sketchpad')].canvas) self.drawcv = canvas(self.experiment) # keyboard self.kb = keyboard(self.experiment, keylist=None, timeout=1) # timeout self.notimeout = False if type(self.timeout) in [int, tuple]: if self.timeout <= 0: self.notimeout = True elif type(self.timeout) in [None, u'None']: self.notimeout = True else: raise exceptions.runtime_error( \ u"FRL timeout should be an integer value (use None or 0 milliseconds for no timeout)") # FRL properties self.frlcor = pol2car(self.get(u'dist'), self.get(u'angle')) # psycho if self.get("canvas_backend") == u'psycho': # create Aperture from psychopy.visual import Aperture self.frl = Aperture(self.experiment.window, self.get(u'size'), pos=pos2psychopos(self.frlcor,self.experiment.resolution()), shape='circle', units='pix') # update function self.updatefunc = self.psychoupdate # legacy and xpyriment elif self.get("canvas_backend") in [u'legacy',u'xpyriment']: # PyGame specific properties self.r = self.get(u'size')/2 self.h = 1 # updaterect height; increase to lower FRL resolution (which increases processing speed) # update function self.updatefunc = self.pygameupdate pass # any other backend produces an error else: raise exceptions.runtime_error( \ u"Unsupported canvas backend: FRL plugin only supports legacy, psycho, and xpyriment backends") return True def pygameupdate(self, gazepos): """update frl using PyGame; for internal use""" # frl position frlpos = (gazepos[0]-self.frlcor[0], gazepos[1]-self.frlcor[1]) # clear canvas self.drawcv.clear() # top half for y in range(0,int(self.r/self.h)): y = self.r - y x = (self.r**2-y**2)**0.5 updaterect = [frlpos[0]-x,frlpos[1]-self.h*y,2*x,self.h] self.drawcv.surface.set_clip(updaterect) self.drawcv.surface.blit(self.cv.surface,(0,0)) # bottom half for y in range(0,int((self.r+1)/self.h)): x = (self.r**2-y**2)**0.5 updaterect = [frlpos[0]-x,frlpos[1]+self.h*y,2*x,self.h] self.drawcv.surface.set_clip(updaterect) self.drawcv.surface.blit(self.cv.surface,(0,0)) # unset clip and show canvas self.drawcv.surface.set_clip(None) self.drawcv.show() def psychoupdate(self, gazepos): """update frl using PsychoPy; for internal use""" # frl position in PsychoPy coordinates gazepos = pos2psychopos(gazepos, self.experiment.resolution()) frlpos = (gazepos[0]-self.frlcor[0], gazepos[1]+self.frlcor[1]) # apply frl self.frl.setPos(frlpos) self.frl.enable() self.cv.show() self.frl.disable() def run(self): """ Run the plug-in Returns: True """ self.set_item_onset() stop = False t0 = self.time() while not stop: # get gaze position gazepos = self.experiment.eyetracker.sample() # update frl accordingly self.updatefunc(gazepos) # response response, t1 = self.kb.get_key() # timeout if (self.time() - t0 > self.timeout and not self.notimeout) or (response != None): stop = True self.experiment.set(u'response', response) self.experiment.set(u'response_time', t1-t0) return True
def __init__(self, disptype=settings.DISPTYPE, pos='centre', dist=125, size=200): """Initializes FRL object arguments None keyword arguments disptype -- display type, either 'psychopy' or 'pygame' (default = DISPTYPE) pos -- a string indicating the FRL position in relation to gaze position; allowed are 'centre', 'top', 'topright', 'right', 'bottomright', 'bottom', 'bottomleft', 'left', 'topleft' (default = 'centre') dist -- distance between gaze position and FRL center in pixels (default = 125) size -- FRL diameter in pixels (default = 200) """ # FRL characteristics self.pos = pos self.dist = dist self.size = size # FRL distance self.frlxdis = ( (self.dist**2) / 2)**0.5 # horizontal distance between gaze position and FRL-centre self.frlydis = ( (self.dist**2) / 2)**0.5 # vertical distance between gaze position and FRL-centre # FRL position if pos in ['center', 'centre']: self.frlcor = (0, 0) elif pos == 'top': self.frlcor = (0, -self.dist) elif pos == 'topright': self.frlcor = (-self.frlxdis, self.frlydis) elif pos == 'right': self.frlcor = (self.dist, 0) elif pos == 'bottomright': self.frlcor = (-self.frlxdis, -self.frlydis) elif pos == 'bottom': self.frlcor = (0, self.dist) elif pos == 'bottomleft': self.frlcor = (self.frlxdis, -self.frlydis) elif pos == 'left': self.frlcor = (-self.dist, 0) elif pos == 'topleft': self.frlcor = (self.frlxdis, self.frlydis) else: print( "WARNING! plugins.frl.__init__: FRL position argument '%s' not recognized; FRL position set to 'centre'." % pos) self.frlcor = (0, 0) if disptype in ['pygame', 'psychopy']: self.disptype = disptype else: raise Exception( "Error in plugins.frl.__init__: disptype '%s' not recognized" % disptype) if self.disptype == 'pygame': self.__class__ = PyGameFRL elif self.disptype == 'psychopy': self.__class__ = PsychoPyFRL self.frl = Aperture(pygaze.expdisplay, self.size, pos=pos2psychopos(self.frlcor), shape='circle', units='pix')
def prepare(self): """ Prepare the plug-in Returns: True """ item.item.prepare(self) # check for eyetracker if not hasattr(self.experiment, "eyetracker"): raise exceptions.runtime_error( \ u"Please connect to the eyetracker using the the eyetracker_calibrate plugin before using the FRL plugin") # canvas self.cv = canvas(self.experiment) self.cv.copy(self.experiment.items[self.get(u'sketchpad')].canvas) self.drawcv = canvas(self.experiment) # keyboard self.kb = keyboard(self.experiment, keylist=None, timeout=1) # timeout self.notimeout = False if type(self.timeout) in [int, tuple]: if self.timeout <= 0: self.notimeout = True elif type(self.timeout) in [None, u'None']: self.notimeout = True else: raise exceptions.runtime_error( \ u"FRL timeout should be an integer value (use None or 0 milliseconds for no timeout)") # FRL properties self.frlcor = pol2car(self.get(u'dist'), self.get(u'angle')) # psycho if self.get("canvas_backend") == u'psycho': # create Aperture from psychopy.visual import Aperture self.frl = Aperture(self.experiment.window, self.get(u'size'), pos=pos2psychopos(self.frlcor,self.experiment.resolution()), shape='circle', units='pix') # update function self.updatefunc = self.psychoupdate # legacy and xpyriment elif self.get("canvas_backend") in [u'legacy',u'xpyriment']: # PyGame specific properties self.r = self.get(u'size')/2 self.h = 1 # updaterect height; increase to lower FRL resolution (which increases processing speed) # update function self.updatefunc = self.pygameupdate pass # any other backend produces an error else: raise exceptions.runtime_error( \ u"Unsupported canvas backend: FRL plugin only supports legacy, psycho, and xpyriment backends") return True