Package VisionEgg :: Module MoreStimuli |
[frames] | no frames]

# Source Code for Module VisionEgg.MoreStimuli

      1  # The Vision Egg: MoreStimuli
      2  #
      3  # Copyright (C) 2001-2003 Andrew Straw.
      4  #           (C) 2005 by Hertie Institute for Clinical Brain Research,
      5  #            Department of Cognitive Neurology, University of Tuebingen
      6  #           (C) 2005,2008 California Institute of Technology
      7  #           (C) 2006 Peter Jurica and Gijs Plomp
      8  #
      9  # URL: http://www.visionegg.org
     10  #
     11  # Distributed under the terms of the GNU Lesser General Public License
     12  # (LGPL). See LICENSE.TXT that came with this file.
     13
     14  """
     15  Assorted stimuli.
     16
     17  """
     18
     19  ####################################################################
     20  #
     21  #        Import all the necessary packages
     22  #
     23  ####################################################################
     24
     25  import logging
     26
     27  import VisionEgg
     28  import VisionEgg.Core
     29  import VisionEgg.ParameterTypes as ve_types
     30
     31  import numpy.oldnumeric as Numeric
     32
     33  import math
     34
     35  import VisionEgg.GL as gl # get all OpenGL stuff in one namespace
     36
     37 -class Target2D(VisionEgg.Core.Stimulus):
     38      """Rectanglular stimulus.
     39
     40      Parameters
     41      ==========
     42      anchor        -- specifies how position parameter is interpreted (String)
     43                       Default: center
     44      anti_aliasing -- (Boolean)
     45                       Default: True
     46      center        -- DEPRECATED: don't use (Sequence2 of Real)
     47                       Default: (determined at runtime)
     48      color         -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
     49                       Default: (1.0, 1.0, 1.0)
     50      on            -- draw stimulus? (Boolean) (Boolean)
     51                       Default: True
     52      orientation   -- (Real)
     53                       Default: 0.0
     54      position      -- units: eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real))
     55                       Default: (320.0, 240.0)
     56      size          -- units: eye coordinates (Sequence2 of Real)
     57                       Default: (64.0, 16.0)
     58      """
     59
     60      parameters_and_defaults = {
     61          'on':(True,
     62                ve_types.Boolean,
     63                "draw stimulus? (Boolean)"),
     64          'color':((1.0,1.0,1.0),
     65                   ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
     66                                  ve_types.Sequence4(ve_types.Real))),
     67          'anti_aliasing':(True,
     68                           ve_types.Boolean),
     69          'orientation':(0.0,
     70                         ve_types.Real),
     71          'position' : ( ( 320.0, 240.0 ),
     72                         ve_types.AnyOf(ve_types.Sequence2(ve_types.Real),
     73                                        ve_types.Sequence3(ve_types.Real),
     74                                        ve_types.Sequence4(ve_types.Real)),
     75                         "units: eye coordinates"),
     76          'anchor' : ('center',
     77                      ve_types.String,
     78                      "specifies how position parameter is interpreted"),
     79          'size':((64.0,16.0),
     80                  ve_types.Sequence2(ve_types.Real),
     81                  "units: eye coordinates"),
     82          'center' : (None,
     83                      ve_types.Sequence2(ve_types.Real),
     84                      "DEPRECATED: don't use"),
     85          }
     86
     87      __slots__ = (
     88          '_gave_alpha_warning',
     89          )
     90
     91 -    def __init__(self,**kw):
     92          VisionEgg.Core.Stimulus.__init__(self,**kw)
     93          self._gave_alpha_warning = 0
     94
     95 -    def draw(self):
     96          p = self.parameters # shorthand
     97          if p.center is not None:
     98              if not hasattr(VisionEgg.config,"_GAVE_CENTER_DEPRECATION"):
     99                  logger = logging.getLogger('VisionEgg.MoreStimuli')
    100                  logger.warning("Specifying Target2D by deprecated "
    101                                 "'center' parameter deprecated.  Use "
    102                                 "'position' parameter instead.  (Allows "
    103                                 "use of 'anchor' parameter to set to "
    104                                 "other values.)")
    105                  VisionEgg.config._GAVE_CENTER_DEPRECATION = 1
    106              p.anchor = 'center'
    107              p.position = p.center[0], p.center[1] # copy values (don't copy ref to tuple)
    108          if p.on:
    109              # calculate center
    110              center = VisionEgg._get_center(p.position,p.anchor,p.size)
    111              gl.glMatrixMode(gl.GL_MODELVIEW)
    112              gl.glPushMatrix()
    113              gl.glTranslate(center[0],center[1],0.0)
    114              gl.glRotate(p.orientation,0.0,0.0,1.0)
    115
    116              if len(p.color)==3:
    117                  gl.glColor3f(*p.color)
    118              elif len(p.color)==4:
    119                  gl.glColor4f(*p.color)
    120              gl.glDisable(gl.GL_DEPTH_TEST)
    121              gl.glDisable(gl.GL_TEXTURE_2D)
    122              gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
    123              gl.glEnable(gl.GL_BLEND)
    124
    125              w = p.size[0]/2.0
    126              h = p.size[1]/2.0
    127
    128              gl.glBegin(gl.GL_QUADS)
    129              gl.glVertex3f(-w,-h, 0.0)
    130              gl.glVertex3f( w,-h, 0.0)
    131              gl.glVertex3f( w, h, 0.0)
    132              gl.glVertex3f(-w, h, 0.0)
    133              gl.glEnd() # GL_QUADS
    134
    135              if p.anti_aliasing:
    136                  if not self._gave_alpha_warning:
    137                      if len(p.color) > 3 and p.color[3] != 1.0:
    138                          logger = logging.getLogger('VisionEgg.MoreStimuli')
    139                          logger.warning("The parameter anti_aliasing is "
    140                                         "set to true in the Target2D "
    141                                         "stimulus class, but the color "
    142                                         "parameter specifies an alpha "
    143                                         "value other than 1.0.  To "
    144                                         "acheive anti-aliasing, ensure "
    145                                         "that the alpha value for the "
    146                                         "color parameter is 1.0.")
    147                          self._gave_alpha_warning = 1
    148
    149                  # We've already drawn a filled polygon (aliased), now
    150                  # redraw the outline of the polygon (with
    151                  # anti-aliasing).  (Using GL_POLYGON_SMOOTH results in
    152                  # artifactual lines where triangles were joined to
    153                  # create quad, at least on some OpenGL
    154                  # implementations.)
    155
    156                  # Calculate coverage value for each pixel of outline
    157                  # and store as alpha
    158                  gl.glEnable(gl.GL_LINE_SMOOTH)
    159                  # Now specify how to use the alpha value
    160                  gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
    161                  gl.glEnable(gl.GL_BLEND)
    162
    163                  # Draw a second polygon in line mode, so the edges are anti-aliased
    164                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
    165                  gl.glBegin(gl.GL_QUADS)
    166                  gl.glVertex3f(-w,-h, 0.0);
    167                  gl.glVertex3f( w,-h, 0.0);
    168                  gl.glVertex3f( w, h, 0.0);
    169                  gl.glVertex3f(-w, h, 0.0);
    170                  gl.glEnd() # GL_QUADS
    171
    172                  # Set the polygon mode back to fill mode
    173                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
    174                  gl.glDisable(gl.GL_LINE_SMOOTH)
    175              gl.glPopMatrix()
    176
    177 -class Rectangle3D(VisionEgg.Core.Stimulus):
    178      """Solid color rectangle positioned explicitly by four vertices.
    179
    180      Parameters
    181      ==========
    182      color   -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
    183                 Default: (1.0, 1.0, 1.0, 1.0)
    184      on      -- (Boolean)
    185                 Default: True
    186      vertex1 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real))
    187                 Default: (-10.0, 0.0, -10.0)
    188      vertex2 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real))
    189                 Default: (-10.0, 0.0, 10.0)
    190      vertex3 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real))
    191                 Default: (10.0, 0.0, 10.0)
    192      vertex4 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real))
    193                 Default: (10.0, 0.0, -10.0)
    194      """
    195
    196      parameters_and_defaults = {
    197          'on':(True,
    198                ve_types.Boolean),
    199          'color':((1.0,1.0,1.0,1.0),
    200                   ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    201                                  ve_types.Sequence4(ve_types.Real))),
    202          'vertex1':(( -10.0, 0.0, -10.0),
    203                     ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    204                                    ve_types.Sequence4(ve_types.Real)),
    205                   "units: eye coordinates"),
    206          'vertex2':(( -10.0, 0.0,  10.0),
    207                     ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    208                                    ve_types.Sequence4(ve_types.Real)),
    209                   "units: eye coordinates"),
    210          'vertex3':((  10.0, 0.0,  10.0),
    211                     ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    212                                    ve_types.Sequence4(ve_types.Real)),
    213                   "units: eye coordinates"),
    214          'vertex4':((  10.0, 0.0, -10.0),
    215                     ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    216                                    ve_types.Sequence4(ve_types.Real)),
    217                   "units: eye coordinates"),
    218          }
    219
    220 -    def __init__(self,**kw):
    221          VisionEgg.Core.Stimulus.__init__(self,**kw)
    222
    223 -    def draw(self):
    224          p = self.parameters # shorthand
    225          if p.on:
    226              if len(p.color)==3:
    227                  gl.glColor3f(*p.color)
    228              elif len(p.color)==4:
    229                  gl.glColor4f(*p.color)
    230
    231              gl.glDisable(gl.GL_TEXTURE_2D)
    232              gl.glDisable(gl.GL_DEPTH_TEST)
    233              gl.glDisable(gl.GL_BLEND)
    234
    235              gl.glBegin(gl.GL_QUADS)
    236              gl.glVertex(*p.vertex1)
    237              gl.glVertex(*p.vertex2)
    238              gl.glVertex(*p.vertex3)
    239              gl.glVertex(*p.vertex4)
    240              gl.glEnd() # GL_QUADS
    241
    242              gl.glDisable(gl.GL_TEXTURE_2D)
    243              gl.glDisable(gl.GL_BLEND)
    244
    245              gl.glBegin(gl.GL_QUADS)
    246              gl.glVertex(*p.vertex1)
    247              gl.glVertex(*p.vertex2)
    248              gl.glVertex(*p.vertex3)
    249              gl.glVertex(*p.vertex4)
    250              gl.glEnd() # GL_QUADS
    251
    252 -class Arrow(VisionEgg.Core.Stimulus):
    253      """Arrow stimulus.
    254
    255      Parameters
    256      ==========
    257      anchor        -- (String)
    258                       Default: center
    259      anti_aliasing -- (Boolean)
    260                       Default: True
    261      color         -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
    262                       Default: (1.0, 1.0, 1.0)
    263      on            -- (Boolean)
    264                       Default: True
    265      orientation   -- (Real)
    266                       Default: 0.0
    267      position      -- units: eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real))
    268                       Default: (320.0, 240.0)
    269      size          -- (Sequence2 of Real)
    270                       Default: (64.0, 16.0)
    271      """
    272
    273      parameters_and_defaults = {
    274          'on':(True,
    275                ve_types.Boolean),
    276          'color':((1.0,1.0,1.0),
    277                   ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    278                                  ve_types.Sequence4(ve_types.Real))),
    279          'anti_aliasing':(True,
    280                           ve_types.Boolean),
    281          'orientation':(0.0, # 0.0 degrees = right, 90.0 degrees = up
    282                         ve_types.Real),
    283          'position' : ( ( 320.0, 240.0 ), # In eye coordinates
    284                         ve_types.AnyOf(ve_types.Sequence2(ve_types.Real),
    285                                        ve_types.Sequence3(ve_types.Real),
    286                                        ve_types.Sequence4(ve_types.Real)),
    287                         "units: eye coordinates"),
    288          'anchor' : ('center',
    289                      ve_types.String),
    290          'size':((64.0,16.0), # In eye coordinates
    291                  ve_types.Sequence2(ve_types.Real)),
    292          }
    293
    294      __slots__ = VisionEgg.Core.Stimulus.__slots__ + (
    295          '_gave_alpha_warning',
    296          )
    297
    298 -    def __init__(self,**kw):
    299          VisionEgg.Core.Stimulus.__init__(self,**kw)
    300          self._gave_alpha_warning = 0
    301
    302 -    def draw(self):
    303          p = self.parameters # Shorthand
    304          if p.on:
    305              # Calculate center
    306              center = VisionEgg._get_center(p.position,p.anchor,p.size)
    307              gl.glMatrixMode(gl.GL_MODELVIEW)
    308              gl.glPushMatrix()
    309              gl.glTranslate(center[0],center[1],0.0)
    310              gl.glRotate(-p.orientation,0.0,0.0,1.0)
    311
    312              if len(p.color)==3:
    313                  gl.glColor3f(*p.color)
    314              elif len(p.color)==4:
    315                  gl.glColor4f(*p.color)
    316              gl.glDisable(gl.GL_DEPTH_TEST)
    317              gl.glDisable(gl.GL_TEXTURE_2D)
    318              gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
    319              gl.glEnable(gl.GL_BLEND)
    320
    321              w = p.size[0]/2.0
    322              h = p.size[1]/2.0
    323
    324              gl.glBegin(gl.GL_QUADS) # Draw Rectangle
    325              gl.glVertex3f( 0.25*w, h, 0.0)
    326              gl.glVertex3f(-w, h, 0.0)
    327              gl.glVertex3f(-w,-h, 0.0)
    328              gl.glVertex3f( 0.25*w, -h, 0.0)
    329              gl.glEnd() # GL_QUADS
    330
    331              gl.glBegin(gl.GL_TRIANGLES) # Draw Triangle
    332              gl.glVertex3f( 1.00*w, 0.0*h, 0.0) # Top
    333              gl.glVertex3f( 0.25*w,-3.0*h, 0.0)
    334              gl.glVertex3f( 0.25*w, 3.0*h, 0.0)
    335              gl.glEnd() # GL_QUADS
    336
    337              if p.anti_aliasing:
    338                  if not self._gave_alpha_warning:
    339                      if len(p.color) > 3 and p.color[3] != 1.0:
    340                          logger = logging.getLogger('VisionEgg.Arrow')
    341                          logger.warning("The parameter anti_aliasing is "
    342                                         "set to true in the Arrow "
    343                                         "stimulus class, but the color "
    344                                         "parameter specifies an alpha "
    345                                         "value other than 1.0.  To "
    346                                         "acheive anti-aliasing, ensure "
    347                                         "that the alpha value for the "
    348                                         "color parameter is 1.0.")
    349                          self._gave_alpha_warning = 1
    350
    351                  # We've already drawn a filled polygon (aliased), now redraw
    352                  # the outline of the polygon (with anti-aliasing). (Using
    353                  # GL_POLYGON_SMOOTH results in artifactual lines where
    354                  # triangles were joined to create quad, at least on some OpenGL
    355                  # implementations.)
    356
    357                  # Calculate coverage value for each pixel of outline
    358                  # and store as alpha
    359                  gl.glEnable(gl.GL_LINE_SMOOTH)
    360                  # Now specify how to use the alpha value
    361                  gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
    362                  gl.glEnable(gl.GL_BLEND)
    363
    364                  # Draw a second polygon in line mode, so the edges are anti-aliased
    365                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
    366                  gl.glBegin(gl.GL_QUADS)
    367
    368                  gl.glVertex3f( 0.25*w, h, 0.0) # Draw Rectangle
    369                  gl.glVertex3f(-w, h, 0.0)
    370                  gl.glVertex3f(-w,-h, 0.0)
    371                  gl.glVertex3f( 0.25*w, -h, 0.0)
    372                  gl.glVertex3f( 1.00*w, 0.0*h, 0.0) # Draw Triangle
    373                  gl.glVertex3f( 0.25*w,-3.0*h, 0.0)
    374                  gl.glVertex3f( 0.25*w, 3.0*h, 0.0)
    375                  gl.glEnd() # GL_QUADS
    376
    377                  # Set the polygon mode back to fill mode
    378                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
    379                  gl.glDisable(gl.GL_LINE_SMOOTH)
    380              gl.glPopMatrix()
    381
    382 -class FilledCircle(VisionEgg.Core.Stimulus):
    383      """  A circular stimulus, typically used as a fixation point.
    384
    385      (Note, this implementation almost certainly could be made faster
    386      using display lists.)
    387
    388      Parameters
    389      ==========
    390      anchor        -- how position parameter is used (String)
    391                       Default: center
    392      anti_aliasing -- (Boolean)
    393                       Default: True
    394      color         -- color (AnyOf(Sequence3 of Real or Sequence4 of Real))
    395                       Default: (1.0, 1.0, 1.0)
    396      num_triangles -- number of triangles used to draw circle (Integer)
    397                       Default: 51
    398      on            -- draw? (Boolean)
    399                       Default: True
    400      position      -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real))
    401                       Default: (320.0, 240.0)
    402      radius        -- radius in eye coordinates (Real)
    403                       Default: 2.0
    404      """
    405
    406      parameters_and_defaults = VisionEgg.ParameterDefinition({
    407          'on':(True,
    408                ve_types.Boolean,
    409                'draw?'),
    410          'color':((1.0,1.0,1.0),
    411                   ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
    412                                  ve_types.Sequence4(ve_types.Real)),
    413                   'color'),
    414          'anti_aliasing':(True,
    415                           ve_types.Boolean),
    416          'position' : ( ( 320.0, 240.0 ), # in eye coordinates
    417                         ve_types.AnyOf(ve_types.Sequence2(ve_types.Real),
    418                                        ve_types.Sequence3(ve_types.Real),
    419                                        ve_types.Sequence4(ve_types.Real)),
    420                         'position in eye coordinates'),
    421          'anchor' : ('center',
    422                      ve_types.String,
    423                      'how position parameter is used'),
    424          'radius':(2.0,
    425                    ve_types.Real,
    426                    'radius in eye coordinates'),
    427          'num_triangles':(51,
    428                           ve_types.Integer,
    429                           'number of triangles used to draw circle'),
    430          })
    431      __slots__ = VisionEgg.Core.Stimulus.__slots__ + (
    432          '_gave_alpha_warning',
    433          )
    434
    435 -    def __init__(self,**kw):
    436          VisionEgg.Core.Stimulus.__init__(self,**kw)
    437          self._gave_alpha_warning = 0
    438
    439 -    def draw(self):
    440          p = self.parameters # shorthand
    441          if p.on:
    442              # calculate center
    443              center = VisionEgg._get_center(p.position,p.anchor,(p.radius, p.radius))
    444              gl.glDisable(gl.GL_DEPTH_TEST)
    445              gl.glDisable(gl.GL_TEXTURE_2D)
    446              gl.glDisable(gl.GL_BLEND)
    447
    448              if len(p.color)==3:
    449                  gl.glColor3f(*p.color)
    450              elif len(p.color)==4:
    451                  gl.glColor4f(*p.color)
    452
    453            # Build filled circle from points
    454  #           gl.glBegin(gl.GL_POINTS)
    455  #           radius = int(math.ceil(p.radius))
    456  #           for i in range(-radius, radius):
    457  #               for j in range(-radius, radius):
    458  #                   if(i * i + j * j < radius * radius):
    459  #                       gl.glVertex3f(p.position[0] + i, p.position[1] + j, 0.0)
    460  #           gl.glEnd() # GL_POINTS
    461
    462              # Build filled circle from triangles (this is typically faster
    463              # then the commented code above with the points)
    464              gl.glBegin(gl.GL_TRIANGLE_FAN)
    465              gl.glVertex3f(p.position[0], p.position[1], 0.0)
    466              angles = Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
    467              verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
    468              verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
    469              verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
    470              for i in range(verts.shape[0]):
    471                  gl.glVertex2fv(verts[i])
    472              gl.glVertex2fv(verts[0])
    473
    474              gl.glEnd() # GL_TRIANGLE_FAN
    475              if p.anti_aliasing:
    476                  if not self._gave_alpha_warning:
    477                      if len(p.color) > 3 and p.color[3] != 1.0:
    478                          logger = logging.getLogger('VisionEgg.Arrow')
    479                          logger.warning("The parameter anti_aliasing is "
    480                                         "set to true in the Arrow "
    481                                         "stimulus class, but the color "
    482                                         "parameter specifies an alpha "
    483                                         "value other than 1.0.  To "
    484                                         "acheive anti-aliasing, ensure "
    485                                         "that the alpha value for the "
    486                                         "color parameter is 1.0.")
    487                          self._gave_alpha_warning = 1
    488
    489                          # We've already drawn a filled polygon (aliased), now redraw
    490                          # the outline of the polygon (with anti-aliasing). (Using
    491                          # GL_POLYGON_SMOOTH results in artifactual lines where
    492                          # triangles were joined to create quad, at least on some OpenGL
    493                          # implementations.)
    494
    495                  # Calculate coverage value for each pixel of outline
    496                  # and store as alpha
    497                  gl.glEnable(gl.GL_LINE_SMOOTH)
    498                  # Now specify how to use the alpha value
    499                  gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
    500                  gl.glEnable(gl.GL_BLEND)
    501
    502                  # Draw a second polygon in line mode, so the edges are anti-aliased
    503                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
    504                  gl.glBegin(gl.GL_TRIANGLE_FAN)
    505                  gl.glVertex3f(p.position[0], p.position[1], 0.0)
    506                  angles = Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
    507                  verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
    508                  verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
    509                  verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
    510                  for i in range(verts.shape[0]):
    511                      gl.glVertex2fv(verts[i])
    512                  gl.glVertex2fv(verts[0])
    513                  gl.glEnd() # GL_TRIANGLE_FAN
    514
    515                  # Set the polygon mode back to fill mode
    516                  gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
    517                  gl.glDisable(gl.GL_LINE_SMOOTH)
    518