Skip to content

Commit 8b1087a

Browse files
jaeilepplarsoner
authored andcommitted
[MRG+2] Save name attribute of Epochs. (#4031)
* [MRG] Save name attribute of Epochs. * Deprecate name. * Fixes. * Fixes. * Generator to list. * Address comments. * Move logic to epochs.average. * Move logic. * name property. * Fixes. * Remove save. * Fix. * fix realtime epochs class * udpate what's new * misc * misc
1 parent 96d8b48 commit 8b1087a

File tree

6 files changed

+58
-24
lines changed

6 files changed

+58
-24
lines changed

doc/whats_new.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ API
209209

210210
- :func:`mne.io.read_raw_egi` now names channels with pattern 'E<idx>'. This behavior can be changed with parameter ``channel_naming`` by `Jaakko Leppakangas`_
211211

212+
- the `name`` parameter in :class:`mne.Epochs` is deprecated, by `Jaakko Leppakangas`_
212213

213214
.. _changes_0_13:
214215

mne/epochs.py

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,17 @@ class BaseEpochs(ProjMixin, ContainsMixin, UpdateChannelsMixin,
214214

215215
def __init__(self, info, data, events, event_id=None, tmin=-0.2, tmax=0.5,
216216
baseline=(None, 0), raw=None,
217-
picks=None, name='Unknown', reject=None, flat=None,
217+
picks=None, name=None, reject=None, flat=None,
218218
decim=1, reject_tmin=None, reject_tmax=None, detrend=None,
219219
add_eeg_ref=False, proj=True, on_missing='error',
220220
preload_at_end=False, selection=None, drop_log=None,
221221
filename=None, verbose=None): # noqa: D102
222222
self.verbose = verbose
223-
self.name = name
223+
if name is not None:
224+
warn('name is deprecated and will be removed in 0.15.')
225+
else:
226+
name = 'Unknown'
227+
self._name = name
224228

225229
if on_missing not in ['error', 'warning', 'ignore']:
226230
raise ValueError('on_missing must be one of: error, '
@@ -823,15 +827,28 @@ def _compute_mean_or_stderr(self, picks, mode='ave'):
823827
else:
824828
kind = 'standard_error'
825829
data /= np.sqrt(n_events)
830+
831+
if self._name not in ['Unknown', None]:
832+
comment = self._name
833+
else:
834+
if len(self.event_id) == 1:
835+
comment = next(iter(self.event_id.keys()))
836+
else:
837+
count = np.bincount(self.events[:, 2])
838+
comments = list()
839+
for key, value in self.event_id.items():
840+
comments.append('%.2f * %s' % (
841+
float(count[value]) / len(self.events), key))
842+
comment = ' + '.join(comments)
826843
return self._evoked_from_epoch_data(data, self.info, picks, n_events,
827-
kind)
844+
kind, comment)
828845

829-
def _evoked_from_epoch_data(self, data, info, picks, n_events, kind):
846+
def _evoked_from_epoch_data(self, data, info, picks, n_events, kind,
847+
comment):
830848
"""Create an evoked object from epoch data."""
831849
info = deepcopy(info)
832-
evoked = EvokedArray(data, info, tmin=self.times[0],
833-
comment=self.name, nave=n_events, kind=kind,
834-
verbose=self.verbose)
850+
evoked = EvokedArray(data, info, tmin=self.times[0], comment=comment,
851+
nave=n_events, kind=kind, verbose=self.verbose)
835852
# XXX: above constructor doesn't recreate the times object precisely
836853
evoked.times = self.times.copy()
837854

@@ -1287,6 +1304,18 @@ def tmax(self):
12871304
"""Last time point."""
12881305
return self.times[-1]
12891306

1307+
@property
1308+
def name(self):
1309+
"""Name for the epoch set."""
1310+
warn('name attribute is deprecated and will be removed in 0.15.')
1311+
return self._name
1312+
1313+
@name.setter
1314+
def name(self, name):
1315+
"""Name for the epoch set."""
1316+
warn('name attribute is deprecated and will be removed in 0.15.')
1317+
self._name = name
1318+
12901319
def __repr__(self):
12911320
"""Build string representation."""
12921321
s = 'n_events : %s ' % len(self.events)
@@ -1363,7 +1392,7 @@ def __getitem__(self, item):
13631392
if isinstance(item, (list, tuple)) and \
13641393
isinstance(item[0], string_types):
13651394
select = epochs._keys_to_idx(item)
1366-
epochs.name = '+'.join(item)
1395+
epochs._name = '+'.join(item)
13671396
else:
13681397
select = item if isinstance(item, slice) else np.atleast_1d(item)
13691398

@@ -1761,7 +1790,7 @@ class Epochs(BaseEpochs):
17611790
picks : array-like of int | None (default)
17621791
Indices of channels to include (if None, all channels are used).
17631792
name : string
1764-
Comment that describes the Epochs data created.
1793+
Comment that describes the Epochs data created. Deprecated.
17651794
preload : boolean
17661795
Load all epochs from disk when creating the object
17671796
or wait before accessing each epoch (more memory
@@ -1878,7 +1907,7 @@ class Epochs(BaseEpochs):
18781907

18791908
@verbose
18801909
def __init__(self, raw, events, event_id=None, tmin=-0.2, tmax=0.5,
1881-
baseline=(None, 0), picks=None, name='Unknown', preload=False,
1910+
baseline=(None, 0), picks=None, name=None, preload=False,
18821911
reject=None, flat=None, proj=True, decim=1, reject_tmin=None,
18831912
reject_tmax=None, detrend=None, add_eeg_ref=None,
18841913
on_missing='error', reject_by_annotation=True,
@@ -2579,7 +2608,7 @@ def _check_merge_epochs(epochs_list):
25792608

25802609

25812610
@verbose
2582-
def add_channels_epochs(epochs_list, name='Unknown', add_eeg_ref=False,
2611+
def add_channels_epochs(epochs_list, name=None, add_eeg_ref=False,
25832612
verbose=None):
25842613
"""Concatenate channels, info and data from two Epochs objects.
25852614
@@ -2588,7 +2617,7 @@ def add_channels_epochs(epochs_list, name='Unknown', add_eeg_ref=False,
25882617
epochs_list : list of Epochs
25892618
Epochs object to concatenate.
25902619
name : str
2591-
Comment that describes the Epochs data created.
2620+
Comment that describes the Epochs data created. Deprecated.
25922621
add_eeg_ref : bool
25932622
If True, an EEG average reference will be added (unless there is
25942623
no EEG in the data). This parameter will be removed in 0.15. Use
@@ -2603,6 +2632,8 @@ def add_channels_epochs(epochs_list, name='Unknown', add_eeg_ref=False,
26032632
epochs : instance of Epochs
26042633
Concatenated epochs.
26052634
"""
2635+
if name is not None:
2636+
warn('name is deprecated and will be removed in 0.15.')
26062637
add_eeg_ref = _dep_eeg_ref(add_eeg_ref)
26072638
if not all(e.preload for e in epochs_list):
26082639
raise ValueError('All epochs must be preloaded.')
@@ -2634,7 +2665,7 @@ def add_channels_epochs(epochs_list, name='Unknown', add_eeg_ref=False,
26342665
epochs = epochs_list[0].copy()
26352666
epochs.info = info
26362667
epochs.picks = None
2637-
epochs.name = name
2668+
epochs._name = name
26382669
epochs.verbose = verbose
26392670
epochs.events = events
26402671
epochs.preload = True
@@ -2970,7 +3001,8 @@ def average_movements(epochs, head_pos=None, orig_sfreq=None, picks=None,
29703001
data[meg_picks] = np.dot(mapping, data[good_picks])
29713002
info_to['dev_head_t'] = recon_trans # set the reconstruction transform
29723003
evoked = epochs._evoked_from_epoch_data(data, info_to, picks,
2973-
n_events=count, kind='average')
3004+
n_events=count, kind='average',
3005+
comment=epochs._name)
29743006
_remove_meg_projs(evoked) # remove MEG projectors, they won't apply now
29753007
logger.info('Created Evoked dataset from %s epochs' % (count,))
29763008
return (evoked, mapping) if return_mapping else evoked

mne/io/eeglab/tests/test_eeglab.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
@requires_version('scipy', '0.12')
3232
@testing.requires_testing_data
3333
def test_io_set():
34-
"""Test importing EEGLAB .set files"""
34+
"""Test importing EEGLAB .set files."""
3535
from scipy import io
3636
with warnings.catch_warnings(record=True) as w:
3737
warnings.simplefilter('always')

mne/realtime/epochs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class RtEpochs(BaseEpochs):
6262
picks : array-like of int | None (default)
6363
Indices of channels to include (if None, all channels are used).
6464
name : string
65-
Comment that describes the Evoked data created.
65+
Comment that describes the Evoked data created. Deprecated.
6666
reject : dict | None
6767
Rejection parameters based on peak-to-peak amplitude.
6868
Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg'.
@@ -136,7 +136,7 @@ class RtEpochs(BaseEpochs):
136136
@verbose
137137
def __init__(self, client, event_id, tmin, tmax, stim_channel='STI 014',
138138
sleep_time=0.1, baseline=(None, 0), picks=None,
139-
name='Unknown', reject=None, flat=None, proj=True,
139+
name=None, reject=None, flat=None, proj=True,
140140
decim=1, reject_tmin=None, reject_tmax=None, detrend=None,
141141
add_eeg_ref=False, isi_max=2., find_events=None,
142142
verbose=None): # noqa: D102

mne/tests/test_epochs.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def test_epoch_combine_ids():
513513
tmin, tmax, picks=picks, preload=False)
514514
events_new = merge_events(events, [1, 2], 12)
515515
epochs_new = combine_event_ids(epochs, ['a', 'b'], {'ab': 12})
516-
assert_equal(epochs_new['ab'].name, 'ab')
516+
assert_equal(epochs_new['ab']._name, 'ab')
517517
assert_array_equal(events_new, epochs_new.events)
518518
# should probably add test + functionality for non-replacement XXX
519519

@@ -698,6 +698,7 @@ def test_read_write_epochs():
698698
epochs_read2 = read_epochs(op.join(tempdir, 'foo-epo.fif'),
699699
preload=preload)
700700
assert_equal(epochs_read2.event_id, epochs.event_id)
701+
assert_equal(epochs_read2['a:a'].average().comment, 'a:a')
701702

702703
# add reject here so some of the epochs get dropped
703704
epochs = Epochs(raw, events, event_id, tmin, tmax, picks=picks,
@@ -911,8 +912,8 @@ def test_evoked_standard_error():
911912
evoked = [epochs.average(), epochs.standard_error()]
912913
write_evokeds(op.join(tempdir, 'evoked-ave.fif'), evoked)
913914
evoked2 = read_evokeds(op.join(tempdir, 'evoked-ave.fif'), [0, 1])
914-
evoked3 = [read_evokeds(op.join(tempdir, 'evoked-ave.fif'), 'Unknown'),
915-
read_evokeds(op.join(tempdir, 'evoked-ave.fif'), 'Unknown',
915+
evoked3 = [read_evokeds(op.join(tempdir, 'evoked-ave.fif'), '1'),
916+
read_evokeds(op.join(tempdir, 'evoked-ave.fif'), '1',
916917
kind='standard_error')]
917918
for evoked_new in [evoked2, evoked3]:
918919
assert_true(evoked_new[0]._aspect_kind ==
@@ -1478,8 +1479,8 @@ def test_access_by_name():
14781479
assert_array_almost_equal(epochs.get_data(), epochs6.get_data(), 20)
14791480

14801481
# Make sure we preserve names
1481-
assert_equal(epochs['a'].name, 'a')
1482-
assert_equal(epochs[['a', 'b']]['a'].name, 'a')
1482+
assert_equal(epochs['a']._name, 'a')
1483+
assert_equal(epochs[['a', 'b']]['a']._name, 'a')
14831484

14841485

14851486
@requires_pandas

mne/viz/epochs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,8 @@ def _prepare_mne_browse_epochs(params, projs, n_channels, n_epochs, scalings,
658658
size = size.split(',')
659659
size = tuple(float(s) for s in size)
660660
if title is None:
661-
title = epochs.name
662-
if epochs.name is None or len(title) == 0:
661+
title = epochs._name
662+
if title is None or len(title) == 0:
663663
title = ''
664664
fig = figure_nobar(facecolor='w', figsize=size, dpi=80)
665665
fig.canvas.set_window_title('mne_browse_epochs')

0 commit comments

Comments
 (0)