Repository: mne-tools/mne-bids

Issue:
Reading bombs if  extra_params=dict(exclude=...) is used
Discovered by @MaelysSolal

### Problem Description
The following code bombs:

```python
from mne_bids import BIDSPath, read_raw_bids

bids_root = [redacted]
bids_path = [redacted]

raw2 = read_raw_bids(bids_path=bids_path, extra_params=dict(exclude=['ECG I']))
```

Output:

```python
Extracting EDF parameters from [redacted]...
EDF file detected
Setting channel info structure...
Creating raw.info structure...
Reading events from [redacted]
Reading channel info from [redacted].
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-ec97eb4b84ce> in <module>
----> 1 raw2 = read_raw_bids(bids_path=bids_path, extra_params=dict(exclude=['ECG I']))

~/mne-bids/mne_bids/read.py in read_raw_bids(bids_path, extra_params, verbose)
    497                                             on_error='warn')
    498     if channels_fname is not None:
--> 499         raw = _handle_channels_reading(channels_fname, raw)
    500 
    501     # Try to find an associated electrodes.tsv and coordsystem.json

~/mne-bids/mne_bids/read.py in _handle_channels_reading(channels_fname, raw)
    391 
    392     # Set the channel types in the raw data according to channels.tsv
--> 393     raw.set_channel_types(channel_type_dict)
    394 
    395     # Set bad channels based on _channels.tsv sidecar

<decorator-gen-33> in set_channel_types(self, mapping, verbose)

~/miniconda3/envs/mne/lib/python3.8/site-packages/mne/channels/channels.py in set_channel_types(self, mapping, verbose)
    423         for ch_name, ch_type in mapping.items():
    424             if ch_name not in ch_names:
--> 425                 raise ValueError("This channel name (%s) doesn't exist in "
    426                                  "info." % ch_name)
    427 

ValueError: This channel name (EMG Chin3) doesn't exist in info.
```

### Proposed Workaround (Users)
Drop channels **after** loading the data, e.g. via `raw.pick()`, `raw.pick_types()`, `raw.drop_channels()`

### Proposed Fix
Easiest would be to disallow `extra_params=dict(exclude=...)`, otherwise we might have to deal with too many complexities. Haven't really looked into this though.


Discussion:

Resolving patch:
diff --git a/mne_bids/read.py b/mne_bids/read.py
--- a/mne_bids/read.py
+++ b/mne_bids/read.py
@@ -417,6 +417,9 @@ def read_raw_bids(bids_path, extra_params=None, verbose=True):
     extra_params : None | dict
         Extra parameters to be passed to MNE read_raw_* functions.
         If a dict, for example: ``extra_params=dict(allow_maxshield=True)``.
+        Note that the ``exclude`` parameter, which is supported by some
+        MNE-Python readers, is not supported; instead, you need to subset
+        your channels **after** reading.
     verbose : bool
         The verbosity level.
 
@@ -478,6 +481,10 @@ def read_raw_bids(bids_path, extra_params=None, verbose=True):
 
     if extra_params is None:
         extra_params = dict()
+    elif 'exclude' in extra_params:
+        del extra_params['exclude']
+        logger.info('"exclude" parameter is not supported by read_raw_bids')
+
     raw = _read_raw(bids_fpath, electrode=None, hsp=None, hpi=None,
                     config=config, verbose=None, **extra_params)
 


Test patch:
diff --git a/mne_bids/tests/test_read.py b/mne_bids/tests/test_read.py
--- a/mne_bids/tests/test_read.py
+++ b/mne_bids/tests/test_read.py
@@ -780,3 +780,17 @@ def test_write_read_fif_split_file():
     assert len(raw) == len(raw1)
     assert len(raw) == len(raw2)
     assert len(raw) > len(raw3)
+
+
+@pytest.mark.filterwarnings(warning_str['channel_unit_changed'])
+def test_ignore_exclude_param():
+    """Test that extra_params=dict(exclude=...) is being ignored."""
+    bids_root = _TempDir()
+    bids_path = _bids_path.copy().update(root=bids_root)
+    ch_name = 'EEG 001'
+    raw = _read_raw_fif(raw_fname, verbose=False)
+    write_raw_bids(raw, bids_path=bids_path, overwrite=True, verbose=False)
+
+    raw = read_raw_bids(bids_path=bids_path, verbose=False,
+                        extra_params=dict(exclude=[ch_name]))
+    assert ch_name in raw.ch_names