[Numpy-discussion] dtype "reduction" [SOLVED]

Nicolas Rougier Nicolas.Rougier@inria...
Tue Jan 15 11:37:52 CST 2013



I ended coding the dtype reduction, it's not foolproof but it might be useful for others as well.

Nicolas



import numpy as np

def dtype_reduce(dtype, level=0, depth=0):
    """
    Try to reduce dtype up to a given level when it is possible

    dtype =  [ ('vertex',  [('x', 'f4'), ('y', 'f4'), ('z', 'f4')]),
               ('normal',  [('x', 'f4'), ('y', 'f4'), ('z', 'f4')]),
               ('color',   [('r', 'f4'), ('g', 'f4'), ('b', 'f4'), ('a', 'f4')])]

    level 0: ['color,vertex,normal,', 10, 'float32']
    level 1: [['color', 4, 'float32']
              ['normal', 3, 'float32']
              ['vertex', 3, 'float32']]
    """
    dtype = np.dtype(dtype)
    fields = dtype.fields
    
    # No fields
    if fields is None:
        if dtype.shape:
            count = reduce(mul, dtype.shape)
        else:
            count = 1
        size = dtype.itemsize/count
        if dtype.subdtype:
            name = str( dtype.subdtype[0] )
        else:
            name = str( dtype )
        return ['', count, name]
    else:
        items = []
        name = ''
        # Get reduced fields
        for key,value in fields.items():
            l =  dtype_reduce(value[0], level, depth+1)
            if type(l[0]) is str:
                items.append( [key, l[1], l[2]] )
            else:
                items.append( l )
            name += key+','

        # Check if we can reduce item list
        ctype = None
        count = 0
        for i,item in enumerate(items):
            # One item is a list, we cannot reduce
            if type(item[0]) is not str:
                return items
            else:
                if i==0:
                    ctype = item[2]
                    count += item[1]
                else:
                    if item[2] != ctype:
                        return items
                    count += item[1]
        if depth >= level:
            return [name, count, ctype]
        else:
            return items

if __name__ == '__main__':

    # Fully reductible
    dtype =  [ ('vertex',  [('x', 'f4'), ('y', 'f4'), ('z', 'f4')]),
               ('normal',  [('x', 'f4'), ('y', 'f4'), ('z', 'f4')]),
               ('color',   [('r', 'f4'), ('g', 'f4'), ('b', 'f4'), ('a', 'f4')])]
    print 'level 0:'
    print dtype_reduce(dtype,level=0)
    print 'level 1:'
    print dtype_reduce(dtype,level=1)
    print

    # Not fully reductible
    dtype =  [ ('vertex',  [('x', 'i4'), ('y', 'i4'), ('z', 'i4')]),
               ('normal',  [('x', 'f4'), ('y', 'f4'), ('z', 'f4')]),
               ('color',   [('r', 'f4'), ('g', 'f4'), ('b', 'f4'), ('a', 'f4')])]
    print 'level 0:'
    print dtype_reduce(dtype,level=0)
    print

    # Not reductible at all
    dtype =  [ ('vertex',  [('x', 'f4'), ('y', 'f4'), ('z', 'i4')]),
               ('normal',  [('x', 'f4'), ('y', 'f4'), ('z', 'i4')]),
               ('color',   [('r', 'f4'), ('g', 'f4'), ('b', 'i4'), ('a', 'f4')])]
    print 'level 0:'
    print dtype_reduce(dtype,level=0)





On Dec 27, 2012, at 9:11 , Nicolas Rougier wrote:

> 
> Yep, I'm trying to construct dtype2 programmaticaly and was hoping for some function giving me a "canonical" expression of the dtype. I've started playing with fields but it's just a bit harder than I though (lot of different cases and recursion).
> 
> Thanks for the answer.
> 
> 
> Nicolas
> 
> On Dec 27, 2012, at 1:32 , Nathaniel Smith wrote:
> 
>> On Wed, Dec 26, 2012 at 8:09 PM, Nicolas Rougier
>> <Nicolas.Rougier@inria.fr> wrote:
>>> 
>>> 
>>> Hi all,
>>> 
>>> 
>>> I'm looking for a way to "reduce" dtype1 into dtype2 (when it is possible of course).
>>> Is there some easy way to do that by any chance ?
>>> 
>>> 
>>> dtype1 = np.dtype( [ ('vertex',  [('x', 'f4'),
>>>                                 ('y', 'f4'),
>>>                                 ('z', 'f4')]),
>>>                   ('normal',  [('x', 'f4'),
>>>                                ('y', 'f4'),
>>>                                ('z', 'f4')]),
>>>                   ('color',   [('r', 'f4'),
>>>                                ('g', 'f4'),
>>>                                ('b', 'f4'),
>>>                                ('a', 'f4')]) ] )
>>> 
>>> dtype2 = np.dtype( [ ('vertex',  'f4', 3),
>>>                    ('normal',  'f4', 3),
>>>                    ('color',   'f4', 4)] )
>>> 
>> 
>> If you have an array whose dtype is dtype1, and you want to convert it
>> into an array with dtype2, then you just do
>> my_dtype2_array = my_dtype1_array.view(dtype2)
>> 
>> If you have dtype1 and you want to programmaticaly construct dtype2,
>> then that's a little more fiddly and depends on what exactly you're
>> trying to do, but start by poking around with dtype1.names and
>> dtype1.fields, which contain information on how dtype1 is put together
>> in the form of regular python structures.
>> 
>> -n
>> _______________________________________________
>> NumPy-Discussion mailing list
>> NumPy-Discussion@scipy.org
>> http://mail.scipy.org/mailman/listinfo/numpy-discussion
> 
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion



More information about the NumPy-Discussion mailing list