Идентификация зависящих от времени сигналов по спектрограмме - PullRequest
1 голос
/ 30 мая 2019

Я пытаюсь проследить несколько сигналов во времени от спектрограммы. Проблема в том, что с течением времени сигналы меняются по частоте, поэтому их трудно изолировать. (См. Изображения ниже). Существует ли функция Python, способная отслеживать сигналы во времени? Обратите внимание, что у меня нет доступа к необработанным данным до каких-либо ФТ - только двумерный массив самой спектрограммы.

То, что я пытался (чтобы смягчить успех :)

  1. Разрезать 2D-спектрограмму по времени и определять пики частоты каждый раз.
  2. Постарайтесь проследить местоположение пиков во времени, чтобы зафиксировать эволюцию каждого сигнала как функцию времени.

Этот подход представляет собой пэчворк-код, но результаты выглядят многообещающими, как показано здесь:

Исходная спектрограмма: The spectrogram

Отслеживание частоты по времени: Line tracing across the spectrogram

То, что я ищу, - это более надежный метод для достижения этой цели. Я надеюсь, что мне придется написать не собственный сценарий, а использовать какой-то разработанный инструмент, способный выполнить этот анализ данных. Существует ли такой инструмент Python?

Спасибо.

Вот код, который я использовал для создания этих графиков. Полностью открыт для капитального ремонта, поскольку он явно не надежный.

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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...