Repository: mne-tools/mne-python

Issue:
BUG: next epochs when data not preloaded throws error
Issue only on dev

```python
import mne
from mne import io
from mne.datasets import sample
data_path = sample.data_path()
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'

raw = io.read_raw_fif(raw_fname)
events = mne.read_events(event_fname)
epochs = mne.Epochs(raw, events, preload=False)
next(epochs)
```

```python
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-06328153984c> in <module>
      9 events = mne.read_events(event_fname)
     10 epochs = mne.Epochs(raw, events, preload=False)
---> 11 next(epochs)

~/.conda/envs/bm/lib/python3.8/site-packages/mne/utils/mixin.py in __next__(self, return_event_id)
    343                 epoch_noproj = self._get_epoch_from_raw(self._current)
    344                 epoch_noproj = self._detrend_offset_decim(
--> 345                     epoch_noproj, self._current_detrend_picks)
    346                 epoch = self._project_epoch(epoch_noproj)
    347                 self._current += 1

AttributeError: 'Epochs' object has no attribute '_current_detrend_picks'
```


Discussion:
It is caused by https://github.com/mne-tools/mne-python/commit/59429c3b8022f61cf3539dc421cadff4ab675d24#diff-a8ad12a27877498bd9fe2ce1990d63852c08edca624268ae8d73dbac17b50b59

It can be fixed by simply using: 
```python
next(iter(epochs))
```

but it's a change of API, not sure you what you'd prefer (change of API versus change of current code)
Glad there is a workaround, I should be able to look into a proper fix later this week because I agree this is a bug

Resolving patch:
diff --git a/mne/utils/mixin.py b/mne/utils/mixin.py
--- a/mne/utils/mixin.py
+++ b/mne/utils/mixin.py
@@ -330,6 +330,8 @@ def __next__(self, return_event_id=False):
         event_id : int
             The event id. Only returned if ``return_event_id`` is ``True``.
         """
+        if not hasattr(self, '_current_detrend_picks'):
+            self.__iter__()  # ensure we're ready to iterate
         if self.preload:
             if self._current >= len(self._data):
                 self._stop_iter()


Test patch:
diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py
--- a/mne/tests/test_epochs.py
+++ b/mne/tests/test_epochs.py
@@ -1780,6 +1780,27 @@ def test_iter_evoked():
         assert_array_equal(x, y)
 
 
+@pytest.mark.parametrize('preload', (True, False))
+def test_iter_epochs(preload):
+    """Test iteration over epochs."""
+    raw, events, picks = _get_data()
+    epochs = Epochs(
+        raw, events[:5], event_id, tmin, tmax, picks=picks, preload=preload)
+    assert not hasattr(epochs, '_current_detrend_picks')
+    epochs_data = epochs.get_data()
+    data = list()
+    for _ in range(10):
+        try:
+            data.append(next(epochs))
+        except StopIteration:
+            break
+        else:
+            assert hasattr(epochs, '_current_detrend_picks')
+    assert not hasattr(epochs, '_current_detrend_picks')
+    data = np.array(data)
+    assert_allclose(data, epochs_data, atol=1e-20)
+
+
 def test_subtract_evoked():
     """Test subtraction of Evoked from Epochs."""
     raw, events, picks = _get_data()