Viewing file: numpymodule.py (9.06 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
"""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, }
|