1
"""Numpy (new version) module implementation of the OpenGL-ctypes array interfaces
3
XXX Need to register handlers for all of the scalar types that numpy returns,
4
would like to have all return values be int/float if they are of compatible
7
REGISTRY_NAME = 'numpy'
10
except ImportError as err:
11
raise ImportError( """No numpy module present: %s"""%(err))
13
import operator,logging
16
c_void_p = ctypes.c_void_p
17
from OpenGL import constants, constant, error
18
from OpenGL.arrays import formathandler
19
log = logging.getLogger( 'OpenGL.arrays.numpymodule' )
21
from OpenGL import acceleratesupport
23
if acceleratesupport.ACCELERATE_AVAILABLE:
25
from OpenGL_accelerate.numpy_formathandler import NumpyHandler
26
except ImportError as err:
28
"Unable to load numpy_formathandler accelerator from OpenGL_accelerate"
30
if NumpyHandler is None:
31
# numpy's array interface has changed over time :(
32
testArray = numpy.array( [1,2,3,4],'i' )
33
# Numpy's "ctypes" interface actually creates a new ctypes object
34
# in python for every access of the .ctypes attribute... which can take
35
# ridiculously large periods when you multiply it by millions of iterations
36
if hasattr(testArray,'__array_interface__'):
37
def dataPointer( cls, instance ):
38
"""Convert given instance to a data-pointer value (integer)"""
40
return int(instance.__array_interface__['data'][0])
41
except AttributeError as err:
42
instance = cls.asArray( instance )
44
return int(instance.__array_interface__['data'][0])
45
except AttributeError as err:
46
return int(instance.__array_data__[0],0)
48
def dataPointer( cls, instance ):
49
"""Convert given instance to a data-pointer value (integer)"""
51
return int(instance.__array_data__[0],0)
52
except AttributeError as err:
53
instance = cls.asArray( instance )
55
return int(instance.__array_interface__['data'][0])
56
except AttributeError as err:
57
return int(instance.__array_data__[0],0)
59
dataPointer = classmethod( dataPointer )
62
class NumpyHandler( formathandler.FormatHandler ):
63
"""Numpy-specific data-type handler for OpenGL
67
ERROR_ON_COPY -- if True, will raise errors
68
if we have to copy an array object in order to produce
69
a contiguous array of the correct type.
71
HANDLED_TYPES = (numpy.ndarray,)# list, tuple )
72
dataPointer = dataPointer
74
ERROR_ON_COPY = OpenGL.ERROR_ON_COPY
76
def zeros( cls, dims, typeCode ):
77
"""Return Numpy array of zeros in given size"""
78
return numpy.zeros( dims, GL_TYPE_TO_ARRAY_MAPPING[typeCode])
80
def arrayToGLType( cls, value ):
81
"""Given a value, guess OpenGL type of the corresponding pointer"""
82
typeCode = value.dtype
83
constant = ARRAY_TO_GL_TYPE_MAPPING.get( typeCode )
86
"""Don't know GL type for array of type %r, known types: %s\nvalue:%s"""%(
87
typeCode, list(ARRAY_TO_GL_TYPE_MAPPING.keys()), value,
93
def arraySize( cls, value, typeCode = None ):
94
"""Given a data-value, calculate dimensions for the array"""
97
def arrayByteCount( cls, value, typeCode = None ):
98
"""Given a data-value, calculate number of bytes required to represent"""
101
except AttributeError as err:
102
if cls.ERROR_ON_COPY:
103
raise error.CopyError(
104
"""Non-numpy array passed to numpy arrayByteCount: %s""",
107
value = cls.asArray( value, typeCode )
110
def asArray( cls, value, typeCode=None ):
111
"""Convert given value to an array value of given typeCode"""
115
return cls.contiguous( value, typeCode )
118
def contiguous( cls, source, typeCode=None ):
119
"""Get contiguous array from source
121
source -- numpy Python array (or compatible object)
122
for use as the data source. If this is not a contiguous
123
array of the given typeCode, a copy will be made,
124
otherwise will just be returned unchanged.
125
typeCode -- optional 1-character typeCode specifier for
126
the numpy.array function.
128
All gl*Pointer calls should use contiguous arrays, as non-
129
contiguous arrays will be re-copied on every rendering pass.
130
Although this doesn't raise an error, it does tend to slow
133
typeCode = GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]
135
contiguous = source.flags.contiguous
136
except AttributeError as err:
138
return numpy.ascontiguousarray( source, typeCode )
140
return numpy.ascontiguousarray( source )
142
if contiguous and (typeCode is None or typeCode==source.dtype.char):
144
elif (contiguous and cls.ERROR_ON_COPY):
145
from OpenGL import error
146
raise error.CopyError(
147
"""Array of type %r passed, required array of type %r""",
148
source.dtype.char, typeCode,
151
# We have to do astype to avoid errors about unsafe conversions
152
# XXX Confirm that this will *always* create a new contiguous array
153
# XXX Guard against wacky conversion types like uint to float, where
154
# we really don't want to have the C-level conversion occur.
155
# XXX ascontiguousarray is apparently now available in numpy!
156
if cls.ERROR_ON_COPY:
157
from OpenGL import error
158
raise error.CopyError(
159
"""Non-contiguous array passed""",
163
typeCode = source.dtype.char
164
return numpy.ascontiguousarray( source, typeCode )
166
def unitSize( cls, value, typeCode=None ):
167
"""Determine unit size of an array (if possible)"""
168
return value.shape[-1]
170
def dimensions( cls, value, typeCode=None ):
171
"""Determine dimensions of the passed array value (if possible)"""
174
def from_param( cls, instance, typeCode=None ):
176
pointer = cls.dataPointer( instance )
177
except TypeError as err:
178
array = cls.asArray( instance, typeCode )
179
pp = cls.dataPointer( array )
180
pp._temporary_array_ = (array,)
183
if typeCode and instance.dtype != GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]:
184
raise error.CopyError(
185
"""Array of type %r passed, required array of type %r""",
186
instance.dtype.char, typeCode,
188
return c_void_p( pointer )
191
numpy.array( [1], 's' )
193
except TypeError as err:
197
def lookupDtype( char ):
198
return numpy.zeros( (1,), dtype=char ).dtype
200
ARRAY_TO_GL_TYPE_MAPPING = {
201
lookupDtype('d'): constants.GL_DOUBLE,
202
lookupDtype('f'): constants.GL_FLOAT,
203
lookupDtype('i'): constants.GL_INT,
204
lookupDtype(SHORT_TYPE): constants.GL_SHORT,
205
lookupDtype(USHORT_TYPE): constants.GL_UNSIGNED_SHORT,
206
lookupDtype('B'): constants.GL_UNSIGNED_BYTE,
207
lookupDtype('c'): constants.GL_UNSIGNED_BYTE,
208
lookupDtype('b'): constants.GL_BYTE,
209
lookupDtype('I'): constants.GL_UNSIGNED_INT,
212
GL_TYPE_TO_ARRAY_MAPPING = {
213
constants.GL_DOUBLE: lookupDtype('d'),
214
constants.GL_FLOAT:lookupDtype('f'),
215
constants.GL_INT: lookupDtype('i'),
216
constants.GL_BYTE: lookupDtype('b'),
217
constants.GL_SHORT: lookupDtype(SHORT_TYPE),
218
constants.GL_UNSIGNED_INT: lookupDtype('I'),
219
constants.GL_UNSIGNED_BYTE: lookupDtype('B'),
220
constants.GL_UNSIGNED_SHORT: lookupDtype(USHORT_TYPE),
b'\\ No newline at end of file'