0

A small intro to my question. I want to plot a sound file with numpy in dB. Just doing 20 * np.log10(arr) doesn't work because of negative numbers. So I was looking into using np.where(). because np.where() is part of ufunc I just want to do it in that way (easier and more readable than using brackets).

I had some difficulties with it (unexpected results with a small test of random numbers). So I updated to latest version of numpy (was 1.18.x and is now 1.19.1).
Also I updated Spyder to 4.1.4.

So I did the following steps in the console for checking. I also added comments for some steps.

In [1]: import numpy as np

In [2]: a = np.round(np.random.rand(10) * 3, 0)

In [3]: a
Out[3]: array([2., 1., 2., 1., 1., 3., 2., 0., 2., 1.])

In [4]: tf = np.where(a==2, True, False)

In [5]: b = np.power(a,3, where=np.where(a==2, True, False))
In [6]: b
Out[6]: 
array([8.        , 1.42180731, 8.        , 1.31799691, 1.01436297,
       2.82985094, 8.        , 0.35036821, 8.        , 0.73520376])

In [7]: np.power(a,3, where=tf)
Out[7]: array([8., 1., 8., 1., 1., 3., 8., 0., 8., 1.])

In[8]: np.power(a,3, where=np.where(a==2, True, False))
Out[8]: array([8., 1., 8., 1., 1., 3., 8., 0., 8., 1.])

So when just calculating in the console it looks fine, but when using a variable the original values messed up.

In[9]: b=np.power(a,3, where=tf)

In[10]: b
Out[10]: 
array([8.        , 1.42180731, 8.        , 1.31799691, 1.01436297,
       2.82985094, 8.        , 0.35036821, 8.        , 0.73520376])

In[11]: np.log10(a, where=np.where(a>2, True, False))
Out[11]: 
array([8.        , 1.42180731, 8.        , 1.31799691, 1.01436297,
       0.47712125, 8.        , 0.35036821, 8.        , 0.73520376])

Because of weird results I checked if a is still right

In[12]: a  # Check if a still right
Out[12]: array([2., 1., 2., 1., 1., 3., 2., 0., 2., 1.])

Looks like it is. So I tried np.log10() next. Check what happens:

In[13]: np.log10(a, where=np.where(a>2, True, False))
Out[13]: 
array([2.        , 1.        , 2.        , 1.        , 1.        ,
       0.47712125, 2.        , 0.        , 2.        , 1.        ])

In[14]: c = np.log10(a, where=np.where(a>2, True, False))

In[15]: c
Out[15]: 
array([2.        , 1.        , 2.        , 1.        , 1.        ,
       0.47712125, 2.        , 0.        , 2.        , 1.        ])

somehow with c (log10) everything works / looks fine. So I removed b (I use spyder so I removed it from the variable explorer). Then I recreated b

In[16]: b = np.power(a, 3, where=np.where(a==2, True, False))

In[17]: b
Out[17]: array([8., 1., 8., 1., 1., 3., 8., 0., 8., 1.])

In[18]: b1 = np.power(a, 3, where=tf)

In[19]: b1
Out[19]: 
array([8.00000000e+000, 1.82804289e-322, 8.00000000e+000, 0.00000000e+000,
       0.00000000e+000, 6.52741159e-038, 8.00000000e+000, 7.63251534e+169,
       8.00000000e+000, 1.23967276e+224])

So I can't follow why this is the case. Did I do something wrong? (If yes please explain). Is this a bug in Numpy?

Edit: I have occurence on multiple laptops. So i created a mini script what should do the trick if it is on your pc / laptop. One adition before the script i use anaconda on all my machines for if that matters.

a = np.round(np.random.rand(10) * 3, 0)
tf = np.where(a==2, True, False)
b = np.power(a, 3, where=np.where(a==2, True, False))
b1 = np.power(a, 3, where=tf)
c = np.log10(a, where=np.where(a>2, True, False))

bits = 16
linarr = np.arange(2 ** bits) - 2 ** (bits - 1)
logarr = np.copy(linarr)
logarr = 20 * np.log10(logarr, where=np.where(linarr > 0, True, False))

I would expect that at least for the logarr i get something in the following direction array([-32768, -32767,-32766, ... , 0, ... 90.3085, 90.3087]) but i get array([1.76e-314, 1.72-314, 2.12e-312, ... , 0, ... 90.3085, 90.3087])

Jan-Bert
  • 921
  • 4
  • 13
  • 22
  • 1
    I can't reproduce the issue; maybe you should write out your entire code in one block so you/we can be sure the inputs and outputs are as you expect – Tom Aug 25 '20 at 13:13
  • I cleared the variable explorer. redo the previous comments as described here both from console and also from script and now averything looks oke. I can't explain it. I will try on another computer... and if same result i close this question. – Jan-Bert Aug 25 '20 at 14:19
  • You need to use the `out` parameter along with the `where`. – hpaulj Aug 25 '20 at 14:22
  • Could you get the dB by taking the magnitude a fourier series? Then you won't have issues with negative numbers? I guess this would give you dB per frequency, so you might need some sort of aggregate like maybe max. – Dan Aug 25 '20 at 14:24
  • If you don't provide an `out` array, `power` creates a `np.empty` array, and writes the `where` selection to it. That means the ~where values will be 'random'. – hpaulj Aug 26 '20 at 19:25

0 Answers0