class Line(DisplayListStimulus): """ A line. Parameters ========== anti_aliasing -- (Boolean) Default: True color -- color (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) on -- draw? (Boolean) Default: True position -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) end -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (420.0, 240.0) """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on': (True, ve_types.Boolean, 'draw?'), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color'), 'anti_aliasing': (True, ve_types.Boolean), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'position in eye coordinates'), 'end': ( (420.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'end point in eye coordinates'), 'width': (1., ve_types.Real, 'line width'), }) __slots__ = VisionEgg.Core.Stimulus.__slots__ + ('_gave_alpha_warning', ) def __init__(self, **kw): DisplayListStimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def _draw(self): p = self.parameters gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_BLEND) gl.glColor(p.color) if p.anti_aliasing: gl.glEnable(gl.GL_LINE_SMOOTH) gl.glLineWidth(p.width) gl.glBegin(gl.GL_LINES) gl.glVertex(p.position) gl.glVertex(p.end) gl.glEnd() gl.glDisable(gl.GL_LINE_SMOOTH)
class GlutTextBase(VisionEgg.Core.Stimulus): """DEPRECATED. Base class: don't instantiate this class directly. Base class that defines the common interface between the other glut-based text stimuli. Parameters ========== color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) lowerleft -- (Sequence2 of Real) Default: (320, 240) on -- (Boolean) Default: True text -- (String) Default: the string to display """ parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'lowerleft': ((320, 240), ve_types.Sequence2(ve_types.Real)), 'text': ('the string to display', ve_types.String) } def __init__(self, **kw): if not hasattr(VisionEgg.config, "_GAVE_GLUT_TEXT_DEPRECATION"): logger = logging.getLogger('VisionEgg.Text') logger.warning("Using GlutTextBase class. This will be " "removed in a future release. Use " "VisionEgg.Text.Text instead.") VisionEgg.config._GAVE_GLUT_TEXT_DEPRECATION = 1 VisionEgg.Core.Stimulus.__init__(self, **kw)
class GlutTextBase(VisionEgg.Core.Stimulus): """DEPRECATED. Base class: don't instantiate this class directly. Base class that defines the common interface between the other glut-based text stimuli. Parameters ========== color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) lowerleft -- (Sequence2 of Real) Default: (320, 240) on -- (Boolean) Default: True text -- (String) Default: the string to display """ parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'lowerleft': ((320, 240), ve_types.Sequence2(ve_types.Real)), 'text': ('the string to display', ve_types.String) } def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw)
class Foo(ClassWithParameters): parameters_and_defaults = { 'position': ((320, 240), vtype.Sequence2(vtype.Real)), 'numCols': (15, vtype.UnsignedInteger), 'numRows': (15, vtype.UnsignedInteger), 'dotSize': (10, vtype.UnsignedInteger), 'scale': (50, vtype.Real), 'angle': (0, vtype.Real), 'gamma': (85, vtype.Real), 'aspectRatio': (1, vtype.Real), 'apertureSize': (300, vtype.Real), 'perturb': (False, vtype.Boolean), 'lighting': (False, vtype.Boolean), 'lightPos': ((100, 100, -100), vtype.Sequence3(vtype.Real)), 'foreground': ((0, 0, 0, 1), vtype.Sequence4(vtype.Real)), 'background': ((0.3, 0.3, 0.3, 1), vtype.Sequence4(vtype.Real)) } def __init__(self, **kw): ClassWithParameters.__init__(self, **kw) def __str__(self): return 'Foo'
class SinGrating3D(LuminanceGratingCommon): """Sine wave grating stimulus texture mapped onto quad in 3D This is a general-purpose, realtime sine-wave luminace grating generator. This 3D version doesn't support an orientation parameter. This could be implemented, but for now should be done by orienting the quad in 3D. Parameters ========== bit_depth -- precision with which grating is calculated and sent to OpenGL (UnsignedInteger) Inherited from LuminanceGratingCommon Default: 8 color1 -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) color2 -- optional color with which to perform interpolation with color1 in RGB space (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (determined at runtime) contrast -- (Real) Default: 1.0 depth -- (Real) Default: (determined at runtime) depth_test -- perform depth test? (Boolean) Default: True ignore_time -- (Boolean) Default: False lowerleft -- vertex position (units: eye coordinates) (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (0.0, 0.0, -1.0) lowerright -- vertex position (units: eye coordinates) (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 0.0, -1.0) mask -- optional masking function (Instance of <class 'VisionEgg.Textures.Mask2D'>) Default: (determined at runtime) max_alpha -- (Real) Default: 1.0 num_samples -- (UnsignedInteger) Default: 512 on -- draw stimulus? (Boolean) Default: True pedestal -- (Real) Default: 0.5 phase_at_t0 -- (Real) Default: 0.0 polygon_offset_enabled -- perform polygon offset? (Boolean) Default: False polygon_offset_factor -- polygon factor (Real) Default: 1.0 polygon_offset_units -- polygon units (Real) Default: 1.0 recalculate_phase_tolerance -- (Real) Default: (determined at runtime) size -- defines coordinate size of grating (in eye coordinates) (Sequence2 of Real) Default: (1.0, 1.0) spatial_freq -- frequency defined relative to coordinates defined in size parameter (units; cycles/eye_coord_unit) (Real) Default: 4.0 t0_time_sec_absolute -- (Real) Default: (determined at runtime) temporal_freq_hz -- (Real) Default: 5.0 upperleft -- vertex position (units: eye coordinates) (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (0.0, 1.0, -1.0) upperright -- vertex position (units: eye coordinates) (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, -1.0) """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on':(True, ve_types.Boolean, "draw stimulus?"), 'mask':(None, # allows window onto otherwise (tilted) rectangular grating ve_types.Instance(VisionEgg.Textures.Mask2D), "optional masking function"), 'contrast':(1.0, ve_types.Real), 'pedestal':(0.5, ve_types.Real), 'depth':(None, # if not None, turns on depth testing and allows for occlusion ve_types.Real), 'size':((1.0,1.0), # in eye coordinates ve_types.Sequence2(ve_types.Real), "defines coordinate size of grating (in eye coordinates)"), 'spatial_freq':(4.0, # cycles/eye coord units ve_types.Real, "frequency defined relative to coordinates defined in size parameter (units; cycles/eye_coord_unit)"), 'temporal_freq_hz':(5.0, # hz ve_types.Real), 't0_time_sec_absolute':(None, # Will be assigned during first call to draw() ve_types.Real), 'ignore_time':(False, # ignore temporal frequency variable - allow control purely with phase_at_t0 ve_types.Boolean), 'phase_at_t0':(0.0, # degrees [0.0-360.0] ve_types.Real), 'num_samples':(512, # number of spatial samples, should be a power of 2 ve_types.UnsignedInteger), 'max_alpha':(1.0, # controls "opacity": 1.0 = completely opaque, 0.0 = completely transparent ve_types.Real), 'color1':((1.0, 1.0, 1.0), # alpha is ignored (if given) -- use max_alpha parameter ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'color2':(None, # perform interpolation with color1 in RGB space. ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "optional color with which to perform interpolation with color1 in RGB space"), 'recalculate_phase_tolerance':(None, # only recalculate texture when phase is changed by more than this amount, None for always recalculate. (Saves time.) ve_types.Real), 'depth_test':(True, ve_types.Boolean, "perform depth test?"), 'lowerleft':((0.0,0.0,-1.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "vertex position (units: eye coordinates)"), 'lowerright':((1.0,0.0,-1.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "vertex position (units: eye coordinates)"), 'upperleft':((0.0,1.0,-1.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "vertex position (units: eye coordinates)"), 'upperright':((1.0,1.0,-1.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "vertex position (units: eye coordinates)"), 'polygon_offset_enabled':(False, ve_types.Boolean, "perform polygon offset?"), 'polygon_offset_factor':(1.0, ve_types.Real, "polygon factor"), 'polygon_offset_units':(1.0, ve_types.Real, "polygon units"), }) __slots__ = ( '_texture_object_id', '_last_phase', ) def __init__(self,**kw): LuminanceGratingCommon.__init__(self,**kw) p = self.parameters # shorthand self._texture_object_id = gl.glGenTextures(1) if p.mask: gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB) gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id) # Do error-checking on texture to make sure it will load max_dim = gl.glGetIntegerv(gl.GL_MAX_TEXTURE_SIZE) if p.num_samples > max_dim: raise NumSamplesTooLargeError("Grating num_samples too large for video system.\nOpenGL reports maximum size of %d"%(max_dim,)) self.calculate_bit_depth_dependencies() w = p.size[0] inc = w/float(p.num_samples) phase = 0.0 # this data won't get used - don't care about phase self._last_phase = phase floating_point_sin = numpy.sin(2.0*math.pi*p.spatial_freq*numpy.arange(0.0,w,inc,dtype=numpy.float)+(phase/180.0*math.pi))*0.5*p.contrast+p.pedestal floating_point_sin = numpy.clip(floating_point_sin,0.0,1.0) # allow square wave generation if contrast > 1 texel_data = (floating_point_sin*self.max_int_val).astype(self.numpy_dtype).tostring() # Because the MAX_TEXTURE_SIZE method is insensitive to the current # state of the video system, another check must be done using # "proxy textures". gl.glTexImage1D(gl.GL_PROXY_TEXTURE_1D, # target 0, # level self.gl_internal_format, # video RAM internal format p.num_samples, # width 0, # border self.format, # format of texel data self.gl_type, # type of texel data texel_data) # texel data (irrelevant for proxy) if gl.glGetTexLevelParameteriv(gl.GL_PROXY_TEXTURE_1D, # Need PyOpenGL >= 2.0 0, gl.GL_TEXTURE_WIDTH) == 0: raise NumSamplesTooLargeError("Grating num_samples is too wide for your video system!") # If we got here, it worked and we can load the texture for real. gl.glTexImage1D(gl.GL_TEXTURE_1D, # target 0, # level self.gl_internal_format, # video RAM internal format p.num_samples, # width 0, # border self.format, # format of texel data self.gl_type, # type of texel data texel_data) # texel data # Set texture object defaults gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_S,gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_T,gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR) if p.color2 is not None: if VisionEgg.Core.gl_renderer == 'ATi Rage 128 Pro OpenGL Engine' and VisionEgg.Core.gl_version == '1.1 ATI-1.2.22': logger = logging.getLogger('VisionEgg.Gratings') logger.warning("Your video card and driver have known " "bugs which prevent them from rendering " "color gratings properly.") def __del__(self): gl.glDeleteTextures( [self._texture_object_id] ) def draw(self): p = self.parameters # shorthand if p.on: if p.mask: gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB) if p.depth_test: gl.glEnable(gl.GL_DEPTH_TEST) else: gl.glDisable(gl.GL_DEPTH_TEST) if p.polygon_offset_enabled: gl.glEnable(gl.GL_POLYGON_OFFSET_EXT) gl.glPolygonOffset(p.polygon_offset_factor, p.polygon_offset_units) gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id) gl.glEnable(gl.GL_TEXTURE_1D) gl.glDisable(gl.GL_TEXTURE_2D) if p.bit_depth != self.cached_bit_depth: self.calculate_bit_depth_dependencies() # allow max_alpha value to control blending gl.glEnable( gl.GL_BLEND ) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) if p.color2: gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_BLEND) gl.glTexEnvfv(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_COLOR, p.color2) ## alpha is ignored because the texture base internal format is luminance else: gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE) if p.t0_time_sec_absolute is None and not p.ignore_time: p.t0_time_sec_absolute = VisionEgg.time_func() w = p.size[0] inc = w/float(p.num_samples) if p.ignore_time: phase = p.phase_at_t0 else: t_var = VisionEgg.time_func() - p.t0_time_sec_absolute phase = t_var*p.temporal_freq_hz*-360.0 + p.phase_at_t0 if p.recalculate_phase_tolerance is None or abs(self._last_phase - phase) > p.recalculate_phase_tolerance: self._last_phase = phase # we're re-drawing the phase at this angle floating_point_sin = numpy.sin(2.0*math.pi*p.spatial_freq*numpy.arange(0.0,w,inc,dtype=numpy.float)+(phase/180.0*math.pi))*0.5*p.contrast+p.pedestal floating_point_sin = numpy.clip(floating_point_sin,0.0,1.0) # allow square wave generation if contrast > 1 texel_data = (floating_point_sin*self.max_int_val).astype(self.numpy_dtype).tostring() gl.glTexSubImage1D(gl.GL_TEXTURE_1D, # target 0, # level 0, # x offset p.num_samples, # width self.format, # format of new texel data self.gl_type, # type of new texel data texel_data) # new texel data # in the case of only color1, # the texel data multiplies color1 to produce a color # with color2, # the texel data linearly interpolates between color1 and color2 gl.glColor4f(p.color1[0],p.color1[1],p.color1[2],p.max_alpha) if p.mask: p.mask.draw_masked_quad_3d(0.0,1.0,0.0,1.0, # for texture coordinates p.lowerleft,p.lowerright,p.upperright,p.upperleft) else: # draw unmasked quad gl.glBegin(gl.GL_QUADS) gl.glTexCoord2f(0.0,0.0) gl.glVertex(*p.lowerleft) gl.glTexCoord2f(1.0,0.0) gl.glVertex(*p.lowerright) gl.glTexCoord2f(1.0,1.0) gl.glVertex(*p.upperright) gl.glTexCoord2f(0.0,1.0) gl.glVertex(*p.upperleft) gl.glEnd() # GL_QUADS gl.glDisable(gl.GL_TEXTURE_1D) if p.polygon_offset_enabled: gl.glDisable(gl.GL_POLYGON_OFFSET_EXT)
class SinGrating2D(LuminanceGratingCommon): """Sine wave grating stimulus This is a general-purpose, realtime sine-wave luminace grating generator. To acheive an arbitrary orientation, this class rotates a textured quad. To draw a grating with sides that always remain horizontal and vertical, draw a large grating in a small viewport. (The viewport will clip anything beyond its edges.) Parameters ========== anchor -- specifies how position parameter is interpreted (String) Default: center bit_depth -- precision with which grating is calculated and sent to OpenGL (UnsignedInteger) Inherited from LuminanceGratingCommon Default: 8 color1 -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) color2 -- optional color with which to perform interpolation with color1 in RGB space (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (determined at runtime) contrast -- (Real) Default: 1.0 depth -- (Real) Default: (determined at runtime) ignore_time -- (Boolean) Default: False mask -- optional masking function (Instance of <class 'VisionEgg.Textures.Mask2D'>) Default: (determined at runtime) max_alpha -- (Real) Default: 1.0 num_samples -- (UnsignedInteger) Default: 512 on -- draw stimulus? (Boolean) Default: True orientation -- (Real) Default: 0.0 pedestal -- (Real) Default: 0.5 phase_at_t0 -- (Real) Default: 0.0 position -- (units: eye coordinates) (Sequence2 of Real) Default: (320.0, 240.0) recalculate_phase_tolerance -- (Real) Default: (determined at runtime) size -- defines coordinate size of grating (in eye coordinates) (Sequence2 of Real) Default: (640.0, 480.0) spatial_freq -- frequency defined relative to coordinates defined in size parameter (units: cycles/eye_coord_unit) (Real) Default: 0.0078125 t0_time_sec_absolute -- (Real) Default: (determined at runtime) temporal_freq_hz -- (Real) Default: 5.0 """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on':(True, ve_types.Boolean, "draw stimulus?"), 'mask':(None, # allows window onto otherwise (tilted) rectangular grating ve_types.Instance(VisionEgg.Textures.Mask2D), "optional masking function"), 'contrast':(1.0, ve_types.Real), 'pedestal':(0.5, ve_types.Real), 'position':((320.0,240.0), # in eye coordinates ve_types.Sequence2(ve_types.Real), "(units: eye coordinates)"), 'anchor':('center', ve_types.String, "specifies how position parameter is interpreted"), 'depth':(None, # if not None, turns on depth testing and allows for occlusion ve_types.Real), 'size':((640.0,480.0), ve_types.Sequence2(ve_types.Real), "defines coordinate size of grating (in eye coordinates)", ), 'spatial_freq':(1.0/128.0, # cycles/eye coord units ve_types.Real, "frequency defined relative to coordinates defined in size parameter (units: cycles/eye_coord_unit)", ), 'temporal_freq_hz':(5.0, # hz ve_types.Real), 't0_time_sec_absolute':(None, # Will be assigned during first call to draw() ve_types.Real), 'ignore_time':(False, # ignore temporal frequency variable - allow control purely with phase_at_t0 ve_types.Boolean), 'phase_at_t0':(0.0, # degrees [0.0-360.0] ve_types.Real), 'orientation':(0.0, # 0=right, 90=up ve_types.Real), 'num_samples':(512, # number of spatial samples, should be a power of 2 ve_types.UnsignedInteger), 'max_alpha':(1.0, # controls "opacity": 1.0 = completely opaque, 0.0 = completely transparent ve_types.Real), 'color1':((1.0, 1.0, 1.0), # alpha is ignored (if given) -- use max_alpha parameter ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'color2':(None, # perform interpolation with color1 in RGB space. ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "optional color with which to perform interpolation with color1 in RGB space"), 'recalculate_phase_tolerance':(None, # only recalculate texture when phase is changed by more than this amount, None for always recalculate. (Saves time.) ve_types.Real), }) __slots__ = ( '_texture_object_id', '_last_phase', ) def __init__(self,**kw): LuminanceGratingCommon.__init__(self,**kw) p = self.parameters # shorthand self._texture_object_id = gl.glGenTextures(1) if p.mask: gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB) gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id) # Do error-checking on texture to make sure it will load max_dim = gl.glGetIntegerv(gl.GL_MAX_TEXTURE_SIZE) if p.num_samples > max_dim: raise NumSamplesTooLargeError("Grating num_samples too large for video system.\nOpenGL reports maximum size of %d"%(max_dim,)) self.calculate_bit_depth_dependencies() w = p.size[0] inc = w/float(p.num_samples) phase = 0.0 # this data won't get used - don't care about phase self._last_phase = phase floating_point_sin = numpy.sin(2.0*math.pi*p.spatial_freq*numpy.arange(0.0,w,inc,dtype=numpy.float)+(phase/180.0*math.pi))*0.5*p.contrast+p.pedestal floating_point_sin = numpy.clip(floating_point_sin,0.0,1.0) # allow square wave generation if contrast > 1 texel_data = (floating_point_sin*self.max_int_val).astype(self.numpy_dtype).tostring() # Because the MAX_TEXTURE_SIZE method is insensitive to the current # state of the video system, another check must be done using # "proxy textures". gl.glTexImage1D(gl.GL_PROXY_TEXTURE_1D, # target 0, # level self.gl_internal_format, # video RAM internal format p.num_samples, # width 0, # border self.format, # format of texel data self.gl_type, # type of texel data texel_data) # texel data (irrelevant for proxy) if gl.glGetTexLevelParameteriv(gl.GL_PROXY_TEXTURE_1D, # Need PyOpenGL >= 2.0 0, gl.GL_TEXTURE_WIDTH) == 0: raise NumSamplesTooLargeError("Grating num_samples is too wide for your video system!") # If we got here, it worked and we can load the texture for real. gl.glTexImage1D(gl.GL_TEXTURE_1D, # target 0, # level self.gl_internal_format, # video RAM internal format p.num_samples, # width 0, # border self.format, # format of texel data self.gl_type, # type of texel data texel_data) # texel data # Set texture object defaults gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_S,gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_T,gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR) if p.color2 is not None: if VisionEgg.Core.gl_renderer == 'ATi Rage 128 Pro OpenGL Engine' and VisionEgg.Core.gl_version == '1.1 ATI-1.2.22': logger = logging.getLogger('VisionEgg.Gratings') logger.warning("Your video card and driver have known " "bugs which prevent them from rendering " "color gratings properly.") def __del__(self): gl.glDeleteTextures( [self._texture_object_id] ) def draw(self): p = self.parameters # shorthand if p.on: # calculate center center = VisionEgg._get_center(p.position,p.anchor,p.size) if p.mask: gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB) gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id) gl.glEnable(gl.GL_TEXTURE_1D) gl.glDisable(gl.GL_TEXTURE_2D) if p.bit_depth != self.cached_bit_depth: self.calculate_bit_depth_dependencies() # Clear the modeview matrix gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() # Rotate about the center of the texture gl.glTranslate(center[0], center[1], 0) gl.glRotate(p.orientation,0,0,1) if p.depth is None: gl.glDisable(gl.GL_DEPTH_TEST) depth = 0.0 else: gl.glEnable(gl.GL_DEPTH_TEST) depth = p.depth # allow max_alpha value to control blending gl.glEnable( gl.GL_BLEND ) gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA ) if p.color2: gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_BLEND) gl.glTexEnvfv(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_COLOR, p.color2) ## alpha is ignored because the texture base internal format is luminance else: gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE) if p.t0_time_sec_absolute is None and not p.ignore_time: p.t0_time_sec_absolute = VisionEgg.time_func() w = p.size[0] inc = w/float(p.num_samples) if p.ignore_time: phase = p.phase_at_t0 else: t_var = VisionEgg.time_func() - p.t0_time_sec_absolute phase = t_var*p.temporal_freq_hz*-360.0 + p.phase_at_t0 if p.recalculate_phase_tolerance is None or abs(self._last_phase - phase) > p.recalculate_phase_tolerance: self._last_phase = phase # we're re-drawing the phase at this angle floating_point_sin = numpy.sin(2.0*math.pi*p.spatial_freq*numpy.arange(0.0,w,inc,dtype=numpy.float)+(phase/180.0*math.pi))*0.5*p.contrast+p.pedestal floating_point_sin = numpy.clip(floating_point_sin,0.0,1.0) # allow square wave generation if contrast > 1 texel_data = (floating_point_sin*self.max_int_val).astype(self.numpy_dtype) # PyOpenGL 2.0.1.09 has a bug, so use our own wrapper _vegl.veglTexSubImage1D(gl.GL_TEXTURE_1D, # target 0, # level 0, # x offset p.num_samples, # width self.format, # format of new texel data self.gl_type, # type of new texel data texel_data) # new texel data if 0: compare_array = numpy.empty(texel_data.shape,dtype=texel_data.dtype) pixels = _vegl.veglGetTexImage(gl.GL_TEXTURE_1D, # target 0, # level self.format, # format self.gl_type, # type compare_array) assert numpy.allclose( compare_array, texel_data ) h_w = p.size[0]/2.0 h_h = p.size[1]/2.0 l = -h_w r = h_w b = -h_h t = h_h # in the case of only color1, # the texel data multiplies color1 to produce a color # with color2, # the texel data linearly interpolates between color1 and color2 gl.glColor4f(p.color1[0],p.color1[1],p.color1[2],p.max_alpha) if p.mask: p.mask.draw_masked_quad(0.0,1.0,0.0,1.0, # l,r,b,t for texture coordinates l,r,b,t, # l,r,b,t in eye coordinates depth ) # also in eye coordinates else: # draw unmasked quad gl.glBegin(gl.GL_QUADS) gl.glTexCoord2f(0.0,0.0) gl.glVertex3f(l,b,depth) gl.glTexCoord2f(1.0,0.0) gl.glVertex3f(r,b,depth) gl.glTexCoord2f(1.0,1.0) gl.glVertex3f(r,t,depth) gl.glTexCoord2f(0.0,1.0) gl.glVertex3f(l,t,depth) gl.glEnd() # GL_QUADS gl.glDisable(gl.GL_TEXTURE_1D) gl.glPopMatrix()
class DotArea2D(VisionEgg.Core.Stimulus): """Random dots of constant velocity Every dot has the same velocity. Some fraction of the dots all move in the one direction, while the rest move in random directions. Dots wrap around edges. Each dot has a lifespan. This is just one example of the endless variations on drawing random dots. Parameters ========== anchor -- (String) Default: center anti_aliasing -- (Boolean) Default: True color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) depth -- (Real) Default: (determined at runtime) dot_lifespan_sec -- (Real) Default: 5.0 dot_size -- (Real) Default: 4.0 on -- (Boolean) Default: True position -- (Sequence2 of Real) Default: (320.0, 240.0) signal_direction_deg -- (Real) Default: 90.0 signal_fraction -- (Real) Default: 0.5 size -- (Sequence2 of Real) Default: (300.0, 300.0) velocity_pixels_per_sec -- (Real) Default: 10.0 Constant Parameters =================== num_dots -- (UnsignedInteger) Default: 100 """ parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.Sequence2(ve_types.Real)), 'anchor': ('center', ve_types.String), 'size': ( (300.0, 300.0), # in eye coordinates ve_types.Sequence2(ve_types.Real)), 'signal_fraction': (0.5, ve_types.Real), 'signal_direction_deg': (90.0, ve_types.Real), 'velocity_pixels_per_sec': (10.0, ve_types.Real), 'dot_lifespan_sec': (5.0, ve_types.Real), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'dot_size': ( 4.0, # pixels ve_types.Real), 'anti_aliasing': (True, ve_types.Boolean), 'depth': ( None, # set for depth testing ve_types.Real), 'center': ( None, # DEPRECATED -- don't use ve_types.Sequence2(ve_types.Real), "", VisionEgg.ParameterDefinition.DEPRECATED), } constant_parameters_and_defaults = { 'num_dots': (100, ve_types.UnsignedInteger), } __slots__ = ( 'x_positions', 'y_positions', 'random_directions_radians', 'last_time_sec', 'start_times_sec', '_gave_alpha_warning', ) def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw) # store positions normalized between 0 and 1 so that re-sizing is ok num_dots = self.constant_parameters.num_dots # shorthand self.x_positions = RandomArray.uniform(0.0, 1.0, (num_dots, )) self.y_positions = RandomArray.uniform(0.0, 1.0, (num_dots, )) self.random_directions_radians = RandomArray.uniform( 0.0, 2 * math.pi, (num_dots, )) self.last_time_sec = VisionEgg.time_func() self.start_times_sec = None # setup variable, assign later self._gave_alpha_warning = 0 def draw(self): # XXX This method is not speed-optimized. I just wrote it to # get the job done. (Nonetheless, it seems faster than the C # version commented out above.) p = self.parameters # shorthand if p.center is not None: if not hasattr(VisionEgg.config, "_GAVE_CENTER_DEPRECATION"): logger = logging.getLogger('VisionEgg.Dots') logger.warning("Specifying DotArea2D by deprecated " "'center' parameter deprecated. Use " "'position' parameter instead. (Allows " "use of 'anchor' parameter to set to " "other values.)") VisionEgg.config._GAVE_CENTER_DEPRECATION = 1 p.anchor = 'center' p.position = p.center[0], p.center[ 1] # copy values (don't copy ref to tuple) if p.on: # calculate center center = VisionEgg._get_center(p.position, p.anchor, p.size) if p.anti_aliasing: if len(p.color) == 4 and not self._gave_alpha_warning: if p.color[3] != 1.0: logger = logging.getLogger('VisionEgg.Dots') logger.warning("The parameter anti_aliasing is " "set to true in the DotArea2D " "stimulus class, but the color " "parameter specifies an alpha " "value other than 1.0. To " "acheive the best anti-aliasing, " "ensure that the alpha value for " "the color parameter is 1.0.") self._gave_alpha_warning = 1 gl.glEnable(gl.GL_POINT_SMOOTH) # allow max_alpha value to control blending gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) else: gl.glDisable(gl.GL_BLEND) now_sec = VisionEgg.time_func() if self.start_times_sec is not None: # compute extinct dots and generate new positions replace_indices = Numeric.nonzero( Numeric.greater(now_sec - self.start_times_sec, p.dot_lifespan_sec)) Numeric.put(self.start_times_sec, replace_indices, now_sec) new_x_positions = RandomArray.uniform(0.0, 1.0, (len(replace_indices), )) Numeric.put(self.x_positions, replace_indices, new_x_positions) new_y_positions = RandomArray.uniform(0.0, 1.0, (len(replace_indices), )) Numeric.put(self.y_positions, replace_indices, new_y_positions) new_random_directions_radians = RandomArray.uniform( 0.0, 2 * math.pi, (len(replace_indices), )) Numeric.put(self.random_directions_radians, replace_indices, new_random_directions_radians) else: # initialize dot extinction values to random (uniform) distribution self.start_times_sec = RandomArray.uniform( now_sec - p.dot_lifespan_sec, now_sec, (self.constant_parameters.num_dots, )) signal_num_dots = int( round(p.signal_fraction * self.constant_parameters.num_dots)) time_delta_sec = now_sec - self.last_time_sec self.last_time_sec = now_sec # reset for next loop x_increment_normalized = math.cos( p.signal_direction_deg / 180.0 * math.pi ) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec y_increment_normalized = -math.sin( p.signal_direction_deg / 180.0 * math.pi ) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec self.x_positions[:signal_num_dots] += x_increment_normalized self.y_positions[:signal_num_dots] += y_increment_normalized num_random_dots = self.constant_parameters.num_dots - signal_num_dots random_x_increment_normalized = Numeric.cos( self.random_directions_radians[signal_num_dots:] ) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec random_y_increment_normalized = -Numeric.sin( self.random_directions_radians[signal_num_dots:] ) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec self.x_positions[signal_num_dots:] += random_x_increment_normalized self.y_positions[signal_num_dots:] += random_y_increment_normalized self.x_positions = Numeric.fmod(self.x_positions, 1.0) # wrap self.y_positions = Numeric.fmod(self.y_positions, 1.0) self.x_positions = Numeric.fmod(self.x_positions + 1, 1.0) # wrap again for values < 1 self.y_positions = Numeric.fmod(self.y_positions + 1, 1.0) xs = (self.x_positions - 0.5) * p.size[0] + center[0] ys = (self.y_positions - 0.5) * p.size[1] + center[1] if len(p.color) == 3: gl.glColor3f(*p.color) elif len(p.color) == 4: gl.glColor4f(*p.color) gl.glPointSize(p.dot_size) # Clear the modeview matrix gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() gl.glDisable(gl.GL_TEXTURE_2D) if p.depth is None: depth = 0.0 else: gl.glEnable(gl.GL_DEPTH_TEST) depth = p.depth zs = (depth, ) * len(xs) # make N tuple with repeat value of depth draw_dots(xs, ys, zs) if p.anti_aliasing: gl.glDisable(gl.GL_POINT_SMOOTH) # turn off gl.glPopMatrix()
class FilledCircle(VisionEgg.Core.Stimulus): """ A circular stimulus, typically used as a fixation point. (Note, this implementation almost certainly could be made faster using display lists.) Parameters ========== anchor -- how position parameter is used (String) Default: center anti_aliasing -- (Boolean) Default: True color -- color (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) num_triangles -- number of triangles used to draw circle (Integer) Default: 51 on -- draw? (Boolean) Default: True position -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) radius -- radius in eye coordinates (Real) Default: 2.0 """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on': (True, ve_types.Boolean, 'draw?'), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color'), 'anti_aliasing': (True, ve_types.Boolean), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'position in eye coordinates'), 'anchor': ('center', ve_types.String, 'how position parameter is used'), 'radius': (2.0, ve_types.Real, 'radius in eye coordinates'), 'num_triangles': (51, ve_types.Integer, 'number of triangles used to draw circle'), }) __slots__ = VisionEgg.Core.Stimulus.__slots__ + ('_gave_alpha_warning', ) def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def draw(self): p = self.parameters # shorthand if p.on: # calculate center center = VisionEgg._get_center(p.position, p.anchor, (p.radius, p.radius)) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_BLEND) if len(p.color) == 3: gl.glColor3f(*p.color) elif len(p.color) == 4: gl.glColor4f(*p.color) # Build filled circle from points # gl.glBegin(gl.GL_POINTS) # radius = int(math.ceil(p.radius)) # for i in range(-radius, radius): # for j in range(-radius, radius): # if(i * i + j * j < radius * radius): # gl.glVertex3f(p.position[0] + i, p.position[1] + j, 0.0) # gl.glEnd() # GL_POINTS # Build filled circle from triangles (this is typically faster # then the commented code above with the points) gl.glBegin(gl.GL_TRIANGLE_FAN) gl.glVertex3f(p.position[0], p.position[1], 0.0) angles = Numeric.arange(p.num_triangles) / float( p.num_triangles) * 2.0 * math.pi verts = Numeric.zeros((p.num_triangles, 2), Numeric.Float) verts[:, 0] = p.position[0] + p.radius * Numeric.cos(angles) verts[:, 1] = p.position[1] + p.radius * Numeric.sin(angles) for i in range(verts.shape[0]): gl.glVertex2fv(verts[i]) gl.glVertex2fv(verts[0]) gl.glEnd() # GL_TRIANGLE_FAN if p.anti_aliasing: if not self._gave_alpha_warning: if len(p.color) > 3 and p.color[3] != 1.0: logger = logging.getLogger('VisionEgg.Arrow') logger.warning("The parameter anti_aliasing is " "set to true in the Arrow " "stimulus class, but the color " "parameter specifies an alpha " "value other than 1.0. To " "acheive anti-aliasing, ensure " "that the alpha value for the " "color parameter is 1.0.") self._gave_alpha_warning = 1 # We've already drawn a filled polygon (aliased), now redraw # the outline of the polygon (with anti-aliasing). (Using # GL_POLYGON_SMOOTH results in artifactual lines where # triangles were joined to create quad, at least on some OpenGL # implementations.) # Calculate coverage value for each pixel of outline # and store as alpha gl.glEnable(gl.GL_LINE_SMOOTH) # Now specify how to use the alpha value gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) # Draw a second polygon in line mode, so the edges are anti-aliased gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE) gl.glBegin(gl.GL_TRIANGLE_FAN) gl.glVertex3f(p.position[0], p.position[1], 0.0) angles = Numeric.arange(p.num_triangles) / float( p.num_triangles) * 2.0 * math.pi verts = Numeric.zeros((p.num_triangles, 2), Numeric.Float) verts[:, 0] = p.position[0] + p.radius * Numeric.cos(angles) verts[:, 1] = p.position[1] + p.radius * Numeric.sin(angles) for i in range(verts.shape[0]): gl.glVertex2fv(verts[i]) gl.glVertex2fv(verts[0]) gl.glEnd() # GL_TRIANGLE_FAN # Set the polygon mode back to fill mode gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL) gl.glDisable(gl.GL_LINE_SMOOTH)
class Target2D(VisionEgg.Core.Stimulus): """Rectanglular stimulus. Parameters ========== anchor -- specifies how position parameter is interpreted (String) Default: center anti_aliasing -- (Boolean) Default: True center -- DEPRECATED: don't use (Sequence2 of Real) Default: (determined at runtime) color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) on -- draw stimulus? (Boolean) (Boolean) Default: True orientation -- (Real) Default: 0.0 position -- units: eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) size -- units: eye coordinates (Sequence2 of Real) Default: (64.0, 16.0) """ parameters_and_defaults = { 'on': (True, ve_types.Boolean, "draw stimulus? (Boolean)"), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'anti_aliasing': (True, ve_types.Boolean), 'orientation': (0.0, ve_types.Real), 'position': ((320.0, 240.0), ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), 'anchor': ('center', ve_types.String, "specifies how position parameter is interpreted"), 'size': ((64.0, 16.0), ve_types.Sequence2(ve_types.Real), "units: eye coordinates"), 'center': (None, ve_types.Sequence2(ve_types.Real), "DEPRECATED: don't use"), } __slots__ = ('_gave_alpha_warning', ) def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def draw(self): p = self.parameters # shorthand if p.center is not None: if not hasattr(VisionEgg.config, "_GAVE_CENTER_DEPRECATION"): logger = logging.getLogger('VisionEgg.MoreStimuli') logger.warning("Specifying Target2D by deprecated " "'center' parameter deprecated. Use " "'position' parameter instead. (Allows " "use of 'anchor' parameter to set to " "other values.)") VisionEgg.config._GAVE_CENTER_DEPRECATION = 1 p.anchor = 'center' p.position = p.center[0], p.center[ 1] # copy values (don't copy ref to tuple) if p.on: # calculate center center = VisionEgg._get_center(p.position, p.anchor, p.size) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() gl.glTranslate(center[0], center[1], 0.0) gl.glRotate(p.orientation, 0.0, 0.0, 1.0) if len(p.color) == 3: gl.glColor3f(*p.color) elif len(p.color) == 4: gl.glColor4f(*p.color) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) w = p.size[0] / 2.0 h = p.size[1] / 2.0 gl.glBegin(gl.GL_QUADS) gl.glVertex3f(-w, -h, 0.0) gl.glVertex3f(w, -h, 0.0) gl.glVertex3f(w, h, 0.0) gl.glVertex3f(-w, h, 0.0) gl.glEnd() # GL_QUADS if p.anti_aliasing: if not self._gave_alpha_warning: if len(p.color) > 3 and p.color[3] != 1.0: logger = logging.getLogger('VisionEgg.MoreStimuli') logger.warning("The parameter anti_aliasing is " "set to true in the Target2D " "stimulus class, but the color " "parameter specifies an alpha " "value other than 1.0. To " "acheive anti-aliasing, ensure " "that the alpha value for the " "color parameter is 1.0.") self._gave_alpha_warning = 1 # We've already drawn a filled polygon (aliased), now # redraw the outline of the polygon (with # anti-aliasing). (Using GL_POLYGON_SMOOTH results in # artifactual lines where triangles were joined to # create quad, at least on some OpenGL # implementations.) # Calculate coverage value for each pixel of outline # and store as alpha gl.glEnable(gl.GL_LINE_SMOOTH) # Now specify how to use the alpha value gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) # Draw a second polygon in line mode, so the edges are anti-aliased gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE) gl.glBegin(gl.GL_QUADS) gl.glVertex3f(-w, -h, 0.0) gl.glVertex3f(w, -h, 0.0) gl.glVertex3f(w, h, 0.0) gl.glVertex3f(-w, h, 0.0) gl.glEnd() # GL_QUADS # Set the polygon mode back to fill mode gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL) gl.glDisable(gl.GL_LINE_SMOOTH) gl.glPopMatrix()
class Arrow(VisionEgg.Core.Stimulus): """Arrow stimulus. Parameters ========== anchor -- (String) Default: center anti_aliasing -- (Boolean) Default: True color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) on -- (Boolean) Default: True orientation -- (Real) Default: 0.0 position -- units: eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) size -- (Sequence2 of Real) Default: (64.0, 16.0) """ parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'anti_aliasing': (True, ve_types.Boolean), 'orientation': ( 0.0, # 0.0 degrees = right, 90.0 degrees = up ve_types.Real), 'position': ( (320.0, 240.0), # In eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), 'anchor': ('center', ve_types.String), 'size': ( (64.0, 16.0), # In eye coordinates ve_types.Sequence2(ve_types.Real)), } __slots__ = VisionEgg.Core.Stimulus.__slots__ + ('_gave_alpha_warning', ) def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def draw(self): p = self.parameters # Shorthand if p.on: # Calculate center center = VisionEgg._get_center(p.position, p.anchor, p.size) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() gl.glTranslate(center[0], center[1], 0.0) gl.glRotate(-p.orientation, 0.0, 0.0, 1.0) if len(p.color) == 3: gl.glColor3f(*p.color) elif len(p.color) == 4: gl.glColor4f(*p.color) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) w = p.size[0] / 2.0 h = p.size[1] / 2.0 gl.glBegin(gl.GL_QUADS) # Draw Rectangle gl.glVertex3f(0.25 * w, h, 0.0) gl.glVertex3f(-w, h, 0.0) gl.glVertex3f(-w, -h, 0.0) gl.glVertex3f(0.25 * w, -h, 0.0) gl.glEnd() # GL_QUADS gl.glBegin(gl.GL_TRIANGLES) # Draw Triangle gl.glVertex3f(1.00 * w, 0.0 * h, 0.0) # Top gl.glVertex3f(0.25 * w, -3.0 * h, 0.0) gl.glVertex3f(0.25 * w, 3.0 * h, 0.0) gl.glEnd() # GL_QUADS if p.anti_aliasing: if not self._gave_alpha_warning: if len(p.color) > 3 and p.color[3] != 1.0: logger = logging.getLogger('VisionEgg.Arrow') logger.warning("The parameter anti_aliasing is " "set to true in the Arrow " "stimulus class, but the color " "parameter specifies an alpha " "value other than 1.0. To " "acheive anti-aliasing, ensure " "that the alpha value for the " "color parameter is 1.0.") self._gave_alpha_warning = 1 # We've already drawn a filled polygon (aliased), now redraw # the outline of the polygon (with anti-aliasing). (Using # GL_POLYGON_SMOOTH results in artifactual lines where # triangles were joined to create quad, at least on some OpenGL # implementations.) # Calculate coverage value for each pixel of outline # and store as alpha gl.glEnable(gl.GL_LINE_SMOOTH) # Now specify how to use the alpha value gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) # Draw a second polygon in line mode, so the edges are anti-aliased gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE) gl.glBegin(gl.GL_QUADS) gl.glVertex3f(0.25 * w, h, 0.0) # Draw Rectangle gl.glVertex3f(-w, h, 0.0) gl.glVertex3f(-w, -h, 0.0) gl.glVertex3f(0.25 * w, -h, 0.0) gl.glVertex3f(1.00 * w, 0.0 * h, 0.0) # Draw Triangle gl.glVertex3f(0.25 * w, -3.0 * h, 0.0) gl.glVertex3f(0.25 * w, 3.0 * h, 0.0) gl.glEnd() # GL_QUADS # Set the polygon mode back to fill mode gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL) gl.glDisable(gl.GL_LINE_SMOOTH) gl.glPopMatrix()
class Rectangle3D(VisionEgg.Core.Stimulus): """Solid color rectangle positioned explicitly by four vertices. Parameters ========== color -- (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0, 1.0) on -- (Boolean) Default: True vertex1 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (-10.0, 0.0, -10.0) vertex2 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (-10.0, 0.0, 10.0) vertex3 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (10.0, 0.0, 10.0) vertex4 -- units: eye coordinates (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (10.0, 0.0, -10.0) """ parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'blending_enabled': (False, ve_types.Boolean), # different default than TextureStimulus3D due to not break backwards compatibility 'depth_test': (False, ve_types.Boolean), 'color': ((1.0, 1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'vertex1': ((-10.0, 0.0, -10.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), 'vertex2': ((-10.0, 0.0, 10.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), 'vertex3': ((10.0, 0.0, 10.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), 'vertex4': ((10.0, 0.0, -10.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), "units: eye coordinates"), } def __init__(self, **kw): VisionEgg.Core.Stimulus.__init__(self, **kw) def draw(self): p = self.parameters # shorthand if p.on: if len(p.color) == 3: gl.glColor3f(*p.color) elif len(p.color) == 4: gl.glColor4f(*p.color) gl.glDisable(gl.GL_TEXTURE_2D) if p.depth_test: gl.glEnable(gl.GL_DEPTH_TEST) else: gl.glDisable(gl.GL_DEPTH_TEST) if p.blending_enabled: gl.glEnable(gl.GL_BLEND) else: gl.glDisable(gl.GL_BLEND) gl.glBegin(gl.GL_QUADS) gl.glVertex(*p.vertex1) gl.glVertex(*p.vertex2) gl.glVertex(*p.vertex3) gl.glVertex(*p.vertex4) gl.glEnd() # GL_QUADS
class CircleSector(DisplayListStimulus): """ A sector of a circular stimulus, optionally filled. Parameters ========== anchor -- how position parameter is used (String) Default: center anti_aliasing -- (Boolean) Default: True color -- color (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) num_triangles -- number of triangles used to draw circle (Integer) Default: 51 on -- draw? (Boolean) Default: True position -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) radius -- radius in eye coordinates (Real) Default: 2.0 """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on': (True, ve_types.Boolean, 'draw?'), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color'), 'color_edge': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color for the circle edge'), 'anti_aliasing': (True, ve_types.Boolean), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'position in eye coordinates'), 'anchor': ('center', ve_types.String, 'how position parameter is used'), 'radius': (2.0, ve_types.Real, 'radius in eye coordinates'), 'num_triangles': (51, ve_types.Integer, 'number of triangles used to draw circle'), 'start': (0., ve_types.Real, 'start angle'), 'end': (360., ve_types.Real, 'end angle'), 'disk': (True, ve_types.Boolean, 'draw the interior?'), 'circle': (True, ve_types.Boolean, 'draw the edge?'), 'circle_width': (1., ve_types.Real, 'line width of the circle edge'), }) __slots__ = VisionEgg.Core.Stimulus.__slots__ + ('_gave_alpha_warning', ) def __init__(self, **kw): DisplayListStimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def _draw(self): p = self.parameters center = VisionEgg._get_center(p.position, p.anchor, (p.radius, p.radius)) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_BLEND) gl.glColor(p.color) start, end = p.start, p.end if end < start: start -= 360. start, end = map(numpy.deg2rad, (start, end)) frac = (end - start) / (2 * numpy.pi) num_triangles = float(p.num_triangles) * frac angles = numpy.linspace(start, end, num_triangles) verts = numpy.zeros((num_triangles, 2)) verts[:, 0] = center[0] + p.radius * numpy.cos(angles) verts[:, 1] = center[1] + p.radius * numpy.sin(angles) if p.disk: gl.glBegin(gl.GL_TRIANGLE_FAN) gl.glVertex(center) self._draw_vertices(*verts) gl.glEnd() if p.anti_aliasing: gl.glEnable(gl.GL_LINE_SMOOTH) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) # Draw a second polygon in line mode, so the edges are anti-aliased gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE) gl.glBegin(gl.GL_TRIANGLE_FAN) gl.glVertex(center) self._draw_vertices(*verts) gl.glEnd() gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL) gl.glDisable(gl.GL_LINE_SMOOTH) if p.circle: if p.anti_aliasing: gl.glEnable(gl.GL_LINE_SMOOTH) gl.glColor(p.color_edge) gl.glLineWidth(p.circle_width) gl.glBegin(gl.GL_LINES) for i in range(verts.shape[0] - 1): self._draw_vertices(verts[i], verts[i + 1]) gl.glEnd() gl.glDisable(gl.GL_LINE_SMOOTH)
class Triangle(DisplayListStimulus): """ An equilateral triangle. Parameters ========== anti_aliasing -- (Boolean) Default: True color -- color (AnyOf(Sequence3 of Real or Sequence4 of Real)) Default: (1.0, 1.0, 1.0) on -- draw? (Boolean) Default: True position -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) side -- side length """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'anchor': ('center', ve_types.String, 'how position parameter is used'), 'on': (True, ve_types.Boolean, 'draw?'), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color'), 'color_edge': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'color for the edge'), 'anti_aliasing': (True, ve_types.Boolean), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'position in eye coordinates'), 'side': (10., ve_types.Real, 'side length'), 'width': (1., ve_types.Real, 'line width'), }) __slots__ = VisionEgg.Core.Stimulus.__slots__ + ('_gave_alpha_warning', ) def __init__(self, **kw): DisplayListStimulus.__init__(self, **kw) self._gave_alpha_warning = 0 def _draw(self): p = self.parameters side = p.side height = side * numpy.sqrt(3) / 2. center = VisionEgg._get_center(p.position, p.anchor, (side, height)) position = numpy.array(center) hh = height / 2 ll = position - (hh, hh) lr = position - (-hh, hh) u = position + (0., hh) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glDisable(gl.GL_BLEND) gl.glColor(p.color) gl.glBegin(gl.GL_TRIANGLES) self._draw_vertices(ll, lr, u) gl.glEnd() gl.glColor(p.color_edge) if p.anti_aliasing: gl.glEnable(gl.GL_LINE_SMOOTH) gl.glLineWidth(p.width) gl.glBegin(gl.GL_LINE_STRIP) self._draw_vertices(ll, lr, u, ll) gl.glEnd() gl.glDisable(gl.GL_LINE_SMOOTH)
class CheckBoard(Stimulus): """A checkboard stimulus, typically used as a aux stimulus for whitenoise. Parameters ========== anchor -- how position parameter is used (String) Default: center color -- color (256 jet colormap ) Default: 0(gray) on -- draw? (Boolean) Default: True position -- position in eye coordinates (AnyOf(Sequence2 of Real or Sequence3 of Real or Sequence4 of Real)) Default: (320.0, 240.0) size -- size in eye coordinates (Sequence2 of Real) Default: (4.0, 4.0) """ parameters_and_defaults = VisionEgg.ParameterDefinition({ 'on': (True, ve_types.Boolean, 'draw?'), 'bgcolor': ((0.5, 0.5, 0.5), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'backgroud color'), 'linecolor': ((0.5, 0.0, 0.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'grid line color'), 'cellcolor': ('gbr', ve_types.String, 'color map for the range [0.0,1.0]'), 'colorindex': (None, ve_types.Sequence(ve_types.Integer), 'color index in jet colormap'), 'drawline': (False, ve_types.Boolean, 'draw line?'), 'orientation': (0.0, ve_types.Real), 'position': ( (320.0, 240.0), # in eye coordinates ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real)), 'position in eye coordinates'), 'anchor': ('center', ve_types.String, 'how position parameter is used'), 'size': ( (100.0, 100.0), # horiz and vertical size ve_types.Sequence2(ve_types.Real), 'size in eye coordinates'), 'grid': ( (8, 8), # grid dimension of the checkboard ve_types.Sequence2(ve_types.Integer), 'grid dimension'), 'center': ( None, # DEPRECATED -- don't use ve_types.Sequence2(ve_types.Real), 'position in eye coordinates', VisionEgg.ParameterDefinition.DEPRECATED), }) def __init__(self, **kw): Stimulus.__init__(self, **kw) self.parameters.colorindex = np.zeros(self.parameters.grid) self.parameters.colorindex.fill(0.5) def draw(self): p = self.parameters # shorthand if p.center is not None: p.anchor = 'center' p.position = p.center[0], p.center[ 1] # copy values (don't copy ref to tuple) if p.on: # calculate center center = VisionEgg._get_center(p.position, p.anchor, p.size) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glPushMatrix() gl.glTranslate(center[0], center[1], 0.0) gl.glRotate(p.orientation, 0.0, 0.0, 1.0) if len(p.bgcolor) == 3: gl.glColor3f(*p.bgcolor) elif len(p.bgcolor) == 4: gl.glColor4f(*p.bgcolor) gl.glDisable(gl.GL_DEPTH_TEST) gl.glDisable(gl.GL_TEXTURE_2D) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glEnable(gl.GL_BLEND) w = p.size[0] / 2.0 #grid half-size h = p.size[1] / 2.0 m = p.size[0] / p.grid[0] #cell size n = p.size[1] / p.grid[1] i = range(p.grid[0]) #grid index j = range(p.grid[1]) #draw colorful cell # vertices_list = [((-w+column*m, h-(row+1)*n, 0.0),(-w+column*m, h-row*n, 0.0),\ # (-w+(column+1)*m, h-row*n, 0.0),(-w+(column+1)*m, h-row*n, 0.0))\ # for column in j for row in i] vertices_list = [((-w+column*m, h-(row+1)*n, 0.0),(-w+column*m, h-row*n, 0.0),\ (-w+(column+1)*m, h-row*n, 0.0),(-w+(column+1)*m, h-(row+1)*n, 0.0))\ for column in j for row in i] colors_list = [ colormap(p.colorindex[row, column], color=p.cellcolor) * 4 for column in j for row in i ] #flattening the vertices and colors vertices_flat = [ num for tuple in vertices_list for vertex in tuple for num in vertex ] colors_flat = [num for tuple in colors_list for num in tuple] vertices = np.array(vertices_flat) colors = np.array(colors_flat) vertices.shape = (-1, 3) colors.shape = (-1, 3) gl.glVertexPointerd(vertices) gl.glColorPointerd(colors) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glEnableClientState(gl.GL_COLOR_ARRAY) gl.glDisable(gl.GL_LIGHTING) gl.glDrawArrays(gl.GL_QUADS, 0, p.grid[0] * p.grid[1] * 4) #draw grid lines if p.drawline: if len(p.linecolor) == 3: gl.glColor3f(*p.linecolor) elif len(p.linecolor) == 4: gl.glColor4f(*p.linecolor) row_list = [((-w, h - i * n), (w, h - i * n)) for i in range(p.grid[1] + 1)] col_list = [((-w + i * m, h), (-w + i * m, -h)) for i in range(p.grid[0] + 1)] ver_row_flat = [ num for tuple in row_list for vertex in tuple for num in vertex ] ver_col_flat = [ num for tuple in col_list for vertex in tuple for num in vertex ] vertices_row = np.array(ver_row_flat) vertices_col = np.array(ver_col_flat) vertices_row.shape = (-1, 2) vertices_col.shape = (-1, 2) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_COLOR_ARRAY) gl.glVertexPointerd(vertices_row) gl.glDrawArrays(gl.GL_LINES, 0, (p.grid[1] + 1) * 2) gl.glVertexPointerd(vertices_col) gl.glDrawArrays(gl.GL_LINES, 0, (p.grid[0] + 1) * 2) # gl.glBegin(gl.GL_LINES); # for i in range(p.grid[1] + 1): # gl.glVertex2f(-w, h - i * n) # gl.glVertex2f(w, h - i * n) # for i in range(p.grid[0] + 1): # gl.glVertex2f(-w + i * m, h) # gl.glVertex2f(-w + i * m, -h) # gl.glEnd(); gl.glPopMatrix() #save checkboard to file def save(self): import time, os (year, month, day, hour24, min, sec) = time.localtime(time.time())[:6] trial_time_str = "%04d%02d%02d_%02d%02d%02d" % (year, month, day, hour24, min, sec) dummy_filename = os.path.abspath(os.curdir)+ os.path.sep + 'screenshoot' + \ os.path.sep + 'checkboard' + trial_time_str + '.jpg'
class WrappedText(VisionEgg.Core.Stimulus): """Multi-line text stimulus. No fancy formatting, but line breaks ('\\n') are preserved, and text is wrapped to fit within the stimulus boundaries.""" parameters_and_defaults = { 'on': (True, ve_types.Boolean), 'position': ((0.0, 0.0), ve_types.AnyOf(ve_types.Sequence2(ve_types.Real), ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))), 'size': (None, ve_types.Sequence2(ve_types.Real), """Defaults to the size of the screen."""), 'text': ('hello', ve_types.AnyOf(ve_types.String, ve_types.Unicode)), 'color': ((1.0, 1.0, 1.0), ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), ve_types.Sequence4(ve_types.Real))) } constant_parameters_and_defaults = { 'font_name': (None, ve_types.AnyOf(ve_types.String, ve_types.Unicode), "Name of font to use. If None, use the default font"), 'font_size': (30, ve_types.UnsignedInteger) } def __init__(self, **kw): """Initialize the object, perform the initial line-splitting""" VisionEgg.Core.Stimulus.__init__(self, **kw) if self.parameters.size is None: self.parameters.size = (VisionEgg.config.VISIONEGG_SCREEN_W, VisionEgg.config.VISIONEGG_SCREEN_H) self._splitText() def _splitText(self): """Split a single string into multiple lines of text, storing each as a VisionEgg.Text.Text instance""" p = self.parameters cp = self.constant_parameters self._text = p.text textAreaWidth = None maxLineLength = len(self._text) minLineLength = 1 lineLength = maxLineLength while ((textAreaWidth > p.size[0]) or ((maxLineLength - minLineLength) > 1)) and (maxLineLength > 1): nextPosition = p.position self._textLines = [] try: textLineList = [] for text in self._text.split("\n"): if text == "": textLineList.append("") else: textLineList.extend(textwrap.wrap(text, lineLength)) textAreaWidth = None for textLine in textLineList: if textLine != "": line = VisionEgg.Text.Text(text=textLine, position=nextPosition, anchor="upperleft", ignore_size_parameter=True, color=p.color, font_name=cp.font_name, font_size=cp.font_size) textAreaWidth = max(textAreaWidth, line.parameters.size[0]) self._textLines.append(line) nextPosition = (nextPosition[0], nextPosition[1] - line.parameters.size[1]) # Stop adding lines if the text area's height has been reached if (p.position[1] - nextPosition[1]) > p.size[1]: break except VisionEgg.Textures.TextureTooLargeError: textAreaWidth = p.size[0] + 1 if textAreaWidth > p.size[0]: maxLineLength = lineLength else: minLineLength = lineLength lineLength = (maxLineLength + minLineLength) / 2 def draw(self): """Draw the lines of text on the screen""" p = self.parameters if p.on: if p.text != self._text: self._splitText() for line in self._textLines: line.parameters.color = p.color line.draw()