def draw_line(self, colour=None, color=None, spos=None, epos=None, pw=1): """Draws a line on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) spos -- line start, an (x,y) position tuple or None for a quarter x and a central y position (default = None) epos -- line end, an (x,y) position tuple or None for a three-quarter x and a central y position (default = None) pw -- penwidth: line thickness (default = 1) returns Nothing -- draws a line on (PyGame) or adds a Line stimulus to (PsychoPy) the self.screen property """ if color is None and colour is None: pass elif color is None and colour is not None: pass elif color is not None and colour is None: colour = color elif colour != color: raise Exception( "The arguments 'color' and 'colour' are the same, but set to different values: color={}, colour={}" .format(color, colour)) if colour is None: colour = self.fgc if spos is None: spos = (int(self.dispsize[0] * 0.25), self.dispsize[1] / 2) if epos is None: epos = (int(self.dispsize[0] * 0.75), self.dispsize[1] / 2) colour = rgb2psychorgb(colour) spos = pos2psychopos(spos, dispsize=self.dispsize) epos = pos2psychopos(epos, dispsize=self.dispsize) # The `Line` class appears to be broken in a recent update of # PsychoPy. Hence the fallback to `ShapeStim`. See also: # <https://groups.google.com/forum/#!topic/psychopy-dev/1sKn6RrqH-8> #self.screen.append(Line(pygaze.expdisplay, start=spos, end=epos, \ # lineColor=colour, lineColorSpace='rgb', lineWidth=pw)) stim = ShapeStim(pygaze.expdisplay, lineWidth=pw, \ vertices=[spos, epos], lineColor=colour) self.screen.append(stim)
def draw_polygon(self, pointlist, colour=None, pw=1, fill=True): """Draws a polygon on the screen arguments pointlist -- a list of (x,y) tuples resembling the cornerpoints of the polygon keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pw -- penwidth: polygon line thickness (default = 1) fill -- Boolean indicating whether polygon should be filled or not (default = False) returns Nothing -- draws a polygon on (PyGame) or adds a ShapeStim stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc colour = rgb2psychorgb(colour) pl = [] for pos in pointlist: pl.append(pos2psychopos(pos,dispsize=self.dispsize)) if fill: self.screen.append(ShapeStim(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb',vertices=pl, closeShape=True)) else: self.screen.append(ShapeStim(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=rgb2psychorgb(self.bgc), fillColorSpace='rgb',vertices=pl, closeShape=True))
def draw_image(self, image, pos=None, scale=None): """Draws an image on the screen arguments image -- a full path to an image file keyword arguments pos -- image center position, an (x,y) position tuple or None for a central position (default = None) scale -- scale factor for the image or None for no scaling (default = None) returns Nothing -- loads and draws an image surface on (PyGame) or adds SimpleImageStim to (PsychoPy) the self.screen property """ if pos == None: pos = (self.dispsize[0]/2, self.dispsize[1]/2) pos = pos2psychopos(pos,dispsize=self.dispsize) if scale == None: imgsize = None else: if pilimp: img = Image.open(image) imgsize = (img.size[0]*scale, img.size[1]*scale) else: imgsize = None print("WARNING! libscreen.Screen: PIL's Image class could not be loaded; image scaling with PsychoPy disptype is now impossible!") self.screen.append(ImageStim(pygaze.expdisplay, image=image, pos=pos, size=imgsize))
def update(self, display, stimscreen, gazepos): """Updates display with FRL, showing part of the stimulus screen inside of a FRL and backgroundcolour everywhere else arguments display -- a libscreen.Display object stimscreen -- a libscreen.Screen object containing the stimuli that are to be presented gazepos -- current gaze position (a (x,y) tuple) returns disptime -- directly updates display and returns refresh time (PsychoPy) or an estimate (PyGame) """ # FRL position frlpos = pos2psychopos(self.get_pos(gazepos)) # set FRL self.frl.setPos(frlpos) self.frl.enable() # draw stimuli display.fill(stimscreen) # update screen disptime = display.show() # unset FRL self.frl.disable() return disptime
def draw_rect(self, colour=None, color=None, x=None, y=None, w=50, h=50, \ pw=1, fill=False): """Draws a rectangle on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) x -- x coordinate of the rectangle or None for a horizontal centrally drawn rectangle (default = None) y -- y coordinate of the rectangle or None for a vertical centrally drawn rectangle (default = None) w -- width of the rectangle (default = 50) h -- height of the rectangle (default = 50) pw -- penwidth: ellipse line thickness (default = 1) fill -- Boolean indicating whether rectangle should be filled or not (default = False) returns Nothing -- draws a rectangle on (PyGame) or adds a GratinsStim stimulus to (PsychoPy) the self.screen property """ if color is None and colour is None: pass elif color is None and colour is not None: pass elif color is not None and colour is None: colour = color elif colour != color: raise Exception( "The arguments 'color' and 'colour' are the same, but set to different values: color={}, colour={}" .format(color, colour)) if colour is None: colour = self.fgc if x is None: x = self.dispsize[0] / 2 if y is None: y = self.dispsize[1] / 2 pos = x, y colour = rgb2psychorgb(colour) pos = pos2psychopos(pos, dispsize=self.dispsize) pos = pos[0] + w / 2, pos[1] - h / 2 if fill: self.screen.append(Rect(pygaze.expdisplay, width=w, height=h, \ lineWidth=pw, lineColor=colour, lineColorSpace='rgb', \ fillColor=colour, fillColorSpace='rgb', pos=pos)) else: self.screen.append(Rect(pygaze.expdisplay, width=w, height=h, \ lineWidth=pw, lineColor=colour, lineColorSpace='rgb', \ fillColor=None, pos=pos))
def draw_line(self, colour=None, spos=None, epos=None, pw=1): """Draws a line on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) spos -- line start, an (x,y) position tuple or None for a quarter x and a central y position (default = None) epos -- line end, an (x,y) position tuple or None for a three-quarter x and a central y position (default = None) pw -- penwidth: line thickness (default = 1) returns Nothing -- draws a line on (PyGame) or adds a Line stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if spos == None: spos = (int(self.dispsize[0]*0.25), self.dispsize[1]/2) if epos == None: epos = (int(self.dispsize[0]*0.75), self.dispsize[1]/2) colour = rgb2psychorgb(colour) spos = pos2psychopos(spos,dispsize=self.dispsize) epos = pos2psychopos(epos,dispsize=self.dispsize) # The `Line` class appears to be broken in a recent update of # PsychoPy. Hence the fallback to `ShapeStim`. See also: # <https://groups.google.com/forum/#!topic/psychopy-dev/1sKn6RrqH-8> #self.screen.append(Line(pygaze.expdisplay, start=spos, end=epos, lineColor=colour, lineColorSpace='rgb', lineWidth=pw)) stim = ShapeStim(pygaze.expdisplay, lineWidth=pw, vertices=[spos, epos], lineColor=colour) self.screen.append(stim)
def draw_circle(self, colour=None, pos=None, r=50, pw=1, fill=False): """Draws a circle on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pos -- circle center, an (x,y) position tuple or None for a central position (default = None) r -- circle radius (default = 50) pw -- penwidth: circle line thickness (default = 1) fill -- Boolean indicating whether circle should be filled or not (default = False) returns Nothing -- draws a circle on (PyGame) or adds a Circle stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if pos == None: pos = (self.dispsize[0] / 2, self.dispsize[1] / 2) colour = rgb2psychorgb(colour) pos = pos2psychopos(pos, dispsize=self.dispsize) if fill: self.screen.append( Circle(pygaze.expdisplay, radius=r, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb')) else: self.screen.append( Circle(pygaze.expdisplay, radius=r - pw, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb'))
def draw_ellipse(self, colour=None, x=None, y=None, w=50, h=50, pw=1, fill=False): """Draws an ellipse on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) x -- x coordinate of the rectangle in which the ellipse is drawn or None for a horizontal centrally drawn ellipse (default = None) y -- y coordinate of the rectangle in which the ellipse is drawn or None for a vertical centrally drawn ellipse (default = None) w -- width of the rectangle in which the ellipse is drawn (default = 50) h -- height of the rectangle in which the ellipse is drawn (default = 50) pw -- penwidth: circle line thickness (default = 1) fill -- Boolean indicating whether ellipse should be filled or not (default = False) returns Nothing -- draws an ellipse on (PyGame) or adds a GratinsStim stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if x == None: x = 0 if y == None: y = 0 pos = x,y colour = rgb2psychorgb(colour) pos = pos2psychopos(pos,dispsize=self.dispsize) pos = pos[0] + w/2, pos[1] - h/2 if fill: self.screen.append(Circle(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb', pos=pos, size=(w,h))) else: self.screen.append(Circle(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=None, pos=pos, size=(w,h)))
def draw_text(self, text='text', colour=None, pos=None, center=True, font='mono', fontsize=12, antialias=True): """Draws a text on the screen arguments None keyword arguments text -- string to be displayed (newlines are allowed and will be recognized) (default = 'text') colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pos -- text position, an (x,y) position tuple or None for a central position (default = None) center -- Boolean indicating is the pos keyword argument should indicate the text center (True) or the top right coordinate (False) (default = True) font -- font name (a string value); should be the name of a font included in the PyGaze resources/fonts directory (default = 'mono') fontsize -- fontsize in pixels (an integer value) (default = 12) antialias -- Boolean indicating whether text should be antialiased or not (default = True) returns Nothing -- renders and draws a surface with text on (PyGame) or adds SimpleTextStim to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if pos == None: pos = (self.dispsize[0]/2, self.dispsize[1]/2) if center: align = 'center' else: align = 'left' colour = rgb2psychorgb(colour) pos = pos2psychopos(pos,dispsize=self.dispsize) self.screen.append(TextStim(pygaze.expdisplay, text=str(text), font=font, pos=pos, color=colour, height=fontsize, antialias=antialias, alignHoriz=align, fontFiles=pygaze.FONTFILES, wrapWidth=None))
def draw_circle(self, colour=None, pos=None, r=50, pw=1, fill=False): """Draws a circle on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pos -- circle center, an (x,y) position tuple or None for a central position (default = None) r -- circle radius (default = 50) pw -- penwidth: circle line thickness (default = 1) fill -- Boolean indicating whether circle should be filled or not (default = False) returns Nothing -- draws a circle on (PyGame) or adds a Circle stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if pos == None: pos = (self.dispsize[0]/2, self.dispsize[1]/2) colour = rgb2psychorgb(colour) pos = pos2psychopos(pos,dispsize=self.dispsize) if fill: self.screen.append(Circle(pygaze.expdisplay, radius=r, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb')) else: self.screen.append(Circle(pygaze.expdisplay, radius=r-pw, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb'))
def draw_text(self, text="text", colour=None, color=None, pos=None, \ centre=None, center=None, font="mono", fontsize=12, \ antialias=True, wrap_width=None): """Draws a text on the screen arguments None keyword arguments text -- string to be displayed (newlines are allowed and will be recognized) (default = 'text') colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pos -- text position, an (x,y) position tuple or None for a central position (default = None) center -- Boolean indicating is the pos keyword argument should indicate the text centre (True) or the top right coordinate (False) (default = True) font -- font name (a string value); should be the name of a font included in the PyGaze resources/fonts directory (default = 'mono') fontsize -- fontsize in pixels (an integer value) (default = 12) antialias -- Boolean indicating whether text should be antialiased or not (default = True) returns Nothing -- renders and draws a surface with text on (PyGame) or adds SimpleTextStim to (PsychoPy) the self.screen property """ if color is None and colour is None: pass elif color is None and colour is not None: pass elif color is not None and colour is None: colour = color elif colour != color: raise Exception( "The arguments 'color' and 'colour' are the same, but set to different values: color={}, colour={}" .format(color, colour)) if center is None and centre is None: centre = True elif center is None and centre is not None: pass elif center is not None and centre is None: centre = center elif centre != center: raise Exception( "The arguments 'center' and 'centre' are the same, but set to different values: center={}, centre={}" .format(center, centre)) if colour is None: colour = self.fgc if pos is None: pos = (self.dispsize[0] / 2, self.dispsize[1] / 2) if centre: align = "center" else: align = "left" colour = rgb2psychorgb(colour) pos = pos2psychopos(pos, dispsize=self.dispsize) self.screen.append(TextStim(pygaze.expdisplay, text=str(text), \ font=font, pos=pos, color=colour, height=fontsize, \ antialias=antialias, alignHoriz=align, \ fontFiles=pygaze.FONTFILES, wrapWidth=wrap_width)) # PsychoPy deprecated "alignHoriz", but in version 3.2.4 (and maybe # also others, who knows?) its replacements "alignText" and # "anchorHoriz" are unknown keyword arguments to __init__. Yet, # "alignHoriz" does NOT work any longer. I guess alignment is just # broken now? The ugly workaround below will NOT work for those broken # versions of PsychoPy, but will at least not crash them. self.screen[-1].anchorHoriz = align self.screen[-1].alignText = align
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 update(self, locs, oris, linewidth=None, stimtypes=None): """Updates the locations, colours, line colours, and line widths of this stimulus array. Arguments locs - List of (x,y) tuples that determine the positions of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. oris - List of integers that determine the orientations of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. Keyword Arguments linewidth - Integer or a list of integers that determines the width of the lines around stimuli (in pixels), or None to leave the width as it is. Default value is None. stimtypes - String or a list of strings that determines the type of stimulus. Options are 'gabor' and 'noise', or None to not update. Default is None. """ # Convert the linewidth to a list (if necessary). if type(linewidth) in [int, float]: linewidth = len(self._stimindexnrs) * [int(linewidth)] # Convert the stimulus types to a list (if necessary). if type(stimtypes) in [str, unicode]: stimtypes = len(self._stimindexnrs) * [stimtypes] # Loop through all stimuli. # stimnr is a number between 0 and nstim # stimindexnr refers to the index of a stimulus in self.screen for stimnr, stimindexnr in enumerate(self._stimindexnrs): # Update the stimulus location. self.screen[stimindexnr].pos = pos2psychopos(locs[stimnr]) self.screen[self._outlineindexnrs[stimnr]].pos = pos2psychopos( locs[stimnr]) # # Update the stimulus colour. # self.screen[stimindexnr].fillColor = rgb2psychorgb(list(oris[stimnr])) # Update the stimulus orientation. self.screen[stimindexnr].setOri(oris[stimnr]) # Update the stimulus line width and colour. if linewidth != None: self.screen[self._outlineindexnrs[ stimnr]].lineWidth = linewidth[stimnr] if linewidth[stimnr] == PROBELINEWIDTH: self.screen[self._outlineindexnrs[stimnr]].lineColor = \ (1,-1,-1) else: self.screen[self._outlineindexnrs[stimnr]].lineColor = \ (0,0,0) # Update the stimulus texture. if stimtypes != None: if stimtypes[stimnr] == 'gabor': self.screen[stimindexnr].setTex('sin') else: self.screen[stimindexnr].setTex(self._noisetex)
def set_pos(self, pos=(0,0)): # See _mouse.basemouse.BaseMouse self.mouse.setPos(newPos=pos2psychopos(pos))
def set_pos(self, pos=(0, 0)): # See _mouse.basemouse.BaseMouse self.mouse.setPos(newPos=pos2psychopos(pos))
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 __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")
def __init__(self, nstim, locs, oris, linewidth=3, \ stimtypes='gabor', showcolourwheel=False): """Initialises a new StimScreen instance. Arguments nstim - Integer that determines the number of stimuli on this screen. locs - List of (x,y) tuples that determine the positions of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. oris - List of integers that determine the orientations of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. Keyword Arguments linewidth - Integer or a list of integers that determines the width of the lines around stimuli (in pixels). Default value is 3. stimtypes - String or a list of strings that determines the type of stimulus. Options are 'gabor' and 'noise'. Default is 'gabor'. showcolourwheel- Boolean that determines whether a central colour wheel should be drawn of not. Default is False. """ # Settings from the constants. self._sf = float(STIMSF) / float(STIMSIZE) self._alpha = STIMALPHA self._contrast = STIMCONTRAST # Noise texture. self._noisetex = numpy.random.rand(STIMNOISERES, STIMNOISERES) # Convert the linewidth to a list (if necessary). if type(linewidth) in [int, float]: linewidth = nstim * [int(linewidth)] # Convert the stimulus types to a list (if necessary). if type(stimtypes) in [str, unicode]: stimtypes = nstim * [stimtypes] # Create a Screen to use its wonderful drawing functions. self.scr = Screen() # Draw the fixation cross. self.scr.draw_fixation(fixtype=FIXTYPE, diameter=FIXSIZE) # Draw the colouw wheel if showcolourwheel: # Load the image. self.scr.draw_image(CWIMG, scale=CWIMGSCALE) # Create an internal list of stimuli (=PsychoPy stimulus instances) by # copying it from the internal screen. self.screen = self.scr.screen # Keep a list of the index numbers of all stimuli. The indices refer # to positions within the self.scr.screen list of PsychoPy stimuli. self._stimindexnrs = [] self._outlineindexnrs = [] # Draw the stimuli. for i in range(nstim): # Add the stimulus' index number to the list of indices. self._stimindexnrs.append(len(self.screen)) # # Create a new Rect stimulus instance. # stim = Rect(pygaze.expdisplay, \ # pos=pos2psychopos(locs[i]), \ # fillColor=rgb2psychorgb(list(oris[i])), \ # lineColor=rgb2psychorgb(list(linecols[i])), \ # lineWidth=linewidth[i], \ # width=STIMSIZE, \ # height=STIMSIZE) # Create a Gabor-ish GratingStim. if stimtypes[i] == 'gabor': tex = 'sin' else: tex = self._noisetex stim = GratingStim(pygaze.expdisplay, \ pos=pos2psychopos(locs[i]), \ ori=oris[i], \ size=STIMSIZE, \ sf=self._sf, \ opacity=self._alpha, \ contrast=self._contrast, \ tex=tex, \ mask='circle', \ color=(1,1,1) ) # Add the new stimulus to our list of stimuli. self.screen.append(stim) # Add an outline for the stimulus. self._outlineindexnrs.append(len(self.screen)) stim = Circle(pygaze.expdisplay, \ pos=pos2psychopos(locs[i]), \ lineWidth=linewidth[i], \ radius=STIMSIZE//2, \ edges=32, \ closeShape=False, \ fillColor=None, \ lineColor=(0,0,0) ) # Add the new stimulus to our list of stimuli. self.screen.append(stim)