[med-svn] [python-mne] 99/353: Save memory if n_jobs=1 and dtype stays the same

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 08fbe22078d52227b0b306b9058c26de6ce2348a
Author: Martin Luessi <mluessi at nmr.mgh.harvard.edu>
Date:   Mon Mar 5 11:10:39 2012 -0500

    Save memory if n_jobs=1 and dtype stays the same
---
 mne/fiff/raw.py            | 122 ++++++++++++++++++++++++---------------------
 mne/fiff/tests/test_raw.py |   9 ++--
 2 files changed, 69 insertions(+), 62 deletions(-)

diff --git a/mne/fiff/raw.py b/mne/fiff/raw.py
index 20ff73b..4fb12b0 100644
--- a/mne/fiff/raw.py
+++ b/mne/fiff/raw.py
@@ -232,48 +232,15 @@ class Raw(object):
         # set the data
         self._data[sel, start:stop] = value
 
-    def analytic_signal(self, picks, n_jobs=1, verbose=5):
-        """ Compute analytic signal for a subset of channels.
-
-        Compute analytic signal for the channels defined in "picks". The
-        data of the Raw object is modified inplace and converted to a
-        complex representation (the analytic signal is complex valued).
-
-        The Raw object has to be constructed using preload=True (or string).
-
-        Parameters
-        ----------
-        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.
-
-        Notes
-        -----
-        The analytic signal "x_a(t)" of "x(t)" is::
-
-            x_a = F^{-1}(F(x) 2U) = x + i y
-
-        where "F" is the Fourier transform, "U" the unit step function,
-        and "y" the Hilbert transform of "x". One usage of the analytic
-        signal is the computation of the enevelope signal, which is given by
-        "e(t) = abs(x_a(t))". Due to the linearity of Hilbert transform and the
-        MNE inverse solution, the enevlope in source space can be obtained
-        by computing the analytic signal in sensor space, applying the MNE
-        inverse, and computing the envelope in source space.
-        """
-        self.apply_function(hilbert, picks, n_jobs, verbose)
-
-
-    def apply_function(self, fun, picks, n_jobs, verbose, *args, **kwargs):
+    def apply_function(self, fun, picks, dtype, 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 inplace.
+        data of the Raw object is modified inplace. If the function returns
+        a different data type (e.g. numpy.complex) it must be specified using
+        the dtype parameter, which causes the data type used for representing
+        the raw data to change.
 
         The Raw object has to be constructed using preload=True (or string).
 
@@ -287,6 +254,10 @@ class Raw(object):
         picks : list of int
             Indices of channels to apply the function to.
 
+        dtype : numpy.dtype
+            Data type to use for raw data after applying the function. If None
+            the data type is not modified.
+
         n_jobs: int
             Number of jobs to run in parallel.
 
@@ -307,24 +278,59 @@ class Raw(object):
         if not callable(fun):
             raise ValueError('fun needs to be a function')
 
-        # create parallel function
-        parallel, p_fun, _ = parallel_func(fun, n_jobs, verbose)
+        data_in = self._data
+        if dtype is not None and dtype != self._data.dtype:
+            self._data = self._data.astype(dtype)
+
+        if n_jobs == 1:
+            # modify data inplace to save memory
+            for idx in picks:
+                self._data[idx, :] = fun(data_in[idx, :], *args, **kwargs)
+        else:
+            # use parallel function
+            parallel, p_fun, _ = parallel_func(fun, n_jobs, verbose)
+
+            data_picks = data_in[picks, :]
+            data_picks_new = np.array(parallel(p_fun(x, *args, **kwargs)
+                                      for x in data_picks))
+
+            self._data[picks, :] = data_picks_new
+
+    def apply_hilbert(self, picks, n_jobs=1, verbose=5):
+        """ Compute analytic signal for a subset of channels.
+
+        Compute analytic signal for the channels defined in "picks". The
+        data of the Raw object is modified inplace and converted to a
+        complex representation (the analytic signal is complex valued).
 
-        # 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))
+        The Raw object has to be constructed using preload=True (or string).
 
-        if np.any(data_picks_new.shape != data_picks.shape):
-            raise ValueError('fun must return array with the same size as '
-                              'input')
+        Parameters
+        ----------
+        picks : list of int
+            Indices of channels to apply the function to.
 
-        # convert the type of _data if necessary
-        if data_picks_new.dtype != self._data.dtype:
-            print 'Converting raw data to %s' % data_picks_new.dtype
-            self._data = np.array(self._data, dtype=data_picks_new.dtype)
+        n_jobs: int
+            Number of jobs to run in parallel.
 
-        self._data[picks, :] = data_picks_new
+        verbose: int
+            Verbosity level.
+
+        Notes
+        -----
+        The analytic signal "x_a(t)" of "x(t)" is::
+
+            x_a = F^{-1}(F(x) 2U) = x + i y
+
+        where "F" is the Fourier transform, "U" the unit step function,
+        and "y" the Hilbert transform of "x". One usage of the analytic
+        signal is the computation of the enevelope signal, which is given by
+        "e(t) = abs(x_a(t))". Due to the linearity of Hilbert transform and the
+        MNE inverse solution, the enevlope in source space can be obtained
+        by computing the analytic signal in sensor space, applying the MNE
+        inverse, and computing the envelope in source space.
+        """
+        self.apply_function(hilbert, picks, np.complex64, n_jobs, verbose)
 
     def band_pass_filter(self, picks, f_low, f_high, filter_length=None,
                          n_jobs=1, verbose=5):
@@ -359,7 +365,7 @@ class Raw(object):
             Verbosity level.
         """
         fs = float(self.info['sfreq'])
-        self.apply_function(band_pass_filter, picks, n_jobs, verbose, fs,
+        self.apply_function(band_pass_filter, picks, None, n_jobs, verbose, fs,
                             f_low, f_high, filter_length=filter_length)
 
     def high_pass_filter(self, picks, fp, filter_length=None, n_jobs=1,
@@ -393,8 +399,8 @@ class Raw(object):
         """
 
         fs = float(self.info['sfreq'])
-        self.apply_function(high_pass_filter, picks, n_jobs, verbose, fs, fp,
-                            filter_length=filter_length)
+        self.apply_function(high_pass_filter, picks, None, n_jobs, verbose,
+                            fs, fp, filter_length=filter_length)
 
     def low_pass_filter(self, picks, fp, filter_length=None, n_jobs=1,
                         verbose=5):
@@ -426,8 +432,8 @@ class Raw(object):
             Verbosity level.
         """
         fs = float(self.info['sfreq'])
-        self.apply_function(low_pass_filter, picks, n_jobs, verbose, fs, fp,
-                            filter_length=filter_length)
+        self.apply_function(low_pass_filter, picks, None, 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):
diff --git a/mne/fiff/tests/test_raw.py b/mne/fiff/tests/test_raw.py
index 2ceb6a2..744a36b 100644
--- a/mne/fiff/tests/test_raw.py
+++ b/mne/fiff/tests/test_raw.py
@@ -148,7 +148,7 @@ def test_filter():
     picks = picks_meg[:4]
 
     raw_lp = deepcopy(raw)
-    raw_lp.low_pass_filter(picks, 4.0, verbose=0)
+    raw_lp.low_pass_filter(picks, 4.0, verbose=0, n_jobs=2)
 
     raw_hp = deepcopy(raw)
     raw_hp.high_pass_filter(picks, 8.0, verbose=0)
@@ -170,12 +170,13 @@ def test_filter():
 
     assert_array_equal(data, bp_data)
 
-def test_analytic():
-    """ Test computation of analytic signal """
+
+def test_hilbert():
+    """ Test computation of analytic signal using hilbert """
     raw = Raw(fif_fname, preload=True)
     picks_meg = pick_types(raw.info, meg=True)
     picks = picks_meg[:4]
 
-    raw.analytic_signal(picks, verbose=0)
+    raw.apply_hilbert(picks, verbose=0)
 
     #XXX what to test?

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