Поиск циклов в данных

Пытаюсь найти циклы в данных представленных ниже. Как сделать это правильно и эффективно?

import matplotlib.pyplot as plt
from scipy.misc import electrocardiogram

x = electrocardiogram()[2000:4000]

plt.plot(x)
plt.show()

введите сюда описание изображения


Ответы (1 шт):

Автор решения: Pak Uula

Под поисками циклов вы понимаете поиск периодических колебаний максимальными амплитудами?

Если да, то вам нужно построить спектр сигнала и найти частоты с максимальными амплитудами.

Пусть ваша ЭКГ снималась с частотой F отсчетов в секунду (частота дискретизации). Тогда спектр можно вычислить средствами scipy.signal.periodogram. Эта функция возвращает два массива - частоты и спектральную плотность сигнала, которая в простейшем случае равна просто квадрату модуля соотвествующего члена в разложении Фурье.

freqs, psd = signal.periodogram(x, fs=F)
plt.plot(freqs, psd)

Получится что-то такое: введите сюда описание изображения

Для упрощения картинки можно отбросить высокие частоты. Например, все частоты выше 4 Гц (т.е. сокращения сердца чаще, чем 240 в минуту)

low_freqs = freqs[freqs < 4.0]
psd_low_freqs = psd[:len(low_freqs)]
plt.plot(low_freqs, psd_low_freqs)

В результате картинка станет заметно менее "зубастой" введите сюда описание изображения

Я взял для примера кардиограмму из набора данных https://data.mendeley.com/datasets/7dybx7wyfn/3

Для выбранной кардиограммы получил частоту с максимальной амплитудой: freqs[np.argmax(psd)] результат равен 1.3

Частоты, соответствующие наибольшим амплитудам в нижней части спектра:

idx = np.argsort(psd_low_freqs)
idx_most = idx[-3:]
print(low_freqs[idx_most], psd_low_freqs[idx_most])

Результат

array([3.9, 2.6, 1.3]), array([1662.1819, 5103.5654, 9900.397 ], dtype=float32)

Код, данные и графики можно посмотреть в блокноте Junyper.

Там же добавлен пример обработки средствами быстрого преобразования Фурье, без периодограммы.

→ Ссылка