带有FFT阵列的matplotlib pcolormesh中的越野行为?

时间:2014-07-16 09:51:24

标签: python matplotlib plot fft

我正在尝试重现它在维基百科条目中的Gabor变换的例子,我不知道它是否是一个bug或者我错过了什么。例子是计算正弦信号的Gabor变换:

The function

要绘制已排序的频率,我会创建一个未排序的轴。然后我使用网格来创建2D轴并用pcolormesh绘图。这是代码片段:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridsp

dt = 0.05
x = np.arange(-50.0,50.0,dt)
y = np.sin(2.0 * np.pi * x)
Nx = len(x)
w = np.fft.fftfreq(Nx,dt)

sigma = 1.0 / 3.0 
neg = np.where (x <= 0.0)
pos = np.where (x > 0.0)

T,W = np.meshgrid(x,w)
func = np.zeros(Nx)
tmp = np.zeros(Nx,dtype='complex64')
gabor = np.zeros((Nx,Nx))

func[neg] = np.sin(2.0 * np.pi * x[neg])
func[pos] = np.sin(4.0 * np.pi * x[pos])

for it in range(Nx):    
        tmp[:] = np.fft.fft(func[:] * np.exp( - ( x[it] - x[:] ) * ( x[it] - x[:] ) / 2.0 / sigma / sigma ) ) 

        gabor[:,it] = np.real(np.conj(tmp) * tmp)

fig = plt.figure(figsize=(20,10),facecolor='white')
gs = gridsp.GridSpec(2, 1)

ax1 = plt.subplot(gs[0,0])
ax1.plot(x,func,'r',linewidth=2)
ax1.axis('tight')
ax1.set_xticks(np.arange(min(x),max(x),1.) )
ax1.set_xlabel('time',fontsize=20)
ax1.set_ylabel(r'$\sin{time}$',fontsize=20)
ax1.set_xlim([-6.0,6.0])


ax2 = plt.subplot(gs[1,0])
surf1 = ax2.pcolormesh(T,W,gabor,shading='gouraud')
ax2.axis('tight')
ax2.set_xticks(np.arange(min(x),max(x),2.) )
ax2.set_yticks(np.arange(min(w),max(w),2.) )
ax2.set_xlabel('time',fontsize=20)
ax2.set_ylabel('frequency',fontsize=20)
ax2.set_xlim([-6.0,6.0])
ax2.set_ylim([-4.0,4.0])

gs.tight_layout(fig)
plt.show()

这是我得到的数字,

Only negative frequencies. The lower part of the array is plotted

似乎情节的上半部分减少到零。如果我在创建变换和轴时使用fftshift尝试它,

for it in range(Nx):
        tmp[:] = np.fft.fftshift(np.fft.fft(func[:] * np.exp( - ( x[it] - x[:] ) * ( x[it] - x[:] ) / 2.0 / sigma / sigma ) ) )     


        gabor[:,it] = np.real(np.conj(tmp) * tmp)

T,W = np.meshgrid(x,np.fft.fftshift(w))

然后我得到这个数字:

Finally, the right figure

似乎pcolormesh例程不能颠倒数组,因为它通常在1D图中完成。有人知道为什么会这样做吗?

谢谢,

Alex

1 个答案:

答案 0 :(得分:3)

问题在于W。或实际上在w。绘制w时:

enter image description here

因此pcolormesh接收非单调Y坐标并感到困惑。如果你看一下pcolorpcolormesh的描述,很明显他们对非单调数据不能做任何合理的事情。

所以,你的gabor很好:

ax.imshow(gabor)

你可以看到:

enter image description here

如何解决这个问题有多种可能性。其中之一是将Wgabor同时馈送到fftshift,这样频率就会回滚到单调。或者 - 如果您想获得上面的数字(顶部的负频率),只需将最大频率添加到W的所有负值。

使用pcolormeshx代替wT提供W也可能更为清晰。


如果你想要性能,你可能会更好地使用imshow(当数据在两个维度中均衡时,可以使用它。唯一的小问题是范围的计算(实际上可能稍微偏差)在问题中。范围告诉最高,最低,最左边和最右边像素的外部石灰。然而,像素矢量只告诉像素的中心。

我们需要了解以下内容:

  • X方向上的点数(num_x
  • Y方向上的点数(num_y
  • 第一个和最后一个x样本(x0x1
  • 的值
  • 第一个和最后一个y样本的值(y0y1

之后我们可以使用imshow以正确的缩放比例显示数据:

dx = 1. * (x1 - x0) / (num_x-1)
dy = 1. * (y1 - y0) / (num_y-1)

ax.imshow(img, extent=[x0 - dx/2, x1 + dx/2, y0 - dy/2, y1 + dy/2], origin='lower', interpolation='nearest')

所以,应用于问题的数据:

gabor_shifted = np.fft.fftshift(gabor, axes=0)
w_shifted = np.fft.fftshift(w)

x0 = x[0]
x1 = x[-1]
w0 = w_shifted[0]
w1 = w_shifted[-1]

dx = 1.*(x1-x0) / (len(x) - 1)
dw = 1.*(w1-w0) / (len(w) - 1)

ax2.imshow(gabor_shifted, extent=[x0-dx/2, x1+dx/2, w0-dw/2, w1+dw/2], interpolation='nearest', origin='lower', aspect='auto')
ax2.grid('on', color='w')
ax2.ylim(-4,4)

给出:

enter image description here