FFT 分贝值不正确
FFT decibel value not correct
我正在研究thispost,有一个例子可以将7000个样本零填充到1000个样本信号!
所以我尝试编写下面的代码来模拟这种情况,但输出与 post 图像不匹配:
在post中,预期的输出图像如下:
但是我的输出图像是这样的:
显然:
- 信号分贝信息不匹配(峰值-15.96 vs. 11)。
- 我的输出中不存在这两个峰值频率。
我的完整代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.ticker import FuncFormatter, MultipleLocator
import scipy.fftpack
num = 1000
samplerate = 100*1000000
freq1 = 1*1000000
freq2 = 1.05*1000000
duration = num/samplerate
T = 1.0/samplerate
x = np.arange(0,num,1)*T
y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
fig,ax = plt.subplots(1,1,figsize=(8,6),constrained_layout=True)
M = 8000
x2 = np.arange(0,duration*8,T)
y2 = np.pad(y, (0, num*7), 'constant')
yfft = np.abs(scipy.fftpack.fft(y2,n=M))[:M//2]
freqs1 = np.fft.fftfreq(M,T)[:M//2]
freqs = np.arange(0, M)[:M//2]*(samplerate/M)
print(freqs[len(freqs)-1])
print(freqs1[len(freqs)-1])
ydb = 20*np.log10(yfft*2/M)
df = pd.DataFrame(list(zip(freqs,ydb)),columns=['freq','value'])
ax.plot(df['freq'],df['value'],marker='.')
print("signal length:%d,frequency length:%d"%(len(y2),len(freqs)))
xmin = 500000
xmax = 1500000
df = df.query('freq > %d and freq < %d'%(xmin,xmax))
ymin = df['value'].min()
ymax = df['value'].max()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.set_xticks(np.append(ax.get_xticks(),[xmin,xmax]))
ax.set_yticks(np.append(ax.get_yticks(),[ymin,ymax]))
ax.xaxis.set_major_formatter(FuncFormatter(
lambda val,pos: '{:.1f}$MHz$'.format(val/1000000)
))
ax.tick_params(axis='x', rotation=45)
ax.grid()
print(freqs[1] - freqs[0])
plt.show()
为了看到两个峰,post 的作者在图的标题中声明您 posted:
Power spectrum - 7000 Time Samples and 1000 Zero Padding / 8000 FFT points
你的 y2
只有 1000 个支持样本,7000 个填充样本。我这样做了:
# Make the signal: 7000 points.
x = np.arange(0, num*7, 1) * T
y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
# Pad the signal with 1000 points.
x2 = np.arange(0, num*8, 1) * T
y2 = np.pad(y, (0, num), 'constant')
现在信号看起来正确(绘制 y2
与 x2
):
功率应该是10分贝;我认为只需要为这个更长的信号更新乘数,例如:
ydb = 20*np.log10(yfft*7/M)
我最终得到:
我正在研究thispost,有一个例子可以将7000个样本零填充到1000个样本信号!
所以我尝试编写下面的代码来模拟这种情况,但输出与 post 图像不匹配:
在post中,预期的输出图像如下:
但是我的输出图像是这样的:
显然:
- 信号分贝信息不匹配(峰值-15.96 vs. 11)。
- 我的输出中不存在这两个峰值频率。
我的完整代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.ticker import FuncFormatter, MultipleLocator
import scipy.fftpack
num = 1000
samplerate = 100*1000000
freq1 = 1*1000000
freq2 = 1.05*1000000
duration = num/samplerate
T = 1.0/samplerate
x = np.arange(0,num,1)*T
y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
fig,ax = plt.subplots(1,1,figsize=(8,6),constrained_layout=True)
M = 8000
x2 = np.arange(0,duration*8,T)
y2 = np.pad(y, (0, num*7), 'constant')
yfft = np.abs(scipy.fftpack.fft(y2,n=M))[:M//2]
freqs1 = np.fft.fftfreq(M,T)[:M//2]
freqs = np.arange(0, M)[:M//2]*(samplerate/M)
print(freqs[len(freqs)-1])
print(freqs1[len(freqs)-1])
ydb = 20*np.log10(yfft*2/M)
df = pd.DataFrame(list(zip(freqs,ydb)),columns=['freq','value'])
ax.plot(df['freq'],df['value'],marker='.')
print("signal length:%d,frequency length:%d"%(len(y2),len(freqs)))
xmin = 500000
xmax = 1500000
df = df.query('freq > %d and freq < %d'%(xmin,xmax))
ymin = df['value'].min()
ymax = df['value'].max()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.set_xticks(np.append(ax.get_xticks(),[xmin,xmax]))
ax.set_yticks(np.append(ax.get_yticks(),[ymin,ymax]))
ax.xaxis.set_major_formatter(FuncFormatter(
lambda val,pos: '{:.1f}$MHz$'.format(val/1000000)
))
ax.tick_params(axis='x', rotation=45)
ax.grid()
print(freqs[1] - freqs[0])
plt.show()
为了看到两个峰,post 的作者在图的标题中声明您 posted:
Power spectrum - 7000 Time Samples and 1000 Zero Padding / 8000 FFT points
你的 y2
只有 1000 个支持样本,7000 个填充样本。我这样做了:
# Make the signal: 7000 points.
x = np.arange(0, num*7, 1) * T
y = np.sin(2*np.pi*freq1*x) + np.sin(2*np.pi*freq2*x)
# Pad the signal with 1000 points.
x2 = np.arange(0, num*8, 1) * T
y2 = np.pad(y, (0, num), 'constant')
现在信号看起来正确(绘制 y2
与 x2
):
功率应该是10分贝;我认为只需要为这个更长的信号更新乘数,例如:
ydb = 20*np.log10(yfft*7/M)
我最终得到: