home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / OpenGL / arrays / numpymodule.py < prev    next >
Encoding:
Python Source  |  2009-01-03  |  7.8 KB  |  231 lines

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