1

I use special np.dtypes for a program that have a structure like so:

POINT = np.dtype([('vertices', '<f4', 2), ('center', '<f4', 2), ('bbox', '<f4', 4)])

I need to specify another np.dtype that only uses the last field above, like so:

MBR = np.dtype([('bbox', '<f4', 4)])

This is so I can later access that field of both arrays like so:

def intersection(s, t):

    sxmin, sxmax, symin, sxmax = s['bbox']
    txmin, txmax, tymin, tymax = t['bbox']

    # do stuff

However, when I create the following array, it is being expanded and I'm unsure why:

box = np.array([1, 2, 3, 4], dtype=MBR)
# expected output...
array([1., 2., 3., 4.], dtype=[('bbox', '<f4', 4)])
# actual output...
array([([1., 1., 1., 1.],), ..., ([4., 4., 4., 4.],)], dtype=[('bbox', '<f4', 4)])

A quick test returns what I had expected...

np.empty([], dtype=MBR)
array(([nan, nan, inf, nan],), dtype=[('bbox', '<f4', 4)])

Edit:

Doing the following returns the expected result:

box = np.array(([1, 2, 3, 4],), dtype=MBR)

So now the question: Why do I have to wrap it in a tuple to conform to the dtype?

0

1 Answer 1

1

The short answer is that the input format, with nested lists and tuples, has to match the display format:

In [59]: MBR = np.dtype([('bbox', '<f4', 4)])                                                    
In [60]: arr = np.zeros(3, dtype=MBR)                                                            
In [61]: arr                                                                                     
Out[61]: 
array([([0., 0., 0., 0.],), ([0., 0., 0., 0.],), ([0., 0., 0., 0.],)],
      dtype=[('bbox', '<f4', (4,))])
In [62]: arr[0]                                                                                  
Out[62]: ([0., 0., 0., 0.],)
In [63]: arr[0]=[1,2,3,4]                                                                        
In [64]: arr[1]=[10,11,12,13]                                                                    
In [65]: arr                                                                                     
Out[65]: 
array([([ 1.,  2.,  3.,  4.],), ([10., 11., 12., 13.],),
       ([ 0.,  0.,  0.,  0.],)], dtype=[('bbox', '<f4', (4,))])
In [66]: np.array([([1,2,3,4],)],MBR)                                                            
Out[66]: array([([1., 2., 3., 4.],)], dtype=[('bbox', '<f4', (4,))])

So with a typical compound dtype, we say the inputs should be a list of tuples, one tuple per 'record' of the array. Within the tuple, one element per field.

You have the added complication of the size (4,) dimension within the field.

Note that the shape of the field, extracted from the array, combines the outer array shape with the inner field shape:

In [67]: arr['bbox']                                                                             
Out[67]: 
array([[ 1.,  2.,  3.,  4.],
       [10., 11., 12., 13.],
       [ 0.,  0.,  0.,  0.]], dtype=float32)

Often it is easier to assign values to a structured array by field, rather than by record:

In [68]: arr['bbox']=np.arange(12).reshape(3,4)                                                  
In [69]: arr                                                                                     
Out[69]: 
array([([ 0.,  1.,  2.,  3.],), ([ 4.,  5.,  6.,  7.],),
       ([ 8.,  9., 10., 11.],)], dtype=[('bbox', '<f4', (4,))])
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.