Esempio n. 1
0
    def __init__(self, win, start=(-.5, -.5), end=(.5, .5), **kwargs):
        """
        Line accepts all input parameters, that :class:`~psychopy.visual.ShapeStim` accepts, except
        for vertices, closeShape and fillColor.

        The methods `contains` and `overlaps` are inherited from `~psychopy.visual.ShapeStim`,
        but always return False (because a line is not a proper (2D) polygon).

        :Parameters:

            start : tuple, list or 2x1 array
                Specifies the position of the start of the line

            end : tuple, list or 2x1 array
                Specifies the position of the end of the line

        """
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        #kwargs isn't a parameter, but a list of params
        self._initParams.remove('kwargs')
        self._initParams.extend(kwargs)

        self.start = start
        self.end = end
        self.vertices = [start, end]
        kwargs['closeShape'] = False  # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices
        kwargs['fillColor'] = None
        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 2
0
    def __init__(self, win, edges=3, radius=.5, **kwargs):
        """
        Polygon accepts all input parameters that :class:`~psychopy.visual.ShapeStim` accepts, except for vertices and closeShape.

        :Parameters:

            edges : int
                Number of edges of the polygon

            radius : float, int, tuple, list or 2x1 array
                Radius of the Polygon (distance from the center to the corners).
                May be a -2tuple or list to stretch the polygon asymmetrically
        """
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        #kwargs isn't a parameter, but a list of params
        self._initParams.remove('kwargs')
        self._initParams.extend(kwargs)
        self.autoLog = False #but will be changed if needed at end of init
        self.edges = edges
        self.radius = numpy.asarray(radius)
        self._calcVertices()
        kwargs['closeShape'] = True # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices
        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 3
0
    def __init__(self, win, width=.5, height=.5, **kwargs):
        """
        Rect accepts all input parameters, that `~psychopy.visual.ShapeStim` accept, except for vertices and closeShape.

        :Parameters:

            width : int or float
                Width of the Rectangle (in its respective units, if specified)

            height : int or float
                Height of the Rectangle (in its respective units, if specified)

        """
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        #kwargs isn't a parameter, but a list of params
        self._initParams.remove('kwargs')
        self._initParams.extend(kwargs)

        self.width = width
        self.height = height
        self._calcVertices()
        kwargs['closeShape'] = True  # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices

        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 4
0
    def __init__(self, win, start=(-.5, -.5), end=(.5, .5), **kwargs):
        """
        Line accepts all input parameters, that :class:`~psychopy.visual.ShapeStim` accepts, except
        for vertices, closeShape and fillColor.

        The methods `contains` and `overlaps` are inherited from `~psychopy.visual.ShapeStim`,
        but always return False (because a line is not a proper (2D) polygon).

        :Parameters:

            start : tuple, list or 2x1 array
                Specifies the position of the start of the line

            end : tuple, list or 2x1 array
                Specifies the position of the end of the line

        """
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        #kwargs isn't a parameter, but a list of params
        self._initParams.remove('kwargs')
        self._initParams.extend(kwargs)

        self.start = start
        self.end = end
        self.vertices = [start, end]
        kwargs['closeShape'] = False # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices
        kwargs['fillColor'] = None
        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 5
0
    def __init__(self,
                 win,
                 size=1,
                 pos=(0, 0),
                 ori=0,
                 nVert=120,
                 shape='circle',
                 units=None,
                 name='',
                 autoLog=True):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog = False  #set this False first and change after attribs are set
        self.win = win
        self.size = size
        self.pos = pos
        self.name = name
        self.ori = ori
        #unit conversions
        if units != None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            vertices = [(0.5 * sin(theta * pi / 180),
                         0.5 * cos(theta * pi / 180))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5, -0.5], [-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5]]
        elif shape == 'triangle':
            vertices = [[0.5, -0.5], [0, 0.5], [-0.5, -0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error(
                "Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s"
                % (repr(shape)))

        self._shape = ShapeStim(win=self.win,
                                vertices=vertices,
                                fillColor=1,
                                lineColor=None,
                                interpolate=False,
                                pos=pos,
                                size=size,
                                autoLog=False)
        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._reset()  #implicitly runs an self.enable()
        self.autoLog = autoLog
        if autoLog:
            logging.exp("Created %s = %s" % (self.name, str(self)))
Esempio n. 6
0
    def __init__(self, win, width=.5, height=.5, **kwargs):
        """
        Rect accepts all input parameters, that `~psychopy.visual.ShapeStim` accept, except for vertices and closeShape.

        :Parameters:

            width : int or float
                Width of the Rectangle (in its respective units, if specified)

            height : int or float
                Height of the Rectangle (in its respective units, if specified)

        """
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        #kwargs isn't a parameter, but a list of params
        self._initParams.remove('kwargs')
        self._initParams.extend(kwargs)

        self.width = width
        self.height = height
        self._calcVertices()
        kwargs['closeShape'] = True # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices

        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 7
0
 def __init__(self, win, vert):
     ''' Initialize FillingBar object'''
     ShapeStim.__init__(self,
                        win=win,
                        fillColor='skyblue',
                        lineWidth=0,
                        opacity=1,
                        units='cm',
                        vertices=vert)
Esempio n. 8
0
    def __init__(self, win, size=1, pos=(0,0), ori=0, nVert=120, shape='circle', units=None,
            name=None, autoLog=None):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog=False #set this False first and change after attribs are set
        self.win=win
        if not win.allowStencil:
            logging.error('Aperture has no effect in a window created without allowStencil=True')
            core.quit()
        self.__dict__['size'] = size
        self.__dict__['pos'] = pos
        self.__dict__['ori'] = ori
        
        #unit conversions
        if units!=None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            # NB: pentagon etc point upwards by setting x,y to be y,x (sin,cos):
            vertices = [(0.5*sin(radians(theta)), 0.5*cos(radians(theta)))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5,-0.5],[-0.5,-0.5],[-0.5,0.5],[0.5,0.5]]
        elif shape == 'triangle':
            vertices = [[0.5,-0.5],[0,0.5],[-0.5,-0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error("Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s" %(repr(shape)))
        self._shape = ShapeStim(win=self.win, vertices=vertices,
                                fillColor=1, lineColor=None,
                                interpolate=False, pos=pos, size=size,
                                autoLog=False)

        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._needReset = True  # Default when setting attributes
        self._reset()  #implicitly runs a self.enabled = True. Also sets self._needReset = True on every call
        
        # set autoLog now that params have been initialised
        self.__dict__['autoLog'] = autoLog or autoLog is None and self.win.autoLog
        if self.autoLog:
            logging.exp("Created %s = %s" %(self.name, str(self)))
Esempio n. 9
0
    def __init__(self, win, edges=3, radius=.5, **kwargs):
        """
        Polygon accepts all input parameters that :class:`~psychopy.visual.ShapeStim` accepts, except for vertices and closeShape.

        :Parameters:

            edges : int
                Number of edges of the polygon

            radius : float, int, tuple, list or 2x1 array
                Radius of the Polygon (distance from the center to the corners).
                May be a -2tuple or list to stretch the polygon asymmetrically
        """
        self.edges = edges
        self.radius = numpy.asarray(radius)
        self._calcVertices()
        kwargs['closeShape'] = True # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices
        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 10
0
    def __init__(self, win, width=.5, height=.5, **kwargs):
        """
        Rect accepts all input parameters, that `~psychopy.visual.ShapeStim` accept, except for vertices and closeShape.

        :Parameters:

            width : int or float
                Width of the Rectangle (in its respective units, if specified)

            height : int or float
                Height of the Rectangle (in its respective units, if specified)

        """
        self.width = width
        self.height = height
        self._calcVertices()
        kwargs['closeShape'] = True # Make sure nobody messes around here
        kwargs['vertices'] = self.vertices

        ShapeStim.__init__(self, win, **kwargs)
Esempio n. 11
0
    def __init__(self, win, size=1, pos=(0,0), ori=0, nVert=120, shape='circle', units=None,
            name='', autoLog=True):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog=False #set this False first and change after attribs are set
        self.win=win
        self.size = size
        self.pos = pos
        self.name = name
        self.ori = ori
        #unit conversions
        if units!=None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            vertices = [(0.5*sin(theta*pi/180), 0.5*cos(theta*pi/180))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
                vertices = [[0.5,-0.5],[-0.5,-0.5],[-0.5,0.5],[0.5,0.5]]
        elif shape == 'triangle':
                vertices = [[0.5,-0.5],[0,0.5],[-0.5,-0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error("Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s" %(repr(shape)))

        self._shape = ShapeStim(win=self.win, vertices=vertices,
                fillColor=1, lineColor=None,
                interpolate=False, pos=pos, size=size,
                autoLog=False)
        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._reset()#implicitly runs an self.enable()
        self.autoLog= autoLog
        if autoLog:
            logging.exp("Created %s = %s" %(self.name, str(self)))
Esempio n. 12
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or list of vertices.

    When enabled, any drawing commands will only operate on pixels within the
    Aperture. Once disabled, subsequent draw operations affect the whole screen
    as usual.

    If shape is 'square' or 'triangle' then that is what will be used (obviously)
    If shape is 'circle' or `None` then a polygon with nVerts will be used (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly as the vertices to a :class:`~psychopy.visual.ShapeStim`

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options, Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
    """
    def __init__(self,
                 win,
                 size=1,
                 pos=(0, 0),
                 ori=0,
                 nVert=120,
                 shape='circle',
                 units=None,
                 name='',
                 autoLog=True):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog = False  #set this False first and change after attribs are set
        self.win = win
        if not win.allowStencil:
            logging.error(
                'Aperture has no effect in a window created without allowStencil=True'
            )
            core.quit()
        self.size = size
        self.pos = pos
        self.name = name
        self.ori = ori
        #unit conversions
        if units != None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            # NB: pentagon etc point upwards by setting x,y to be y,x (sin,cos):
            vertices = [(0.5 * sin(radians(theta)), 0.5 * cos(radians(theta)))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5, -0.5], [-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5]]
        elif shape == 'triangle':
            vertices = [[0.5, -0.5], [0, 0.5], [-0.5, -0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error(
                "Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s"
                % (repr(shape)))
        self._shape = ShapeStim(win=self.win,
                                vertices=vertices,
                                fillColor=1,
                                lineColor=None,
                                interpolate=False,
                                pos=pos,
                                size=size,
                                autoLog=False)

        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._reset()  #implicitly runs an self.enable()
        self.autoLog = autoLog
        if autoLog:
            logging.exp("Created %s = %s" % (self.name, str(self)))

    def _reset(self):
        self.enable()
        GL.glClearStencil(0)
        GL.glClear(GL.GL_STENCIL_BUFFER_BIT)

        GL.glPushMatrix()
        self.win.setScale('pix')

        GL.glDisable(GL.GL_LIGHTING)
        GL.glDisable(GL.GL_DEPTH_TEST)
        GL.glDepthMask(GL.GL_FALSE)
        GL.glStencilFunc(GL.GL_NEVER, 0, 0)
        GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)
        self._shape.draw(keepMatrix=True)  #draw without push/pop matrix
        GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
        GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)

        GL.glPopMatrix()

    def setSize(self, size, needReset=True, log=True):
        """Set the size (diameter) of the Aperture
        """
        self.size = size
        self._shape.size = size
        if needReset:
            self._reset()
        logAttrib(self, log, 'size')

    def setOri(self, ori, needReset=True, log=True):
        """Set the orientation of the Aperture
        """
        self.ori = ori
        self._shape.ori = ori
        if needReset:
            self._reset()
        logAttrib(self, log, 'ori')

    def setPos(self, pos, needReset=True, log=True):
        """Set the pos (centre) of the Aperture
        """
        self.pos = numpy.array(pos)
        self._shape.pos = self.pos
        if needReset:
            self._reset()
        logAttrib(self, log, 'pos')

    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix

    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix

    def enable(self):
        """Enable the aperture so that it is used in future drawing operations

        NB. The Aperture is enabled by default, when created.

        """
        if self._shape._needVertexUpdate:
            self._shape._updateVertices()
        GL.glEnable(GL.GL_STENCIL_TEST)
        self.enabled = True  #by default
        self.status = STARTED

    def disable(self):
        """Disable the Aperture. Any subsequent drawing operations will not be
        affected by the aperture until re-enabled.
        """
        GL.glDisable(GL.GL_STENCIL_TEST)
        self.enabled = False
        self.status = STOPPED

    def __del__(self):
        self.disable()
Esempio n. 13
0
 def test_elements(self):
     s = Slider(self.win, size=(1, 0.1))
     assert type(s.line) == type(Rect(self.win))
     assert type(s.tickLines) == type(ElementArrayStim(self.win))
     assert type(s.marker) == type(ShapeStim(self.win))
     assert type(s.validArea) == type(Rect(self.win))
    def _initialize_elements(self, win, stimulus_a, stimulus_b):
        stimulus_a.pos = (0, -stimulus_a.size[0] / 2 - 90)
        stimulus_b.pos = (0, +stimulus_b.size[0] / 2 + 90)

        self.stimulus_a = stimulus_a
        self.stimulus_b = stimulus_b

        self._elements.append(stimulus_a)
        self._elements.append(stimulus_b)

        # create arrows for confidence rating
        # create vertices for the arrow
        arrow_shape_vertices = [
            (0, 0),
            (230, 0),
            (220, 8),
            (230, 0),
            (220, -8),
        ]
        self.arrow_a_shape = ShapeStim(
            win,
            vertices=arrow_shape_vertices,
            size=1,
            lineColor="black",
            lineWidth=3,
            closeShape=False,
            pos=(-112, 25),
        )
        self.arrow_b_shape = ShapeStim(
            win,
            vertices=arrow_shape_vertices,
            size=1,
            lineColor="black",
            lineWidth=3,
            closeShape=False,
            pos=(-112, -25),
        )
        self._elements.append(self.arrow_a_shape)

        # hide the rectangles until they are needed (opacity=0)
        self.choice_text_rectangle = Rect(win,
                                          40,
                                          40,
                                          lineWidth=5,
                                          lineColor="black",
                                          opacity=0.0)
        self.choice_stimulus_rectangle = Rect(
            win,
            stimulus_a.size[1],
            stimulus_a.size[0],
            lineWidth=5,
            lineColor="black",
            opacity=0.0,
        )
        self.correct_rectangle = Rect(
            win,
            stimulus_a.size[1] + 7.5,
            stimulus_a.size[0] + 7.5,
            lineWidth=5,
            lineColor="green",
            opacity=0.0,
        )
        self._elements.append(self.choice_text_rectangle)
        self._elements.append(self.choice_stimulus_rectangle)
        self._elements.append(self.correct_rectangle)

        self.arrow_a_text = TextStim(
            win,
            text="More confident",
            color="black",
            height=25,
            anchorHoriz="center",
            alignText="center",
            pos=(0, +0),
        )
        self.arrow_b_text = self.arrow_a_text
        self._elements.append(self.arrow_a_text)

        self.arrow_levels_text: List[TextStim] = []
        arrow_levels_values = [1, 2, 3, -1, -2, -3]
        arrow_levels_texts = [
            str(x) if x > 0 else str(-x) for x in arrow_levels_values
        ]
        arrow_levels_positions = [(-100, 60), (0, 60), (+100, 60), (-100, -60),
                                  (0, -60), (+100, -60)]
        for (position_x,
             position_y), text, value in zip(arrow_levels_positions,
                                             arrow_levels_texts,
                                             arrow_levels_values):
            item = TextStim(win,
                            text=text,
                            color="black",
                            height=25,
                            pos=(position_x, position_y))
            rect = Rect(win,
                        width=25,
                        height=25,
                        lineWidth=0.0,
                        pos=(position_x, position_y))
            item.value = value
            item.clickable_area = rect
            self.arrow_levels_text.append(item)
            self._elements.append(item)
            self._elements.append(rect)
Esempio n. 15
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or list of vertices.

    When enabled, any drawing commands will only operate on pixels within the
    Aperture. Once disabled, subsequent draw operations affect the whole screen
    as usual.

    If shape is 'square' or 'triangle' then that is what will be used (obviously)
    If shape is 'circle' or `None` then a polygon with nVerts will be used (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly as the vertices to a :class:`~psychopy.visual.ShapeStim`

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options, Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
    """
    def __init__(self, win, size=1, pos=(0,0), ori=0, nVert=120, shape='circle', units=None,
            name='', autoLog=True):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog=False #set this False first and change after attribs are set
        self.win=win
        if not win.allowStencil:
            logging.error('Aperture has no effect in a window created without allowStencil=True')
            core.quit()
        self.size = size
        self.pos = pos
        self.name = name
        self.ori = ori
        #unit conversions
        if units!=None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            # NB: pentagon etc point upwards by setting x,y to be y,x (sin,cos):
            vertices = [(0.5*sin(radians(theta)), 0.5*cos(radians(theta)))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5,-0.5],[-0.5,-0.5],[-0.5,0.5],[0.5,0.5]]
        elif shape == 'triangle':
            vertices = [[0.5,-0.5],[0,0.5],[-0.5,-0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error("Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s" %(repr(shape)))
        self._shape = ShapeStim(win=self.win, vertices=vertices,
                                fillColor=1, lineColor=None,
                                interpolate=False, pos=pos, size=size,
                                autoLog=False)

        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._reset()#implicitly runs an self.enable()
        self.autoLog= autoLog
        if autoLog:
            logging.exp("Created %s = %s" %(self.name, str(self)))
    def _reset(self):
        self.enable()
        GL.glClearStencil(0)
        GL.glClear(GL.GL_STENCIL_BUFFER_BIT)

        GL.glPushMatrix()
        self.win.setScale('pix')

        GL.glDisable(GL.GL_LIGHTING)
        GL.glDisable(GL.GL_DEPTH_TEST)
        GL.glDepthMask(GL.GL_FALSE)
        GL.glStencilFunc(GL.GL_NEVER, 0, 0)
        GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)
        self._shape.draw(keepMatrix=True) #draw without push/pop matrix
        GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
        GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)

        GL.glPopMatrix()

    def setSize(self, size, needReset=True, log=True):
        """Set the size (diameter) of the Aperture
        """
        self.size = size
        self._shape.size = size
        if needReset:
            self._reset()
        logAttrib(self, log, 'size')
    def setOri(self, ori, needReset=True, log=True):
        """Set the orientation of the Aperture
        """
        self.ori = ori
        self._shape.ori = ori
        if needReset:
            self._reset()
        logAttrib(self, log, 'ori')
    def setPos(self, pos, needReset=True, log=True):
        """Set the pos (centre) of the Aperture
        """
        self.pos = numpy.array(pos)
        self._shape.pos = self.pos
        if needReset:
            self._reset()
        logAttrib(self, log, 'pos')
    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix
    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix
    def enable(self):
        """Enable the aperture so that it is used in future drawing operations

        NB. The Aperture is enabled by default, when created.

        """
        if self._shape._needVertexUpdate:
            self._shape._updateVertices()
        GL.glEnable(GL.GL_STENCIL_TEST)
        self.enabled=True#by default
        self.status=STARTED
    def disable(self):
        """Disable the Aperture. Any subsequent drawing operations will not be
        affected by the aperture until re-enabled.
        """
        GL.glDisable(GL.GL_STENCIL_TEST)
        self.enabled=False
        self.status=STOPPED
    def __del__(self):
        self.disable()
Esempio n. 16
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or list of vertices.

    When enabled, any drawing commands will only operate on pixels within the
    Aperture. Once disabled, subsequent draw operations affect the whole screen
    as usual.

    If shape is 'square' or 'triangle' then that is what will be used (obviously)
    If shape is 'circle' or `None` then a polygon with nVerts will be used (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly as the vertices to a :class:`~psychopy.visual.ShapeStim`

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options, Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
    """
    def __init__(self,
                 win,
                 size=1,
                 pos=(0, 0),
                 ori=0,
                 nVert=120,
                 shape='circle',
                 units=None,
                 name=None,
                 autoLog=None):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog = False  #set this False first and change after attribs are set
        self.win = win
        if not win.allowStencil:
            logging.error(
                'Aperture has no effect in a window created without allowStencil=True'
            )
            core.quit()
        self.__dict__['size'] = size
        self.__dict__['pos'] = pos
        self.__dict__['ori'] = ori

        #unit conversions
        if units != None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            # NB: pentagon etc point upwards by setting x,y to be y,x (sin,cos):
            vertices = [(0.5 * sin(radians(theta)), 0.5 * cos(radians(theta)))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5, -0.5], [-0.5, -0.5], [-0.5, 0.5], [0.5, 0.5]]
        elif shape == 'triangle':
            vertices = [[0.5, -0.5], [0, 0.5], [-0.5, -0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        else:
            logging.error(
                "Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, or None; got %s"
                % (repr(shape)))
        self._shape = ShapeStim(win=self.win,
                                vertices=vertices,
                                fillColor=1,
                                lineColor=None,
                                interpolate=False,
                                pos=pos,
                                size=size,
                                autoLog=False)

        self.vertices = self._shape.vertices
        self._needVertexUpdate = True
        self._needReset = True  # Default when setting attributes
        self._reset(
        )  #implicitly runs a self.enabled = True. Also sets self._needReset = True on every call

        # set autoLog now that params have been initialised
        self.__dict__[
            'autoLog'] = autoLog or autoLog is None and self.win.autoLog
        if self.autoLog:
            logging.exp("Created %s = %s" % (self.name, str(self)))

    def _reset(self):
        """Internal method to rebuild the shape - shouldn't be called by the user.
        You have to explicitly turn resetting off by setting self._needReset = False"""
        if not self._needReset:
            self._needReset = True
        else:
            self.enabled = True  # attributeSetter, turns on.
            GL.glClearStencil(0)
            GL.glClear(GL.GL_STENCIL_BUFFER_BIT)

            GL.glPushMatrix()
            self.win.setScale('pix')

            GL.glDisable(GL.GL_LIGHTING)
            GL.glDisable(GL.GL_DEPTH_TEST)
            GL.glDepthMask(GL.GL_FALSE)
            GL.glStencilFunc(GL.GL_NEVER, 0, 0)
            GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)
            self._shape.draw(keepMatrix=True)  #draw without push/pop matrix
            GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
            GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)

            GL.glPopMatrix()

    @attributeSetter
    def size(self, size):
        """Set the size (diameter) of the Aperture. 
        
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.size.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.
        
        Use setSize() if you want to control 0logging and resetting."""
        self.__dict__['size'] = size
        self._shape.size = size  # a ShapeStim
        self._reset()

    def setSize(self, size, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'size', size, log)

    @attributeSetter
    def ori(self, ori):
        """Set the orientation of the Aperture.
        
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.ori.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.
        
        Use setOri() if you want to control logging and resetting."""
        self.__dict__['ori'] = ori
        self._shape.ori = ori  # a ShapeStim
        self._reset()

    def setOri(self, ori, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message.
        """
        self._needReset = needReset
        setAttribute(self, 'ori', ori, log)

    @attributeSetter
    def pos(self, pos):
        """Set the pos (centre) of the Aperture. :ref:`Operations <attrib-operations>` supported.
                
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.pos.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.

        Use setPos() if you want to control logging and resetting.
        """
        self.__dict__['pos'] = numpy.array(pos)
        self._shape.pos = self.pos  # a ShapeStim
        self._reset()

    def setPos(self, pos, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'pos', pos, log)

    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix

    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix

    @attributeSetter
    def enabled(self, value):
        """True / False. Enable or disable the aperture. 
        Determines whether it is used in future drawing operations.

        NB. The Aperture is enabled by default, when created.
        """
        if value:
            if self._shape._needVertexUpdate:
                self._shape._updateVertices()
            GL.glEnable(GL.GL_STENCIL_TEST)
            self.status = STARTED
        else:
            GL.glDisable(GL.GL_STENCIL_TEST)
            self.status = STOPPED

        self.__dict__['enabled'] = value

    def enable(self):
        """Use Aperture.enabled = True instead."""
        self.enabled = True

    def disable(self):
        """Use Aperture.enabled = False instead."""
        self.enabled = False

    def __del__(self):
        self.enabled = False
Esempio n. 17
0
class Aperture(MinimalStim, ContainerMixin):
    """Restrict a stimulus visibility area to a basic shape or list of vertices.

    When enabled, any drawing commands will only operate on pixels within the
    Aperture. Once disabled, subsequent draw operations affect the whole screen
    as usual.

    If shape is 'square' or 'triangle' then that is what will be used (obviously)
    If shape is 'circle' or `None` then a polygon with nVerts will be used (120 for a rough circle)
    If shape is a list or numpy array (Nx2) then it will be used directly as the vertices to a :class:`~psychopy.visual.ShapeStim`
    If shape is a filename then it will be used to load and image as a :class:`~psychopy.visual.ImageStim`.
        Note that transparent parts in the image (e.g. in a PNG file) will not be included in the mask shape. The color of the image will be ignored.

    See demos/stimuli/aperture.py for example usage

    :Author:
        2011, Yuri Spitsyn
        2011, Jon Peirce added units options, Jeremy Gray added shape & orientation
        2014, Jeremy Gray added .contains() option
        2015, Thomas Emmerling added ImageStim option
    """
    def __init__(self, win, size=1, pos=(0,0), ori=0, nVert=120, shape='circle', inverted=False, units=None,
            name=None, autoLog=None):
        #what local vars are defined (these are the init params) for use by __repr__
        self._initParams = dir()
        self._initParams.remove('self')
        super(Aperture, self).__init__(name=name, autoLog=False)

        #set self params
        self.autoLog=False #set this False first and change after attribs are set
        self.win=win
        if not win.allowStencil:
            logging.error('Aperture has no effect in a window created without allowStencil=True')
            core.quit()
        self.__dict__['size'] = size
        self.__dict__['pos'] = pos
        self.__dict__['ori'] = ori
        self.__dict__['inverted'] = inverted
        self.__dict__['filename'] = False

        #unit conversions
        if units!=None and len(units):
            self.units = units
        else:
            self.units = win.units

        # set vertices using shape, or default to a circle with nVerts edges
        if hasattr(shape, 'lower'):
            shape = shape.lower()
        if shape is None or shape == 'circle':
            # NB: pentagon etc point upwards by setting x,y to be y,x (sin,cos):
            vertices = [(0.5*sin(radians(theta)), 0.5*cos(radians(theta)))
                        for theta in numpy.linspace(0, 360, nVert, False)]
        elif shape == 'square':
            vertices = [[0.5,-0.5],[-0.5,-0.5],[-0.5,0.5],[0.5,0.5]]
        elif shape == 'triangle':
            vertices = [[0.5,-0.5],[0,0.5],[-0.5,-0.5]]
        elif type(shape) in [tuple, list, numpy.ndarray] and len(shape) > 2:
            vertices = shape
        elif type(shape) in [str, unicode]:
            #is a string - see if it points to a file
            if os.path.isfile(shape):
                self.__dict__['filename'] = shape
            else:
                logging.error("Unrecognized shape for aperture. Expected 'circle', 'square', 'triangle', vertices, filename, or None; got %s" %(repr(shape)))

        if self.__dict__['filename']:
            self._shape = ImageStim(win=self.win, image=self.__dict__['filename'],
                                pos=pos, size=size,
                                autoLog=False)
        else:
            self._shape = ShapeStim(win=self.win, vertices=vertices,
                                fillColor=1, lineColor=None,
                                interpolate=False, pos=pos, size=size,
                                autoLog=False)
            self.vertices = self._shape.vertices
            self._needVertexUpdate = True

        self._needReset = True  # Default when setting attributes
        self._reset()  #implicitly runs a self.enabled = True. Also sets self._needReset = True on every call
        
        # set autoLog now that params have been initialised
        self.__dict__['autoLog'] = autoLog or autoLog is None and self.win.autoLog
        if self.autoLog:
            logging.exp("Created %s = %s" %(self.name, str(self)))
    def _reset(self):
        """Internal method to rebuild the shape - shouldn't be called by the user.
        You have to explicitly turn resetting off by setting self._needReset = False"""
        if not self._needReset:
            self._needReset = True
        else:
            self.enabled = True  # attributeSetter, turns on.
            GL.glClearStencil(0)
            GL.glClear(GL.GL_STENCIL_BUFFER_BIT)
    
            GL.glPushMatrix()
            if self.__dict__['filename']==False:
                self.win.setScale('pix')

            GL.glDisable(GL.GL_LIGHTING)
            GL.glDisable(GL.GL_DEPTH_TEST)
            GL.glDepthMask(GL.GL_FALSE)
            GL.glStencilFunc(GL.GL_NEVER, 0, 0)
            GL.glStencilOp(GL.GL_INCR, GL.GL_INCR, GL.GL_INCR)

            if self.__dict__['filename']:
                GL.glEnable(GL.GL_ALPHA_TEST)
                GL.glAlphaFunc(GL.GL_GREATER,0)
                self._shape.draw()
                GL.glDisable(GL.GL_ALPHA_TEST)
            else:
                self._shape.draw(keepMatrix=True) #draw without push/pop matrix

            if self.inverted:
                GL.glStencilFunc(GL.GL_EQUAL, 0, 1)
            else:
                GL.glStencilFunc(GL.GL_EQUAL, 1, 1)
            GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP)
    
            GL.glPopMatrix()
    
    @attributeSetter
    def size(self, size):
        """Set the size (diameter) of the Aperture. 
        
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.size.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.
        
        Use setSize() if you want to control 0logging and resetting."""
        self.__dict__['size'] = size
        self._shape.size = size  # a ShapeStim
        self._reset()
    def setSize(self, size, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'size', size, log)
    @attributeSetter
    def ori(self, ori):
        """Set the orientation of the Aperture.
        
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.ori.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.
        
        Use setOri() if you want to control logging and resetting."""
        self.__dict__['ori'] = ori
        self._shape.ori = ori  # a ShapeStim
        self._reset()
    def setOri(self, ori, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message.
        """
        self._needReset = needReset
        setAttribute(self, 'ori', ori, log)
    @attributeSetter
    def pos(self, pos):
        """Set the pos (centre) of the Aperture. :ref:`Operations <attrib-operations>` supported.
                
        This essentially controls a :class:`.ShapeStim` so see documentation for ShapeStim.pos.
        
        :ref:`Operations <attrib-operations>` supported here as well as ShapeStim.

        Use setPos() if you want to control logging and resetting.
        """
        self.__dict__['pos'] = numpy.array(pos)
        self._shape.pos = self.pos  # a ShapeStim
        self._reset()
    def setPos(self, pos, needReset=True, log=None):
        """Usually you can use 'stim.attribute = value' syntax instead,
        but use this method if you need to suppress the log message
        """
        self._needReset = needReset
        setAttribute(self, 'pos', pos, log)
    @attributeSetter
    def inverted(self, value):
        """True / False. Set to true to invert the aperture.
        A non-inverted aperture masks everything BUT the selected shape.
        An inverted aperture masks the selected shape.

        NB. The Aperture is not inverted by default, when created.
        """
        self.__dict__['inverted'] = value
        self._reset()
    def invert(self):
        """Use Aperture.inverted = True instead."""
        self.inverted = True
    @property
    def posPix(self):
        """The position of the aperture in pixels
        """
        return self._shape.posPix
    @property
    def sizePix(self):
        """The size of the aperture in pixels
        """
        return self._shape.sizePix
    @attributeSetter
    def enabled(self, value):
        """True / False. Enable or disable the aperture. 
        Determines whether it is used in future drawing operations.

        NB. The Aperture is enabled by default, when created.
        """
        if value:
            if self._shape._needVertexUpdate:
                self._shape._updateVertices()
            GL.glEnable(GL.GL_STENCIL_TEST)
            self.status = STARTED
        else:
            GL.glDisable(GL.GL_STENCIL_TEST)
            self.status = STOPPED
        
        self.__dict__['enabled'] = value
    def enable(self):
        """Use Aperture.enabled = True instead."""
        self.enabled = True
    def disable(self):
        """Use Aperture.enabled = False instead."""
        self.enabled = False
    def __del__(self):
        self.enabled = False