[med-svn] [mne-python] 01/01: Imported Upstream version 0.7~rc3

Alexandre Gramfort agramfort-guest at moszumanska.debian.org
Sat Nov 23 14:41:40 UTC 2013


This is an automated email from the git hooks/post-receive script.

agramfort-guest pushed a commit to branch upstream
in repository mne-python.

commit 6f7c0563066ba434033479decec10815dc43e467
Author: Alexandre Gramfort <alexandre.gramfort at m4x.org>
Date:   Sat Nov 23 15:40:32 2013 +0100

    Imported Upstream version 0.7~rc3
---
 mne/decoding/classifier.py | 11 +++---
 mne/fiff/raw.py            | 15 ++++----
 mne/filter.py              | 91 +++++++++++++++++++++++++++-------------------
 mne/preprocessing/ssp.py   | 23 +++++++-----
 mne/tests/test_filter.py   | 22 +++++++++++
 mne/tests/test_viz.py      | 41 +++++++++++++++++++--
 6 files changed, 140 insertions(+), 63 deletions(-)

diff --git a/mne/decoding/classifier.py b/mne/decoding/classifier.py
index 05c9852..56b699c 100644
--- a/mne/decoding/classifier.py
+++ b/mne/decoding/classifier.py
@@ -302,16 +302,17 @@ class FilterEstimator(TransformerMixin):
     method : str
         'fft' will use overlap-add FIR filtering, 'iir' will use IIR
         forward-backward filtering (via filtfilt).
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     verbose : bool, str, int, or None
         If not None, override default verbose level (see mne.verbose).
         Defaults to self.verbose.
     """
     def __init__(self, info, l_freq, h_freq, picks=None, filter_length='10s',
                  l_trans_bandwidth=0.5, h_trans_bandwidth=0.5, n_jobs=1,
-                 method='fft', iir_params=dict(order=4, ftype='butter')):
+                 method='fft', iir_params=None):
         self.info = info
         self.l_freq = l_freq
         self.h_freq = h_freq
@@ -341,8 +342,8 @@ class FilterEstimator(TransformerMixin):
                              % type(epochs_data))
 
         if self.picks is None:
-            self.picks = pick_types(self.info, meg=True, eeg=True, ref_meg=False,
-                                    exclude=[])
+            self.picks = pick_types(self.info, meg=True, eeg=True,
+                                    ref_meg=False, exclude=[])
 
         if self.l_freq == 0:
             self.l_freq = None
diff --git a/mne/fiff/raw.py b/mne/fiff/raw.py
index 5c0032a..0fd2db6 100644
--- a/mne/fiff/raw.py
+++ b/mne/fiff/raw.py
@@ -520,8 +520,7 @@ class Raw(ProjMixin):
     @verbose
     def filter(self, l_freq, h_freq, picks=None, filter_length='10s',
                l_trans_bandwidth=0.5, h_trans_bandwidth=0.5, n_jobs=1,
-               method='fft', iir_params=dict(order=4, ftype='butter'),
-               verbose=None):
+               method='fft', iir_params=None, verbose=None):
         """Filter a subset of channels.
 
         Applies a zero-phase low-pass, high-pass, band-pass, or band-stop
@@ -570,9 +569,10 @@ class Raw(ProjMixin):
         method : str
             'fft' will use overlap-add FIR filtering, 'iir' will use IIR
             forward-backward filtering (via filtfilt).
-        iir_params : dict
+        iir_params : dict | None
             Dictionary of parameters to use for IIR filtering.
-            See mne.filter.construct_iir_filter for details.
+            See mne.filter.construct_iir_filter for details. If iir_params
+            is None and method="iir", 4th order Butterworth will be used.
         verbose : bool, str, int, or None
             If not None, override default verbose level (see mne.verbose).
             Defaults to self.verbose.
@@ -649,7 +649,7 @@ class Raw(ProjMixin):
     @verbose
     def notch_filter(self, freqs, picks=None, filter_length='10s',
                      notch_widths=None, trans_bandwidth=1.0, n_jobs=1,
-                     method='fft', iir_params=dict(order=4, ftype='butter'),
+                     method='fft', iir_params=None,
                      mt_bandwidth=None, p_value=0.05, verbose=None):
         """Notch filter a subset of channels.
 
@@ -690,9 +690,10 @@ class Raw(ProjMixin):
             'fft' will use overlap-add FIR filtering, 'iir' will use IIR
             forward-backward filtering (via filtfilt). 'spectrum_fit' will
             use multi-taper estimation of sinusoidal components.
-        iir_params : dict
+        iir_params : dict | None
             Dictionary of parameters to use for IIR filtering.
-            See mne.filter.construct_iir_filter for details.
+            See mne.filter.construct_iir_filter for details. If iir_params
+            is None and method="iir", 4th order Butterworth will be used.
         mt_bandwidth : float | None
             The bandwidth of the multitaper windowing function in Hz.
             Only used in 'spectrum_fit' mode.
diff --git a/mne/filter.py b/mne/filter.py
index 70adb9a..5ca7f8c 100644
--- a/mne/filter.py
+++ b/mne/filter.py
@@ -345,10 +345,20 @@ def _filter(x, Fs, freq, gain, filter_length='10s', picks=None, n_jobs=1,
     return x
 
 
+def _check_coefficients(b, a):
+    """Check for filter stability"""
+    z, p, k = signal.tf2zpk(b, a)
+    if np.any(np.abs(p) > 1.0):
+        raise RuntimeError('Filter poles outside unit circle, filter will be '
+                           'unstable. Consider using different filter '
+                           'coefficients.')
+
+
 def _filtfilt(x, b, a, padlen, picks, n_jobs, copy):
     """Helper to more easily call filtfilt"""
     # set up array for filtering, reshape to 2D, operate on last axis
     x, orig_shape, picks = _prep_for_filtering(x, copy, picks)
+    _check_coefficients(b, a)
     if n_jobs == 1:
         for p in picks:
             x[p] = filtfilt(b, a, x[p], padlen=padlen)
@@ -502,10 +512,29 @@ def construct_iir_filter(iir_params=dict(b=[1, 0], a=[1, 0], padlen=0),
     return iir_params
 
 
+def _check_method(method, iir_params, extra_types):
+    """Helper to parse method arguments"""
+    allowed_types = ['iir', 'fft'] + extra_types
+    if not isinstance(method, basestring):
+        raise TypeError('method must be a string')
+    if method not in allowed_types:
+        raise ValueError('method must be one of %s, not "%s"'
+                         % (allowed_types, method))
+    if method == 'iir':
+        if iir_params is None:
+            iir_params = dict(order=4, ftype='butter')
+        if not isinstance(iir_params, dict) or 'ftype' not in iir_params:
+            raise ValueError('iir_params must be a dict with entry "ftype"')
+    elif iir_params is not None:
+        raise ValueError('iir_params must be None if method != "iir"')
+    method = method.lower()
+    return iir_params
+
+
 @verbose
 def band_pass_filter(x, Fs, Fp1, Fp2, filter_length='10s',
                      l_trans_bandwidth=0.5, h_trans_bandwidth=0.5,
-                     method='fft', iir_params=dict(order=4, ftype='butter'),
+                     method='fft', iir_params=None,
                      picks=None, n_jobs=1, copy=True, verbose=None):
     """Bandpass filter for the signal x.
 
@@ -536,9 +565,10 @@ def band_pass_filter(x, Fs, Fp1, Fp2, filter_length='10s',
     method : str
         'fft' will use overlap-add FIR filtering, 'iir' will use IIR
         forward-backward filtering (via filtfilt).
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     picks : list of int | None
         Indices to filter. If None all indices will be filtered.
     n_jobs : int | str
@@ -571,10 +601,7 @@ def band_pass_filter(x, Fs, Fp1, Fp2, filter_length='10s',
     Fs1 = Fp1 - l_trans_bandwidth in Hz
     Fs2 = Fp2 + h_trans_bandwidth in Hz
     """
-
-    method = method.lower()
-    if method not in ['fft', 'iir']:
-        raise RuntimeError('method should be fft or iir (not %s)' % method)
+    iir_params = _check_method(method, iir_params, [])
 
     Fs = float(Fs)
     Fp1 = float(Fp1)
@@ -607,7 +634,7 @@ def band_pass_filter(x, Fs, Fp1, Fp2, filter_length='10s',
 @verbose
 def band_stop_filter(x, Fs, Fp1, Fp2, filter_length='10s',
                      l_trans_bandwidth=0.5, h_trans_bandwidth=0.5,
-                     method='fft', iir_params=dict(order=4, ftype='butter'),
+                     method='fft', iir_params=None,
                      picks=None, n_jobs=1, copy=True, verbose=None):
     """Bandstop filter for the signal x.
 
@@ -638,9 +665,10 @@ def band_stop_filter(x, Fs, Fp1, Fp2, filter_length='10s',
     method : str
         'fft' will use overlap-add FIR filtering, 'iir' will use IIR
         forward-backward filtering (via filtfilt).
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     picks : list of int | None
         Indices to filter. If None all indices will be filtered.
     n_jobs : int | str
@@ -675,10 +703,8 @@ def band_stop_filter(x, Fs, Fp1, Fp2, filter_length='10s',
 
     Note that multiple stop bands can be specified using arrays.
     """
+    iir_params = _check_method(method, iir_params, [])
 
-    method = method.lower()
-    if method not in ['fft', 'iir']:
-        raise RuntimeError('method should be fft or iir (not %s)' % method)
     Fp1 = np.atleast_1d(Fp1)
     Fp2 = np.atleast_1d(Fp2)
     if not len(Fp1) == len(Fp2):
@@ -718,7 +744,7 @@ def band_stop_filter(x, Fs, Fp1, Fp2, filter_length='10s',
 
 @verbose
 def low_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
-                    method='fft', iir_params=dict(order=4, ftype='butter'),
+                    method='fft', iir_params=None,
                     picks=None, n_jobs=1, copy=True, verbose=None):
     """Lowpass filter for the signal x.
 
@@ -745,9 +771,10 @@ def low_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
     method : str
         'fft' will use overlap-add FIR filtering, 'iir' will use IIR
         forward-backward filtering (via filtfilt).
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     picks : list of int | None
         Indices to filter. If None all indices will be filtered.
     n_jobs : int | str
@@ -777,11 +804,7 @@ def low_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
                               Fp  Fp+trans_bandwidth
 
     """
-
-    method = method.lower()
-    if method not in ['fft', 'iir']:
-        raise RuntimeError('method should be fft or iir (not %s)' % method)
-
+    iir_params = _check_method(method, iir_params, [])
     Fs = float(Fs)
     Fp = float(Fp)
     Fstop = Fp + trans_bandwidth
@@ -804,7 +827,7 @@ def low_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
 
 @verbose
 def high_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
-                     method='fft', iir_params=dict(order=4, ftype='butter'),
+                     method='fft', iir_params=None,
                      picks=None, n_jobs=1, copy=True, verbose=None):
     """Highpass filter for the signal x.
 
@@ -831,9 +854,10 @@ def high_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
     method : str
         'fft' will use overlap-add FIR filtering, 'iir' will use IIR
         forward-backward filtering (via filtfilt).
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     picks : list of int | None
         Indices to filter. If None all indices will be filtered.
     n_jobs : int | str
@@ -864,11 +888,7 @@ def high_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
 
     where Fstop = Fp - trans_bandwidth
     """
-
-    method = method.lower()
-    if method not in ['fft', 'iir']:
-        raise RuntimeError('method should be fft or iir (not %s)' % method)
-
+    iir_params = _check_method(method, iir_params, [])
     Fs = float(Fs)
     Fp = float(Fp)
 
@@ -894,7 +914,7 @@ def high_pass_filter(x, Fs, Fp, filter_length='10s', trans_bandwidth=0.5,
 @verbose
 def notch_filter(x, Fs, freqs, filter_length='10s', notch_widths=None,
                  trans_bandwidth=1, method='fft',
-                 iir_params=dict(order=4, ftype='butter'), mt_bandwidth=None,
+                 iir_params=None, mt_bandwidth=None,
                  p_value=0.05, picks=None, n_jobs=1, copy=True, verbose=None):
     """Notch filter for the signal x.
 
@@ -929,9 +949,10 @@ def notch_filter(x, Fs, freqs, filter_length='10s', notch_widths=None,
         use multi-taper estimation of sinusoidal components. If freqs=None
         and method='spectrum_fit', significant sinusoidal components
         are detected using an F test, and noted by logging.
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     mt_bandwidth : float | None
         The bandwidth of the multitaper windowing function in Hz.
         Only used in 'spectrum_fit' mode.
@@ -979,11 +1000,7 @@ def notch_filter(x, Fs, freqs, filter_length='10s', notch_widths=None,
     & Hemant Bokil, Oxford University Press, New York, 2008. Please
     cite this in publications if method 'spectrum_fit' is used.
     """
-
-    method = method.lower()
-    if method not in ['fft', 'iir', 'spectrum_fit']:
-        raise RuntimeError('method should be fft, iir, or spectrum_fit '
-                           '(not %s)' % method)
+    iir_params = _check_method(method, iir_params, ['spectrum_fit'])
 
     if freqs is not None:
         freqs = np.atleast_1d(freqs)
diff --git a/mne/preprocessing/ssp.py b/mne/preprocessing/ssp.py
index f1f77bf..d6727d4 100644
--- a/mne/preprocessing/ssp.py
+++ b/mne/preprocessing/ssp.py
@@ -31,8 +31,7 @@ def _compute_exg_proj(mode, raw, raw_event, tmin, tmax,
                       average, filter_length, n_jobs, ch_name,
                       reject, flat, bads, avg_ref, no_proj, event_id,
                       exg_l_freq, exg_h_freq, tstart, qrs_threshold,
-                      filter_method, iir_params=dict(order=4, ftype='butter'),
-                      verbose=None):
+                      filter_method, iir_params=None, verbose=None):
     """Compute SSP/PCA projections for ECG or EOG artifacts
 
     Note: raw has to be constructed with preload=True (or string)
@@ -92,9 +91,10 @@ def _compute_exg_proj(mode, raw, raw_event, tmin, tmax,
         number of heartbeats (40-160 beats / min). Only for ECG.
     filter_method : str
         Method for filtering ('iir' or 'fft').
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     verbose : bool, str, int, or None
         If not None, override default verbose level (see mne.verbose).
 
@@ -217,8 +217,7 @@ def compute_proj_ecg(raw, raw_event=None, tmin=-0.2, tmax=0.4,
                      flat=None, bads=[], avg_ref=False,
                      no_proj=False, event_id=999, ecg_l_freq=5, ecg_h_freq=35,
                      tstart=0., qrs_threshold='auto', filter_method='fft',
-                     iir_params=dict(order=4, ftype='butter'),
-                     copy=True, verbose=None):
+                     iir_params=None, copy=True, verbose=None):
     """Compute SSP/PCA projections for ECG artifacts
 
     Note: raw has to be constructed with preload=True (or string)
@@ -276,9 +275,10 @@ def compute_proj_ecg(raw, raw_event=None, tmin=-0.2, tmax=0.4,
         number of heartbeats (40-160 beats / min).
     filter_method : str
         Method for filtering ('iir' or 'fft').
-    iir_params : dict
+    iir_params : dict | None
         Dictionary of parameters to use for IIR filtering.
-        See mne.filter.construct_iir_filter for details.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     copy : bool
         If False, filtering raw data is done in place. Defaults to True.
     verbose : bool, str, int, or None
@@ -313,8 +313,7 @@ def compute_proj_eog(raw, raw_event=None, tmin=-0.2, tmax=0.2,
                                  eog=np.inf), flat=None, bads=[],
                      avg_ref=False, no_proj=False, event_id=998, eog_l_freq=1,
                      eog_h_freq=10, tstart=0., filter_method='fft',
-                     iir_params=dict(order=4, ftype='butter'), ch_name=None,
-                     copy=True, verbose=None):
+                     iir_params=None, ch_name=None, copy=True, verbose=None):
     """Compute SSP/PCA projections for EOG artifacts
 
     Note: raw has to be constructed with preload=True (or string)
@@ -368,6 +367,10 @@ def compute_proj_eog(raw, raw_event=None, tmin=-0.2, tmax=0.2,
         Start artifact detection after tstart seconds.
     filter_method : str
         Method for filtering ('iir' or 'fft').
+    iir_params : dict | None
+        Dictionary of parameters to use for IIR filtering.
+        See mne.filter.construct_iir_filter for details. If iir_params
+        is None and method="iir", 4th order Butterworth will be used.
     copy : bool
         If False, filtering raw data is done in place. Defaults to True.
     ch_name: str | None
diff --git a/mne/tests/test_filter.py b/mne/tests/test_filter.py
index 56b0230..5e929d2 100644
--- a/mne/tests/test_filter.py
+++ b/mne/tests/test_filter.py
@@ -19,6 +19,28 @@ tempdir = _TempDir()
 log_file = op.join(tempdir, 'temp_log.txt')
 
 
+def test_iir_stability():
+    """Test IIR filter stability check
+    """
+    sig = np.empty(1000)
+    fs = 1000
+    # This will make an unstable filter, should throw RuntimeError
+    assert_raises(RuntimeError, high_pass_filter, sig, fs, 0.6,
+                  method='iir', iir_params=dict(ftype='butter', order=8))
+    # can't pass iir_params if method='fir'
+    assert_raises(ValueError, high_pass_filter, sig, fs, 0.1,
+                  method='fir', iir_params=dict(ftype='butter', order=2))
+    # method must be string
+    assert_raises(TypeError, high_pass_filter, sig, fs, 0.1,
+                  method=1)
+    # unknown method
+    assert_raises(ValueError, high_pass_filter, sig, fs, 0.1,
+                  method='blah')
+    # bad iir_params
+    assert_raises(ValueError, high_pass_filter, sig, fs, 0.1,
+                  method='fir', iir_params='blah')
+
+
 def test_notch_filters():
     """Test notch filters
     """
diff --git a/mne/tests/test_viz.py b/mne/tests/test_viz.py
index 583c398..0dbbc24 100644
--- a/mne/tests/test_viz.py
+++ b/mne/tests/test_viz.py
@@ -1,7 +1,7 @@
 import os.path as op
 from functools import wraps
 import numpy as np
-from numpy.testing import assert_raises
+from numpy.testing import assert_raises, assert_equal
 import warnings
 
 from mne import fiff, read_events, Epochs, SourceEstimate, read_cov, read_proj
@@ -68,6 +68,20 @@ n_chan = 15
 layout = read_layout('Vectorview-all')
 
 
+def _fake_click(fig, ax, point, xform='ax'):
+    """Helper to fake a click at a relative point within axes"""
+    if xform == 'ax':
+        x, y = ax.transAxes.transform_point(point)
+    elif xform == 'data':
+        x, y = ax.transData.transform_point(point)
+    else:
+        raise ValueError('unknown transform')
+    try:
+        fig.canvas.button_press_event(x, y, 1, False, None)
+    except:  # for old MPL
+        fig.canvas.button_press_event(x, y, 1, False)
+
+
 def _get_raw():
     return fiff.Raw(raw_fname, preload=False)
 
@@ -360,9 +374,28 @@ def test_plot_raw():
     """
     raw = _get_raw()
     events = _get_events()
+    plt.close('all')  # ensure all are closed
     fig = raw.plot(events=events, show_options=True)
-    # test mouse clicks (XXX not complete yet)
-    fig.canvas.button_press_event(0.5, 0.5, 1)
+    # test mouse clicks
+    x = fig.get_axes()[0].lines[1].get_xdata().mean()
+    y = fig.get_axes()[0].lines[1].get_ydata().mean()
+    data_ax = fig.get_axes()[0]
+    _fake_click(fig, data_ax, [x, y], xform='data')  # mark a bad channel
+    _fake_click(fig, data_ax, [x, y], xform='data')  # unmark a bad channel
+    _fake_click(fig, data_ax, [0.5, 0.999])  # click elsewhere in first axes
+    _fake_click(fig, fig.get_axes()[1], [0.5, 0.5])  # change time
+    _fake_click(fig, fig.get_axes()[2], [0.5, 0.5])  # change channels
+    _fake_click(fig, fig.get_axes()[3], [0.5, 0.5])  # open SSP window
+    fig.canvas.button_press_event(1, 1, 1)  # outside any axes
+    # sadly these fail when no renderer is used (i.e., when using Agg):
+    #ssp_fig = set(plt.get_fignums()) - set([fig.number])
+    #assert_equal(len(ssp_fig), 1)
+    #ssp_fig = plt.figure(list(ssp_fig)[0])
+    #ax = ssp_fig.get_axes()[0]  # only one axis is used
+    #t = [c for c in ax.get_children() if isinstance(c, matplotlib.text.Text)]
+    #pos = np.array(t[0].get_position()) + 0.01
+    #_fake_click(ssp_fig, ssp_fig.get_axes()[0], pos, xform='data')  # off
+    #_fake_click(ssp_fig, ssp_fig.get_axes()[0], pos, xform='data')  # on
     # test keypresses
     fig.canvas.key_press_event('escape')
     fig.canvas.key_press_event('down')
@@ -393,7 +426,7 @@ def test_plot_raw_psds():
 
 @sample.requires_sample_data
 def test_plot_topomap():
-    """Testing topomap plotting
+    """Test topomap plotting
     """
     # evoked
     evoked = fiff.read_evoked(evoked_fname, 'Left Auditory',

-- 
Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/mne-python.git



More information about the debian-med-commit mailing list