[SciPy-user] shape problem after flipud

Dominik Szczerba domi@vision.ee.ethz...
Fri Jun 15 01:39:10 CDT 2007


Robert Kern wrote:
> Dominik Szczerba wrote:
>> 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.
> 
> I don't recommend using deepcopy. Use reshape().
> 
>>>> 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.
> 
> It returns a (possibly new) object with the requested shape. It does not affect
> the shape of the original array since it is not always possible to do that
> safely. Assigning to .shape is the appropriate way to change the shape of an
> existing array in-place if it is safe to do so. Two different ways to do two
> different things.
> 

OK, so data3 = reshape(data2,(256*256,)) fixes it at a least expense.
Thanks a lot for clearing up the confusion.
- Dominik

>> BTW> Why (size,) and not (size,1)?
> 
> Because they are different things. Not everything is a 2D array.
> 


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