Python 计算FFT振幅的不确定度
我的编程问题如下: 我想创建一个测量结果数组。每个结果都可以描述为正态分布,其平均值为测量结果本身,标准偏差为其不确定度 伪代码可以是:Python 计算FFT振幅的不确定度,python,numpy,fft,uncertainty,Python,Numpy,Fft,Uncertainty,我的编程问题如下: 我想创建一个测量结果数组。每个结果都可以描述为正态分布,其平均值为测量结果本身,标准偏差为其不确定度 伪代码可以是: x1 = N(result1, unc1) x2 = N(result2, unc2) ... x = array(x1, x2, ..., xN) 然后我想计算x的: 我想要的是,x中包含的测量不确定度通过FFT计算传播,因此f是振幅阵列及其不确定度,如下所示: f = (a +/- unc(a), b +/- unc(b), ...) 你能给我一个方
x1 = N(result1, unc1)
x2 = N(result2, unc2)
...
x = array(x1, x2, ..., xN)
然后我想计算x的:
我想要的是,x中包含的测量不确定度通过FFT计算传播,因此f是振幅阵列及其不确定度,如下所示:
f = (a +/- unc(a), b +/- unc(b), ...)
你能给我一个方法吗?通过离散傅里叶变换计算的每个傅里叶系数 数组的
x
是x
元素的线性组合;看见
上X_k的公式,
我会把它写成
X_k = sum_(n=0)^(n=N-1) [ x_n * exp(-i*2*pi*k*n/N) ]
(也就是说,X
是X
的离散傅里叶变换)
如果x_n是正态分布,平均μn和方差σn**2,
然后一点代数表明X_k的方差是和
x_n的方差
Var(X_k) = sum_(n=0)^(n=N-1) sigma_n**2
换句话说,每个傅里叶系数的方差是相同的;
它是x
中测量值的方差之和
使用您的符号,其中unc(z)
是z
的标准偏差
unc(X_0) = unc(X_1) = ... = unc(X_(N-1)) = sqrt(unc(x1)**2 + unc(x2)**2 + ...)
(请注意,X_k的大小分布是相同的。)
下面是一个演示此结果的脚本。在本例中,标准
x
值的偏差从0.01线性增加到0.5
import numpy as np
from numpy.fft import fft
import matplotlib.pyplot as plt
np.random.seed(12345)
n = 16
# Create 'x', the vector of measured values.
t = np.linspace(0, 1, n)
x = 0.25*t - 0.2*t**2 + 1.25*np.cos(3*np.pi*t) + 0.8*np.cos(7*np.pi*t)
x[:n//3] += 3.0
x[::4] -= 0.25
x[::3] += 0.2
# Compute the Fourier transform of x.
f = fft(x)
num_samples = 5000000
# Suppose the std. dev. of the 'x' measurements increases linearly
# from 0.01 to 0.5:
sigma = np.linspace(0.01, 0.5, n)
# Generate 'num_samples' arrays of the form 'x + noise', where the standard
# deviation of the noise for each coefficient in 'x' is given by 'sigma'.
xn = x + sigma*np.random.randn(num_samples, n)
fn = fft(xn, axis=-1)
print("Sum of input variances: %8.5f" % (sigma**2).sum())
print()
print("Variances of Fourier coefficients:")
np.set_printoptions(precision=5)
print(fn.var(axis=0))
# Plot the Fourier coefficient of the first 800 arrays.
num_plot = min(num_samples, 800)
fnf = fn[:num_plot].ravel()
clr = "#4080FF"
plt.plot(fnf.real, fnf.imag, 'o', color=clr, mec=clr, ms=1, alpha=0.3)
plt.plot(f.real, f.imag, 'kD', ms=4)
plt.grid(True)
plt.axis('equal')
plt.title("Fourier Coefficients")
plt.xlabel("$\Re(X_k)$")
plt.ylabel("$\Im(X_k)$")
plt.show()
打印输出为
Sum of input variances: 1.40322
Variances of Fourier coefficients:
[ 1.40357 1.40288 1.40331 1.40206 1.40231 1.40302 1.40282 1.40358
1.40376 1.40358 1.40282 1.40302 1.40231 1.40206 1.40331 1.40288]
正如预期的那样,傅里叶系数的样本方差为
所有(近似)与测量方差之和相同
下面是脚本生成的情节。黑钻石是最好的
单个x
向量的傅里叶系数。蓝色的圆点是蓝色的
x+噪声的800次实现的傅里叶系数
。你可以看到
每个傅里叶系数周围的点云大致对称
和所有相同的“尺寸”(当然,除了真正的系数,
在该图中显示为实轴上的水平线)
我不确定您是否能利用提供的数据实现自己的目标。当然你们可以对均值进行FFT,但对偏差进行FFT对我来说并没有意义。我不确定如何转换数据使其有意义。如果
x
值不相关,则fft高频部分的不确定性将毫无意义(无限不确定性)。事实上,取决于x
中的值和不确定度,fft的不确定度可能没有意义。fft取决于相邻值之间的差值。当前表示未污染的方式是,每个值完全独立于相邻值。我不认为你想做什么有一个解析解。你可以引导它,但我不确定结果会有多大意义。嗯,我的直觉完全错了。那会教我不经深思熟虑就直言不讳!回答得很好!我花了一段时间来说明这一点,因为我想明确一点:ax
方差的最一般形式不是(ax)^2
,而是(ax)(ax)*
,其中*表示复共轭。当ax
是真的时,这并不是一个问题,但在这里它很复杂,而且它是一个非常重要的区别。
Sum of input variances: 1.40322
Variances of Fourier coefficients:
[ 1.40357 1.40288 1.40331 1.40206 1.40231 1.40302 1.40282 1.40358
1.40376 1.40358 1.40282 1.40302 1.40231 1.40206 1.40331 1.40288]