Python以4D结构过滤信号

时间:2016-12-05 01:21:28

标签: python numpy scipy filtering signal-processing

我的4D结构包含形状为class HTMLRenderer(QWebEngineView): def __init__(self): super(HTMLRenderer, self).__init__() self.setHtml('<div>Try HTML</div>') self.show()

的EEG数据

这表示3432个数据试验,其中每个试验包含512个电极的512个时间样本

对于每个试验,我想用某些滤波器参数过滤每个电极,这会产生一个新的2D (3432,1,30,512)滤波阵列。然后,我想沿着4D结构的轴1堆叠它们。

目前,我正在迭代每个试验,然后是每个电极,过滤信号并将所有内容重新插入4D:

(30,512)

迭代试验和电极非常慢(完成整个循环需要大约2个小时)。是否有更有效的方法将此过滤器应用于所有电极/试验?

我一直试图找到一种方法将滤镜应用于2D,所以我不需要迭代电极,但却找不到任何东西。

编辑:

这是使用from scipy import signal NUM_CHANS = 30 NUM_TIMESTAMPS = 512 FREQ_BANDS = ((0.1, 3), (4, 7), (8, 13), (16, 31)) all_data = np.reshape(all_data, (-1, 1, NUM_CHANS, NUM_TIMESTAMPS)) # (3432,1,30,512) for i in range(all_data.shape[0]): num_band = 1 for band in FREQ_BANDS: lower = float(band[0])/(SAMPLE_RATE/2) upper = float(band[1])/(SAMPLE_RATE/2) # Design new filter for the current frequency band b, a = signal.butter(2, [lower, upper], 'bandpass') temp_trial = np.zeros((NUM_CHANS, NUM_TIMESTAMPS)) for ch in range(NUM_CHANS): # Filter the current electrode output_signal = signal.filtfilt(b, a, all_data[i,0,ch,:]) temp_trial[ch,:] = output_signal # Insert temp_trial (2D) into all_data (4D) along axis 1 num_band += 1 轴参数的正确方法吗?

filtfilt

1 个答案:

答案 0 :(得分:1)

这是一项可能会改善效果的变化。 filtfilt有一个axis参数,它允许您沿着n维数组的轴应用相同的1-d滤镜。您可以替换此代码

    temp_trial = np.zeros((NUM_CHANS, NUM_TIMESTAMPS))
    for ch in range(NUM_CHANS):
        # Filter the current electrode
        output_signal = signal.filtfilt(b, a, all_data[i,0,ch,:])
        temp_trial[ch,:] = output_signal

    temp_trial = signal.filtfilt(b, a, all_data[i,0,:,:], axis=1)

由于默认axisaxis=-1,如果您愿意,可以省略轴参数:

    temp_trial = signal.filtfilt(b, a, all_data[i,0,:,:])

通过重新排列外环,你可以做得更好。使“band”循环成外循环。然后,对于每个频段,您可以将filtfilt 一次应用于三维数组all_data[:, 0, :, :]

这样的事情:

shp = all_data.shape

# This assumes `all_data` has shape (3432,1,30,512), but I don't
# think you need that trivial extra dimension in there if you
# preallocate `filtered_data` like I am doing here.
filtered_data = np.empty(shp[0:1] + (len(FREQ_BANDS),) + shp[2:])

for k, band in enumerate(FREQ_BANDS):
    lower = float(band[0])/(SAMPLE_RATE/2)
    upper = float(band[1])/(SAMPLE_RATE/2)

    # Design new filter for the current frequency band
    b, a = signal.butter(2, [lower, upper], 'bandpass')

    filtered_data[:, k, :, :] = filtfilt(b, a, all_data[:,0,:,:])

这不包括all_data中的原始filtered_data。如果您需要,请在创建len(FREQ_BANDS)+1的{​​{1}}调用中使用np.empty(),设置filtered_data,然后使用filtered_data[:,0,:,:] = all_data代替k+1赋值语句,用于保存k调用的结果。