从 CSD 查找二维空间谱的正确方法

2023-11-29

enter image description here

我尝试从上述方程中实现空间谱(附后)

其中kX,kY是k空间中的网格点, C(w,r) - 第 i 个和第 j 个传感器之间的互谱密度(这里是大小为 ns * ns > 传感器数量的矩阵)。 x、y 是传感器之间的距离。 (nk - kx、ky 的网格密度)

我寻找上述方程的合适的 python 实现。我有 34 个传感器,可以生成大小数据[row*column]=[n*34]。首先,我找到了每个传感器数据的交叉光谱密度(CSD)。然后对 CSD 值进行 2D DFT 以获得空间谱。

*)我不确定程序是否正确。 **) python的实现过程是否正确? ***)另外,如果有人提供一些相关的教程/链接,它也会对我有帮助。

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
import cmath

# Finding cross spectral density (CSD)
fs=500
def csdMat(data):
    rows, cols = data.shape
    total_csd = []
  
    for i in range(cols):
 
        for j in range(cols):
            f, Pxy = signal.csd(data[:,i], data[:,j], fs, nperseg=512)
            abs_csd = np.abs(Pxy)
            total_csd.append(abs_csd)                     # output as list
            csd_mat = np.array(total_csd)
    return csd_mat

## Spatial Spectra:- DFT of the csd along two dimension

def DFT2D(data):
    #data = np.asarray(data)
    dft2d = np.zeros((M,N), dtype=complex)
    for k in range(len(kx)):
        for l in range(len(ky)):
            sum_matrix = 0.0
            for m in range(M):
                for n in range(N):
                    e = cmath.exp(- 1j * ((kx[k] * dx[m]) / len(dx) + (ky[l] * dy[n]) / len(dy)))
                    sum_matrix +=  data[m,n] * e
            dft2d[k,l] = sum_matrix
    return dft2d

raw_data=np.reshape(np.random.rand(10000*34),(10000,34))

# Call the seismic array
#** Open .NPY files as an array 
#with open('res_array_1000f_131310.npy', 'rb') as f:
#    arr= np.load(f)
#raw_data = arr[0:10000, :]

#CSD of the seismic data
csd = csdMat(raw_data)
print('Shape of CSD data', csd.shape)

# CSD data of a specific frequency
csd_dat=csd[:, 11]  
fcsd = np.reshape(csd_dat, (-1, 34))
fcsd.shape

n = 34
f = 10  # frequency in Hz
c = 50  # wave speed 50, 80, 100, 200  m/s
k = 2.0*np.pi*f/c  # wavenumber
nx = n  # grid density
ny = n
kx = np.linspace(-k,k,nx)  # space vector
ky=  np.linspace(-k,k,ny)   # space vector

# Distance[Meter] between sensors 
x = [2.1,2.1,-0.7,-2.1,-2.1,-0.7,-0.7,0.6,-5.7,-8.5,-11.4,-7.7,-6.3,-3.5,-2.1,-3.4,5.4,-5.2,-8.9,-10,-10,5.4,5.4,-0.8,-3.6,-6.2,-6.8,-12.2,-17.1,-19,-18.6,-13.5,14.8,14.8]
y = [6.65,4.15,3.65,5.05,7.25,8.95,11.85,8.95,-2,-0.6,-0.9,1.25,2.9,0.9,-0.1,-1.4,9.2,5.2,4.8,6.1,8.9,13.3,17.1,17.9,13.8,-9.3,-5.2,-3.6,-3.6,-0.9,3.7,3.7,-1.8,5.7]

dx = np.array(x);  M = len(dx)
dy = np.array(y) ; N = len(dy)
X,Y = np.meshgrid(kx, ky)

dft = DFT2D(fcsd)  # Data or cross-correlation matrix
spec = dft.real    # Spectrum or 2D_DFT of data[real part]

spec = spec/spec.max()

plt.figure()
c = plt.imshow(spec, cmap ='seismic', vmin = spec.min(), vmax = spec.max(),
                 extent =[kx.min(), kx.max(), ky.min(), ky.max()],
                interpolation ='nearest', origin ='lower')
plt.colorbar(c)
plt.rcParams.update({'font.size': 18})
plt.xlabel("Wavenumber, $K_x$ [rad/m]", fontsize=18)
plt.ylabel("Wavenumber,$K_y$ [rad/m]", fontsize=18)
plt.title(f'Spatial Spectrum @10Hz', weight="bold")


#c = Wave Speed; 50, 80,100,200
cc = 2*np.pi*f /c *np.cos(np.linspace(0, 2*np.pi, 34)) 
cs = 2*np.pi*f /c *np.sin(np.linspace(0, 2*np.pi, 34))
plt.plot(cc,cs)
I want to generate the figure as Fig. 01 below Fig.01 However, by using improved code I get the figure with higher resolution as Fig. 02 which is different from Fig. 01. Fig.02

I've added another two figures to compare with the Fig. 01. When consider the range [-k, k], the plot looks like Fig. 03 Fig. 03 which is analogous [w.r.t. XY-axis] to Fig. 01, I think this figure is OK except some K-space missed. I hope here exist an issue that need to be fixed.

In Fig. 04, we consider the k-space range [-20k, 20k], which looks good but don't have similar axis as of Fig. 01. Fig. 04

I've put the update Figure as follows: Fig. 05 Can anyone help me to generate the figure 01 or similar type? I'm confused about the Figure 02. Can anybody help to make me understand? Thanks in advance.


在我看来,你正在放大中央瓣。这也可以解释为什么等级不会从 0 变为 1。

如果我改变这些行:

kx = np.linspace(-20*k,20*k,nx)  # space vector
ky=  np.linspace(-20*k,20*k,ny)   # space vector

然后我得到

My version of the picture

这看起来更接近您正在寻找的东西。

为了提高分辨率,我做了一些重写以获得这张新图片。请参阅下面更新的代码。

注意:我仍然不确定这是否正确。

Higher resolution version of image


我使用的代码

# Code from https://stackoverflow.com/questions/70768384/right-method-for-finding-2-d-spatial-spectrum-from-cross-spectral-densities

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
import cmath

# Set up data
# Distance[Meter] between sensors 
x = [2.1,2.1,-0.7,-2.1,-2.1,-0.7,-0.7,0.6,-5.7,-8.5,-11.4,-7.7,-6.3,-3.5,-2.1,-3.4,5.4,-5.2,-8.9,-10,-10,5.4,5.4,-0.8,-3.6,-6.2,-6.8,-12.2,-17.1,-19,-18.6,-13.5,14.8,14.8]
y = [6.65,4.15,3.65,5.05,7.25,8.95,11.85,8.95,-2,-0.6,-0.9,1.25,2.9,0.9,-0.1,-1.4,9.2,5.2,4.8,6.1,8.9,13.3,17.1,17.9,13.8,-9.3,-5.2,-3.6,-3.6,-0.9,3.7,3.7,-1.8,5.7]

if (len(x) != len(y)):
    raise Exception('X and Y lengthd differ')

n = len(x)
dx = np.array(x);  M = len(dx)
dy = np.array(y) ; N = len(dy)

np.random.seed(12345)
raw_data=np.reshape(np.random.rand(10000*n),(10000,n))

f = 10  # frequency in Hz
c = 50  # wave speed 50, 80, 100, 200  m/s
k = 2.0*np.pi*f/c  # wavenumber
kx = np.linspace(-20*k,20*k,n*10)  # space vector
ky=  np.linspace(-20*k,20*k,n*10)   # space vector


# Finding cross spectral density (CSD)
fs=500
def csdMat(data):
    rows, cols = data.shape
    total_csd = []
  
    for i in range(cols):
        for j in range(cols):
            f, Pxy = signal.csd(data[:,i], data[:,j], fs, nperseg=512)
            #real_csd = np.real(Pxy)
            total_csd.append(Pxy)                     # output as list
            
    return np.array(total_csd)

## Spatial Spectra:- DFT of the csd along two dimension

def DFT2D(data):
    #data = np.asarray(data)
    dft2d = np.zeros((len(kx),len(ky)), dtype=complex)
    for k in range(len(kx)):
        for l in range(len(ky)):
            sum_matrix = 0.0
            for m in range(M):
                for n in range(N):
                    e = cmath.exp(- 1j * ((kx[k] * dx[m]) / len(dx) + (ky[l] * dy[n]) / len(dy)))
                    sum_matrix +=  data[m,n] * e
            dft2d[k,l] = sum_matrix
    return dft2d


# Call the seismic array
#** Open .NPY files as an array 
#with open('res_array_1000f_131310.npy', 'rb') as f:
#    arr= np.load(f)
#raw_data = arr[0:10000, :]

#CSD of the seismic data
csd = csdMat(raw_data)
print('Shape of CSD data', csd.shape)

# CSD data of a specific frequency
csd_dat=csd[:, 11]  
fcsd = np.reshape(csd_dat, (-1, n))

dft = DFT2D(fcsd)  # Data or cross-correlation matrix
spec = np.abs(dft) #dft.real    # Spectrum or 2D_DFT of data[real part]

spec = spec/spec.max()

plt.figure()
c = plt.imshow(spec, cmap ='seismic', vmin = spec.min(), vmax = spec.max(),
                 extent =[kx.min(), kx.max(), ky.min(), ky.max()],
                interpolation ='nearest', origin ='lower')
plt.colorbar(c)
plt.rcParams.update({'font.size': 18})
plt.xlabel("Wavenumber, $K_x$ [rad/m]", fontsize=18)
plt.ylabel("Wavenumber,$K_y$ [rad/m]", fontsize=18)
plt.title(f'Spatial Spectrum @10Hz', weight="bold")
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 CSD 查找二维空间谱的正确方法 的相关文章

随机推荐