[SciPy-user] shape problem after flipud

Robert Kern robert.kern@gmail....
Thu Jun 14 16:04:26 CDT 2007

Dominik Szczerba wrote:
> Hi,
> The following trivial codelet does not work as expected:
> -------------------------------
> from scipy import *
> import copy
> shape = (256,256)
> data = zeros(256*256)
> data.shape = shape
> print 'old shape', data.shape
> print data
> data=flipud(data)
> data.shape=(256*256,)
> print 'new shape', data.shape
> -------------------------------
> exiting with an uncomprehensive error:
>      data.shape=(256*256,)
> AttributeError: incompatible shape for a non-contiguous array
> If 'flipud' is ommited, it works as expected. I tried via a deepcopy, 
> the problem persists. Why should flipud invalidate 'reshapeability'?

Assigning to .shape only adjusts the strides. It does not change any of the
memory. It will only let you do that when the memory layout is consistent with
the desired shape. flipud() just gets a view on the original memory by using
different strides; the result is non-contiguous. The memory layout is no longer
consistent with the flattened view that you are requesting. Here is an example:

  In [25]: data = arange(4)

This is the layout in memory for 'data' and (later) 'd2':

  In [26]: data
  Out[26]: array([0, 1, 2, 3])

  In [29]: data.shape = (2, 2)

  In [30]: data
  array([[0, 1],
         [2, 3]])

  In [31]: d2 = flipud(data)

  In [32]: d2
  array([[2, 3],
         [0, 1]])

Calling .ravel() will copy the array if it is non-contiguous and will show you
the memory layout that 'd2' is mimicking with its strides.

  In [33]: d2.ravel()
  Out[33]: array([2, 3, 0, 1])

Assigning to .shape will only let you do that if the memory layout is consistent
with the view that the array is trying to do.

  In [52]: import copy

  In [53]: d3 = copy.deepcopy(d2)

  In [54]: d3
  array([[2, 3],
         [0, 1]])

  In [55]: d3.shape = (4,)

  In [56]: d3
  Out[56]: array([2, 3, 0, 1])

copy.deepcopy() should have worked. I don't know why it didn't for you. However:

> What am I doing wrong?

You will want to use numpy.reshape() if you want the most foolproof and
idiomatic way to get a reshaped array. It will copy the array if necessary.

  In [57]: reshape(d2, (4,))
  Out[57]: array([2, 3, 0, 1])

Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
 that is made terrible by our own mad attempt to interpret it as though it had
 an underlying truth."
  -- Umberto Eco

More information about the SciPy-user mailing list