0

I have a numpy array with 8 16 byte long void records that looks like this:

array([[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]], 
       dtype='|V16')

And need to cast it to an array with 8 16B long records of a custom dtype that looks like this:

[(('x', 's0'), '<u4'), (('y', 's1'), '<u4'), (('z', 's2'), '<u4'), ('padding0', '<u4')]

How can I achieve that?

I've tried array.astype(self.dtype, copy=False, casting="unsafe"), but I get

ValueError: setting an array element with a sequence.

Which doesn't make much sense to me.

This data comes from PyOpenCL (memory mapping a buffer), I can't really change the input format or the dtype.

2
  • 1
    numpy.ndarray.view might do it, or there might be a more specific and more safe tool, but I'd question whether it's really impossible to change the input format. Commented Sep 12, 2017 at 20:13
  • numpy.ndarray.view worked perfectly, thank you. Can you make it into an answer so I can accept it? There is a knob for controlling the dtype in PyOpencl, but it seems to only work for simple dtypes, not records. It's most likely a bug, but view is probably still necessary even to fix it properly. Commented Sep 13, 2017 at 5:58

1 Answer 1

1

As long as the number of bytes match, view can make this kind of transformation. It just changes how the data buffer is 'viewed'.

In [36]: dt=np.dtype([(('x', 's0'), '<u4'), (('y', 's1'), '<u4'), (('z', 's2'), '<u4'), ('padding0', '<u4')])
In [37]: dt
Out[37]: dtype([(('x', 's0'), '<u4'), (('y', 's1'), '<u4'), (('z', 's2'), '<u4'), ('padding0', '<u4')])

In [39]: x = np.zeros((3,), dtype=dt)
In [40]: x
Out[40]: 
array([(0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)],
      dtype=[(('x', 's0'), '<u4'), (('y', 's1'), '<u4'), (('z', 's2'), '<u4'), ('padding0', '<u4')])
In [41]: x.view('|V16')
Out[41]: 
array([[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]],
      dtype='|V16')
In [42]: x.view('|V16').view(dt)
Out[42]: 
array([(0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)],
      dtype=[(('x', 's0'), '<u4'), (('y', 's1'), '<u4'), (('z', 's2'), '<u4'), ('padding0', '<u4')])

I often have to experiment to figure out whether astype or view is the right way to transform a structured array.

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.