Numpy fft在短时间历史中寻找低频

Numpy fft在短时间历史中寻找低频,numpy,signal-processing,fft,Numpy,Signal Processing,Fft,我有一个信号历史的时间单位。我的主频是1/100时间单位。当我使用numpy的fft函数时,我的分辨率受到信号历史范围的限制如何在不损坏信号的情况下提高频率梳的分辨率? import numpy as np import matplotlib.pyplot as plt ''' I need to caputre a low-frequency oscillation with only 1 time unit of data. So far, I have not been able to f

我有一个信号历史的时间单位。我的主频是1/100时间单位。当我使用numpy的fft函数时,我的分辨率受到信号历史范围的限制如何在不损坏信号的情况下提高频率梳的分辨率?

import numpy as np
import matplotlib.pyplot as plt
'''
I need to caputre a low-frequency oscillation with only 1 time unit of data.
So far, I have not been able to find a way to make the fft resolution < 1.
'''
timeResolution = 10000
mytimes = np.linspace(0, 1, timeResolution)
mypressures = np.sin(2 * np.pi * mytimes / 100)


fft = np.fft.fft(mypressures[:])
T = mytimes[1] - mytimes[0]
N = mypressures.size

# fft of original signal is limitted by the maximum time
f = np.linspace(0, 1 / T, N)
filteredidx = f > 0.001
freq = f[filteredidx][np.argmax(np.abs(fft[filteredidx][:N//2]))]
print('freq bin is is ', f[1] - f[0]) # 1.0
print('frequency is ', freq) # 1.0
print('(real frequency is 0.01)')

你的目标是从“太短”中恢复光谱信息,也就是说,有一件事让我对你的答案感到困惑,如果关于
@kilojoules的事情我不这么认为的话。如果你看第一幅图,你可以任意插值,它看起来总是现在的样子。我相信你的问题很难解决。顺便说一句,很抱歉搞混了。这种不平等性的关键在于,以你感兴趣的频率,你的抽样远远少于一个完整的周期。在您的示例中,您拥有的是单个周期的百分之一。当然,这看起来就像一条直线。嗯,也许其他人能想出比我更好的主意。如果我是你,我肯定会把这个问题留一段时间。这就像说你只知道第一个字母,需要知道单词的其余部分是什么。如果你只知道“b”,你根本不知道这个词是“篮球”还是“假”或“蝙蝠”。对字母“b”进行进一步的数据分析不会让你达到目的。
import numpy as np
import matplotlib.pyplot as plt

timeResolution = 10000
mytimes = np.linspace(0, 1, timeResolution)
mypressures = np.sin(2 * np.pi * mytimes / 100)

# glue data to itself to make signal articicially longer
timesby = 1000
newtimes = np.concatenate([mytimes * ii for ii in range(1, timesby + 1)])
newpressures = np.concatenate([mypressures] * timesby)


fft = np.fft.fft(newpressures[:])
T = newtimes[1] - newtimes[0]
N = newpressures.size

# fft of original signal is limitted by the maximum time
f = np.linspace(0, 1 / T, N)
filteredidx = f > 0.001
freq = f[filteredidx][np.argmax(np.abs(fft[filteredidx][:N//2]))]
print('freq bin is is ', f[1] - f[0]) # 0.001
print('frequency is ', freq) # 1.0
print('(real frequency is 0.01)') 
Estimated freq clean signal:   0.009998
Estimated freq noisy signal:   0.009871
import numpy as np
import matplotlib.pyplot as plt
'''
I need to caputre a low-frequency oscillation with only 1 time unit of data.
So far, I have not been able to find a way to make the fft resolution < 1.
'''
timeResolution = 10000
mytimes = np.linspace(0, 1, timeResolution)
mypressures = np.sin(2 * np.pi * mytimes / 100)


fft = np.fft.fft(mypressures[:])
T = mytimes[1] - mytimes[0]
N = mypressures.size

# fft of original signal is limitted by the maximum time
f = np.linspace(0, 1 / T, N)
filteredidx = f > 0.001
freq = f[filteredidx][np.argmax(np.abs(fft[filteredidx][:N//2]))]
print('freq bin is is ', f[1] - f[0]) # 1.0
print('frequency is ', freq) # 1.0
print('(real frequency is 0.01)')

import scipy.signal as ss

plt.figure(1)
plt.subplot(121)
plt.plot(mytimes, mypressures)
plt.subplot(122)
plt.plot(mytimes, ss.detrend(mypressures))
plt.figure(2)

mycorrupted = mypressures + 0.00001 * np.random.normal(size=mypressures.shape)
plt.plot(mytimes, ss.detrend(mycorrupted))
plt.plot(mytimes, ss.detrend(mypressures))

width, order = 8999, 3
hw = (width+3) // 2
dsdt = ss.savgol_filter(mypressures, width, order, 1, 1/timeResolution)[hw:-hw]
d3sdt3 = ss.savgol_filter(mypressures, width, order, 3, 1/timeResolution)[hw:-hw]
est_freq_clean = np.nanmean(np.sqrt(-d3sdt3/dsdt) / (2 * np.pi))

dsdt = ss.savgol_filter(mycorrupted, width, order, 1, 1/timeResolution)[hw:-hw]
d3sdt3 = ss.savgol_filter(mycorrupted, width, order, 3, 1/timeResolution)[hw:-hw]
est_freq_noisy = np.nanmean(np.sqrt(-d3sdt3/dsdt) / (2 * np.pi))

print(f"Estimated freq clean signal: {est_freq_clean:10.6f}")
print(f"Estimated freq noisy signal: {est_freq_noisy:10.6f}")