如何从加速度计数据中提取冻结指数进行雾检测?

2024-04-23 19:00:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个项目,检测帕金森病患者步态发作的冻结,并根据这个paper和其他项目,提取冻结指数,它是“冻结”带中的力量(3- 8Hz)除以运动频带内的功率(0.5-3Hz)“将是一个很好的特性

以下是解释:从原始信号中提取的一个标准特征是冻结指数(FI),定义为所谓冻结和移动频带(分别为3-8 Hz和0.5-3 Hz)中包含的功率之间的比率。此功能非常方便,因为它只需要FFT计算。

但我不知道如何用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]

现在,我想提取冻结指数,我该怎么做?我需要有人向我解释,因为我不完全理解它


Tags: 数据项目患者dfsizestepcol特征
1条回答
网友
1楼 · 发布于 2024-04-23 19:00:38

我发现这个article非常有用。本文中有一个函数,用于计算特定频带内信号的平均功率。由于冻结指数是所谓的冻结和移动频带(分别为3-8 Hz和0.5-3 Hz)中包含的功率之间的比率,因此我们可以使用此函数来获得每个频带中的功率并对其进行分割

以下是函数:

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]

我希望这是一个正确的解决方案,我希望它能有所帮助

相关问题 更多 >