Repository: mne-tools/mne-python

Issue:
API: default params in `raw.apply_hilbert` and `raw.apply_funtion`
These two methods would be more handsome if equipped with some defaults.
At least picks and n_jobs could default to something, maybe also dtype.
What do you think? @Eric89GXL @agramfort ...


Discussion:
And while we're at it also let them return self.

+1

picks should default to data channels
n_jobs to 1 and dtype to float
and raise a warning if a complex is returned

Ok sending PR later today
On Sun, 6 Nov 2016 at 11:26, Alexandre Gramfort notifications@github.com
wrote:

> +1
> 
> picks should default to data channels
> n_jobs to 1 and dtype to float
> and raise a warning if a complex is returned
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> https://github.com/mne-tools/mne-python/issues/3742#issuecomment-258672090,
> or mute the thread
> https://github.com/notifications/unsubscribe-auth/AB0fissp-tYHW-1sp_yLxgwC1zeM2iwTks5q7as5gaJpZM4Kqgql
> .


Resolving patch:
diff --git a/mne/io/base.py b/mne/io/base.py
--- a/mne/io/base.py
+++ b/mne/io/base.py
@@ -783,7 +783,8 @@ def __setitem__(self, item, value):
         self._data[sel, start:stop] = value
 
     @verbose
-    def apply_function(self, fun, picks, dtype, n_jobs, *args, **kwargs):
+    def apply_function(self, fun, picks=None, dtype=None,
+                       n_jobs=1, *args, **kwargs):
         """Apply a function to a subset of channels.
 
         The function "fun" is applied to the channels defined in "picks". The
@@ -809,13 +810,13 @@ def apply_function(self, fun, picks, dtype, n_jobs, *args, **kwargs):
             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 : array-like of int | None
+        picks : array-like of int (defaul: None)
             Indices of channels to apply the function to. If None, all
-            M-EEG channels are used.
-        dtype : numpy.dtype
+            M-EEG channels are used. If None, all data channels are used.
+        dtype : numpy.dtype (default: None)
             Data type to use for raw data after applying the function. If None
             the data type is not modified.
-        n_jobs: int
+        n_jobs: int (default: 1)
             Number of jobs to run in parallel.
         *args :
             Additional positional arguments to pass to fun (first pos. argument
@@ -825,6 +826,11 @@ def apply_function(self, fun, picks, dtype, n_jobs, *args, **kwargs):
             as a member of ``kwargs``, it will be consumed and will override
             the default mne-python verbose level (see :func:`mne.verbose` and
             :ref:`Logging documentation <tut_logging>` for more).
+
+        Returns
+        -------
+        self : instance of Raw
+            The raw object with transformed data.
         """
         _check_preload(self, 'raw.apply_function')
         if picks is None:
@@ -850,9 +856,10 @@ def apply_function(self, fun, picks, dtype, n_jobs, *args, **kwargs):
                                       for p in picks)
             for pp, p in enumerate(picks):
                 self._data[p, :] = data_picks_new[pp]
+        return self
 
     @verbose
-    def apply_hilbert(self, picks, envelope=False, n_jobs=1, n_fft='auto',
+    def apply_hilbert(self, picks=None, envelope=False, n_jobs=1, n_fft='auto',
                       verbose=None):
         """Compute analytic signal or envelope for a subset of channels.
 
@@ -880,8 +887,9 @@ def apply_hilbert(self, picks, envelope=False, n_jobs=1, n_fft='auto',
 
         Parameters
         ----------
-        picks : array-like of int
-            Indices of channels to apply the function to.
+        picks : array-like of int (default: None)
+            Indices of channels to apply the function to. If None, all data
+            channels are used.
         envelope : bool (default: False)
             Compute the envelope signal of each channel.
         n_jobs: int
@@ -896,6 +904,11 @@ def apply_hilbert(self, picks, envelope=False, n_jobs=1, n_fft='auto',
             :func:`mne.verbose` and :ref:`Logging documentation <tut_logging>`
             for more). Defaults to self.verbose.
 
+        Returns
+        -------
+        self : instance of Raw
+            The raw object with transformed data.
+
         Notes
         -----
         The analytic signal "x_a(t)" of "x(t)" is::
@@ -926,11 +939,11 @@ def apply_hilbert(self, picks, envelope=False, n_jobs=1, n_fft='auto',
         if n_fft < self.n_times:
             raise ValueError("n_fft must be greater than n_times")
         if envelope is True:
-            self.apply_function(_my_hilbert, picks, None, n_jobs, n_fft,
-                                envelope=envelope)
+            dtype = None
         else:
-            self.apply_function(_my_hilbert, picks, np.complex64, n_jobs,
-                                n_fft, envelope=envelope)
+            dtype = np.complex64
+        return self.apply_function(_my_hilbert, picks, dtype, n_jobs, n_fft,
+                                   envelope=envelope)
 
     @verbose
     def filter(self, l_freq, h_freq, picks=None, filter_length='auto',
diff --git a/tutorials/plot_modifying_data_inplace.py b/tutorials/plot_modifying_data_inplace.py
--- a/tutorials/plot_modifying_data_inplace.py
+++ b/tutorials/plot_modifying_data_inplace.py
@@ -68,9 +68,9 @@
 
 # Take the amplitude and phase
 raw_amp = raw_hilb.copy()
-raw_amp.apply_function(np.abs, hilb_picks, float, 1)
+raw_amp.apply_function(np.abs, hilb_picks)
 raw_phase = raw_hilb.copy()
-raw_phase.apply_function(np.angle, hilb_picks, float, 1)
+raw_phase.apply_function(np.angle, hilb_picks)
 
 f, (a1, a2) = plt.subplots(2, 1, figsize=(15, 10))
 a1.plot(raw_band._data[hilb_picks[0]])


Test patch:
diff --git a/mne/io/tests/test_apply_function.py b/mne/io/tests/test_apply_function.py
--- a/mne/io/tests/test_apply_function.py
+++ b/mne/io/tests/test_apply_function.py
@@ -3,7 +3,7 @@
 # License: BSD (3-clause)
 
 import numpy as np
-from nose.tools import assert_equal, assert_raises
+from nose.tools import assert_equal, assert_raises, assert_true
 
 from mne import create_info
 from mne.io import RawArray
@@ -33,20 +33,17 @@ def test_apply_function_verbose():
     raw = RawArray(np.zeros((n_chan, n_times)),
                    create_info(ch_names, 1., 'mag'))
     # test return types in both code paths (parallel / 1 job)
-    assert_raises(TypeError, raw.apply_function, bad_1,
-                  None, None, 1)
-    assert_raises(ValueError, raw.apply_function, bad_2,
-                  None, None, 1)
-    assert_raises(TypeError, raw.apply_function, bad_1,
-                  None, None, 2)
-    assert_raises(ValueError, raw.apply_function, bad_2,
-                  None, None, 2)
+    assert_raises(TypeError, raw.apply_function, bad_1)
+    assert_raises(ValueError, raw.apply_function, bad_2)
+    assert_raises(TypeError, raw.apply_function, bad_1, n_jobs=2)
+    assert_raises(ValueError, raw.apply_function, bad_2, n_jobs=2)
 
     # check our arguments
     with catch_logging() as sio:
-        raw.apply_function(printer, None, None, 1, verbose=False)
+        out = raw.apply_function(printer, verbose=False)
         assert_equal(len(sio.getvalue()), 0)
-        raw.apply_function(printer, None, None, 1, verbose=True)
+        assert_true(out is raw)
+        raw.apply_function(printer, verbose=True)
         assert_equal(sio.getvalue().count('\n'), n_chan)
 
 run_tests_if_main()