理解周期图

信息处理 周期性的 周期图
2022-01-29 19:12:20

我正在尝试通过遵循此处的 astropy Lomb-scargle 周期图教程来使用周期图来判断信号何时是周期性的。

http://docs.astropy.org/en/stable/stats/lombscargle.html

我模拟了一些数据,一个是正弦曲线(周期 = 200),另一个是斜高斯曲线(即单个瞬态事件)。希望周期图能够为周期性对象挑选周期,并为瞬态给出一个周期,这意味着窗口中发生了单个事件。

不幸的是,结果根本没有意义。我在最后附上了代码和下面生成的数字。由于我的模拟中存在随机噪声,每个结果都不同,我在下面提供了两个结果示例。我使用上面链接中概述的相同方法,我们LombScargle.model()在最佳拟合频率上使用函数frequency[argmax[power]]

红线是我模拟数据的真实函数。绿色是周期图中的最佳拟合。右侧图是周期图中的 PSD。

示例 1 在此处输入图像描述

在这里,我们可以看到挑选出的正弦曲线(右上图)的最佳拟合频率是 0.105(即 9-10 天的周期),这并不接近于 0.05 的频率,我期望的周期为 200 天,但是当我将这个 0.105 的最佳拟合频率提供给 lomb-scargle 模型拟合器时,会得出一条周期为 200 天的完美匹配的周期曲线?

这根本不符合逻辑。

示例 2

在此处输入图像描述

在这里我再次运行代码,这一次结果被切换了?它适合瞬态的一个非常大的周期,因此我可以自信地说这是一个单一的瞬态事件,但正弦拟合很糟糕。最佳频率仍然是 0.105(周期 = 10),但 lomb-scargle 模型拟合器覆盖了似乎有 60 天周期的东西,这是错误的吗?

如果我做错了什么,我可以得到澄清吗?有人告诉我,周期图实际上是用于像这样的不均匀采样数据的事实上的工具……结果似乎有一半时间很糟糕。

澄清我的问题

  1. 能否解释在第一个图中,我输入 astropy lomb-scargle 模型拟合器的最佳拟合频率 0.105 以某种方式创建了频率为 0.05 的正确匹配正弦曲线?解释是什么?

  2. 当我只期望 1 时,为什么示例 1 中的周期图的右上角有 5 个强峰?中间两个接近0.05的真实值(分别为0.045和0.055)

这是用于模拟和绘制数据的短代码

import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as sc
from astropy.stats import LombScargle
import math


#simulate parameters
data_range = [i for i in range(1,1001)]
number_of_samples = 50
gauss_skew = sc.skewnorm.pdf
skew = -10
period = 200
location = data_range[int(len(data_range)/2)]


y1= [(2 * (1. + np.sin(2. * np. pi * x/period)) + np.random.normal(loc =0.0, scale = 0.5)) for x in data_range]
errors1 = [np.random.normal(loc = 0.0, scale = 1) for x in data_range]
y2 = [(1000* (gauss_skew(x,skew,loc=location ,scale = 50)) + np.random.normal(loc =0.0, scale = 1)) for x in data_range]
errors2 = [np.random.normal(loc = 0.0, scale = 1) for x in data_range]

sample_rate = int(len(data_range)/number_of_samples)# To thin the data a bit
y1 = y1[::sample_rate]
y2 = y2[::sample_rate]
errors1 = errors1[::sample_rate]
errors2 = errors2[::sample_rate]
x1= x2 =data_range[::sample_rate]

truth1 = [2* (1. + np.sin(2. * np. pi * x/period)) for x in data_range]
truth2 = [1000 * (gauss_skew(x,-10,loc=location ,scale = 50)) for x in data_range]

truths = [truth1,truth2]
x= [x1,x2]
y=[y1,y2]
errors = [errors1,errors2]

fig,ax  = plt.subplots(nrows=2,ncols=2)

ax[0][0].errorbar(x1,y1,yerr=errors1,fmt='o')
ax[0][0].set_xlabel('time')
ax[1][0].errorbar(x2,y2,yerr=errors2,fmt='o')
ax[1][0].set_xlabel('time')
ax[0][1].set_xlabel('frequency')
ax[1][1].set_xlabel('frequency')


for i in range(0,2):
    frequency, power = LombScargle(x[i],y[i],errors[i]).autopower()
    #Get the best fit frequency as in the tutorial
    best_frequency = frequency[np.argmax(power)]
    print('best frequency:',best_frequency)
    t_fit = np.linspace(x[i][0], math.floor(x[i][-1]),num =50)

    #Fit the best fit frequency
    #plot the best best model based on the best fit
    y_fit = LombScargle(x[i], y[i], errors[i]).model(t_fit, best_frequency)
    ax[i][0].plot(t_fit,y_fit,'g')
    ax[i][0].plot(data_range,truths[i],'r')

    #Plot the PSD
    ax[i][1].plot(frequency,power)
    ax[i][1].axvline(x=best_frequency,color='black', ls='--')
plt.show()
2个回答

我将它交叉发布到天文学堆栈交换,我收到了令人满意的答案。有兴趣的可以往下看。

https://astronomy.stackexchange.com/questions/29956/making-sense-of-the-lomb-scargle-periodogram

我认为问题在于您对生成的数据进行下采样,即所谓的“精简数据”。通过不首先对其进行低通滤波,您会产生大量的别名,尤其是,因为您正在按 20 倍进行下采样!

在您的第一个示例中,别名似乎不是问题,因为 fitter 仍然会产生正确的结果,但是您的第二个示例似乎被别名弄乱了。

因子 20 还解释了频率和产生的正弦之间的明显差异。10d20=200d