/usr/share/pyshared/OpenGL/arrays/numpymodule.py is in python-opengl 3.0.1~b2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | """Numpy (new version) module implementation of the OpenGL-ctypes array interfaces
XXX Need to register handlers for all of the scalar types that numpy returns,
would like to have all return values be int/float if they are of compatible
type as well.
"""
REGISTRY_NAME = 'numpy'
try:
import numpy
except ImportError, err:
raise ImportError( """No numpy module present: %s"""%(err))
import operator,logging
import OpenGL
import ctypes
c_void_p = ctypes.c_void_p
from OpenGL import constants, constant, error
from OpenGL.arrays import formathandler
log = logging.getLogger( 'OpenGL.arrays.numpymodule' )
from OpenGL import acceleratesupport
NumpyHandler = None
if acceleratesupport.ACCELERATE_AVAILABLE:
try:
from OpenGL_accelerate.numpy_formathandler import NumpyHandler
except ImportError, err:
log.warn(
"Unable to load numpy_formathandler accelerator from OpenGL_accelerate"
)
if NumpyHandler is None:
# numpy's array interface has changed over time :(
testArray = numpy.array( [1,2,3,4],'i' )
# Numpy's "ctypes" interface actually creates a new ctypes object
# in python for every access of the .ctypes attribute... which can take
# ridiculously large periods when you multiply it by millions of iterations
if hasattr(testArray,'__array_interface__'):
def dataPointer( cls, instance ):
"""Convert given instance to a data-pointer value (integer)"""
try:
return long(instance.__array_interface__['data'][0])
except AttributeError, err:
instance = cls.asArray( instance )
try:
return long(instance.__array_interface__['data'][0])
except AttributeError, err:
return long(instance.__array_data__[0],0)
else:
def dataPointer( cls, instance ):
"""Convert given instance to a data-pointer value (integer)"""
try:
return long(instance.__array_data__[0],0)
except AttributeError, err:
instance = cls.asArray( instance )
try:
return long(instance.__array_interface__['data'][0])
except AttributeError, err:
return long(instance.__array_data__[0],0)
del testArray
dataPointer = classmethod( dataPointer )
class NumpyHandler( formathandler.FormatHandler ):
"""Numpy-specific data-type handler for OpenGL
Attributes:
ERROR_ON_COPY -- if True, will raise errors
if we have to copy an array object in order to produce
a contiguous array of the correct type.
"""
HANDLED_TYPES = (numpy.ndarray,)# list, tuple )
dataPointer = dataPointer
isOutput = True
ERROR_ON_COPY = OpenGL.ERROR_ON_COPY
@classmethod
def zeros( cls, dims, typeCode ):
"""Return Numpy array of zeros in given size"""
return numpy.zeros( dims, GL_TYPE_TO_ARRAY_MAPPING[typeCode])
@classmethod
def arrayToGLType( cls, value ):
"""Given a value, guess OpenGL type of the corresponding pointer"""
typeCode = value.dtype
constant = ARRAY_TO_GL_TYPE_MAPPING.get( typeCode )
if constant is None:
raise TypeError(
"""Don't know GL type for array of type %r, known types: %s\nvalue:%s"""%(
typeCode, ARRAY_TO_GL_TYPE_MAPPING.keys(), value,
)
)
return constant
@classmethod
def arraySize( cls, value, typeCode = None ):
"""Given a data-value, calculate dimensions for the array"""
return value.size
@classmethod
def arrayByteCount( cls, value, typeCode = None ):
"""Given a data-value, calculate number of bytes required to represent"""
try:
return value.nbytes
except AttributeError, err:
if cls.ERROR_ON_COPY:
raise error.CopyError(
"""Non-numpy array passed to numpy arrayByteCount: %s""",
type(value),
)
value = cls.asArray( value, typeCode )
return value.nbytes
@classmethod
def asArray( cls, value, typeCode=None ):
"""Convert given value to an array value of given typeCode"""
if value is None:
return value
else:
return cls.contiguous( value, typeCode )
@classmethod
def contiguous( cls, source, typeCode=None ):
"""Get contiguous array from source
source -- numpy Python array (or compatible object)
for use as the data source. If this is not a contiguous
array of the given typeCode, a copy will be made,
otherwise will just be returned unchanged.
typeCode -- optional 1-character typeCode specifier for
the numpy.array function.
All gl*Pointer calls should use contiguous arrays, as non-
contiguous arrays will be re-copied on every rendering pass.
Although this doesn't raise an error, it does tend to slow
down rendering.
"""
typeCode = GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]
try:
contiguous = source.flags.contiguous
except AttributeError, err:
if typeCode:
return numpy.ascontiguousarray( source, typeCode )
else:
return numpy.ascontiguousarray( source )
else:
if contiguous and (typeCode is None or typeCode==source.dtype.char):
return source
elif (contiguous and cls.ERROR_ON_COPY):
from OpenGL import error
raise error.CopyError(
"""Array of type %r passed, required array of type %r""",
source.dtype.char, typeCode,
)
else:
# We have to do astype to avoid errors about unsafe conversions
# XXX Confirm that this will *always* create a new contiguous array
# XXX Guard against wacky conversion types like uint to float, where
# we really don't want to have the C-level conversion occur.
# XXX ascontiguousarray is apparently now available in numpy!
if cls.ERROR_ON_COPY:
from OpenGL import error
raise error.CopyError(
"""Non-contiguous array passed""",
source,
)
if typeCode is None:
typeCode = source.dtype.char
return numpy.ascontiguousarray( source, typeCode )
@classmethod
def unitSize( cls, value, typeCode=None ):
"""Determine unit size of an array (if possible)"""
return value.shape[-1]
@classmethod
def dimensions( cls, value, typeCode=None ):
"""Determine dimensions of the passed array value (if possible)"""
return value.shape
@classmethod
def from_param( cls, instance, typeCode=None ):
try:
pointer = cls.dataPointer( instance )
except TypeError, err:
array = cls.asArray( instance, typeCode )
pp = cls.dataPointer( array )
pp._temporary_array_ = (array,)
return pp
else:
if typeCode and instance.dtype != GL_TYPE_TO_ARRAY_MAPPING[ typeCode ]:
raise error.CopyError(
"""Array of type %r passed, required array of type %r""",
instance.dtype.char, typeCode,
)
return c_void_p( pointer )
try:
numpy.array( [1], 's' )
SHORT_TYPE = 's'
except TypeError, err:
SHORT_TYPE = 'h'
USHORT_TYPE = 'H'
def lookupDtype( char ):
return numpy.zeros( (1,), dtype=char ).dtype
ARRAY_TO_GL_TYPE_MAPPING = {
lookupDtype('d'): constants.GL_DOUBLE,
lookupDtype('f'): constants.GL_FLOAT,
lookupDtype('i'): constants.GL_INT,
lookupDtype(SHORT_TYPE): constants.GL_SHORT,
lookupDtype(USHORT_TYPE): constants.GL_UNSIGNED_SHORT,
lookupDtype('B'): constants.GL_UNSIGNED_BYTE,
lookupDtype('c'): constants.GL_UNSIGNED_BYTE,
lookupDtype('b'): constants.GL_BYTE,
lookupDtype('I'): constants.GL_UNSIGNED_INT,
None: None,
}
GL_TYPE_TO_ARRAY_MAPPING = {
constants.GL_DOUBLE: lookupDtype('d'),
constants.GL_FLOAT:lookupDtype('f'),
constants.GL_INT: lookupDtype('i'),
constants.GL_BYTE: lookupDtype('b'),
constants.GL_SHORT: lookupDtype(SHORT_TYPE),
constants.GL_UNSIGNED_INT: lookupDtype('I'),
constants.GL_UNSIGNED_BYTE: lookupDtype('B'),
constants.GL_UNSIGNED_SHORT: lookupDtype(USHORT_TYPE),
None: None,
}
|