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):
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