Ваша цель - восстановить спектральную информацию из «слишком короткого» окна, т. Е. << sample_rate / interval_of_interest, окно выглядит амбициозным. </p>
Даже в самом простом случае (чистый синусоидальный сигнал, ваш пример) просмотр данныхочень похоже на прямую линию (левая панель внизу).Только после снятия тренда мы можем увидеть небольшую кривизну (справа внизу, обратите внимание на очень маленькие значения y), и это все, что может пройти любой гипотетический алгоритм.В частности, FT --- насколько я вижу - не будет работать.

Если нам очень повезет, есть один путьвыход: сравнение производных.Если у вас синусоидальный сигнал со смещением - как f = c + sin(om * t
´ ---, то первая и третья производные будут om * cos(om * t)
и -om^3 * cos(om * t)
´´.Если сигнал достаточно простой и чистый, его можно использовать вместе с надежным числовым дифференцированием для восстановления частоты омега.
В демонстрационном коде ниже я использую фильтр SavGol для получения производных при избавлении от некоторой высокой частотышум (синяя кривая ниже), который был добавлен к сигналу (оранжевая кривая).Могут существовать и другие (лучшие) методы численного дифференцирования.

Пример выполнения:
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}")