Repository: mne-tools/mne-python

Issue:
`len(epochs)` on preloaded data
I have preloaded epochs that have been read from a preprocessed eeglab file - so they're already clean (I don't need to drop anything).
However, `len(epochs)` tells me:
> Since bad epochs have not been dropped, the length of the Epochs is not known. Load the Epochs with preload=True, or call Epochs.drop_bad(). To find the number of events in the Epochs, use len(Epochs.events).

Is it necessary for preloaded epochs? The check [here](https://github.com/mne-tools/mne-python/blob/master/mne/epochs.py#L1134) does not tests for `epochs.preload` while the error message suggests that it should.
Who is wrong in this case - me or mne? :)

(the `len(epochs)` is actually performed in `TimeDecoding` so I have to conform to what `len(epochs)` wants)


Discussion:
I believe ``preload_at_end=True`` should be passed to ``_BaseEpochs`` since the non-preloading is not supported for ``EpochsEEGLAB``, right? I've never used EEGLAB files, so I'll let you guys sort this out.
@jaeilepp - yes, IIRC `EpochsEEGLAB` should be always preloaded.
oh no, you can have `preload=False` for EEGLAB files. Sometimes you have an `.fdt` file, so you can read it in chunks ...
@jasmainak so how do you read those with ``preload=False``? I don't see a ``preload`` argument for ``EpochsEEGLAB``.
oh, we're talking about epochs. I'm still in my French class :) you're right.

So, `preload_at_end` does what? Perhaps I'm missing why `preload` should matter when we do `len(epochs)` ...
> So, preload_at_end does what?

Loads the data. In this case the problem is that preload flag is not set when it should be.
From my point of view the issue is rather that `__len__` does not check `epochs.preload` (which returns True in my case) but kind of assumes it is not if epochs were not rejected.
The notes for `__len__` mention that *This function only works if bad epochs have been dropped.*, but I don't get why it shouldn't work if data are preloaded but bad not dropped (especially if there are no bads)...
Well you can always do ``len(Epochs.events)`` which shows what you want (as the error message suggests). I think it's quite nice to have it only return the good epochs. Otherwise it can be a bit misleading.
Okay, it seems that it's the ``_bad_dropped`` flag that gets not being set. I suppose you can just set it to True when reading the file, since the constructor doesn't have rejection parameters available. Normally it gets set when you read in the data.
The issue is not strictly that I cannot do otherwise, but that TimeDecoding checks `len(epochs)`.
I can do `epochs.drop_bad()`, I just didn't think it was necessary if all my epochs were good (preprocessed in eeglab).
@jaeilepp: Ok, I get where it comes from now. I was setting `epochs._bad_dropped` to True myself but though it's not the way the world should work ;)
Yes. PR welcome.

Resolving patch:
diff --git a/mne/io/eeglab/eeglab.py b/mne/io/eeglab/eeglab.py
--- a/mne/io/eeglab/eeglab.py
+++ b/mne/io/eeglab/eeglab.py
@@ -555,6 +555,9 @@ def __init__(self, input_fname, events=None, event_id=None, tmin=0,
             info, data, events, event_id, tmin, tmax, baseline,
             reject=reject, flat=flat, reject_tmin=reject_tmin,
             reject_tmax=reject_tmax, verbose=verbose)
+
+        # data are preloaded but _bad_dropped is not set so we do it here:
+        self._bad_dropped = True
         logger.info('Ready.')
 
 


Test patch:
diff --git a/mne/io/eeglab/tests/test_eeglab.py b/mne/io/eeglab/tests/test_eeglab.py
--- a/mne/io/eeglab/tests/test_eeglab.py
+++ b/mne/io/eeglab/tests/test_eeglab.py
@@ -6,7 +6,7 @@
 import shutil
 
 import warnings
-from nose.tools import assert_raises, assert_equal
+from nose.tools import assert_raises, assert_equal, assert_true
 import numpy as np
 from numpy.testing import assert_array_equal
 
@@ -65,7 +65,7 @@ def test_io_set():
         raw0.filter(1, None, l_trans_bandwidth='auto', filter_length='auto',
                     phase='zero')  # test that preloading works
 
-    # test that using uin16_codec does not break stuff
+    # test that using uint16_codec does not break stuff
     raw0 = read_raw_eeglab(input_fname=raw_fname, montage=montage,
                            event_id=event_id, preload=False,
                            uint16_codec='ascii')
@@ -96,6 +96,8 @@ def test_io_set():
 
     epochs = read_epochs_eeglab(epochs_fname, epochs.events, event_id)
     assert_equal(len(epochs.events), 4)
+    assert_true(epochs.preload)
+    assert_true(epochs._bad_dropped)
     epochs = read_epochs_eeglab(epochs_fname, out_fname, event_id)
     assert_raises(ValueError, read_epochs_eeglab, epochs_fname,
                   None, event_id)