[SciPy-user] shape problem after flipud

Dominik Szczerba domi at vision.ee.ethz.ch
Thu Jun 14 17:41:50 EDT 2007


Thank you for a very helpful explanation. Please see below:

Robert Kern wrote:
> 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
>   Out[30]:
>   array([[0, 1],
>          [2, 3]])
> 
>   In [31]: d2 = flipud(data)
> 
>   In [32]: d2
>   Out[32]:
>   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.

quite a bit of a gotcha for a post-matlab user. deepcopy thing was 
already not pleasant to swallow.

> 
>   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
>   Out[54]:
>   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:

I was doing it in another way, namely flipping a deepcopy. You say to 
deepcopy the result and it works:

data = flipud(data)
data3 = copy.deepcopy(data)
data3.shape = (256*256,)
print 'new shape', data3.shape

> 
>> 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])
> 

This actually did not work:

shape = (256,256)
data = zeros(256*256)
data.shape = shape
print 'old shape', data.shape
print data
data2 = flipud(data)
data2.ravel()
reshape(data2,(256*256,))
print 'new shape', data2.shape

The shape is preserved! Even though I am fine with the previously given 
solution, I am still curious what is wrong here.

BTW> Why (size,) and not (size,1)?

Thanks a lot for your help,
- Dominik


-- 
Dominik Szczerba, Ph.D.
Computer Vision Lab CH-8092 Zurich
http://www.vision.ee.ethz.ch/~domi



More information about the SciPy-User mailing list