Contiguous Array
Juan Nunez-Iglesias
jni.soma at gmail.com
Wed Jul 31 05:47:52 EDT 2013
@Marc: They are very different functions. ravel() gives you a view or a
copy of the array as a 1D array that happens to be contiguous.
ascontiguousarray will give you a view or a copy of the array *of the same
shape* as the original, but guaranteed to be contiguous. Let me try to
illustrate:
In [1]: x = np.arange(20, dtype=np.uint8).reshape((4,5))
In [2]: x
Out[2]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]], dtype=uint8)
In [3]: x.strides
Out[3]: (5, 1)
So I've made an array x that has 4 rows and 5 columns. Internally, the data
in x is stored as a contiguous block of memory of length 20 bytes. The
strides tell numpy that to get to the next row in the array, you need to
skip 5 bytes in the memory, but to get to the next column, you only need to
go to the next (+1) byte in memory. This is called C-contiguous.
Now, let's get a weird view of x:
In [4]: y = x.T[1::2]
I've taken the transpose of x (5 rows and 4 columns) and then taken the 1st
and 3rd rows of that. By default, numpy will use nice tricks with strides
to avoid a copy:
In [5]: y.strides
Out[5]: (2, 5)
In [6]: y
Out[6]:
array([[ 1, 6, 11, 16],
[ 3, 8, 13, 18]], dtype=uint8)
In [7]: y[1, 1] = 45
In [8]: x
Out[8]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 45, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]], dtype=uint8)
So, y is actually pointing to the same memory as x, but it uses different
strides to access its own rows and columns. Notice that changing an entry
in y changed the corresponding entry in x.
In [10]: np.ravel(y)
Out[10]: array([ 1, 6, 11, 16, 3, 45, 13, 18], dtype=uint8)
np.ravel gives you a "linearised" version of y, concatenating all the rows
together.
In [11]: z = np.ascontiguousarray(y)
In [12]: z
Out[12]:
array([[ 1, 6, 11, 16],
[ 3, 45, 13, 18]], dtype=uint8)
In [13]: z.strides
Out[13]: (4, 1)
np.ascontiguousarray gives you the same thing as y, except now it's a
separate contiguous block of memory: look at the strides. You can tell that
it's a copy because modifying z has no effect on x:
In [14]: z[0, 0] = 72
In [15]: x
Out[15]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 45, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]], dtype=uint8)
In [16]: z
Out[16]:
array([[72, 6, 11, 16],
[ 3, 45, 13, 18]], dtype=uint8)
But, if an array is already contiguous, np.ravel() avoids a copy and
returns a view into the same data. So:
In [19]: a = np.ravel(x)
In [20]: a[0] = 72
In [21]: x
Out[21]:
array([[72, 1, 2, 3, 4],
[ 5, 6, 7, 45, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]], dtype=uint8)
If you try to get a contiguous version of x, which is already contiguous,
you are actually getting x back:
In [22]: b = np.ascontiguousarray(x)
In [23]: b is x
Out[23]: True
In [25]: b[3, 4] = 0
In [26]: x
Out[26]:
array([[72, 1, 2, 3, 4],
[ 5, 6, 7, 45, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 0]], dtype=uint8)
Hope that clarifies a few things! It takes quite a bit of playing around
before you can get an intuition for what's a copy, what's a view, what's
contiguous, etc.
On Wed, Jul 31, 2013 at 6:15 PM, Ankit Agrawal <aaaagrawal at gmail.com> wrote:
> Hi Marc,
>
>
> On Wed, Jul 31, 2013 at 1:09 PM, Marc de Klerk <deklerkmc at gmail.com>wrote:
>
>> Hi guys,
>>
>> I've been using np.ravel(). This morning I tried to lookup the difference
>> between np.ravel() and np.ascontiguousarray(). Does anybody know?
>>
> I am not sure if this helps as I don't know your purpose for using
> np.ravel / np.ascontiguousarray. I got to know about the ndarray.flags
> method yesterday from Stefan while discussion on this PR<https://github.com/scikit-image/scikit-image/pull/668>
> .
>
> In [15]: a = np.arange(20).reshape((4,5))
>
> In [16]: a
> Out[16]:
> array([[ 0, 1, 2, 3, 4],
> [ 5, 6, 7, 8, 9],
> [10, 11, 12, 13, 14],
> [15, 16, 17, 18, 19]])
>
> In [17]: a.flags
> Out[17]:
> C_CONTIGUOUS : True
> F_CONTIGUOUS : False
> OWNDATA : False
> WRITEABLE : True
> ALIGNED : True
> UPDATEIFCOPY : False
>
> In [18]: b = np.ravel(a)
>
> In [20]: b
> Out[20]:
> array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> 17, 18, 19])
>
> In [21]: b.flags
> Out[21]:
> C_CONTIGUOUS : True
> F_CONTIGUOUS : True
> OWNDATA : False
> WRITEABLE : True
> ALIGNED : True
> UPDATEIFCOPY : False
>
> Hope this helps!!
>
> Marc
>>
>> On Sunday, July 21, 2013 6:37:47 AM UTC+2, Chintak Sheth wrote:
>>
>>> Hi Ronnie,
>>>
>>> On Jul 21, 2013 10:00 AM, "Ronnie Ghose" <ronnie... at gmail.com> wrote:
>>> >
>>> > So in skimage/colors why does it matter if the array is contiguous? Is
>>> this for Cython operations later?
>>> >
>>>
>>> Yeah it is mainly for using memory views in Cython which is initialized
>>> as C contiguous.
>>> `cdef some_type[:. ::1] var_name`
>>>
>>> In thus case ::1 is for C contiguous.
>>>
>>> Chintak
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "scikit-image" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to scikit-image+unsubscribe at googlegroups.com.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "scikit-image" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to scikit-image+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20130731/b0f3bc16/attachment.html>
More information about the scikit-image
mailing list