1
2
3
4
5
6
7
8
9
10
11 """
12 Grating stimuli.
13
14 """
15
16
17
18
19
20
21
22 import logging
23
24 import VisionEgg
25 import VisionEgg.Core
26 import VisionEgg.Textures
27 import VisionEgg.ParameterTypes as ve_types
28 import numpy
29 import math, types, string
30 import VisionEgg.GL as gl
31 import _vegl
32
34 """Private helper function to calculate type info based on bit depth"""
35 if bitdepth == 8:
36 gl_type = gl.GL_UNSIGNED_BYTE
37 numpy_dtype = numpy.uint8
38 max_int_val = float((2**8)-1)
39 elif bitdepth == 12:
40 gl_type = gl.GL_SHORT
41 numpy_dtype = numpy.int16
42 max_int_val = float((2**15)-1)
43 elif bitdepth == 16:
44 gl_type = gl.GL_INT
45 numpy_dtype = numpy.int32
46 max_int_val = float((2.**31.)-1)
47 else:
48 raise ValueError("supported bitdepths are 8, 12, and 16.")
49 return gl_type, numpy_dtype, max_int_val
50
52 """Base class with common code to all ways of drawing luminance gratings.
53
54 Parameters
55 ==========
56 bit_depth -- precision with which grating is calculated and sent to OpenGL (UnsignedInteger)
57 Default: 8
58 """
59
60 parameters_and_defaults = VisionEgg.ParameterDefinition({
61 'bit_depth':(8,
62 ve_types.UnsignedInteger,
63 'precision with which grating is calculated and sent to OpenGL'),
64 })
65
66 __slots__ = (
67 'gl_internal_format',
68 'format',
69 'gl_type',
70 'numpy_dtype',
71 'max_int_val',
72 'cached_bit_depth',
73 )
74
76 """Calculate a number of parameters dependent on bit depth."""
77 bit_depth_warning = False
78 p = self.parameters
79
80 red_bits = gl.glGetIntegerv( gl.GL_RED_BITS )
81 green_bits = gl.glGetIntegerv( gl.GL_GREEN_BITS )
82 blue_bits = gl.glGetIntegerv( gl.GL_BLUE_BITS )
83 min_bits = min( (red_bits,green_bits,blue_bits) )
84 if min_bits < p.bit_depth:
85 logger = logging.getLogger('VisionEgg.Gratings')
86 logger.warning("Requested bit depth of %d in "
87 "LuminanceGratingCommon, which is "
88 "greater than your current OpenGL context "
89 "supports (%d)."% (p.bit_depth,min_bits))
90 self.gl_internal_format = gl.GL_LUMINANCE
91 self.format = gl.GL_LUMINANCE
92 self.gl_type, self.numpy_dtype, self.max_int_val = _get_type_info( p.bit_depth )
93 self.cached_bit_depth = p.bit_depth
94
96 """Base class with common code to all ways of drawing gratings in alpha.
97
98 This class is currently not used by any other classes.
99
100 Parameters
101 ==========
102 bit_depth -- precision with which grating is calculated and sent to OpenGL (UnsignedInteger)
103 Default: 8
104 """
105
106 parameters_and_defaults = VisionEgg.ParameterDefinition({
107 'bit_depth':(8,
108 ve_types.UnsignedInteger,
109 'precision with which grating is calculated and sent to OpenGL'),
110 })
111
112 __slots__ = (
113 'gl_internal_format',
114 'format',
115 'gl_type',
116 'numpy_dtype',
117 'max_int_val',
118 'cached_bit_depth',
119 )
120
122 """Calculate a number of parameters dependent on bit depth."""
123 p = self.parameters
124 alpha_bit_depth = gl.glGetIntegerv( gl.GL_ALPHA_BITS )
125 if alpha_bit_depth < p.bit_depth:
126 logger = logging.getLogger('VisionEgg.Gratings')
127 logger.warning("Requested bit depth of %d, which is "
128 "greater than your current OpenGL context "
129 "supports (%d)."% (p.bit_depth,min_bits))
130 self.gl_internal_format = gl.GL_ALPHA
131 self.format = gl.GL_ALPHA
132 self.gl_type, self.numpy_dtype, self.max_int_val = _get_type_info( p.bit_depth )
133 self.cached_bit_depth = p.bit_depth
134
136 """Sine wave grating stimulus
137
138 This is a general-purpose, realtime sine-wave luminace grating
139 generator. To acheive an arbitrary orientation, this class rotates
140 a textured quad. To draw a grating with sides that always remain
141 horizontal and vertical, draw a large grating in a small viewport.
142 (The viewport will clip anything beyond its edges.)
143
144 Parameters
145 ==========
146 anchor -- specifies how position parameter is interpreted (String)
147 Default: center
148 bit_depth -- precision with which grating is calculated and sent to OpenGL (UnsignedInteger)
149 Inherited from LuminanceGratingCommon
150 Default: 8
151 color1 -- (AnyOf(Sequence3 of Real or Sequence4 of Real))
152 Default: (1.0, 1.0, 1.0)
153 color2 -- optional color with which to perform interpolation with color1 in RGB space (AnyOf(Sequence3 of Real or Sequence4 of Real))
154 Default: (determined at runtime)
155 contrast -- (Real)
156 Default: 1.0
157 depth -- (Real)
158 Default: (determined at runtime)
159 ignore_time -- (Boolean)
160 Default: False
161 mask -- optional masking function (Instance of <class 'VisionEgg.Textures.Mask2D'>)
162 Default: (determined at runtime)
163 max_alpha -- (Real)
164 Default: 1.0
165 num_samples -- (UnsignedInteger)
166 Default: 512
167 on -- draw stimulus? (Boolean)
168 Default: True
169 orientation -- (Real)
170 Default: 0.0
171 pedestal -- (Real)
172 Default: 0.5
173 phase_at_t0 -- (Real)
174 Default: 0.0
175 position -- (units: eye coordinates) (Sequence2 of Real)
176 Default: (320.0, 240.0)
177 recalculate_phase_tolerance -- (Real)
178 Default: (determined at runtime)
179 size -- defines coordinate size of grating (in eye coordinates) (Sequence2 of Real)
180 Default: (640.0, 480.0)
181 spatial_freq -- frequency defined relative to coordinates defined in size parameter (units: cycles/eye_coord_unit) (Real)
182 Default: 0.0078125
183 t0_time_sec_absolute -- (Real)
184 Default: (determined at runtime)
185 temporal_freq_hz -- (Real)
186 Default: 5.0
187 """
188
189 parameters_and_defaults = VisionEgg.ParameterDefinition({
190 'on':(True,
191 ve_types.Boolean,
192 "draw stimulus?"),
193 'mask':(None,
194 ve_types.Instance(VisionEgg.Textures.Mask2D),
195 "optional masking function"),
196 'contrast':(1.0,
197 ve_types.Real),
198 'pedestal':(0.5,
199 ve_types.Real),
200 'position':((320.0,240.0),
201 ve_types.Sequence2(ve_types.Real),
202 "(units: eye coordinates)"),
203 'anchor':('center',
204 ve_types.String,
205 "specifies how position parameter is interpreted"),
206 'depth':(None,
207 ve_types.Real),
208 'size':((640.0,480.0),
209 ve_types.Sequence2(ve_types.Real),
210 "defines coordinate size of grating (in eye coordinates)",
211 ),
212 'spatial_freq':(1.0/128.0,
213 ve_types.Real,
214 "frequency defined relative to coordinates defined in size parameter (units: cycles/eye_coord_unit)",
215 ),
216 'temporal_freq_hz':(5.0,
217 ve_types.Real),
218 't0_time_sec_absolute':(None,
219 ve_types.Real),
220 'ignore_time':(False,
221 ve_types.Boolean),
222 'phase_at_t0':(0.0,
223 ve_types.Real),
224 'orientation':(0.0,
225 ve_types.Real),
226 'num_samples':(512,
227 ve_types.UnsignedInteger),
228 'max_alpha':(1.0,
229 ve_types.Real),
230 'color1':((1.0, 1.0, 1.0),
231 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
232 ve_types.Sequence4(ve_types.Real))),
233 'color2':(None,
234 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
235 ve_types.Sequence4(ve_types.Real)),
236 "optional color with which to perform interpolation with color1 in RGB space"),
237 'recalculate_phase_tolerance':(None,
238 ve_types.Real),
239 })
240
241 __slots__ = (
242 '_texture_object_id',
243 '_last_phase',
244 )
245
247 LuminanceGratingCommon.__init__(self,**kw)
248
249 p = self.parameters
250
251 self._texture_object_id = gl.glGenTextures(1)
252 if p.mask:
253 gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB)
254 gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id)
255
256
257 max_dim = gl.glGetIntegerv(gl.GL_MAX_TEXTURE_SIZE)
258 if p.num_samples > max_dim:
259 raise NumSamplesTooLargeError("Grating num_samples too large for video system.\nOpenGL reports maximum size of %d"%(max_dim,))
260
261 self.calculate_bit_depth_dependencies()
262
263 w = p.size[0]
264 inc = w/float(p.num_samples)
265 phase = 0.0
266 self._last_phase = phase
267 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
268 floating_point_sin = numpy.clip(floating_point_sin,0.0,1.0)
269 texel_data = (floating_point_sin*self.max_int_val).astype(self.numpy_dtype).tostring()
270
271
272
273
274 gl.glTexImage1D(gl.GL_PROXY_TEXTURE_1D,
275 0,
276 self.gl_internal_format,
277 p.num_samples,
278 0,
279 self.format,
280 self.gl_type,
281 texel_data)
282 if gl.glGetTexLevelParameteriv(gl.GL_PROXY_TEXTURE_1D,
283 0,
284 gl.GL_TEXTURE_WIDTH) == 0:
285 raise NumSamplesTooLargeError("Grating num_samples is too wide for your video system!")
286
287
288 gl.glTexImage1D(gl.GL_TEXTURE_1D,
289 0,
290 self.gl_internal_format,
291 p.num_samples,
292 0,
293 self.format,
294 self.gl_type,
295 texel_data)
296
297
298 gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_S,gl.GL_CLAMP_TO_EDGE)
299 gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_WRAP_T,gl.GL_CLAMP_TO_EDGE)
300 gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR)
301 gl.glTexParameteri(gl.GL_TEXTURE_1D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR)
302
303 if p.color2 is not None:
304 if VisionEgg.Core.gl_renderer == 'ATi Rage 128 Pro OpenGL Engine' and VisionEgg.Core.gl_version == '1.1 ATI-1.2.22':
305 logger = logging.getLogger('VisionEgg.Gratings')
306 logger.warning("Your video card and driver have known "
307 "bugs which prevent them from rendering "
308 "color gratings properly.")
309
311 gl.glDeleteTextures( [self._texture_object_id] )
312
314 p = self.parameters
315 if p.on:
316
317 center = VisionEgg._get_center(p.position,p.anchor,p.size)
318 if p.mask:
319 gl.glActiveTextureARB(gl.GL_TEXTURE0_ARB)
320 gl.glBindTexture(gl.GL_TEXTURE_1D,self._texture_object_id)
321
322 gl.glEnable(gl.GL_TEXTURE_1D)
323 gl.glDisable(gl.GL_TEXTURE_2D)
324 if p.bit_depth != self.cached_bit_depth:
325 self.calculate_bit_depth_dependencies()
326
327
328 gl.glMatrixMode(gl.GL_MODELVIEW)
329 gl.glPushMatrix()
330
331
332 gl.glTranslate(center[0],
333 center[1],
334 0)
335 gl.glRotate(p.orientation,0,0,1)
336
337 if p.depth is None:
338 gl.glDisable(gl.GL_DEPTH_TEST)
339 depth = 0.0
340 else:
341 gl.glEnable(gl.GL_DEPTH_TEST)
342 depth = p.depth
343
344
345 gl.glEnable( gl.GL_BLEND )
346 gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA )
347
348 if p.color2:
349 gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_BLEND)
350 gl.glTexEnvfv(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_COLOR, p.color2)
351
352 else:
353 gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl