[med-svn] [python-mne] 97/353: ENH: filtering and apply_function for Raw

Yaroslav Halchenko debian at onerussian.com
Fri Nov 27 17:24:37 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 f6cd0f3a5cb412bc4afe67dabf3c38c59197951f
Author: Martin Luessi <mluessi at nmr.mgh.harvard.edu>
Date:   Fri Mar 2 15:02:29 2012 -0500

    ENH: filtering and apply_function for Raw
---
 doc/source/whats_new.rst   |   1 +
 mne/fiff/raw.py            | 161 +++++++++++++++++++++++++++++++++++++++++++++
 mne/fiff/tests/test_raw.py |  32 +++++++++
 3 files changed, 194 insertions(+)

diff --git a/doc/source/whats_new.rst b/doc/source/whats_new.rst
index 277c463..e52f39a 100644
--- a/doc/source/whats_new.rst
+++ b/doc/source/whats_new.rst
@@ -23,6 +23,7 @@ Changelog
 
    - Write BEM surfaces in Python  by `Alex Gramfort`_.
 
+   - Filtering operations and apply_function interface for Raw object by `Martin Luessi`_.
 
 Version 0.2
 -----------
diff --git a/mne/fiff/raw.py b/mne/fiff/raw.py
index e835485..6b98063 100644
--- a/mne/fiff/raw.py
+++ b/mne/fiff/raw.py
@@ -6,6 +6,8 @@
 
 from math import floor, ceil
 import copy
+import types
+
 import numpy as np
 
 from .constants import FIFF
@@ -14,6 +16,9 @@ from .meas_info import read_meas_info, write_meas_info
 from .tree import dir_tree_find
 from .tag import read_tag
 
+from ..filter import low_pass_filter, high_pass_filter, band_pass_filter
+from ..parallel import parallel_func
+
 
 class Raw(object):
     """Raw data
@@ -224,6 +229,162 @@ class Raw(object):
         # set the data
         self._data[sel, start:stop] = value
 
+    def apply_function(self, fun, picks, n_jobs, verbose, *args, **kwargs):
+        """ Apply a function to a subset of channels.
+
+        The function "fun" is applied to the channels defined in "picks". The
+        data of the Raw object is modified in-place.
+
+        The Raw object has to be constructed using preload=True (or string).
+
+        Parameters
+        ----------
+        fun : function
+            A function to be applied to the channels. The first argument of
+            fun has to be a timeseries (numpy.ndarray). The function must
+            return an numpy.ndarray with the same size as the input.
+
+        picks : list of int
+            Indices of channels to apply the function to.
+
+        n_jobs: int
+            Number of jobs to run in parallel.
+
+        verbose: int
+            Verbosity level.
+
+        *args:
+            Additional positional arguments to pass to fun (first pos. argument
+            of fun is the timeseries of a channel).
+
+        **kwargs:
+            Keyword arguments to pass to fun.
+        """
+
+        if not isinstance(fun, types.FunctionType):
+            raise ValueError('fun needs to be a function')
+
+        if not self._preloaded:
+            raise RuntimeError('Raw data needs to be preloaded. Use '
+                               'preload=True (or string) in the constructor.')
+
+        # create parallel function
+        parallel, p_fun, _ = parallel_func(fun, n_jobs, verbose)
+
+        # apply function to channels
+        data_picks = self._data[picks, :]
+        data_picks_new = np.array(parallel(p_fun(x, *args, **kwargs)
+                                  for x in data_picks))
+
+        if np.any(data_picks_new.shape != data_picks.shape):
+            raise ValueError('fun must return array with the same size as '
+                              'input')
+
+        self._data[picks, :] = data_picks_new
+
+    def band_pass_filter(self, picks, Fp1, Fp2, filter_length=None, n_jobs=1,
+                         verbose=5):
+        """Band-pass filter a subset of channels.
+
+        Applies a zero-phase band-pass filter to the channels selected by
+        "picks". The data of the Raw object is modified in-place.
+
+        The Raw object has to be constructed using preload=True (or string).
+
+        Parameters
+        ----------
+        picks : list of int
+            Indices of channels to filter.
+
+        Fp1 : float
+            Low cut-off frequency in Hz.
+
+        Fp2 : float
+            High cut-off frequency in Hz.
+
+        filter_length : int (default: None)
+            Length of the filter to use. If None or "ntimes < filter_length",
+            (ntimes: number of timepoints in Raw object) the filter length
+            used is ntimes. Otherwise, overlap-add filtering with a
+            filter of the specified length is used (faster for long signals).
+
+        n_jobs: int (default: 1)
+            Number of jobs to run in parallel.
+
+        verbose: int (default: 5)
+            Verbosity level.
+        """
+        Fs = float(self.info['sfreq'])
+        self.apply_function(band_pass_filter, picks, n_jobs, verbose, Fs, Fp1,
+                            Fp2, filter_length=filter_length)
+
+    def high_pass_filter(self, picks, Fp, filter_length=None, n_jobs=1,
+                         verbose=5):
+        """High-pass filter a subset of channels.
+
+        Applies a zero-phase high-pass filter to the channels selected by
+        "picks". The data of the Raw object is modified in-place.
+
+        The Raw object has to be constructed using preload=True (or string).
+
+        Parameters
+        ----------
+        picks : list of int
+            Indices of channels to filter.
+
+        Fp : float
+            Cut-off frequency in Hz.
+
+        filter_length : int (default: None)
+            Length of the filter to use. If None or "ntimes < filter_length",
+            (ntimes: number of timepoints in Raw object) the filter length
+            used is ntimes. Otherwise, overlap-add filtering with a
+            filter of the specified length is used (faster for long signals).
+
+        n_jobs: int (default: 1)
+            Number of jobs to run in parallel.
+
+        verbose: int (default: 5)
+            Verbosity level.
+        """
+
+        Fs = float(self.info['sfreq'])
+        self.apply_function(high_pass_filter, picks, n_jobs, verbose, Fs, Fp,
+                            filter_length=filter_length)
+
+    def low_pass_filter(self, picks, Fp, filter_length=None, n_jobs=1,
+                        verbose=5):
+        """Low-pass filter a subset of channels.
+
+        Applies a zero-phase low-pass filter to the channels selected by
+        "picks". The data of the Raw object is modified in-place.
+
+        The Raw object has to be constructed using preload=True (or string).
+
+        Parameters
+        ----------
+        picks : list of int
+            Indices of channels to filter.
+
+        Fp : float
+            Cut-off frequency in Hz.
+
+        filter_length : int (default: None)
+            Length of the filter to use. If None or "ntimes < filter_length",
+            (ntimes: number of timepoints in Raw object) the filter length
+            used is ntimes. Otherwise, overlap-add filtering with a
+            filter of the specified length is used (faster for long signals).
+
+        n_jobs: int (default: 1)
+            Number of jobs to run in parallel.
+
+        verbose: int (default: 5)
+            Verbosity level.
+        """
+        Fs = float(self.info['sfreq'])
+        self.apply_function(low_pass_filter, picks, n_jobs, verbose, Fs, Fp,
+                            filter_length=filter_length)
+
     def save(self, fname, picks=None, tmin=0, tmax=None, buffer_size_sec=10,
              drop_small_buffer=False):
         """Save raw data to file
diff --git a/mne/fiff/tests/test_raw.py b/mne/fiff/tests/test_raw.py
index 35edb86..520e32b 100644
--- a/mne/fiff/tests/test_raw.py
+++ b/mne/fiff/tests/test_raw.py
@@ -1,4 +1,5 @@
 import os.path as op
+from copy import deepcopy
 
 import numpy as np
 from nose.tools import assert_true
@@ -111,3 +112,34 @@ def test_preload_modify():
         data_new, _ = raw_new[picks, :nsamp / 2]
 
         assert_array_almost_equal(data, data_new)
+
+
+def test_filter():
+    """ Test filtering and Raw.apply_function interface """
+
+    raw = Raw(fif_fname, preload=True)
+    picks_meg = pick_types(raw.info, meg=True)
+    picks = picks_meg[:4]
+
+    raw_lp = deepcopy(raw)
+    raw_lp.low_pass_filter(picks, 4.0)
+
+    raw_hp = deepcopy(raw)
+    raw_hp.high_pass_filter(picks, 8.0)
+
+    raw_bp = deepcopy(raw)
+    raw_bp.band_pass_filter(picks, 4.0, 8.0)
+
+    data, _ = raw[picks, :]
+
+    lp_data, _ = raw_lp[picks, :]
+    hp_data, _ = raw_hp[picks, :]
+    bp_data, _ = raw_bp[picks, :]
+
+    assert_array_almost_equal(data, lp_data + hp_data + bp_data)
+
+    # make sure we didn't touch other channels
+    data, _ = raw[picks_meg[4:], :]
+    bp_data, _ = raw_bp[picks_meg[4:], :]
+
+    assert_array_equal(data, bp_data)

-- 
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