Repository: mne-tools/mne-python

Issue:
Reorder channels stopped working when preceded with add_reference_channels
I have a file reader for some of my files, which worked well some time ago but fails on master when trying to reorder channels:

```python-traceback

  File "C:\src\DiamSar\__init__.py", line 140, in read_raw
    raw.reorder_channels(chan_ord)

  File "c:\src\mne-python\mne\channels\channels.py", line 874, in reorder_channels
    return self._pick_drop_channels(idx)

  File "c:\src\mne-python\mne\channels\channels.py", line 938, in _pick_drop_channels
    self._read_picks = [r[idx] for r in self._read_picks]

  File "c:\src\mne-python\mne\channels\channels.py", line 938, in <listcomp>
    self._read_picks = [r[idx] for r in self._read_picks]

IndexError: index 63 is out of bounds for axis 0 with size 63
```
it seems that the problem arises because in my reader first a reference channel is added (`mne.add_reference_channels(raw, 'Cz', copy=False)`) and then `raw.reorder_channels()` is called. I can change the order of operations in my code, but thought I should let you know. :)


Discussion:
please share a full code snippet to replicate this

Resolving patch:
diff --git a/mne/io/reference.py b/mne/io/reference.py
--- a/mne/io/reference.py
+++ b/mne/io/reference.py
@@ -163,13 +163,10 @@ def add_reference_channels(inst, ref_channels, copy=True):
         Data with added EEG reference channels.
     """
     # Check to see that data is preloaded
-    if not inst.preload:
-        raise RuntimeError('Data needs to be preloaded.')
+    _check_preload(inst, 'add_reference_channels')
+    _validate_type(ref_channels, (list, tuple, str), 'ref_channels')
     if isinstance(ref_channels, str):
         ref_channels = [ref_channels]
-    elif not isinstance(ref_channels, list):
-        raise ValueError("`ref_channels` should be either str or list of str. "
-                         "%s was provided." % type(ref_channels))
     for ch in ref_channels:
         if ch in inst.info['ch_names']:
             raise ValueError("Channel %s already specified in inst." % ch)
@@ -238,6 +235,8 @@ def add_reference_channels(inst, ref_channels, copy=True):
         inst.info._update_redundant()
     if isinstance(inst, BaseRaw):
         inst._cals = np.hstack((inst._cals, [1] * len(ref_channels)))
+        for pi, picks in enumerate(inst._read_picks):
+            inst._read_picks[pi] = np.concatenate([picks, [np.max(picks) + 1]])
     inst.info._check_consistency()
     set_eeg_reference(inst, ref_channels=ref_channels, copy=False)
     return inst


Test patch:
diff --git a/mne/io/tests/test_reference.py b/mne/io/tests/test_reference.py
--- a/mne/io/tests/test_reference.py
+++ b/mne/io/tests/test_reference.py
@@ -24,6 +24,9 @@
 from mne.datasets import testing
 from mne.utils import run_tests_if_main, catch_logging
 
+base_dir = op.join(op.dirname(__file__), 'data')
+raw_fname = op.join(base_dir, 'test_raw.fif')
+
 data_dir = op.join(testing.data_path(download=False), 'MEG', 'sample')
 fif_fname = op.join(data_dir, 'sample_audvis_trunc_raw.fif')
 eve_fname = op.join(data_dir, 'sample_audvis_trunc_raw-eve.fif')
@@ -553,9 +556,33 @@ def test_add_reference():
                        evoked_ref.data[picks_eeg, :])
 
     # Test invalid inputs
-    raw_np = read_raw_fif(fif_fname, preload=False)
-    pytest.raises(RuntimeError, add_reference_channels, raw_np, ['Ref'])
-    pytest.raises(ValueError, add_reference_channels, raw, 1)
+    raw = read_raw_fif(fif_fname, preload=False)
+    with pytest.raises(RuntimeError, match='loaded'):
+        add_reference_channels(raw, ['Ref'])
+    raw.load_data()
+    with pytest.raises(ValueError, match='Channel.*already.*'):
+        add_reference_channels(raw, raw.ch_names[:1])
+    with pytest.raises(TypeError, match='instance of'):
+        add_reference_channels(raw, 1)
+
+
+def test_add_reorder():
+    """Test that a reference channel can be added and then data reordered."""
+    # gh-8300
+    raw = read_raw_fif(raw_fname).crop(0, 0.1).del_proj().pick('eeg')
+    assert len(raw.ch_names) == 60
+    with pytest.raises(RuntimeError, match='preload'):
+        add_reference_channels(raw, ['EEG 000'], copy=False)
+    raw.load_data()
+    add_reference_channels(raw, ['EEG 000'], copy=False)
+    data = raw.get_data()
+    assert_array_equal(data[-1], 0.)
+    assert raw.ch_names[-1] == 'EEG 000'
+    raw.reorder_channels(raw.ch_names[-1:] + raw.ch_names[:-1])
+    assert raw.ch_names == ['EEG %03d' % ii for ii in range(61)]
+    data_new = raw.get_data()
+    data_new = np.concatenate([data_new[1:], data_new[:1]])
+    assert_allclose(data, data_new)
 
 
 def test_bipolar_combinations():