Re: [Numpy-discussion] read-only or immutable masked array

2013-07-15 Thread Gregorio Bastardo
Hi Pierre,

 I'm a bit surprised, though. Here's what I tried

 np.version.version
  1.7.0
 x = np.ma.array([1,2,3], mask=[0,1,0])
 x.flags.writeable=False
 x[0]=-1
  ValueError: assignment destination is read-only

Thanks, it works perfectly =) Sorry, probably have overlooked this
simple solution, tried to set x.data and x.mask directly. I noticed
that this only protects the data, so mask also has to be set to
read-only or be hardened to avoid accidental (un)masking.

Gregorio
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-15 Thread Pierre Gerard-Marchant

On Jul 15, 2013, at 10:04 , Gregorio Bastardo gregorio.basta...@gmail.com 
wrote:

 Hi Pierre,
 
 I'm a bit surprised, though. Here's what I tried
 
 np.version.version
  1.7.0
 x = np.ma.array([1,2,3], mask=[0,1,0])
 x.flags.writeable=False
 x[0]=-1
  ValueError: assignment destination is read-only
 
 Thanks, it works perfectly =) Sorry, probably have overlooked this
 simple solution, tried to set x.data and x.mask directly. I noticed
 that this only protects the data, so mask also has to be set to
 read-only or be hardened to avoid accidental (un)masking.

Well, yes and no. Settings the flags of `x` doesn't set (yet) the flags of the 
mask, that's true. Still, `.writeable=False` should prevent you to unmask data, 
provided you're not trying to modify the mask directly but use basic assignment 
like `x[…]=…`. However, assigning `np.ma.masked` to array items does modify the 
mask and only the mask, hence the absence of error if the array is not 
writeable.

Note as well that hardening the mask only prevents unmasking: you can still 
grow the mask, which may not be what you want. Use 
`x.mask.flags.writeable=False` to make the mask really read-only.

___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-15 Thread Gregorio Bastardo
Hi Pierre,

 Note as well that hardening the mask only prevents unmasking: you can still 
 grow the mask, which may not be what you want. Use 
 `x.mask.flags.writeable=False` to make the mask really read-only.

I ran into an unmasking problem with the suggested approach:

 np.version.version
'1.7.0'
 x = np.ma.masked_array(xrange(4), [0,1,0,1])
 x
masked_array(data = [0 -- 2 --],
 mask = [False  True False  True],
   fill_value = 99)
 x.flags.writeable = False
 x.mask.flags.writeable = False
 x.mask[1] = 0 # ok
Traceback (most recent call last):
  ...
ValueError: assignment destination is read-only
 x[1] = 0 # ok
Traceback (most recent call last):
  ...
ValueError: assignment destination is read-only
 x.mask[1] = 0 # ??
 x
masked_array(data = [0 1 2 --],
 mask = [False False False  True],
   fill_value = 99)

I noticed that sharedmask attribute changes (from True to False)
after x[1] = 0. Also, some of the ma operations result mask identity
of the new ma, which causes ValueError when the new ma mask is
modified:

 x = np.ma.masked_array(xrange(4), [0,1,0,1])
 x.flags.writeable = False
 x.mask.flags.writeable = False
 x1 = x  0
 x1.mask is x.mask # ok
False
 x2 = x != 0
 x2.mask is x.mask # ??
True
 x2.mask[1] = 0
Traceback (most recent call last):
  ...
ValueError: assignment destination is read-only

which is a bit confusing. And I experienced that *_like operations
give mask identity too:

 y = np.ones_like(x)
 y.mask is x.mask
True

but for that I found a recent discussion (empty_like for masked
arrays) on the mailing list:
http://mail.scipy.org/pipermail/numpy-discussion/2013-June/066836.html

I might be missing something but could you clarify these issues?

Thanks,
Gregorio
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-15 Thread Pierre Gerard-Marchant

On Jul 15, 2013, at 14:40 , Gregorio Bastardo gregorio.basta...@gmail.com 
wrote:

 Hi Pierre,
 
 Note as well that hardening the mask only prevents unmasking: you can still 
 grow the mask, which may not be what you want. Use 
 `x.mask.flags.writeable=False` to make the mask really read-only.
 
 I ran into an unmasking problem with the suggested approach:
 
 np.version.version
 '1.7.0'
 x = np.ma.masked_array(xrange(4), [0,1,0,1])
 x
 masked_array(data = [0 -- 2 --],
 mask = [False  True False  True],
   fill_value = 99)
 x.flags.writeable = False
 x.mask.flags.writeable = False
 x.mask[1] = 0 # ok
 Traceback (most recent call last):
  ...
 ValueError: assignment destination is read-only
 x[1] = 0 # ok
 Traceback (most recent call last):
  ...
 ValueError: assignment destination is read-only
 x.mask[1] = 0 # ??
 x
 masked_array(data = [0 1 2 --],
 mask = [False False False  True],
   fill_value = 99)

Ouch…
Quick workaround:  use `x.harden_mask()` *then* `x.mask.flags.writeable=False`

[Longer explanation]
 I noticed that sharedmask attribute changes (from True to False)
 after x[1] = 0.

Indeed, indeed… When setting items, the mask is unshared to limit some issues 
(like propagation to the other masked_arrays sharing the mask). Unsharing the 
mask involves a copy, which unfortunately doesn't copy the flags. In other 
terms, when you try `x[1]=0`, the mask becomes rewritable. That hurts…
But! This call to `unshare_mask` is performed only when the mask is 'soft' 
hence the quick workaround…

Note to self (or whomever will fix the issue before I can do it):
* We could make sure that copying a mask copies some of its flags to (like the 
`writeable` one, which other ones?)
* The call to `unshare_mask` is made *before* we try to call `__setitem__` on 
the `_data` part: that's silly, if we called `__setitem__(_data,index,dval)` 
before, the `ValueError: assignment destination is read-only` would be raised 
before the mask could get unshared… TLD;DR: move L3073 of np.ma.core to L3068
* There should be some simpler ways to make a masked_array read-only, this 
little dance is rapidly tiring.





 Also, some of the ma operations result mask identity
 of the new ma, which causes ValueError when the new ma mask is
 modified:
 
 x = np.ma.masked_array(xrange(4), [0,1,0,1])
 x.flags.writeable = False
 x.mask.flags.writeable = False
 x1 = x  0
 x1.mask is x.mask # ok
 False
 x2 = x != 0
 x2.mask is x.mask # ??
 True
 x2.mask[1] = 0
 Traceback (most recent call last):
  ...
 ValueError: assignment destination is read-only
 
 which is a bit confusing.

Ouch again. 
[TL;DR] No workaround, sorry
[Long version]
The inconsistency comes from the fact that '!=' or '==' call the `__ne__` or 
`__eq__` methods while other comparison operators call their own function. In 
the first case, because we're comparing with a non-masked scalar, no copy of 
the mask is made; in the second case, a copy is systematically made. As pointed 
out earlier, copies of a mask don't preserve its flags…
[Note to self]
* Define a factory for __lt__/__le__/__gt__/__ge__ based on __eq__ : 
MaskedArray.__eq__ and __ne__ already have almost the same code.. (but what 
about filling? Is it an issue?)



 And I experienced that *_like operations
 give mask identity too:
 
 y = np.ones_like(x)
 y.mask is x.mask
 True

This may change in the future, depending on a yet-to-be-achieved consensus on  
the definition of 'least-surprising behaviour'. Right now, the *-like functions 
return an array that shares the mask with the input, as you've noticed. Some 
people complained about it, what's your take on that?

 I might be missing something but could you clarify these issues?

You were not missing anything, np.ma isn't the most straightforward module: 
plenty of corner cases, and the implementation is pretty naive at times (but 
hey, it works). My only advice is to never lose hope.


___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-15 Thread Gregorio Bastardo
 Ouch…
 Quick workaround:  use `x.harden_mask()` *then* `x.mask.flags.writeable=False`

Thanks for the update and the detailed explanation. I'll try this trick.

 This may change in the future, depending on a yet-to-be-achieved consensus on 
  the definition of 'least-surprising behaviour'. Right now, the *-like 
 functions return an array that shares the mask with the input, as you've 
 noticed. Some people complained about it, what's your take on that?

I already took part in the survey (possibly out of thread):
http://mail.scipy.org/pipermail/numpy-discussion/2013-July/067136.html

 You were not missing anything, np.ma isn't the most straightforward module: 
 plenty of corner cases, and the implementation is pretty naive at times (but 
 hey, it works). My only advice is to never lose hope.

I agree there are plenty of hard-to-define cases, and I came accross a
hot debate on missing data representation in python:
https://github.com/njsmith/numpy/wiki/NA-discussion-status

but still I believe np.ma is very usable when compression is not
strongly needed.
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-14 Thread Pierre GM

On Jul 13, 2013, at 13:36 , Gregorio Bastardo gregorio.basta...@gmail.com 
wrote:

 Hi Stéfan,
 
 Thanks for the suggestion, but it does not protect the array:

Thinking about it, it can't: when `x` is a MaskedArray, `x.data` is just a view 
of the underlying array as a regular ndarray. As far as I understand, changing 
the `.flags` of a view doesn't affect the original.

I'm a bit surprised, though. Here's what I tried

 np.version.version
 1.7.0
 x = np.ma.array([1,2,3], mask=[0,1,0])
 x.flags.writeable=False
 x[0]=-1
 ValueError: assignment destination is read-only

What did you mean by 

 array.flags.writeable = False
 
 is perfectly fine, but it does not work on ma-s.

? Could you post what you did and what you got?


 Moreover, mask
 hardening only protects masked elements, and does not raise error (as
 I'd expect).

Yes, that's how it supposed to work.
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-13 Thread Gregorio Bastardo
Hi Stéfan,

Thanks for the suggestion, but it does not protect the array:

 x = np.ma.masked_array(xrange(4), [0,1,0,1])
 x
masked_array(data = [0 -- 2 --],
 mask = [False  True False  True],
   fill_value = 99)
 x.mask.flags.writeable = False
 x.data.flags.writeable = False
 x.data.flags.writeable
True
 x.mask.flags.writeable
False
 x[0] = -1
 x
masked_array(data = [-1 -- 2 --],
 mask = [False  True False  True],
   fill_value = 99)

Is there a working solution for this problem?

Thanks,
Gregorio

2013/7/12 Stéfan van der Walt ste...@sun.ac.za:
 On Fri, Jul 12, 2013 at 4:41 PM, Gregorio Bastardo
 gregorio.basta...@gmail.com wrote:
 array.flags.writeable = False

 is perfectly fine, but it does not work on ma-s. Moreover, mask
 hardening only protects masked elements, and does not raise error (as
 I'd expect).

 You probably have to modify the underlying array and mask:

 x = np.ma.array(...)
 x.mask.flags.writeable = False
 x.data.flags.writeable = False

 Stéfan
 ___
 NumPy-Discussion mailing list
 NumPy-Discussion@scipy.org
 http://mail.scipy.org/mailman/listinfo/numpy-discussion
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


[Numpy-discussion] read-only or immutable masked array

2013-07-12 Thread Gregorio Bastardo
Hi,

I use masked arrays to mark missing values in data and found it very
convenient, although sometimes counterintuitive.

I'd like to make a pool of masked arrays (shared between several
processing steps) read-only (both data and mask property) to protect
the arrays from accidental modification (and the array users from
hours of debugging). The regular ndarray trick

array.flags.writeable = False

is perfectly fine, but it does not work on ma-s. Moreover, mask
hardening only protects masked elements, and does not raise error (as
I'd expect).

Could you recommend an easy way to set an ma read-only?

Thanks,
Gregorio
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] read-only or immutable masked array

2013-07-12 Thread Stéfan van der Walt
On Fri, Jul 12, 2013 at 4:41 PM, Gregorio Bastardo
gregorio.basta...@gmail.com wrote:
 array.flags.writeable = False

 is perfectly fine, but it does not work on ma-s. Moreover, mask
 hardening only protects masked elements, and does not raise error (as
 I'd expect).

You probably have to modify the underlying array and mask:

x = np.ma.array(...)
x.mask.flags.writeable = False
x.data.flags.writeable = False

Stéfan
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion