Как извлечь индекс замерзания из данных акселерометра для обнаружения FoG? - PullRequest
0 голосов
/ 28 мая 2020

Я работаю над проектом по обнаружению эпизодов замирания походки у пациентов с болезнью Паркинсона, и, согласно этой статье и другим, извлекаю индекс замерзания, который составляет « «заморозить» группу (3- 8 Гц), разделенное на мощность в опорно-двигательной зоны (0.5-3Hz) »будет функция хорошо

Вот объяснение:. Одна стандартная функция, которая Из необработанных сигналов извлекается индекс замораживания (FI), определяемый как отношение мощности, содержащейся в так называемых диапазонах частот замораживания и движения (3-8 Гц и 0,5-3 Гц соответственно). Эта функция удобна, поскольку требует только вычисления БПФ.

Но я не могу реализовать это в Python.

У меня есть такой фрейм данных: enter image description here Затем я сделал что-то вроде этого, чтобы извлечь особенности из данных временных рядов датчиков:

win_size=200
step_size=40
for col in df.columns:
    if col != 'Label':
        df[col + '_avg'] = df[col].rolling(win_size).mean()[step_size - 1::step_size]

Теперь я хотел бы извлечь индекс замораживания, как я могу это сделать? и мне нужно, чтобы кто-то объяснил мне это, потому что я не совсем понимаю это!

1 Ответ

0 голосов
/ 29 мая 2020

Я нашел эту статью очень полезной. В этой статье есть функция, которая вычисляет среднюю мощность сигнала в определенной полосе частот c. И поскольку индекс замораживания - это соотношение между мощностью, содержащейся в так называемых диапазонах частот замораживания и движения (3-8 Гц и 0,5-3 Гц соответственно), мы можем использовать эту функцию, чтобы получить мощность в каждой полосе частот и разделить их.

Вот функция:

def bandpower(data, sf, band, window_sec=None, relative=False):
    """Compute the average power of the signal x in a specific frequency band.

    Parameters
    ----------
    data : 1d-array
        Input signal in the time-domain.
    sf : float
        Sampling frequency of the data.
    band : list
        Lower and upper frequencies of the band of interest.
    window_sec : float
        Length of each window in seconds.
        If None, window_sec = (1 / min(band)) * 2
    relative : boolean
        If True, return the relative power (= divided by the total power of the signal).
        If False (default), return the absolute power.

    Return
    ------
    bp : float
        Absolute or relative band power.
    """
    from scipy.signal import welch
    from scipy.integrate import simps
    band = np.asarray(band)
    low, high = band

    # Define window length
    if window_sec is not None:
        nperseg = window_sec * sf
    else:
        nperseg = (2 / low) * sf

    # Compute the modified periodogram (Welch)
    freqs, psd = welch(data, sf, nperseg=nperseg)

    # Frequency resolution
    freq_res = freqs[1] - freqs[0]

    # Find closest indices of band in frequency vector
    idx_band = np.logical_and(freqs >= low, freqs <= high)

    # Integral approximation of the spectrum using Simpson's rule.
    bp = simps(psd[idx_band], dx=freq_res)

    if relative:
        bp /= simps(psd, dx=freq_res)
    return bp

Затем я создал эту простую функцию для возврата FI:

def freeze_index(data, sf, band1, band2, win_sec=None, relative=False):
    fi = bandpower(data, sf, band1, win_sec, relative) / bandpower(data, sf, band2, win_sec, relative)
    return fi

И вот как я ее назвал в функции скользящего окна:

for col in df.columns:
    if col != 'Label':
        df[col + '_fi'] = df[col].rolling(win_size).apply(freeze_index, args=(fs, [3, 8], [0.5, 3], win_size,))[step_size - 1::step_size]

Я надеюсь, что это правильное решение, и у меня sh оно помогает.

...