I am new to python and I am trying to convert python 2 code I found on github (https://github.com/RDCEP/psims) into python 3. It went quite well, but now I am stuck with the following error message:
Traceback (most recent call last):
File "jsons2dssat.py", line 1600, in run
sfileoutput = SOLFileOutput(sfile, efile, use_ptransfer = pfcn)
File "jsons2dssat.py", line 1336, in init
if isMaskedArray(vl): vl[vl.mask] = -99
File "/conda/pSIMS/lib/python3.7/site-packages/numpy/ma/core.py", line 3348, in setitem
raise MaskError('Cannot alter the masked element.')
numpy.ma.core.MaskError: Cannot alter the masked element.
--
in the code source for numpy.ma.core it says:
if self is masked:
raise MaskError('Cannot alter the masked element.')
The code is
def __init__(self, soil_file, exp_file, use_ptransfer = True): # need experiment file to know which soil profiles to write
# load soil data
with nc(soil_file) as f:
soil_vars = setdiff1d(f.variables.keys(), f.dimensions.keys())
soil_attrs = f.ncattrs()
soil_ids = f.variables['soil_id'].long_name.split(', ')
soil_depths = f.variables['depth'][:]
nprofiles, ndepths = len(soil_ids), len(soil_depths)
self.soils = []
for i in range(nprofiles):
self.soils.append({})
for i in range(nprofiles):
soil_layers = []
for j in range(ndepths):
soil_layers.append({})
soil_layers[j]['sllb'] = str(soil_depths[j])
for var in soil_attrs:
self.soils[i][var] = f.getncattr(var)
for var in soil_vars:
v = f.variables[var]
if 'profile' in v.dimensions and 'depth' in v.dimensions: # layer parameter
for j in range(ndepths):
vl = v[i, j, 0, 0]
if isMaskedArray(vl): vl[vl.mask] = -99
I understand why the error is raised, but I have no idea how to solve this. I am using python 3.7 and numpy version 1.24.1. Any help much appreciated. Thank you!
CodePudding user response:
I see that
if self is masked:
raise MaskError('Cannot alter the masked element.')
in my setitem
. np.ma.masked
is a MaskedConstant
(documented)
If looks like vl = v[i, j, 0, 0]
, is an element of an array v
(unless the array is 5d).
If I make a 1d masked array, and test elements:
In [178]: m = np.ma.masked_array(np.arange(5.),[False, True,False,True,False])
In [179]: m
Out[179]:
masked_array(data=[0.0, --, 2.0, --, 4.0],
mask=[False, True, False, True, False],
fill_value=1e 20)
In [180]: [m[i] is np.ma.masked for i in range(5)]
Out[180]: [False, True, False, True, False]
however if I try to change a value: In [182]: m[1] Out[182]: masked In [183]: m[1]=-99 In [184]: m Out[184]: masked_array(data=[0.0, -99.0, 2.0, --, 4.0], mask=[False, False, False, True, False], fill_value=1e 20)
Note that m[1]
is no longer masked.
In [185]: np.ma.isMaskedArray(m[1])
Out[185]: False
In [186]: np.ma.isMaskedArray(m[3])
Out[186]: True
Now if instead of doing m[3]=-99
, let's assign m[3]
to a variable, and try to change that:
In [188]: m1 = m[3]
In [189]: m1
Out[189]: masked
In [190]: m1[m1.mask]
Out[190]:
masked_array(data=[--],
mask=[ True],
fill_value=1e 20,
dtype=float64)
In [191]: m1[m1.mask] = -99
---------------------------------------------------------------------------
MaskError Traceback (most recent call last)
Cell In[191], line 1
----> 1 m1[m1.mask] = -99
File ~\anaconda3\lib\site-packages\numpy\ma\core.py:3348, in MaskedArray.__setitem__(self, indx, value)
3340 """
3341 x.__setitem__(i, y) <==> x[i]=y
3342
(...)
3345
3346 """
3347 if self is masked:
-> 3348 raise MaskError('Cannot alter the masked element.')
3349 _data = self._data
3350 _mask = self._mask
MaskError: Cannot alter the masked element.
m1[...] = -99
doesn't work either.
If instead of assigning m1
, I tried to modify m[i]
directly I can change all masked values:
In [195]: for i in range(5):
...: if np.ma.isMaskedArray(m[i]): m[i]=-99
...:
In [196]: m
Out[196]:
masked_array(data=[0.0, -99.0, 2.0, -99.0, 4.0],
mask=[False, False, False, False, False],
fill_value=1e 20)
But I wonder if you just need to use filled
?
In [207]: m
Out[207]:
masked_array(data=[0.0, --, 2.0, --, 4.0],
mask=[False, True, False, True, False],
fill_value=1e 20)
In [208]: m2 = m.filled(-99)
In [209]: m2
Out[209]: array([ 0., -99., 2., -99., 4.])