繁体   English   中英

Numpy中的功率谱和数据自相关

[英]Power Spectrum and Autocorrelation of Data in Numpy

我对使用Python计算3D空间中的粒子系统(约100,000个)的功率谱感兴趣。 到目前为止,我发现Numpy中的一组函数( fftfftn ,..)计算离散傅里叶变换,其绝对值的平方是功率谱。 我的问题是有关如何表示我的数据的问题-实际上,答案很简单。

我拥有的数据结构是一个形状为( n ,2)的数组, n是我拥有的粒子数,每列代表n个粒子的x,y和z坐标。 我相信我应该使用它的函数fftn()函数,该函数接受n维数组的离散傅里叶变换-但它没有说明格式。 数据应如何表示为要馈入fftn的数据结构?

到目前为止,我已经尝试过测试该功能:

import numpy as np
import random
import matplotlib.pyplot as plt

DATA = np.zeros((100,3))

for i in range(len(DATA)):
    DATA[i,0] = random.uniform(-1,1)
    DATA[i,1] = random.uniform(-1,1)
    DATA[i,2] = random.uniform(-1,1)

FFT = np.fft.fftn(DATA)
PS = abs(FFT)**2

plt.plot(PS)
plt.show()

名为DATA的数组是一个模拟数组,最终它的形状将为100,000 x 3。 代码的输出给了我类似的东西: 在此处输入图片说明

如您所见,我认为这给了我3个1D功率谱(数据的每一列1个),但实际上我希望功率谱是半径的函数。

是否有人知道计算功率谱的任何建议或替代方法/封装(我什至愿意使用两点自相关函数)。

它与您设置的方式完全不同...

您需要一个函数,将其称为f(x, y, z) ,它描述空间中质量的密度。 在您的情况下,您可以将星系视为点质量,因此您将拥有以每个星系的位置为中心的增量功能。 借助此功能,您可以计算三维自相关,从中可以计算功率谱。

如果要使用numpy为您完成此操作,则首先必须离散化函数。 一个可能的模拟示例为:

import numpy as np
import matplotlib.pyplot as plt

space = np.zeros((100, 100, 100), dtype=np.uint8)

x, y, z = np.random.randint(100, size=(3, 1000))
space[x, y, z] += 1

space_ps = np.abs(np.fft.fftn(space))
space_ps *= space_ps

space_ac = np.fft.ifftn(space_ps).real.round()
space_ac /= space_ac[0, 0, 0]

现在space_ac拥有数据集的三维自相关函数。 这不是您想要的,要获得一维相关函数,您必须对原点周围的球形壳上的值求平均值:

dist = np.minimum(np.arange(100), np.arange(100, 0, -1))
dist *= dist
dist_3d = np.sqrt(dist[:, None, None] + dist[:, None] + dist)
distances, _ = np.unique(dist_3d, return_inverse=True)
values = np.bincount(_, weights=space_ac.ravel()) / np.bincount(_)

plt.plot(distances[1:], values[1:])

用这种方式自己做事还有另一个问题:当您如上所述计算功率谱时,数学上就好像您的三维数组环绕边界,即点[999, y, z][0, y, z]的邻居[999, y, z] [0, y, z] 因此,您的自相关可能会将两个非常遥远的星系显示为近邻。 解决此问题的最简单方法是,使数组沿每个维度大两倍,用额外的零填充,然后丢弃多余的数据。

或者,您可以将scipy.ndimage.filters.correlatemode='constant'来为您完成所有肮脏的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM