0

I cannot figure out how to set the fill_value of a real masked array to be np.nan. The array is the result of the calculation of two complex maskedarrays. Somehow, the calculated array's fill_value always gets converted to a complex fill_value, when I want a real fill_value. Even if I explicitly set the fill_value, it won't get set to a float. This is triggering ComplexWarnings in my code because it drops the imaginary part later. I am OK with setting the ang.fill_value manually, but it doesn't work.

import numpy as np
ma1 = np.ma.MaskedArray([1.1+1j, 2.2-1j])
ma2 = np.ma.MaskedArray([2.2+1j, 3.3+1j])
ma1.fill_value = np.nan + np.nan*1j
ma2.fill_value = np.nan + np.nan*1j
ang = np.ma.angle(ma1/ma2, deg=True)
ang.fill_value = np.nan
print(ang.fill_value)
<prints out (nan+0j)>
jbiz
  • 43
  • 5

1 Answers1

0

First, I haven't worked with angle (ma or not), and only played with np.ma on and off, mainly for SO questions.

np.angle is python code; np.ma.angle is produced by a generic wrapper on np.angle.

Without studying those, let's experiement.

Your array ratio:

In [34]: ma1/ma2
Out[34]: 
masked_array(data=[(0.5856164383561644+0.18835616438356162j),
                   (0.526492851135408-0.46257359125315395j)],
             mask=[False, False],
       fill_value=(nan+nanj))

The non-ma version:

In [35]: (ma1/ma2).data
Out[35]: array([0.58561644+0.18835616j, 0.52649285-0.46257359j])

or

In [36]: np.asarray(ma1/ma2)
Out[36]: array([0.58561644+0.18835616j, 0.52649285-0.46257359j])

The angle:

In [37]: np.ma.angle(ma1/ma2, deg=True)
Out[37]: 
masked_array(data=[17.829734225677196, -41.30235354815481],
             mask=[False, False],
       fill_value=(nan+nanj))

The data dtype looks fine, but the fill dtype is complex. Without ma, it's still masked, but with a different fill, and a simple mask:

In [38]: np.angle(ma1/ma2, deg=True)
Out[38]: 
masked_array(data=[ 17.82973423, -41.30235355],
             mask=False,
       fill_value=1e+20)

If we give it the "raw" data:

In [40]: np.angle((ma1/ma2).data, deg=True)
Out[40]: array([ 17.82973423, -41.30235355])

np.ma is not heavily used, so I'm not surprised that there are bugs in details like this, passing the fill and mask through. Especially in a function like this that can take a complex argument, but returns a real result.

If I don't fiddle with the fill values,

In [41]: ma1 = np.ma.MaskedArray([1.1+1j, 2.2-1j])
    ...: ma2 = np.ma.MaskedArray([2.2+1j, 3.3+1j])

In [42]: ma1/ma2
Out[42]: 
masked_array(data=[(0.5856164383561644+0.18835616438356162j),
                   (0.526492851135408-0.46257359125315395j)],
             mask=[False, False],
       fill_value=(1e+20+0j))

In [43]: np.ma.angle(ma1/ma2, deg=True)
Out[43]: 
masked_array(data=[17.829734225677196, -41.30235354815481],
             mask=[False, False],
       fill_value=1e+20)

The angle fill is float.

Casting (nan+nanj) to float might be producing some errors or warnings that it doesn't get with (1e+20+0j). Again we'd have to examine the code.

hpaulj
  • 221,503
  • 14
  • 230
  • 353