Skip to content

Commit 68d0bb8

Browse files
author
Erik Nielsen
committed
Updates ProtectedArray to work with latest NumPy versions.
At (or around) NumPy version 1.16, it only allows ndarrays that *own* data to set their 'writeable' flag. ProtectedArray used the writeable flag to be able to return read-only 'views' of a ProtectedArray and avoid copying when unnecessary. The NumPy update disallows read-only views, as views (I think) don't own their memory by construction. This commit updates ProtectedArray to only set the writable=True flag on a returned *copy* that might be expected to be a view into the base ProtectedArray. This makes the ProtectedArray less memory efficient (as it adds copying) but this should retain the old behavior and restore compatibility with NumPy.
1 parent d3f45e9 commit 68d0bb8

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

pygsti/objects/protectedarray.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ def __init__(self, input_array, indicesToProtect=None):
4545

4646
if len(self.indicesToProtect) == 0:
4747
self.indicesToProtect = None
48-
self.base.flags.writeable = True
48+
49+
#Note: no need to set self.base.flags.writeable = True anymore,
50+
# since this flag can only apply to a data owner as of numpy 1.16 or so.
51+
# Instead, we just copy the data whenever we return a readonly array.
52+
#Here, we just leave the writeable flag of self.base alone (either value is ok)
4953

5054
#Mimic array behavior
5155
def __pos__(self): return self.base
@@ -91,7 +95,8 @@ def __getattr__(self, attr):
9195
# set references to our memory as (entirely) read-only
9296
ret = getattr(self.__dict__['base'], attr)
9397
if isinstance(ret, _np.ndarray) and ret.base is self.base:
94-
ret.flags.writeable = False
98+
ret = _np.require(ret.copy(), requirements=['OWNDATA']) # copy to a new read-only array
99+
ret.flags.writeable = False # as of numpy 1.16, this can only be set by OWNER
95100
return ret
96101

97102
def __getslice__(self, i, j):
@@ -172,9 +177,14 @@ def __getitem__(self, key):
172177
ret = _np.ndarray.__getitem__(self.base, key)
173178

174179
if not _np.isscalar(ret):
175-
ret = ProtectedArray(ret)
176-
ret.base.flags.writeable = writeable
177-
ret.indicesToProtect = new_indicesToProtect
180+
if writeable: # then some of the indices are writeable
181+
ret = ProtectedArray(ret)
182+
ret.indicesToProtect = new_indicesToProtect
183+
else:
184+
ret = _np.require(ret.copy(), requirements=['OWNDATA']) # copy to a new read-only array
185+
ret.flags.writeable = False # a read-only array
186+
ret = ProtectedArray(ret) # return a ProtectedArray that is read-only
187+
178188
#print " writeable = ",ret.flags.writeable
179189
#print " new_toProtect = ",ret.indicesToProtect
180190
#print "<< END getitem"

0 commit comments

Comments
 (0)