The range of converting numbers into squares from (-Pi, Pi) to (0, 2 * Pi)

This seems to be very simple, but I cannot figure out how to match the angles between -Pi and Pi in the range of 0 to 2Pi. I tried using np.select, but for some reason it freezes my program. I need angles in this range, since they will be used as training data for a neural network that cannot output negative numbers.

audio = wav.read('/home/chase/Desktop/ge.wav')[1].astype(np.float32) audio = np.mean(audio, 1) audio /= np.max(np.abs(audio)) audio = np.array([np.fft.rfft(audio[i:i + FRAME_SIZE]) for i in range(0, len(audio) - len(audio) % FRAME_SIZE, FRAME_SIZE)]) audio /= FRAME_SIZE audio_mag = np.abs(audio) audio_phase = np.angle(audio) #this line freezes the program audio_phase = np.select(audio_phase < 0 , 2 * np.pi + audio_phase, audio_phase) 

I need audio

+6
source share
3 answers

Say you have these angles:

 >>> angles = np.linspace(-np.pi, np.pi, 10) >>> angles array([-3.14159265, -2.44346095, -1.74532925, -1.04719755, -0.34906585, 0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265]) 

There are two possible ways to do this ...

  • Use numpy expressions to search for negative values ​​...

Those that are less than zero must be converted to the correct value. Something like that:

 >>> (2*np.pi + angles) * (angles < 0) + angles*(angles > 0) array([ 3.14159265, 3.83972435, 4.53785606, 5.23598776, 5.93411946, 0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265]) 

Remember that in numpy you can do boolean tests ... angles < 0 is a boolean array. However, 1*(angles < 0) is a numeric array where True values ​​are mapped to 1 , and False values ​​are mapped to 0 . You can combine two concepts to get an answer.

  1. You can simply admit that this is a mathematical expression that you are trying to solve:

Therefore, for this, just add 2*np.pi to everything and take the mod. This is exactly the same as finding "place units" or converting a number to an octal number, etc.

 >>> (angles + 2 * np.pi) % (2 * np.pi) array([ 3.14159265, 3.83972435, 4.53785606, 5.23598776, 5.93411946, 0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265]) 

Hope this helps.

+7
source

Here are a few different methods complete with timing:

 In [1]: import numpy as np; from numpy import linspace, pi In [2]: N=10000 In [3]: %timeit x=linspace(-pi, pi, N); np.where(x<0 , 2*pi+x, x) 10000 loops, best of 3: 79.1 Β΅s per loop In [4]: %timeit x=linspace(-pi, pi, N); np.select(x<0 , 2*pi+x, x) 1 loops, best of 3: 354 ms per loop In [5]: %timeit x=linspace(-pi, pi, N); x[x<0] += 2*pi 10000 loops, best of 3: 82.5 Β΅s per loop In [6]: %timeit x=linspace(-pi, pi, N); (x + 2*pi)*(x<0) + x*(x>=0) 10000 loops, best of 3: 149 Β΅s per loop In [7]: %timeit x=linspace(-pi, pi, N); (x + 2*pi)%(2*pi) 10000 loops, best of 3: 192 Β΅s per loop 

I find x[x<0] += 2*pi most readable, but where(x<0, x+2*pi, x) bit faster. The select form is by far the slowest.

For comparison, here is a simple linspace function on one computer:

 In [8]: %timeit x=linspace(-pi, pi, N) 10000 loops, best of 3: 35.9 Β΅s per loop 

Given that the program fails when choosing, rather than a much more expensive fft function, you may encounter a low level of memory with a paging array to disk (both x<0 and 2*pi+x generate arrays, plus you have the original x and the return value created by select ). If so, then you might be better off adjusting the phase by frame.

+5
source

You can try using map function with lambda

 >>>angles = np.linspace(-np.pi, np.pi, 10) array([-3.14159265, -2.44346095, -1.74532925, -1.04719755, -0.34906585, 0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265]) >>>map(lambda x: x if x > 0 else x + 2*np.pi, angles) [3.1415926535897931, 3.839724354387525, 4.5378560551852569, 5.2359877559829879, 5.9341194567807207, 0.34906585039886595, 1.0471975511965974, 1.7453292519943293, 2.4434609527920612, 3.1415926535897931] 
0
source

All Articles