[med-svn] [python-mne] 01/353: wip on overlap add
Yaroslav Halchenko
debian at onerussian.com
Fri Nov 27 17:24:23 UTC 2015
This is an automated email from the git hooks/post-receive script.
yoh pushed a commit to tag 0.4
in repository python-mne.
commit ccb9c1716d1f501a7fdcd8b5edb00419a1ae1ebd
Author: Martin Luessi <mluessi at nmr.mgh.harvard.edu>
Date: Thu Oct 13 13:33:27 2011 -0400
wip on overlap add
---
mne/filter.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 86 insertions(+), 9 deletions(-)
diff --git a/mne/filter.py b/mne/filter.py
index c2f4d73..b492e3c 100644
--- a/mne/filter.py
+++ b/mne/filter.py
@@ -3,7 +3,70 @@ from scipy import signal
from scipy.fftpack import fft, ifft
-def band_pass_filter(x, Fs, Fp1, Fp2):
+def overlap_add_filter(x, h, N_fft=None):
+ """ Calculate linear convolution using overlap-add FFTs
+
+ Implements the linear convolution between x and h using overlap-add FFTs.
+
+ Parameters
+ ----------
+ x : 1d array
+ Signal to filter
+ h : 1d array
+ Filter impule response (FIR filter coefficients)
+ N_fft : int
+ Length of the FFT. If None, the best size is determined automatically.
+ """
+
+ # https://ccrma.stanford.edu/~jos/fp/Forward_Backward_Filtering.html
+ # http://www.mathworks.com/matlabcentral/fileexchange/17061-filtfilthd/content/filtfilthd.m
+ N_h = len(h)
+ N_x = len(x)
+
+ if N_fft == None:
+ if N_x > N_h:
+ N = 2**np.arange(np.ceil(np.log2(N_h)),
+ np.floor(np.log2(N_x)))
+ cost = np.ceil(N_x / (N - N_h + 1)) * N * (np.log2(N) + 1)
+ N_fft = N[np.argmin(cost)]
+ else:
+ # Use only a single block
+ N_fft = 2**np.ceil(np.log2(N_x + N_h - 1))
+
+ print 'FFT length: %d' % (N_fft)
+
+ N_seg = N_fft - N_h + 1
+
+ if N_fft <= 0:
+ raise ValueError('N_fft is too short, has to be at least len(h)')
+
+ # Filter in frequency domain
+ # FIXME: abs?
+ h_fft = np.abs(fft(np.concatenate((h, np.zeros(N_fft - N_h)))))
+
+ x_filtered = np.zeros_like(x)
+
+ # Go through segments
+ num_segments = int(np.ceil(N_x / float(N_seg)))
+
+ for seg_ind in range(num_segments):
+ seg = x[seg_ind*N_seg:(seg_ind+1)*N_seg]
+ seg_fft = fft(np.concatenate((seg, np.zeros(N_fft - len(seg)))))
+
+
+ if seg_ind*N_seg+N_fft < N_x:
+ x_filtered[seg_ind*N_seg:seg_ind*N_seg+N_fft] \
+ += np.real(ifft(h_fft * seg_fft))
+ else:
+ # Last segment
+ x_filtered[seg_ind*N_seg:] \
+ += np.real(ifft(h_fft * seg_fft))[:N_x-seg_ind*N_seg]
+
+ return x_filtered
+
+
+
+def band_pass_filter(x, Fs, Fp1, Fp2, ov_add):
"""Bandpass filter for the signal x.
An acausal fft algorithm is applied (i.e. no phase shift). The filter
@@ -64,14 +127,28 @@ def band_pass_filter(x, Fs, Fp1, Fp2):
Np2 = Fp2 / (Fs / 2)
# Construct the filter function H(f)
- N = len(x)
-
- B = signal.firwin2(N, [0, Ns1, Np1, Np2, Ns2, 1], [0, 0, 1, 1, 0, 0])
-
- # Make zero-phase filter function
- H = np.abs(fft(B))
-
- xf = np.real(ifft(fft(x) * H))
+# N = len(x)
+# B = signal.firwin2(N, [0, Ns1, Np1, Np2, Ns2, 1], [0, 0, 1, 1, 0, 0])
+#
+# # Make zero-phase filter function
+# H = np.abs(fft(B))
+# xf = np.real(ifft(fft(x) * H))
+#
+
+ if ov_add:
+ N = int(2 * Fs)
+ B = signal.firwin2(N, [0, Ns1, Np1, Np2, Ns2, 1], [0, 0, 1, 1, 0, 0])
+
+ xf = overlap_add_filter(x, B)
+ else:
+ N = int(2 * Fs)
+ B = signal.firwin2(N, [0, Ns1, Np1, Np2, Ns2, 1], [0, 0, 1, 1, 0, 0])
+
+ B = ifft(np.abs(fft(B)))
+ # Make zero-phase filter function
+
+ xf = (signal.convolve(x, B, 'full'))
+
xf = xf[:Norig]
x = x[:Norig]
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git
More information about the debian-med-commit
mailing list