I have been trying to find FFT transform of .wav files. My initial program is (For an AMplitude - TIme Plot)
data_dir = 'C:/Users/asus/Desktop/Song_Test/Split/Done1.wav'
audio1, sfreq = lr.load(data_dir)
len(audio1), sfreq
Duration = len(audio1)/sfreq
print(Duration, " seconds")
time = np.arange(0, len(audio1)) / sfreq
fig, ax = plt.subplots()
ax.plot(time, audio1)
ax.set(xlabel='Time (s)', ylabel='Sound Amplitude')
plt.show()
Here is the function I have till now programed.
import scipy
def fft_plot(audio, sampling_rate):
n = int(len(audio))
T = 1 / sampling_rate
yf = scipy.fft.fft(audio)
print(n, T)
xf = np.linspace(0.0, 1.0/(2.0*T), n/2.0)
fig, ax = plt.subplot()
ax.plot(xf, 2.0/n * np.abs(yf[:n//2]))
plt.grid()
plt.xlabel("Freq")
plt.ylabel("Magnitude")
return plt.show()
The moment I call this module, using fft_plot(audio1, sfreq)
The following error pops up
Traceback (most recent call last):
File "C:\Users\asus\anaconda3\envs\untitled\lib\site-packages\numpy\core\function_base.py", line 117, in linspace
num = operator.index(num)
TypeError: 'float' object cannot be interpreted as an integer
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/asus/PycharmProjects/untitled/Librosa_level2.py", line 92, in <module>
fft_plot(audio1, sfreq)
File "C:/Users/asus/PycharmProjects/untitled/Librosa_level2.py", line 59, in fft_plot
xf = np.linspace(0.0, 1.0/(2.0*T), n//2.0)
File "<__array_function__ internals>", line 6, in linspace
File "C:\Users\asus\anaconda3\envs\untitled\lib\site-packages\numpy\core\function_base.py", line 121, in linspace
.format(type(num)))
TypeError: object of type <class 'float'> cannot be safely interpreted as an integer.
How can I sort out this float problem, kindly help me?
The third argument to:
xf = np.linspace(0.0, 1.0/(2.0*T), n/2.0)
that is n / 2.0 is supposed to be an integer:
num : int, optional
Number of samples to generate. Default is 50. Must be non-negative.
Check the docs for details.
Your n is an integer, but when you divide by 2.0 you can a fraction (real number). In Python terms (and vast majority of other programming languages), you will always get a float if you divide integer by a float.
Solution
Make sure you pass an even number, e.g.:
if n % 2 == 0:
pass # Even
else:
n -= 1
Related
This question already has answers here:
Numbers logarithmically spaced between two floats in numpy
(1 answer)
cannot be safely interpreted as an integer in python
(2 answers)
Closed 11 hours ago.
So I have tried to plot a log log curve of intensity vs frequency using planck equation with the help of python.But I didn't get the output.i don't know were are the errors exactly.
import matplotlib.pyplot as plt
import numpy as np
h = 6.626e-34
c = 3.0e+8
k = 1.38e-23
def planck(freq, T):
a = 2.0*h*freq**3
b = h*freq/(k*T)
intensity = a/ ( (c**2) * (np.exp(b) - 1.0) )
return intensity
frequency = np.logspace(10e+9, 10e+19, 1e10,endpoint=False)
# intensity at 3000K, 5000K, 10000K, 20000K,30000K
intensity3000 = planck(frequency, 3000.)
intensity5000 = planck(frequency, 5000.)
intensity10000 = planck(frequency, 10000.)
intensity20000 = planck(frequency, 20000.)
intensity30000=planck(frequency,30000.)
plt.loglog(frequency, intensity3000, 'k-')
# plot intensity3000 versus frequency in Hz as a black line
plt.loglog(frequency, intensity5000, 'y-')
# 5000K yellow line
plt.loglog(frequency, intensity10000, 'r-')
# 10000K red line
plt.loglog(frequency, intensity20000, 'g-')
# 20000K green line
plt.xlim([10e+9,10e+19])
plt.ylim([1,1e10])
# show the plot
plt.show()
I tried to run the program .but this is what I got:
> Traceback (most recent call last): File
> "/data/user/0/ru.iiec.pydroid3/app_HOME/planckplot.py", line 11, in
> <module> File "<__array_function__ internals>", line 5, in logspace
> File
> "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.9/site-packages/numpy/core/function_base.py",
> line 275, in logspace
> y = linspace(start, stop, num=num, endpoint=endpoint, axis=axis) File "<__array_function__ internals>", line 5, in linspace File
> "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.9/site-packages/numpy/core/function_base.py",
> line 120, in linspace
> num = operator.index(num) TypeError: 'float' object cannot be interpreted as an integer
I am really stuck here. What I am looking for is a log-log graph with B_nu in units of Joule/sec/meter^2/steradian/Hertz along the Y-axis and frequency in Hertz along the X-axis. The frequency range is taken from 10^9 Hz to 10^19 Hz.
Ps:I have only beginner level python knowledge.
I'm trying to do some plots of some symbolic data. I have some expression from a regression in the form:
expr = '(((((((((1.0)*(2.0)))-(ER)))-(-0.37419122066665467))*0.006633039574629684)*(0.006633039574629684*((((T)-(((1.0)+(P)))))-(P))))+0.1451920626347467)'
Where expr here is some prediction: f = f(T, P, ER). I know this particular example is a crazy expression but it's not really super important. Basically, supposing I have some dataframe, plotdata, I am trying to produce plots with:
import pandas
import sympy
import numexpr
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
expr = '(((((((((1.0)*(2.0)))-(ER)))-(-0.37419122066665467))*0.006633039574629684)*(0.006633039574629684*((((T)-(((1.0)+(P)))))-(P))))+0.1451920626347467)'
#Extract some data for surface plot but fixing one variable
plotdata = plotdata.loc[(plotdata.P == 1)]
#Extract data as lists for plotting
x = list(plotdata['T'])
y = list(plotdata['ER'])
f_real = list(plotdata['f'])
T_sympy = sympy.Symbol('T')
P_sympy = sympy.Symbol('P')
ER_sympy = sympy.Symbol('ER')
f_pred = numexpr.evaluate(expr)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(x,y,f_real, alpha = 0.3)
ax.plot_surface(x,y,f_pred)
However, I am getting an error with f_pred.
numexpr.evaluate(expr)
Traceback (most recent call last):
File "/anaconda3/lib/python3.7/site-packages/numexpr/necompiler.py", line 744, in getArguments
a = local_dict[name]
KeyError: 'ER'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<ipython-input-100-c765b0f1e5ce>", line 1, in <module>
numexpr.evaluate(expr)
File "/anaconda3/lib/python3.7/site-packages/numexpr/necompiler.py", line 818, in evaluate
arguments = getArguments(names, local_dict, global_dict)
File "/anaconda3/lib/python3.7/site-packages/numexpr/necompiler.py", line 746, in getArguments
a = global_dict[name]
KeyError: 'ER'
I am not super familiar with the numexpr package. However, I have been building this up from a 1D regression to now a 3D regression. ER was my 1D variable and was working fine. I have obviously slightly altered my code since the 1D case but I am still slightly at a loss as to why this error is popping up.
Any pointers would be greatly appreciated.
I've figured it out. Pretty silly error in the end. I needed to change:
#Extract data as lists for plotting
x = list(plotdata['T'])
y = list(plotdata['ER'])
to:
T = list(plotdata['T'])
ER = list(plotdata['ER'])
P = list(plotdata['P'])
i.e. numexpr.evaluate was looking for the input data, not the symbol!
I want to run scipy.signal.spectrogram in a loop with different nperseg, noverlap, and nfft each time. However I got:
TypeError: 'numpy.float64' object cannot be interpreted as an integer
Here is what I wrote:
Fs=10e3
data = testData(Fs)
r = []
for i in numpy.linspace(-0.4, 0.4, 9):
t_step = 0.5+i
f_step = 0.5-i
window_length = round(2 * t_step * Fs)
noverlap = round(t_step * Fs)
nfft = round(Fs / f_step)
arr_f, arr_t, fft = scipy.signal.spectrogram(data, Fs,
nperseg=window_length,
noverlap=noverlap,
nfft=nfft,
window='hanning')
r.append((arr_f, arr_t, fft))
where testData is copied from spectrogram documentation,
Scipy version is 1.1.0.
When I run the same code with constant, hardcoded t_step and f_step (without +/- i) everything is going smoothly in the whole range. So here are my questions:
Why is it not working?
Is there a way not to do it manually?
Full Tracback:
File "/Users/desktop/test.py", line 34, in main window='hanning')
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/signal/spectral.py", line 691, in spectrogram input_length=x.shape[axis])
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/signal/spectral.py", line 1775, in _triage_segments win = get_window(window, nperseg)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/scipy/signal/windows/windows.py", line 2106, in get_window return winfunc(*params)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/signal/windows/windows.py", line 786, in hann return general_hamming(M, 0.5, sym)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/signal/windows/windows.py", line 1016, in general_hamming return general_cosine(M, [alpha, 1. - alpha], sym)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/scipy/signal/windows/windows.py", line 116, in general_cosine w = np.zeros(M)
TypeError: 'numpy.float64' object cannot be interpreted as an integer
Your calculations of tstep and fstep produce float numbers, but scipy expects integers. You could for instance change your code to
arr_f, arr_t, fft = signal.spectrogram(data, Fs,
nperseg=window_length.astype(int),
noverlap=noverlap.astype(int),
nfft=nfft.astype(int),
window='hanning')
and scipy should work without problems. The .astype(int) just tweaks the numpy datatype, so instead of the float number 2000.0 scipy receives the integer number 2000. You can find more information about numpy data types in the official documentation.
A better way is of course to change your calculations, so that they produce integers numbers right away.
How to change the sampling rate of the data in the list result.
The current sampling rate is 256, but the desired sampling rate is 250.
Given:
result - a list of data with a sampling frequency of 256.
buf.size - the amount of signal in the channel
I tried to use scipy.signal.resample
from scipy import signal
result250 = signal.resample(result, buf.size, t=None, axis=0, window=None)
Traceback (most recent call last):
File "****.py", line 82, in <module>
result250 = signal.resample(result, buf.size, t=None, axis=0, window=None)
File "****\scipy\signal\signaltools.py", line 1651, in resample
X = fft(x, axis=axis)
File "****\scipy\fftpack\basic.py", line 249, in fft
tmp = _asfarray(x)
File "****\scipy\fftpack\basic.py", line 134, in _asfarray
return numpy.asfarray(x)
File "****\numpy\lib\type_check.py", line 105, in asfarray
return asarray(a, dtype=dtype)
File "****\numpy\core\numeric.py", line 482, in asarray
return array(a, dtype, copy=False, order=order)
ValueError: invalid literal for float(): 3.3126, 6.6876, 9.3126, 10.0627, ****
There is another option of linear interpolation (preferable), but I also can not figure out how to use.
scipy.interpolate.interp1d
You must record the time (in seconds - f.file_duration).
My answer:
x250 = np.arange(0, f.file_duration, 0.004) #frequency 250
x256 = np.arange(0, f.file_duration, 0.00390625) #frequency 256
result256 = np.interp(x256, x250, result)
I'll try here since the comments are small and I think I'll answer you:
As I was saying python lists are just that, lists, a collection of stuff (not necessarily numerical values) they don't know or care about what is inside and as such they don't know what sampling frequency even means.
Once you accept that the numbers in your list are just a representation of stuff you can sample them at whatever rate you want, it's just a matter of what you plot it against or how many values you consider per unit time.
import numpy as np
import matplotlib.pyplot as plt
data = [3.3126, 6.6876, 9.3126, 10.0627, 9.0626, 6.6876, 4.0626, 2.0625, 0.9375, 0.5625, 0.4375, 0.3125, 0.1875, 0.1875, 0.9375, 2.4375, 4.5626, 6.6876, 7.9376, 7.3126, 4.9376, 1.0625, -3.3126, -6.9376, -8.9376, -8.6876, -6.5626, -3.1875, 0.3125, 2.6875, 3.5626, 2.6875, 0.5625, -2.0625, -4.3126, -5.6876, -5.9376, -5.3126, -4.4376, -3.6876, -3.4376, -3.5626, -3.6876, -3.4376, -2.6875, -1.4375, -0.5625, -0.4375, -1.4375, -3.3126, -5.3126, -6.5626, -6.4376, -5.1876, -3.5626, -2.6875, -3.0625, -4.4376, -5.9376, -6.3126, -5.3126, -2.9375, -0.1875]
x256 = np.arange(0, 1, 1/256)[:len(data)]
x200 = np.arange(0, 1, 1/200)[:len(data)]
plt.plot(x256, data, label='x256')
plt.plot(x200, data, label='x200')
plt.legend()
Output:
Does this solve your resampling problem?
I'm getting this error message:
Traceback (most recent call last):
File "C:/Python27/test", line 14, in <module>
tck = interpolate.bisplrep(X,Y,Z)
File "C:\Python27\lib\site-packages\scipy\interpolate\fitpack.py", line 850, in bisplrep
raise TypeError('m >= (kx+1)(ky+1) must hold')
TypeError: m >= (kx+1)(ky+1) must hold
The error says that len(X) = m is <=(kx+1)(ky+1). How can I solve this? Here's my program:
import scipy
import math
import numpy
from scipy import interpolate
x= [1000,2000,3000,4000,5000,6000]
y= [1000]
Y = numpy.array([[i]*len(x) for i in y])
X = numpy.array([x for i in y])
Z = numpy.array([[21284473.74,2574509.71,453334.97,95761.64,30580.45,25580.60]])
tck = interpolate.bisplrep(x,y,Z)
print interpolate.bisplev(3500,1000,tck)
Have you read the documentation?
If you don't specify kx and ky, default values will be 3:
scipy.interpolate.bisplrep(x, y, z, w=None, xb=None, xe=None, yb=None, ye=None,
kx=3, ky=3, task=0, s=None, eps=1e-16, tx=None, ty=None,
full_output=0, nxest=None, nyest=None, quiet=1)
And of course, len(X) = 6 < 16 = (3+1)(3+1).
Even if you give kx=1 and ky=1 explicitly while calling, you have another problem. Your (x,y) values form a line, and you can not define a surface from a line. Therefore it gives you ValueError: Invalid inputs.. First, you should fix your data. If this is your data, as you have no variation in Y, skip it and do a spline in 2D with X and Z.