Python 从频谱图识别时间相关信号
我正试图从一张光谱图中追踪几个信号。问题在于,随着时间的推移,信号的频率会发生变化,因此很难将其隔离。(见下图)是否有一个python函数能够随时间跟踪信号?请注意,在进行任何FTs之前,我没有访问原始数据的权限-只有光谱图本身的2D阵列 我所尝试的(为了缓和成功:)Python 从频谱图识别时间相关信号,python,image-processing,spectrogram,Python,Image Processing,Spectrogram,我正试图从一张光谱图中追踪几个信号。问题在于,随着时间的推移,信号的频率会发生变化,因此很难将其隔离。(见下图)是否有一个python函数能够随时间跟踪信号?请注意,在进行任何FTs之前,我没有访问原始数据的权限-只有光谱图本身的2D阵列 我所尝试的(为了缓和成功:) 按时间对2D频谱图进行切片,并在每次识别频率中的峰值 尝试跟踪峰值位置,以捕获每个信号随时间的变化 这种方法是拼凑的代码,但结果看起来很有希望,如下所示: 原始光谱图: 跨时间的频率跟踪: 我所寻找的是一种更稳健的方法来实现这
import numpy as np
from matplotlib.pyplot import *
from matplotlib.colors import LogNorm
data = np.load('spectrogram.npz')
## ---- trim data ---- ###
it1=1000
it2=1700
if1=0
if2=1900
tvec = data['tvec'][it1:it2]
fvec = data['fvec'][if1:if2]
spect = data['spect'][0][if1:if2,it1:it2]
v = np.linspace(min(spect.flatten()),0.1*max(spect.flatten()),100)
## ---- spectrogram ---- ###
figure()
contourf(tvec,fvec,spect,v,cmap=plt.cm.jet,norm=LogNorm())
xlabel('Time (ms)')
ylabel('Frequency (Hz)')
## ---- find modes ---- ###
# initialize to NaNs
kHz12 = np.full(len(tvec),np.nan)
kHz25 = np.full(len(tvec),np.nan)
kHz50 = np.full(len(tvec),np.nan)
kHz50_f0 = 50E3
kHz70 = np.full(len(tvec),np.nan)
for i in range(it2-it1):
x = spect[:,i]
peaks, _ = scipy.signal.find_peaks(x,height=100,prominence=50)
#scatter([tvec[i]]*len(peaks),fvec[peaks],1,marker='o')
### --- scroll through time and keep track of each frequency --- ###
kHz12_subsel = [y for j,y in zip(peaks,x[peaks]) if fvec[j] > 11E3 and fvec[j] < 15E3]
if kHz12_subsel: kHz12[i] = fvec[peaks][np.where(x[peaks] == np.max(kHz12_subsel))]
kHz25[i] = fvec[peaks][np.argmax(x[peaks])]
kHz50_subsel = [y for j,y in zip(peaks,x[peaks]) if fvec[j] > 45E3 and fvec[j] < 60E3]
if kHz50_subsel:
kHz50[i] = fvec[peaks][np.argmin([abs(f-kHz50_f0) for f in fvec[peaks]])]
kHz50_f0 = kHz50[i]
kHz70_subsel = [j for j in peaks if fvec[j] > 60E3 and fvec[j] < 80E3]
if kHz70_subsel:
kHz70[i] = np.average(fvec[kHz70_subsel])
## ---- plot modes ---- ###
plot(tvec,kHz12,lw=2,c='k')
plot(tvec,kHz25,lw=2,c='k')
plot(tvec,kHz50,lw=2,c='k')
plot(tvec,kHz70,lw=2,c='k')
将numpy导入为np
从matplotlib.pyplot导入*
从matplotlib.colors导入LogNorm
data=np.load('spectrogram.npz'))
##----修剪数据----###
it1=1000
it2=1700
如果1=0
if2=1900
tvec=数据['tvec'][it1:it2]
fvec=数据['fvec'][if1:if2]
spect=data['spect'][0][if1:if2,it1:it2]
v=np.linspace(最小(spect.flatte()),0.1*max(spect.flatte()),100)
##----光谱图----###
图(
轮廓图(tvec,fvec,spect,v,cmap=plt.cm.jet,norm=LogNorm())
xlabel(‘时间(毫秒)’)
ylabel('频率(Hz)')
##----查找模式--###
#初始化为NaNs
kHz12=np.full(len(tvec),np.nan)
kHz25=np.full(len(tvec),np.nan)
kHz50=np.full(len(tvec),np.nan)
kHz50_f0=50E3
kHz70=np.full(len(tvec),np.nan)
对于范围内的i(it2-it1):
x=spect[:,i]
峰值,u=scipy.signal.find_峰值(x,高度=100,突出度=50)
#散射([tvec[i]]*len(峰值),fvec[峰值],1,标记为'o')
###---滚动时间并跟踪每个频率--###
如果fvec[j]>11E3且fvec[j]<15E3,则kHz12_subsel=[y代表j,y在zip中(峰值,x[peaks])
如果kHz12_海底:kHz12[i]=fvec[peaks][np.式中(x[peaks]==np.max(kHz12_海底))]
kHz25[i]=fvec[峰值][np.argmax(x[峰值]]
kHz50_subsel=[y代表j,y在zip中(峰值,x[peaks]),如果fvec[j]>45E3且fvec[j]<60E3]
如果kHz50_海底:
kHz50[i]=fvec[峰值][np.argmin([abs(f-kHz50_f0)表示fvec[峰值]]
kHz50_f0=kHz50[i]
kHz70_subsel=[j,如果fvec[j]>60E3且fvec[j]<80E3,则峰值中的j为j]
如果kHz70_海底:
kHz70[i]=np.平均值(fvec[kHz70_subsel])
##----打印模式--###
绘图(tvec,kHz12,lw=2,c='k')
绘图(tvec,kHz25,lw=2,c='k')
绘图(tvec,kHz50,lw=2,c='k')
绘图(tvec,kHz70,lw=2,c='k')
请提供您用于创建第二幅图像的代码,好吗?@arnavpodar我已经添加了代码对不起,我找不到一个简单的函数来重建您所做的操作。但是,您可以将代码转换为带有def timething(foo,bar):
和参数的函数,并使用它。稍后,您甚至可以尝试将您的函数/模块上载到python.org,以便其他人也可以使用它。请提供您用于创建第二个映像的代码给我们好吗?@arnavpodar我添加了代码抱歉,我找不到一个简单的函数可以重新创建您所做的操作。但是,您可以将代码转换为带有def timething(foo,bar):
和参数的函数,并使用它。稍后,您甚至可以尝试将函数/模块上传到python.org,以便其他人也可以使用它。