This is an automated email from the git hooks/post-receive script. yoh pushed a commit to annotated tag v0.1 in repository python-mne.
commit ce3505f277aa5e0646cb8189acef4068ee4f4b53 Author: Alexandre Gramfort <[email protected]> Date: Mon Mar 28 14:56:34 2011 -0400 ENH : reject epochs based on threshold + parsing of .ave + .cov files --- examples/plot_read_epochs.py | 5 +-- mne/__init__.py | 1 + mne/epochs.py | 82 ++++++++++++++++++++++++++++++++++++++------ mne/fiff/pick.py | 8 ++++- mne/fiff/tests/data/test.ave | 2 +- mne/misc.py | 64 ++++++++++++++++++++++++++++++++++ mne/tests/test_misc.py | 12 +++++++ 7 files changed, 160 insertions(+), 14 deletions(-) diff --git a/examples/plot_read_epochs.py b/examples/plot_read_epochs.py index c2a94d0..d10cca6 100644 --- a/examples/plot_read_epochs.py +++ b/examples/plot_read_epochs.py @@ -27,18 +27,19 @@ raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif' event_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif' event_id, tmin, tmax = 1, -0.2, 0.5 -# Setup for reading the raw data +# Setup for reading the raw data raw = fiff.Raw(raw_fname) events = mne.read_events(event_fname) # Set up pick list: EEG + MEG - bad channels (modify to your needs) exclude = raw.info['bads'] + ['MEG 2443', 'EEG 053'] # bads + 2 more -picks = fiff.pick_types(raw.info, meg=True, eeg=True, stim=False, +picks = fiff.pick_types(raw.info, meg=True, eeg=False, stim=True, exclude=exclude) # Read epochs epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True) +epochs.reject(grad=4000e-13, mag=4e-12, eog=150e-6) evoked = epochs.average() # average epochs to get the evoked response ############################################################################### diff --git a/mne/__init__.py b/mne/__init__.py index c78f117..15b462f 100644 --- a/mne/__init__.py +++ b/mne/__init__.py @@ -9,4 +9,5 @@ from .source_space import read_source_spaces from .inverse import read_inverse_operator, compute_inverse, minimum_norm from .epochs import Epochs from .label import label_time_courses, read_label +from .misc import parse_config import fiff diff --git a/mne/epochs.py b/mne/epochs.py index cd6d97a..2838039 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -7,6 +7,7 @@ import copy import numpy as np import fiff from .fiff import Evoked +from .fiff.pick import channel_type class Epochs(object): @@ -29,6 +30,9 @@ class Epochs(object): tmax : float End time after event + name : string + Comment that describes the Evoked data created. + keep_comp : boolean Apply CTF gradient compensation @@ -63,15 +67,15 @@ class Epochs(object): """ - def __init__(self, raw, events, event_id, tmin, tmax, - picks=None, keep_comp=False, - dest_comp=0, baseline=(None, 0), + def __init__(self, raw, events, event_id, tmin, tmax, baseline=(None, 0), + picks=None, name='Unknown', keep_comp=False, dest_comp=0, preload=False): self.raw = raw self.event_id = event_id self.tmin = tmin self.tmax = tmax self.picks = picks + self.name = name self.keep_comp = keep_comp self.dest_comp = dest_comp self.baseline = baseline @@ -217,6 +221,69 @@ class Epochs(object): else: return self._get_data_from_disk() + def reject(self, grad=None, mag=None, eeg=None, eog=None): + """Reject some epochs based on threshold values + + Parameters + ---------- + grad : float + Max value for gradiometers. (about 5000e-13). + If None do not reject based on gradiometers. + mag : float + Max value for magnetometers. (about 6e-12) + If None do not reject based on magnetometers. + eeg : float + Max value for EEG. (about 40e-6) + If None do not reject based on EEG. + eog : float + Max value for EEG. (about 250e-6) + If None do not reject based on EOG. + + Returns + ------- + data : array of shape [n_epochs, n_channels, n_times] + The epochs data + """ + grad_idx = [] + mag_idx = [] + eeg_idx = [] + eog_idx = [] + for idx, ch in enumerate(self.ch_names): + if grad is not None and channel_type(self.info, idx) == 'grad': + grad_idx.append(idx) + if mag is not None and channel_type(self.info, idx) == 'mag': + mag_idx.append(idx) + if eeg is not None and channel_type(self.info, idx) == 'eeg': + eeg_idx.append(idx) + if eog is not None and channel_type(self.info, idx) == 'eog': + eog_idx.append(idx) + + if len(eog_idx) == 0: + print "No EOG channel found. Do not rejecting based on EOG." + + good_epochs = [] + for k, e in enumerate(self): + if len(grad_idx) > 0 and np.max(e[grad_idx]) > grad: + print 'Rejecting epoch based on gradiometers.' + continue + if len(mag_idx) > 0 and np.max(e[mag_idx]) > mag: + print 'Rejecting epoch based on magnetometers.' + continue + if len(eeg_idx) > 0 and np.max(e[eeg_idx]) > eeg: + print 'Rejecting epoch based on EEG.' + continue + if len(eog_idx) > 0 and np.max(e[eog_idx]) > eog: + print 'Rejecting epoch based on EOG.' + continue + good_epochs.append(k) + + n_good_epochs = len(good_epochs) + print "Keeping %d epochs (%d bad)" % (n_good_epochs, + len(self.events) - n_good_epochs) + self.events = self.events[good_epochs] + if self.preload: + self._data = self._data[good_epochs] + def __iter__(self): """To iteration over epochs easy. """ @@ -241,14 +308,9 @@ class Epochs(object): s += ", baseline : %s" % str(self.baseline) return "Epochs (%s)" % s - def average(self, comment="Evoked data"): + def average(self): """Compute average of epochs - Parameters - ---------- - comment : string - Comment that describes the Evoked data created. - Returns ------- evoked : Evoked instance @@ -268,7 +330,7 @@ class Epochs(object): data /= n_events evoked.data = data evoked.times = self.times.copy() - evoked.comment = comment + evoked.comment = self.name evoked.aspect_kind = np.array([100]) # XXX evoked.nave = n_events evoked.first = - np.sum(self.times < 0) diff --git a/mne/fiff/pick.py b/mne/fiff/pick.py index 97edd61..b25c544 100644 --- a/mne/fiff/pick.py +++ b/mne/fiff/pick.py @@ -20,7 +20,7 @@ def channel_type(info, idx): Returns ------- - type : 'grad' | 'mag' | 'eeg' | 'stim' + type : 'grad' | 'mag' | 'eeg' | 'stim' | 'eog' | 'emg' | 'ecg' Type of channel """ @@ -34,6 +34,12 @@ def channel_type(info, idx): return 'eeg' elif kind == FIFF.FIFFV_STIM_CH: return 'stim' + elif kind == FIFF.FIFFV_EOG_CH: + return 'eog' + elif kind == FIFF.FIFFV_EMG_CH: + return 'emg' + elif kind == FIFF.FIFFV_ECG_CH: + return 'ecg' def pick_channels(ch_names, include, exclude=[]): diff --git a/mne/fiff/tests/data/test.ave b/mne/fiff/tests/data/test.ave index be6ba6a..abc6533 100644 --- a/mne/fiff/tests/data/test.ave +++ b/mne/fiff/tests/data/test.ave @@ -13,7 +13,7 @@ average { # gradReject 4000e-13 magReject 4e-12 - eegReject 0e-6 + eegReject 40e-6 eogReject 150e-6 # # Category specifications diff --git a/mne/misc.py b/mne/misc.py new file mode 100644 index 0000000..9c25a5b --- /dev/null +++ b/mne/misc.py @@ -0,0 +1,64 @@ +# Authors: Alexandre Gramfort <[email protected]> +# Scott Burns <[email protected]> +# +# License: BSD (3-clause) + +def parse_config(fname): + """Parse a config file (like .ave and .cov files) + + Parameters + ---------- + fname : string + config file name + + Returns + ------- + conditions : list of dict + Each condition is indexed by the event type. + A condition contains as keys: + tmin, tmax, name, grad_reject, mag_reject, + eeg_reject, eog_reject + """ + try: + with open(fname, 'r') as f: + ave_lines = f.readlines() + except: + print("Error while reading %s" % fname) + + reject_names = ['gradReject', 'magReject', 'eegReject', 'eogReject'] + reject_pynames = ['grad_reject', 'mag_reject', 'eeg_reject', 'eog_reject'] + reject_params = dict() + for line in ave_lines: + words = line.split() + if words[0] in reject_names: + reject_params[reject_pynames[reject_names.index(words[0])]] = \ + float(words[1]) + + cat_ind = [i for i, x in enumerate(ave_lines) if "category {" in x] + event_dict = dict() + for ind in cat_ind: + for k in range(ind+1, ind+7): + words = ave_lines[k].split() + if len(words) >= 2: + key = words[0] + if key == 'event': + event = int(words[1]) + break + else: + raise ValueError('Could not find event id.') + event_dict[event] = dict(**reject_params) + for k in range(ind+1, ind+7): + words = ave_lines[k].split() + if len(words) >= 2: + key = words[0] + if key == 'name': + name = ' '.join(words[1:]) + if name[0] == '"': + name = name[1:] + if name[-1] == '"': + name = name[:-1] + event_dict[event]['name'] = name + if key in ['tmin', 'tmax', 'basemin', 'basemax']: + event_dict[event][key] = float(words[1]) + return event_dict + diff --git a/mne/tests/test_misc.py b/mne/tests/test_misc.py new file mode 100644 index 0000000..f7fbddc --- /dev/null +++ b/mne/tests/test_misc.py @@ -0,0 +1,12 @@ +import os.path as op + +from ..misc import parse_config + +ave_fname = op.join(op.dirname(__file__), '..', 'fiff', 'tests', 'data', + 'test.ave') + +def test_parse_ave(): + """Test parsing of .ave file + """ + conditions = parse_config(ave_fname) + assert len(conditions) == 4 -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-mne.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
