Home > front end >  How to solve numpy.ma.core.MaskError: Cannot alter the masked element?
How to solve numpy.ma.core.MaskError: Cannot alter the masked element?

Time:01-13

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.])
  • Related