[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