diff --git a/bin/mne_clean_eog_ecg.py b/bin/mne_clean_eog_ecg.py index 01d3ca36d20..f12e73b3e13 100755 --- a/bin/mne_clean_eog_ecg.py +++ b/bin/mne_clean_eog_ecg.py @@ -56,7 +56,7 @@ def clean_ecg_eog(in_fif_fname, out_fif_fname=None, eog=True, ecg=True, print 'Implementing ECG and EOG artifact rejection on data' if ecg: - ecg_events, _, _ = mne.artifacts.find_ecg_events(raw_in) + ecg_events, _, _ = mne.preprocessing.find_ecg_events(raw_in) print "Writing ECG events in %s" % ecg_event_fname mne.write_events(ecg_event_fname, ecg_events) @@ -73,7 +73,7 @@ def clean_ecg_eog(in_fif_fname, out_fif_fname=None, eog=True, ecg=True, print "Error while running : %s" % command if eog: - eog_events = mne.artifacts.find_eog_events(raw_in) + eog_events = mne.preprocessing.find_eog_events(raw_in) print "Writing EOG events in %s" % eog_event_fname mne.write_events(eog_event_fname, eog_events) diff --git a/doc/source/python_reference.rst b/doc/source/python_reference.rst index 120278ef829..f04379eb934 100644 --- a/doc/source/python_reference.rst +++ b/doc/source/python_reference.rst @@ -22,7 +22,7 @@ Classes reference mne.SourceEstimate mne.Label mne.BiHemiLabel - mne.artifacts.ICA + mne.preprocessing.ICA Functions reference =================== @@ -181,16 +181,18 @@ Functions reference plot_topo_image_epochs mne_analyze_colormap -.. automodule:: mne.artifacts +.. automodule:: mne.preprocessing :no-members: :no-inherited-members: -.. currentmodule:: mne.artifacts +.. currentmodule:: mne.preprocessing .. autosummary:: :toctree: generated/ :template: function.rst + compute_proj_ecg + compute_proj_eog find_eog_events find_ecg_events ica_find_eog_events diff --git a/doc/source/whats_new.rst b/doc/source/whats_new.rst index 30a41fa963b..7ec92372414 100644 --- a/doc/source/whats_new.rst +++ b/doc/source/whats_new.rst @@ -73,6 +73,8 @@ API - Use raw.time_as_index instead of time_to_index (still works but is deprecated). + - The artifacts module (mne.artifacts) is now merged into mne.preprocessing + .. _changes_0_4: Version 0.4 diff --git a/mne/artifacts/__init__.py b/mne/artifacts/__init__.py index e4a6a8127ca..a5c1698dd72 100644 --- a/mne/artifacts/__init__.py +++ b/mne/artifacts/__init__.py @@ -1,6 +1,11 @@ """Artifacts finding/correction related functions """ -from .eog import find_eog_events -from .ecg import find_ecg_events -from .ica import ICA, ica_find_eog_events, ica_find_ecg_events, score_funcs \ No newline at end of file +from ..utils import deprecated +from ..preprocessing import find_eog_events, find_ecg_events + +_preprocessing = ('The artifacts module will no longer be supported in v0.6.' + ' Please use the preprocessing module instead.') + +find_eog_events = deprecated(_preprocessing)(find_eog_events) +find_ecg_events = deprecated(_preprocessing)(find_ecg_events) diff --git a/mne/artifacts/ecg.py b/mne/artifacts/ecg.py deleted file mode 100644 index ee07eba7db2..00000000000 --- a/mne/artifacts/ecg.py +++ /dev/null @@ -1,167 +0,0 @@ -import numpy as np - -import logging -logger = logging.getLogger('mne') - -from .. import fiff, verbose -from ..filter import band_pass_filter -from ..utils import deprecated - -_preprocessing = ('The artifacts module will no longer be supported.' - ' Please use the preprocessing module instead.') - - -@deprecated(_preprocessing) -def qrs_detector(sfreq, ecg, thresh_value=0.6, levels=2.5, n_thresh=3, - l_freq=5, h_freq=35, tstart=0): - """Detect QRS component in ECG channels. - - QRS is the main wave on the heart beat. - - Parameters - ---------- - sfreq : float - Sampling rate - ecg : array - ECG signal - thresh_value: float - qrs detection threshold - levels: float - number of std from mean to include for detection - n_thresh: int - max number of crossings - l_freq: float - Low pass frequency - h_freq: float - High pass frequency - tstart: float - Start detection after tstart seconds. - - Returns - ------- - events : array - Indices of ECG peaks - """ - win_size = round((60.0 * sfreq) / 120.0) - - filtecg = band_pass_filter(ecg, sfreq, l_freq, h_freq) - - absecg = np.abs(filtecg) - init = int(sfreq) - - n_samples_start = int(init * tstart) - absecg = absecg[n_samples_start:] - - n_points = len(absecg) - - maxpt = np.empty(3) - maxpt[0] = np.max(absecg[:init]) - maxpt[1] = np.max(absecg[init:init * 2]) - maxpt[2] = np.max(absecg[init * 2:init * 3]) - - init_max = np.mean(maxpt) - - thresh1 = init_max * thresh_value - - numcross = [] - time = [] - rms = [] - i = 0 - while i < (n_points - win_size): - window = absecg[i:i + win_size] - if window[0] > thresh1: - maxTime = np.argmax(window) - time.append(i + maxTime) - numcross.append(np.sum(np.diff((window > thresh1).astype(np.int) - == 1))) - rms.append(np.sqrt(np.mean(window ** 2))) - i += win_size - else: - i += 1 - - time = np.array(time) - rms_mean = np.mean(rms) - rms_std = np.std(rms) - rms_thresh = rms_mean + (rms_std * levels) - b = np.where(rms < rms_thresh)[0] - a = np.array(numcross)[b] - clean_events = time[b[a < n_thresh]] - - clean_events += n_samples_start - - return clean_events - - -@deprecated(_preprocessing) -@verbose -def find_ecg_events(raw, event_id=999, ch_name=None, tstart=0.0, - l_freq=5, h_freq=35, qrs_threshold=0.6, verbose=None): - """Find ECG peaks - - Parameters - ---------- - raw : instance of Raw - The raw data - event_id : int - The index to assign to found events - ch_name : str - The name of the channel to use for ECG peak detection. - The argument is mandatory if the dataset contains no ECG - channels. - tstart : float - Start detection after tstart seconds. Useful when beginning - of run is noisy. - l_freq : float - Low pass frequency. - h_freq : float - High pass frequency. - qrs_threshold : float - Between 0 and 1. qrs detection threshold. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - - Returns - ------- - ecg_events : array - Events. - ch_ECG : string - Name of channel used. - average_pulse : float - Estimated average pulse. - """ - info = raw.info - - # Geting ECG Channel - if ch_name is None: - ch_ECG = fiff.pick_types(info, meg=False, eeg=False, stim=False, - eog=False, ecg=True, emg=False) - else: - ch_ECG = fiff.pick_channels(raw.ch_names, include=[ch_name]) - if len(ch_ECG) == 0: - raise ValueError('%s not in channel list (%s)' % - (ch_name, raw.ch_names)) - - if len(ch_ECG) == 0 and ch_name is None: - raise Exception('No ECG channel found. Please specify ch_name ' - 'parameter e.g. MEG 1531') - - assert len(ch_ECG) == 1 - - logger.info('Using channel %s to identify heart beats' - % raw.ch_names[ch_ECG[0]]) - - ecg, times = raw[ch_ECG, :] - - # detecting QRS and generating event file - ecg_events = qrs_detector(info['sfreq'], ecg.ravel(), tstart=tstart, - thresh_value=qrs_threshold, l_freq=l_freq, - h_freq=h_freq) - - n_events = len(ecg_events) - average_pulse = n_events * 60.0 / (times[-1] - times[0]) - logger.info("Number of ECG events detected : %d (average pulse %d / " - "min.)" % (n_events, average_pulse)) - - ecg_events = np.c_[ecg_events + raw.first_samp, np.zeros(n_events), - event_id * np.ones(n_events)] - return ecg_events, ch_ECG, average_pulse diff --git a/mne/artifacts/eog.py b/mne/artifacts/eog.py deleted file mode 100644 index ba2d4e47f8c..00000000000 --- a/mne/artifacts/eog.py +++ /dev/null @@ -1,96 +0,0 @@ -import numpy as np - -import logging -logger = logging.getLogger('mne') - -from .peak_finder import peak_finder -from .. import fiff, verbose -from ..filter import band_pass_filter -from .. utils import deprecated - - -_preprocessing = ('The artifacts module will no longer be supported.' - ' Please use the preprocessing module instead.') - - -@deprecated(_preprocessing) -@verbose -def find_eog_events(raw, event_id=998, l_freq=1, h_freq=10, verbose=None): - """Locate EOG artifacts - - Parameters - ---------- - raw : instance of Raw - The raw data. - event_id : int - The index to assign to found events. - low_pass : float - Low pass frequency. - high_pass : float - High pass frequency. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - - Returns - ------- - eog_events : array - Events. - """ - info = raw.info - - # Geting EOG Channel - ch_EOG = fiff.pick_types(info, meg=False, eeg=False, stim=False, - eog=True, ecg=False, emg=False) - - if len(ch_EOG) == 0: - logger.info('No EOG channels found') - logger.info('Trying with EEG 061 and EEG 062') - ch_EOG = fiff.pick_channels(raw.ch_names, - include=['EEG 061', 'EEG 062']) - if len(ch_EOG) != 2: - raise ValueError('EEG 61 or EEG 62 channel not found !!') - - logger.info('EOG channel index for this subject is: %s' % ch_EOG) - - eog, _ = raw[ch_EOG, :] - - eog_events = _find_eog_events(eog, event_id=event_id, l_freq=l_freq, - h_freq=h_freq, - sampling_rate=raw.info['sfreq'], - first_samp=raw.first_samp) - - return eog_events - - -@deprecated(_preprocessing) -def _find_eog_events(eog, event_id, l_freq, h_freq, sampling_rate, first_samp): - """Helper function""" - - logger.info('Filtering the data to remove DC offset to help ' - 'distinguish blinks from saccades') - - # filtering to remove dc offset so that we know which is blink and saccades - filteog = np.array([band_pass_filter(x, sampling_rate, 2, 45) for x in eog]) - temp = np.sqrt(np.sum(filteog ** 2, axis=1)) - - indexmax = np.argmax(temp) - - # easier to detect peaks with filtering. - filteog = band_pass_filter(eog[indexmax], sampling_rate, l_freq, h_freq) - - # detecting eog blinks and generating event file - - logger.info('Now detecting blinks and generating corresponding events') - - temp = filteog - np.mean(filteog) - if np.abs(np.max(temp)) > np.abs(np.min(temp)): - eog_events, _ = peak_finder(filteog, extrema=1) - else: - eog_events, _ = peak_finder(filteog, extrema=-1) - - n_events = len(eog_events) - logger.info("Number of EOG events detected : %d" % n_events) - eog_events = np.c_[eog_events + first_samp, np.zeros(n_events), - event_id * np.ones(n_events)] - - return eog_events diff --git a/mne/artifacts/ica.py b/mne/artifacts/ica.py deleted file mode 100644 index 8ed8573b06f..00000000000 --- a/mne/artifacts/ica.py +++ /dev/null @@ -1,958 +0,0 @@ -# Authors: Alexandre Gramfort -# Matti Hamalainen -# Denis Engemann -# -# License: BSD (3-clause) - -from copy import deepcopy -import inspect -import warnings -from inspect import getargspec, isfunction - -import logging -logger = logging.getLogger('mne') - -import numpy as np -from scipy import stats -from scipy.spatial import distance -from scipy import linalg - -from .ecg import qrs_detector -from .eog import _find_eog_events - -from ..cov import compute_whitener -from ..fiff import pick_types, pick_channels -from ..fiff.constants import Bunch, FIFF -from ..viz import plot_ica_panel -from .. import verbose -from .. utils import deprecated - - -def _make_xy_sfunc(func, ndim_output=False): - """Helper Function""" - if ndim_output: - sfunc = lambda x, y: np.array([func(a, y.ravel()) for a in x])[:, 0] - else: - sfunc = lambda x, y: np.array([func(a, y.ravel()) for a in x]) - sfunc.__name__ = '.'.join(['score_func', func.__module__, func.__name__]) - sfunc.__doc__ = func.__doc__ - return sfunc - -# makes score funcs attr accessible for users -score_funcs = Bunch() - -xy_arg_dist_funcs = [(n, f) for n, f in vars(distance).items() if isfunction(f) - and not n.startswith('_')] - -xy_arg_stats_funcs = [(n, f) for n, f in vars(stats).items() if isfunction(f) - and not n.startswith('_')] - -score_funcs.update(dict((n, _make_xy_sfunc(f)) for n, f in xy_arg_dist_funcs - if getargspec(f).args == ['u', 'v'])) - -score_funcs.update(dict((n, _make_xy_sfunc(f, ndim_output=True)) - for n, f in xy_arg_stats_funcs - if getargspec(f).args == ['x', 'y'])) - - -__all__ = ['ICA', 'ica_find_ecg_events', 'ica_find_eog_events', 'score_funcs'] - -_preprocessing = ('The artifacts module will no longer be supported.' - ' Please use the preprocessing module instead.') - - -class ICA(object): - """M/EEG signal decomposition using Independent Component Analysis (ICA) - - This object can be used to estimate ICA components and then - remove some from Raw or Epochs for data exploration or artifact - correction. - - Parameters - ---------- - n_components : int | float | None - The number of components used for ICA decomposition. If int, it must be - smaller then max_n_components. If None, all PCA components will be - used. If float between 0 and 1 components can will be selected by the - cumulative percentage of explained variance. - max_n_components : int | None - The number of components used for PCA decomposition. If None, no - dimension reduction will be applied and max_n_components will equal - the number of channels supplied on decomposing data. - noise_cov : None | instance of mne.cov.Covariance - Noise covariance used for whitening. If None, channels are just - z-scored. - random_state : None | int | instance of np.random.RandomState - np.random.RandomState to initialize the FastICA estimation. - As the estimation is non-deterministic it can be useful to - fix the seed to have reproducible results. - algorithm : {'parallel', 'deflation'} - Apply parallel or deflational algorithm for FastICA - fun : string or function, optional. Default: 'logcosh' - The functional form of the G function used in the - approximation to neg-entropy. Could be either 'logcosh', 'exp', - or 'cube'. - You can also provide your own function. It should return a tuple - containing the value of the function, and of its derivative, in the - point. - fun_args: dictionary, optional - Arguments to send to the functional form. - If empty and if fun='logcosh', fun_args will take value - {'alpha' : 1.0} - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - - Attributes - ---------- - last_fit : str - Flag informing about which type was last fit. - ch_names : list-like - Channel names resulting from initial picking. - n_components : int - The number of components used for ICA decomposition. - max_n_components : int - The number of PCA dimensions computed. - verbose : bool, str, int, or None - See above. - """ - @deprecated(_preprocessing) - @verbose - def __init__(self, n_components, max_n_components=100, noise_cov=None, - random_state=None, algorithm='parallel', fun='logcosh', - fun_args=None, verbose=None): - try: - from sklearn.decomposition import FastICA # to avoid strong dep. - except ImportError: - raise Exception('the scikit-learn package is missing and ' - 'required for ICA') - self.noise_cov = noise_cov - - # sklearn < 0.11 does not support random_state argument for FastICA - kwargs = {'algorithm': algorithm, 'fun': fun, 'fun_args': fun_args} - - if random_state is not None: - aspec = inspect.getargspec(FastICA.__init__) - if 'random_state' not in aspec.args: - warnings.warn('random_state argument ignored, update ' - 'scikit-learn to version 0.11 or newer') - else: - kwargs['random_state'] = random_state - - if max_n_components is not None and n_components > max_n_components: - raise ValueError('n_components must be smaller than ' - 'max_n_components') - - if isinstance(n_components, float): - if not 0 < n_components <= 1: - raise ValueError('For selecting ICA components by the ' - 'explained variance of PCA components the' - ' float value must be between 0.0 and 1.0 ') - self._explained_var = n_components - logger.info('Selecting pca_components via explained variance.') - else: - self._explained_var = 1.1 - logger.info('Selecting pca_components directly.') - - self._ica = FastICA(**kwargs) - self.current_fit = 'unfitted' - self.verbose = verbose - self.n_components = n_components - self.max_n_components = max_n_components - self.ch_names = None - self._mixing = None - - def __repr__(self): - s = 'ICA ' - if self.current_fit == 'unfitted': - msg = '(no' - elif self.current_fit == 'raw': - msg = '(raw data' - else: - msg = '(epochs' - msg += ' decomposition, ' - - s += msg + ('%s components' % str(self.n_components) if - self.n_components else 'no dimension reduction') + ')' - - return s - - @deprecated(_preprocessing) - @verbose - def decompose_raw(self, raw, picks=None, start=None, stop=None, - verbose=None): - """Run the ICA decomposition on raw data - - Parameters - ---------- - raw : instance of mne.fiff.Raw - Raw measurements to be decomposed. - picks : array-like - Channels to be included. This selection remains throughout the - initialized ICA session. If None only good data channels are used. - start : int - First sample to include (first is 0). If omitted, defaults to the - first sample in data. - stop : int - First sample to not include. If omitted, data is included to the - end. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - Defaults to self.verbose. - - Returns - ------- - self : instance of ICA - Returns the modified instance. - """ - if self.current_fit != 'unfitted': - raise RuntimeError('ICA decomposition has already been fitted. ' - 'Please start a new ICA session.') - - logger.info('Computing signal decomposition on raw data. ' - 'Please be patient, this may take some time') - - if picks is None: # just use good data channels - picks = pick_types(raw.info, meg=True, eeg=True, eog=False, - ecg=False, misc=False, stim=False, - exclude=raw.info['bads']) - - if self.max_n_components is None: - self.max_n_components = len(picks) - logger.info('Inferring max_n_components from picks.') - - self.ch_names = [raw.ch_names[k] for k in picks] - - data, self._pre_whitener = self._pre_whiten(raw[picks, start:stop][0], - raw.info, picks) - - to_ica, self._pca = self._prepare_pca(data, self.max_n_components) - - self._ica.fit(to_ica) - self._mixing = self._ica.get_mixing_matrix().T - self.current_fit = 'raw' - - return self - - @deprecated(_preprocessing) - @verbose - def decompose_epochs(self, epochs, picks=None, verbose=None): - """Run the ICA decomposition on epochs - - Parameters - ---------- - epochs : instance of Epochs - The epochs. The ICA is estimated on the concatenated epochs. - picks : array-like - Channels to be included relative to the channels already picked on - epochs-initialization. This selection remains throughout the - initialized ICA session. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - Defaults to self.verbose. - - Returns - ------- - self : instance of ICA - Returns the modified instance. - """ - if self.current_fit != 'unfitted': - raise RuntimeError('ICA decomposition has already been fitted. ' - 'Please start a new ICA session.') - - logger.info('Computing signal decomposition on epochs. ' - 'Please be patient, this may take some time') - - if picks is None: # just use epochs good data channels and avoid - picks = pick_types(epochs.info, include=epochs.ch_names, # double - exclude=epochs.info['bads']) # picking - - meeg_picks = pick_types(epochs.info, meg=True, eeg=True, eog=False, - ecg=False, misc=False, stim=False, - exclude=epochs.info['bads']) - - # filter out all the channels the raw wouldn't have initialized - picks = np.intersect1d(meeg_picks, picks) - - self.ch_names = [epochs.ch_names[k] for k in picks] - - if self.max_n_components is None: - self.max_n_components = len(picks) - logger.info('Inferring max_n_components from picks.') - - data, self._pre_whitener = self._pre_whiten( - np.hstack(epochs.get_data()[:, picks]), - epochs.info, picks) - - to_ica, self._pca = self._prepare_pca(data, self.max_n_components) - - self._ica.fit(to_ica) - self._mixing = self._ica.get_mixing_matrix().T - self.current_fit = 'epochs' - - return self - - @deprecated(_preprocessing) - def get_sources_raw(self, raw, start=None, stop=None): - """Estimate raw sources given the unmixing matrix - - Parameters - ---------- - raw : instance of Raw - Raw object to draw sources from. - start : int - First sample to include (first is 0). If omitted, defaults to the - first sample in data. - stop : int - First sample to not include. - If omitted, data is included to the end. - - Returns - ------- - sources : array, shape = (n_components, n_times) - The ICA sources time series. - """ - if self._mixing is None: - raise RuntimeError('No fit available. Please first fit ICA ' - 'decomposition.') - - return self._get_sources_raw(raw, start, stop)[0] - - def _get_sources_raw(self, raw, start, stop): - picks = [raw.ch_names.index(k) for k in self.ch_names] - data, _ = self._pre_whiten(raw[picks, start:stop][0], raw.info, picks) - pca_data = self._pca.transform(data.T) - raw_sources = self._ica.transform(pca_data[:, self._comp_idx]).T - - return raw_sources, pca_data - - @deprecated(_preprocessing) - def get_sources_epochs(self, epochs, concatenate=False): - """Estimate epochs sources given the unmixing matrix - - Parameters - ---------- - epochs : instance of Epochs - Epochs object to draw sources from. - concatenate : bool - If true, epochs and time slices will be concatenated. - - Returns - ------- - epochs_sources : ndarray of shape (n_epochs, n_sources, n_times) - The sources for each epoch - """ - if self._mixing is None: - raise RuntimeError('No fit available. Please first fit ICA ' - 'decomposition.') - - return self._get_sources_epochs(epochs, concatenate)[0] - - def _get_sources_epochs(self, epochs, concatenate): - - picks = pick_types(epochs.info, include=self.ch_names, - exclude=epochs.info['bads']) - - # special case where epochs come picked but fit was 'unpicked'. - if len(picks) != len(self.ch_names): - raise RuntimeError('Epochs don\'t match fitted data: %i channels ' - 'fitted but %i channels supplied. \nPlease ' - 'provide Epochs compatible with ' - 'ica.ch_names' % (len(self.ch_names), - len(picks))) - - data, _ = self._pre_whiten(np.hstack(epochs.get_data()[:, picks]), - epochs.info, picks) - - pca_data = self._pca.transform(data.T) - sources = self._ica.transform(pca_data[:, self._comp_idx]).T - sources = np.array(np.split(sources, len(epochs.events), 1)) - - if concatenate: - sources = np.hstack(sources) - - return sources, pca_data - - @deprecated(_preprocessing) - def export_sources(self, raw, picks=None, start=None, stop=None): - """Export sources as raw object - - Parameters - ---------- - raw : instance of Raw - Raw object to export sources from. - picks : array-like - Channels to be included in addition to the sources. If None, - artifact and stimulus channels will be included. - start : int - First sample to include (first is 0). If omitted, defaults to the - first sample in data. - stop : int - First sample to not include. If omitted, data is included to the - end. - - Returns - ------- - out : instance of mne.Raw - Container object for ICA sources - - """ - if not raw._preloaded: - raise ValueError('raw data should be preloaded to have this ' - 'working. Please read raw data with ' - 'preload=True.') - - # include 'reference' channels for comparison with ICA - if picks is None: - picks = pick_types(raw.info, meg=False, eeg=False, misc=True, - ecg=True, eog=True, stim=True) - - # merge copied instance and picked data with sources - out = raw.copy() - out.fids = [] - sources = self.get_sources_raw(raw, start=start, stop=stop) - out._data = np.r_[sources, raw[picks, start:stop][0]] - - # update first and last samples - out.first_samp = raw.first_samp + (start if start else 0) - out.last_samp = out.first_samp + stop if stop else raw.last_samp - - # set channel names and info - ch_names = out.info['ch_names'] = [] - ch_info = out.info['chs'] = [] - for i in xrange(self.n_components): - ch_names.append('ICA %03d' % (i + 1)) - ch_info.append(dict(ch_name='ICA %03d' % (i + 1), cal=1, - logno=i + 1, coil_type=FIFF.FIFFV_COIL_NONE, - kind=FIFF.FIFFV_MISC_CH, coord_Frame=FIFF.FIFFV_COORD_UNKNOWN, - loc=np.array([0., 0., 0., 1., 0., 0., 0., 1., - 0., 0., 0., 1.], dtype=np.float32), - unit=FIFF.FIFF_UNIT_NONE, eeg_loc=None, range=1.0, - scanno=i + 1, unit_mul=0, coil_trans=None)) - - # re-append additionally picked ch_names - ch_names += [raw.ch_names[k] for k in picks] - # re-append additionally picked ch_info - ch_info += [raw.info['chs'][k] for k in picks] - - # update number of channels - out.info['nchan'] = len(picks) + self.n_components - - return out - - @deprecated(_preprocessing) - def plot_sources_raw(self, raw, order=None, start=None, stop=None, - n_components=None, source_idx=None, ncol=3, nrow=10, - show=True): - """Create panel plots of ICA sources. Wrapper around viz.plot_ica_panel - - Parameters - ---------- - raw : instance of mne.fiff.Raw - Raw object to plot the sources from. - order : ndarray | None. - Index of length n_components. If None, plot will show the sources - in the order as fitted. - Example: arg_sort = np.argsort(np.var(sources)). - start : int - X-axis start index. If None from the beginning. - stop : int - X-axis stop index. If None to the end. - n_components : int - Number of components fitted. - source_idx : array-like - Indices for subsetting the sources. - ncol : int - Number of panel-columns. - nrow : int - Number of panel-rows. - show : bool - If True, plot will be shown, else just the figure is returned. - - Returns - ------- - fig : instance of pyplot.Figure - """ - - sources = self.get_sources_raw(raw, start=start, stop=stop) - - if order is not None: - if len(order) != sources.shape[0]: - raise ValueError('order and sources have to be of the ' - 'same length.') - else: - sources = sources[order] - - fig = plot_ica_panel(sources, start=0 if start is not None else start, - stop=(stop - start) if stop is not None else stop, - n_components=n_components, source_idx=source_idx, - ncol=ncol, nrow=nrow) - if show: - import matplotlib.pylab as pl - pl.show() - - return fig - - @deprecated(_preprocessing) - def plot_sources_epochs(self, epochs, epoch_idx=None, order=None, - start=None, stop=None, n_components=None, - source_idx=None, ncol=3, nrow=10, show=True): - """Create panel plots of ICA sources. Wrapper around viz.plot_ica_panel - - Parameters - ---------- - epochs : instance of mne.Epochs - Epochs object to plot the sources from. - epoch_idx : int - Index to plot particular epoch. - order : ndarray | None. - Index of length n_components. If None, plot will show the sources - in the order as fitted. - Example: arg_sort = np.argsort(np.var(sources)). - sources : ndarray - Sources as drawn from self.get_sources. - start : int - X-axis start index. If None from the beginning. - stop : int - X-axis stop index. If None to the end. - n_components : int - Number of components fitted. - source_idx : array-like - Indices for subsetting the sources. - ncol : int - Number of panel-columns. - nrow : int - Number of panel-rows. - show : bool - If True, plot will be shown, else just the figure is returned. - - Returns - ------- - fig : instance of pyplot.Figure - """ - sources = self.get_sources_epochs(epochs, concatenate=True if epoch_idx - is None else False) - source_dim = 1 if sources.ndim > 2 else 0 - if order is not None: - if len(order) != sources.shape[source_dim]: - raise ValueError('order and sources have to be of the ' - 'same length.') - else: - sources = (sources[:, order] if source_dim - else sources[order]) - - fig = plot_ica_panel(sources[epoch_idx], start=start, stop=stop, - n_components=n_components, source_idx=source_idx, - ncol=ncol, nrow=nrow) - if show: - import matplotlib.pylab as pl - pl.show() - - return fig - - @deprecated(_preprocessing) - def find_sources_raw(self, raw, target=None, score_func='pearsonr', - start=None, stop=None): - """Find sources based on own distribution or based on similarity to - other sources or between source and target. - - Parameters - ---------- - raw : instance of Raw - Raw object to draw sources from. - target : array-like | ch_name | None - Signal to which the sources shall be compared. It has to be of - the same shape as the sources. If some string is supplied, a - routine will try to find a matching channel. If None, a score - function expecting only one input-array argument must be used, - for instance, scipy.stats.skew (default). - score_func : callable | str label - Callable taking as arguments either two input arrays - (e.g. pearson correlation) or one input - array (e. g. skewness) and returns a float. For convenience the - most common score_funcs are available via string labels: Currently, - all distance metrics from scipy.spatial and all functions from - scipy.stats taking compatible input arguments are supported. These - function have been modified to support iteration over the rows of a - 2D array. - start : int - First sample to include (first is 0). If omitted, defaults to the - first sample in data. - stop : int - First sample to not include. - If omitted, data is included to the end. - scores : ndarray - Scores for each source as returned from score_func. - - Returns - ------- - scores : ndarray - scores for each source as returned from score_func - """ - # auto source drawing - sources = self.get_sources_raw(raw=raw, start=start, stop=stop) - - # auto target selection - if target is not None: - if hasattr(target, 'ndim'): - if target.ndim < 2: - target = target.reshape(1, target.shape[-1]) - if isinstance(target, str): - pick = _get_target_ch(raw, target) - target, _ = raw[pick, start:stop] - if sources.shape[1] != target.shape[1]: - raise ValueError('Source and targets do not have the same' - 'number of time slices.') - target = target.ravel() - - return _find_sources(sources, target, score_func) - - @deprecated(_preprocessing) - def find_sources_epochs(self, epochs, target=None, score_func='pearsonr'): - """Find sources based on relations between source and target - - Parameters - ---------- - epochs : instance of Epochs - Epochs object to draw sources from. - target : array-like | ch_name | None - Signal to which the sources shall be compared. It has to be of - the same shape as the sources. If some string is supplied, a - routine will try to find a matching channel. If None, a score - function expecting only one input-array argument must be used, - for instance, scipy.stats.skew (default). - score_func : callable | str label - Callable taking as arguments either two input arrays - (e.g. pearson correlation) or one input - array (e. g. skewness) and returns a float. For convenience the - most common score_funcs are available via string labels: Currently, - all distance metrics from scipy.spatial and all functions from - scipy.stats taking compatible input arguments are supported. These - function have been modified to support iteration over the rows of a - 2D array. - - Returns - ------- - scores : ndarray - scores for each source as returned from score_func - """ - sources = self.get_sources_epochs(epochs=epochs) - # auto target selection - if target is not None: - if hasattr(target, 'ndim'): - if target.ndim < 3: - target = target.reshape(1, 1, target.shape[-1]) - if isinstance(target, str): - pick = _get_target_ch(epochs, target) - target = epochs.get_data()[:, pick] - if sources.shape[2] != target.shape[2]: - raise ValueError('Source and targets do not have the same' - 'number of time slices.') - target = target.ravel() - - return _find_sources(np.hstack(sources), target, score_func) - - @deprecated(_preprocessing) - def pick_sources_raw(self, raw, include=None, exclude=None, - n_pca_components=64, start=None, stop=None, - copy=True): - """Recompose raw data including or excluding some sources - - Parameters - ---------- - raw : instance of Raw - Raw object to pick to remove ICA components from. - include : list-like | None - The source indices to use. If None all are used. - exclude : list-like | None - The source indices to remove. If None all are used. - n_pca_components: - The number of PCA components to be unwhitened, where n_components - is the lower bound and max_n_components the upper bound. - If greater than self.n_components, the PCA components that were not - supplied to the ICA will get re-attached. This can be used to take - back the PCA dimension reduction. - start : int | None - The first time index to include. - stop : int | None - The first time index to exclude. - copy: bool - modify raw instance in place or return modified copy. - - Returns - ------- - raw : instance of Raw - raw instance with selected ICA components removed - """ - if not raw._preloaded: - raise ValueError('raw data should be preloaded to have this ' - 'working. Please read raw data with ' - 'preload=True.') - - if self.current_fit != 'raw': - raise ValueError('Currently no raw data fitted.' - 'Please fit raw data first.') - - sources, pca_data = self._get_sources_raw(raw, start=start, stop=stop) - recomposed = self._pick_sources(sources, pca_data, include, exclude, - n_pca_components) - - if copy is True: - raw = raw.copy() - - picks = [raw.ch_names.index(k) for k in self.ch_names] - raw[picks, start:stop] = recomposed - return raw - - @deprecated(_preprocessing) - def pick_sources_epochs(self, epochs, include=None, exclude=None, - n_pca_components=64, copy=True): - """Recompose epochs - - Parameters - ---------- - epochs : instance of Epochs - Epochs object to pick to remove ICA components from. - include : list-like | None - The source indices to use. If None all are used. - exclude : list-like | None - The source indices to remove. If None all are used. - n_pca_components: - The number of PCA components to be unwhitened, where n_components - is the lower bound and max_n_components the upper bound. - If greater than self.n_components, the PCA components that were not - supplied to the ICA will get re-attached. This can be used to take - back the PCA dimension reduction. - copy : bool - Modify Epochs instance in place or return modified copy. - - Returns - ------- - epochs : instance of Epochs - Epochs with selected ICA components removed. - """ - if not epochs.preload: - raise ValueError('raw data should be preloaded to have this ' - 'working. Please read raw data with ' - 'preload=True.') - - sources, pca_data = self._get_sources_epochs(epochs, True) - picks = pick_types(epochs.info, include=self.ch_names, - exclude=epochs.info['bads']) - - if copy is True: - epochs = epochs.copy() - - # put sources-dimension first for selection - recomposed = self._pick_sources(sources, pca_data, include, exclude, - n_pca_components) - # restore epochs, channels, tsl order - epochs._data[:, picks] = np.array(np.split(recomposed, - len(epochs.events), 1)) - epochs.preload = True - - return epochs - - def _pre_whiten(self, data, info, picks): - """Helper function""" - if self.noise_cov is None: # use standardization as whitener - pre_whitener = np.std(data) ** -1 - data *= pre_whitener - else: # pick cov - ncov = deepcopy(self.noise_cov) - if ncov.ch_names != self.ch_names: - ncov['data'] = ncov.data[picks][:, picks] - assert data.shape[0] == ncov.data.shape[0] - pre_whitener, _ = compute_whitener(ncov, info, picks) - data = np.dot(pre_whitener, data) - - return data, pre_whitener - - def _prepare_pca(self, data, max_n_components): - """ Helper Function """ - from sklearn.decomposition import RandomizedPCA - - # sklearn < 0.11 does not support random_state argument - kwargs = {'n_components': max_n_components, 'whiten': False} - - aspec = inspect.getargspec(RandomizedPCA.__init__) - if 'random_state' not in aspec.args: - warnings.warn('RandomizedPCA does not support random_state ' - 'argument. Use scikit-learn to version 0.11 ' - 'or newer to get reproducible results.') - else: - kwargs['random_state'] = 0 - - pca = RandomizedPCA(**kwargs) - pca_data = pca.fit_transform(data.T) - - if self._explained_var > 1.0: - if self.n_components is not None: # normal n case - self._comp_idx = np.arange(self.n_components) - to_ica = pca_data[:, self._comp_idx] - else: # None case - to_ica = pca_data - self.n_components = pca_data.shape[1] - self._comp_idx = np.arange(self.n_components) - else: # float case - expl_var = pca.explained_variance_ratio_ - self._comp_idx = (np.where(expl_var.cumsum() < - self._explained_var)[0]) - to_ica = pca_data[:, self._comp_idx] - self.n_components = len(self._comp_idx) - - return to_ica, pca - - def _pick_sources(self, sources, pca_data, include, exclude, - n_pca_components): - """Helper function""" - if not(self.n_components <= n_pca_components <= self.max_n_components): - raise ValueError('n_pca_components must be between n_components' - ' and max_n_components.') - - if include not in (None, []): - mute = [i for i in xrange(len(sources)) if i not in include] - sources[mute, :] = 0. # include via exclusion - elif exclude not in (None, []): - sources[exclude, :] = 0. # just exclude - - # restore pca data - mixing = self._mixing.copy() - pca_restored = np.dot(sources.T, mixing) - - # re-append deselected pca dimension if desired - if n_pca_components - self.n_components > 0: - add_components = np.arange(self.n_components, n_pca_components) - pca_reappend = pca_data[:, add_components] - pca_restored = np.c_[pca_restored, pca_reappend] - - # restore sensor space data - out = _inverse_t_pca(pca_restored, self._pca) - - # restore scaling - pre_whitener = self._pre_whitener.copy() - if self.noise_cov is None: # revert standardization - pre_whitener **= -1 - out *= pre_whitener - else: - out = np.dot(out, linalg.pinv(pre_whitener)) - - return out.T - - -@deprecated(_preprocessing) -@verbose -def ica_find_ecg_events(raw, ecg_source, event_id=999, - tstart=0.0, l_freq=5, h_freq=35, qrs_threshold=0.6, - verbose=None): - """Find ECG peaks from one selected ICA source - - Parameters - ---------- - ecg_source : ndarray - ICA source resembling ECG to find peaks from. - event_id : int - The index to assign to found events. - raw : instance of Raw - Raw object to draw sources from. - tstart : float - Start detection after tstart seconds. Useful when beginning - of run is noisy. - l_freq : float - Low pass frequency. - h_freq : float - High pass frequency. - qrs_threshold : float - Between 0 and 1. qrs detection threshold. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - - Returns - ------- - ecg_events : array - Events. - ch_ECG : string - Name of channel used. - average_pulse : float. - Estimated average pulse. - """ - logger.info('Using ICA source to identify heart beats') - - # detecting QRS and generating event file - ecg_events = qrs_detector(raw.info['sfreq'], ecg_source.ravel(), - tstart=tstart, thresh_value=qrs_threshold, - l_freq=l_freq, h_freq=h_freq) - - n_events = len(ecg_events) - - ecg_events = np.c_[ecg_events + raw.first_samp, np.zeros(n_events), - event_id * np.ones(n_events)] - - return ecg_events - - -@deprecated(_preprocessing) -@verbose -def ica_find_eog_events(raw, eog_source=None, event_id=998, l_freq=1, - h_freq=10, verbose=None): - """Locate EOG artifacts - - Parameters - ---------- - raw : instance of Raw - The raw data. - eog_source : ndarray - ICA source resembling EOG to find peaks from. - event_id : int - The index to assign to found events. - low_pass : float - Low pass frequency. - high_pass : float - High pass frequency. - verbose : bool, str, int, or None - If not None, override default verbose level (see mne.verbose). - - Returns - ------- - eog_events : array - Events - """ - eog_events = _find_eog_events(eog_source[np.newaxis], event_id=event_id, - l_freq=l_freq, h_freq=h_freq, - sampling_rate=raw.info['sfreq'], - first_samp=raw.first_samp) - return eog_events - - -def _get_target_ch(container, target): - """Helper Function""" - # auto target selection - pick = pick_channels(container.ch_names, include=[target]) - if len(pick) == 0: - raise ValueError('%s not in channel list (%s)' % - (target, container.ch_names)) - return pick - - -def _find_sources(sources, target, score_func): - """Helper Function""" - if isinstance(score_func, str): - score_func = score_funcs.get(score_func, score_func) - - if not callable(score_func): - raise ValueError('%s is not a valid score_func.' % score_func) - - scores = (score_func(sources, target) if target is not None - else score_func(sources, 1)) - - return scores - - -def _inverse_t_pca(X, pca): - """Helper Function""" - components = pca.components_[np.arange(len(X.T))] - X_orig = np.dot(X, components) - - if pca.mean_ is not None: - X_orig += pca.mean_ - - return X_orig diff --git a/mne/artifacts/stim.py b/mne/artifacts/stim.py deleted file mode 100644 index faefb1adca6..00000000000 --- a/mne/artifacts/stim.py +++ /dev/null @@ -1,72 +0,0 @@ -# Authors: Daniel Strohmeier -# -# License: BSD (3-clause) - -import numpy as np -from scipy import signal, interpolate - -from ..fiff import pick_types -from .. utils import deprecated - - -_preprocessing = ('The artifacts module will no longer be supported.' - ' Please use the preprocessing module instead.') - - -@deprecated(_preprocessing) -def eliminate_stim_artifact(raw, events, event_id, tmin=-0.005, - tmax=0.01, mode='linear'): - """Eliminates stimulations artifacts from raw data - - The raw object will be modified in place (no copy) - - Parameters - ---------- - raw: Raw object - raw data object - events: array, shape (n_events, 3) - The list of events - event_id: int - The id of the events generating the stimulation artifacts. - tmin : float - Start time before event in seconds - tmax : float - End time after event in seconds - mode : 'linear' | 'window' - way to fill the artifacted time interval - 'linear' does linear interpolation - 'window' applies a (1 - hanning) window - - Returns - ------- - raw: Raw object - raw data object - """ - if not raw._preloaded: - raise RuntimeError('Modifying data of Raw is only supported ' - 'when preloading is used. Use preload=True ' - '(or string) in the constructor.') - events_sel = (events[:, 2] == event_id) - event_start = events[events_sel, 0] - s_start = np.ceil(raw.info['sfreq'] * np.abs(tmin)) - s_end = np.ceil(raw.info['sfreq'] * tmax) - - picks = pick_types(raw.info, meg=True, eeg=True) - - if mode == 'window': - window = 1 - np.r_[signal.hann(4)[:2], np.ones(s_end + s_start - 4), - signal.hann(4)[-2:]].T - - for k in range(len(event_start)): - first_samp = event_start[k] - raw.first_samp - s_start - last_samp = event_start[k] - raw.first_samp + s_end - data, _ = raw[picks, first_samp:last_samp] - if mode == 'linear': - x = np.array([first_samp, last_samp]) - f = interpolate.interp1d(x, data[:, (0, -1)]) - xnew = np.arange(first_samp, last_samp) - interp_data = f(xnew) - raw[picks, first_samp:last_samp] = interp_data - elif mode == 'window': - raw[picks, first_samp:last_samp] = data * window[np.newaxis, :] - return raw diff --git a/mne/artifacts/tests/__init__.py b/mne/artifacts/tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/mne/artifacts/tests/test_ecg.py b/mne/artifacts/tests/test_ecg.py deleted file mode 100644 index 4c994e0f27c..00000000000 --- a/mne/artifacts/tests/test_ecg.py +++ /dev/null @@ -1,21 +0,0 @@ -import os.path as op - -from nose.tools import assert_true - -from mne.fiff import Raw -from mne.artifacts.ecg import find_ecg_events - -data_path = op.join(op.dirname(__file__), '..', '..', 'fiff', 'tests', 'data') -raw_fname = op.join(data_path, 'test_raw.fif') -event_fname = op.join(data_path, 'test-eve.fif') -proj_fname = op.join(data_path, 'test_proj.fif') - - -def test_find_ecg(): - """Test find ECG peaks""" - raw = Raw(raw_fname) - events, ch_ECG, average_pulse = find_ecg_events(raw, event_id=999, - ch_name='MEG 1531') - n_events = len(events) - _, times = raw[0, :] - assert_true(55 < average_pulse < 60) diff --git a/mne/artifacts/tests/test_eog.py b/mne/artifacts/tests/test_eog.py deleted file mode 100644 index 087c6927786..00000000000 --- a/mne/artifacts/tests/test_eog.py +++ /dev/null @@ -1,18 +0,0 @@ -import os.path as op -from nose.tools import assert_true - -from mne.fiff import Raw -from mne.artifacts.eog import find_eog_events - -data_path = op.join(op.dirname(__file__), '..', '..', 'fiff', 'tests', 'data') -raw_fname = op.join(data_path, 'test_raw.fif') -event_fname = op.join(data_path, 'test-eve.fif') -proj_fname = op.join(data_path, 'test_proj.fif') - - -def test_find_eog(): - """Test find EOG peaks""" - raw = Raw(raw_fname) - events = find_eog_events(raw) - n_events = len(events) - assert_true(n_events == 4) diff --git a/mne/artifacts/tests/test_peak_finder.py b/mne/artifacts/tests/test_peak_finder.py deleted file mode 100644 index 5d607199f56..00000000000 --- a/mne/artifacts/tests/test_peak_finder.py +++ /dev/null @@ -1,10 +0,0 @@ -from numpy.testing import assert_array_equal - -from mne.artifacts.peak_finder import peak_finder - - -def test_peak_finder(): - """Test the peak detection method""" - x = [0, 2, 5, 0, 6, -1] - peak_inds, peak_mags = peak_finder(x) - assert_array_equal(peak_inds, [2, 4]) diff --git a/mne/artifacts/tests/test_stim.py b/mne/artifacts/tests/test_stim.py deleted file mode 100644 index 53bb1ea712e..00000000000 --- a/mne/artifacts/tests/test_stim.py +++ /dev/null @@ -1,36 +0,0 @@ -# Authors: Daniel Strohmeier -# -# License: BSD (3-clause) - -import os.path as op - -import numpy as np -from numpy.testing import assert_array_almost_equal -from nose.tools import assert_true - -from mne.fiff import Raw -from mne.event import read_events -from mne.artifacts.stim import eliminate_stim_artifact - -data_path = op.join(op.dirname(__file__), '..', '..', 'fiff', 'tests', 'data') -raw_fname = op.join(data_path, 'test_raw.fif') -event_fname = op.join(data_path, 'test-eve.fif') - - -def test_stim_elim(): - """Test eliminate stim artifact""" - raw = Raw(raw_fname, preload=True) - events = read_events(event_fname) - event_idx = np.where(events[:, 2] == 1)[0][0] - tidx = events[event_idx, 0] - raw.first_samp - - raw = eliminate_stim_artifact(raw, events, event_id=1, tmin=-0.005, - tmax=0.01, mode='linear') - data, times = raw[:, tidx - 3:tidx + 5] - diff_data0 = np.diff(data[0]) - diff_data0 -= np.mean(diff_data0) - assert_array_almost_equal(diff_data0, np.zeros(len(diff_data0))) - raw = eliminate_stim_artifact(raw, events, event_id=1, tmin=-0.005, - tmax=0.01, mode='window') - data, times = raw[:, tidx:tidx + 1] - assert_true(np.all(data) == 0.) diff --git a/mne/preprocessing/__init__.py b/mne/preprocessing/__init__.py index 18fcdc7e199..f2699f87593 100644 --- a/mne/preprocessing/__init__.py +++ b/mne/preprocessing/__init__.py @@ -7,8 +7,8 @@ # # License: BSD (3-clause) -from . maxfilter import apply_maxfilter -from . ssp import compute_proj_ecg, compute_proj_eog -from . eog import find_eog_events -from . ecg import find_ecg_events -from . ica import ICA, ica_find_eog_events, ica_find_ecg_events, score_funcs \ No newline at end of file +from .maxfilter import apply_maxfilter +from .ssp import compute_proj_ecg, compute_proj_eog +from .eog import find_eog_events +from .ecg import find_ecg_events +from .ica import ICA, ica_find_eog_events, ica_find_ecg_events, score_funcs \ No newline at end of file diff --git a/mne/artifacts/peak_finder.py b/mne/preprocessing/peak_finder.py similarity index 97% rename from mne/artifacts/peak_finder.py rename to mne/preprocessing/peak_finder.py index eaf763712b3..b2630569292 100644 --- a/mne/artifacts/peak_finder.py +++ b/mne/preprocessing/peak_finder.py @@ -8,11 +8,6 @@ from .. utils import deprecated -_preprocessing = ('The artifacts module will no longer be supported.' - ' Please use the preprocessing module instead.') - - -@deprecated(_preprocessing) @verbose def peak_finder(x0, thresh=None, extrema=1, verbose=None): """Noise tolerant fast peak finding algorithm diff --git a/mne/preprocessing/ssp.py b/mne/preprocessing/ssp.py index c24f50d4080..abf89f74283 100644 --- a/mne/preprocessing/ssp.py +++ b/mne/preprocessing/ssp.py @@ -4,16 +4,17 @@ # # License: BSD (3-clause) -import numpy as np import copy as cp +from warnings import warn +import numpy as np import logging logger = logging.getLogger('mne') from .. import Epochs, compute_proj_evoked, compute_proj_epochs, verbose from ..fiff import pick_types, make_eeg_average_ref_proj -from ..artifacts import find_ecg_events, find_eog_events -from warnings import warn +from .ecg import find_ecg_events +from .eog import find_eog_events @verbose diff --git a/mne/artifacts/tests/test_ica.py b/mne/preprocessing/tests/test_ica.py similarity index 98% rename from mne/artifacts/tests/test_ica.py rename to mne/preprocessing/tests/test_ica.py index b0df10a5f0a..0b211fe98f8 100644 --- a/mne/artifacts/tests/test_ica.py +++ b/mne/preprocessing/tests/test_ica.py @@ -11,8 +11,8 @@ from itertools import product from mne import fiff, Epochs, read_events, cov -from mne.artifacts import ICA, ica_find_ecg_events, ica_find_eog_events -from mne.artifacts.ica import score_funcs +from mne.preprocessing import ICA, ica_find_ecg_events, ica_find_eog_events +from mne.preprocessing.ica import score_funcs have_sklearn = True try: diff --git a/mne/utils.py b/mne/utils.py index 4a6a3724c3a..a3c5f9a116f 100644 --- a/mne/utils.py +++ b/mne/utils.py @@ -17,6 +17,8 @@ # Following deprecated class copied from scikit-learn +# force show of DeprecationWarning even on python 2.7 +warnings.simplefilter('default') class deprecated(object): """Decorator to mark a function or class as deprecated. diff --git a/setup.py b/setup.py index 0c0f9de471d..6f3276bb9e5 100755 --- a/setup.py +++ b/setup.py @@ -51,7 +51,6 @@ ], platforms='any', packages=['mne', 'mne.tests', - 'mne.artifacts', 'mne.artifacts.tests', 'mne.beamformer', 'mne.beamformer.tests', 'mne.connectivity', 'mne.connectivity.tests', 'mne.data',