如何根据ylim缩放颜色条

3

我正在使用matplotlib的specgram函数绘制我的数据的频谱图。

Pxx, freqs, bins= mlab.specgram(my_data,NFFT=nFFT,Fs=Fs,detrend=mlab.detrend_linear,noverlap=n_overlap,pad_to=p_to,scale_by_freq=True)

参考一下,以上“freqs”、“bins”(即时间)和“Pxx”的形状分别为(1025,),(45510,)和(1025,45510)。

在这里,我已经定义了函数参数。

Fs = 10E6      # Sampling Rate
w_length= 256      # window length
nFFT=2 * w_length
n_overlap=np.fix(w_length/2)
p_to = 8 *w_length

这个图的频率范围(y轴)从0到5E6 Hz。当我绘制它时,我想查看不同的频率范围,例如100E3 Hz到1E6。如果我更改图的ylim,那么colorbar限制不会更改,即不会更新以反映在这个“新”频率范围内的信号值。是否有一种方法可以做到这一点,使得通过更改所绘制的y轴范围即频率范围限制,colorbar将相应地更新/更改?
interp='nearest'
cmap=seismic
fig = plt.figure()
ax1=fig.add_subplot(111)
img1=ax1.imshow(Pxx, interpolation=interp, aspect='auto',extent=extent,cmap=cmap)
ax1.autoscale(enable=True,axis='x',tight=True)
ax1.autoscale(enable=True,axis='y',tight=True)
ax1.set_autoscaley_on(False)
ax1.set_ylim([100E3,1E6])
fig.colorbar(img1)
plt.show()

我认为,如果能够在感兴趣的频率范围内找到Pxx的上下频率的最大和最小值,就可以使用这些值来设置颜色条限制,例如。

img1.set_clim(min_val, max_val) 

我可以找到Pxx的最大值和最小值,并返回它们的索引,使用以下方法:
import numpy as np
>>> np.unravel_index(Pxx.argmax(),Pxx.shape)
(20, 31805)
>>> np.unravel_index(Pxx.argmin(),Pxx.shape)
(1024, 31347)

如何查找对应于感兴趣频率范围的Pxx值?

我可以采用以下方法来大致确定“freqs”中100E3和1E6的位置,并使用每个的第一个(或最后一个)值...

   fmin_index= [i for i,x in enumerate(freqs) if x >= 100E3][0]
   fmax_index= [i for i,x in enumerate(freqs) if x >= 1000E3][0]

或者

   fmin_index= [i for i,x in enumerate(freqs) if x <= 100E3][-1]
   fmax_index= [i for i,x in enumerate(freqs) if x <= 1000E3][-1]

然后可能
min_val = np.min(Pxx[fmin_index,:])
max_val = np.min(Pxx[fmax_index,:])

最后。
img1.set_clim(min_val, max_val)

很不幸,这似乎无法正常工作,因为色条上的值范围看起来不正确。必须有更好/更容易/更准确的方法来完成以上操作。


添加一些示例图表以展示您的问题将使所有内容更加清晰。 - weronika
尝试包含一个图表图片,但是无法发布我的问题,因为显然你需要获得10个声望才能这样做。 - willf
1个回答

1

不必更改图形中的限制,一种可能的解决方案是更改绘制的数据并让colorbar完成其工作。在pylab环境中的最小工作示例:

#some random data
my_data = np.random.random(2048)

#### Your Code
Fs = 10E6      # Sampling Rate
w_length= 256      # window length
nFFT=2 * w_length
n_overlap=np.fix(w_length/2)
p_to = 8 *w_length

Pxx, freqs, bins= mlab.specgram(my_data,NFFT=nFFT,Fs=Fs,
                                detrend=mlab.detrend_linear,
                                noverlap=n_overlap,
                                pad_to=p_to,scale_by_freq=True)

#find a maximum frequency index
maxfreq = 1E5 #replace by your maximum freq
if maxfreq:
    lastfreq = freqs.searchsorted(maxfreq)
    if lastfreq > len(freqs):
        lastfreq = len(freqs)-1

Pxx = np.flipud(Pxx) #flipping image in the y-axis

interp='nearest'
seismic = plt.get_cmap('seismic')
cmap=seismic
fig = plt.figure()
ax1=fig.add_subplot(111)
extent = 0,4,freqs[0],freqs[lastfreq] # new extent
#plot reduced range
img1=ax1.imshow(Pxx[-lastfreq:], interpolation=interp, aspect='auto',
                extent=extent ,cmap=cmap)
ax1.set_autoscaley_on(False)
fig.colorbar(img1)
plt.show()

我的例子只设置了最大频率,但是通过一些小的调整,你可以设置一个最小频率。

感谢 Rafael 的贡献。 - willf
你提出的寻找最大频率索引的方法与我上面用于fmax_index的例程给出了相同的结果,我也等效地用于fmin_index。为什么要在y轴上翻转图像?我已经相应地更改了extent参数。在img1 = ax1.imshow语句中,为什么Pxx的lastfreq前面有一个减号? - willf
翻转是必要的,因为imshow函数假定图像从左上角开始。pyplot.specgram中也是这样做的。在翻转后,高频率在数组的末尾,-lastfreq表示从末尾开始,向后移动lastfreq个位置。请参考:https://gist.github.com/randomtoor/5106828 以获取等效解决方案。 - Rafael Barbosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接