Repository: mne-tools/mne-python

Issue:
Unable to manually set EOG channels when reading BTI data
#### Describe the bug

[``mne.io.read_raw_bti.html``](https://mne.tools/stable/generated/mne.io.read_raw_bti.html) has an ``eog_ch`` parameter that can be used to set the 4D names of the EOG channels. I think that this parameter doesn't actually do anything. In my usecase, channels I deliberately wanted to set as ``EOG`` kept being read in as ``ECG`` channels. Likewise, setting the parameter ``ecg_ch`` to ``None`` did not result in no ECG channels being recognized, but that may be more of a documentation misunderstanding and byproduct of the described bug than an actual problem.


In my personal use case, I have some legacy BTI/4D data. I was told that this data does not contain an ECG channel, but four EOG channels named RVEOGo-1, RHEOG-1, RVEOGu-1, and LHEOG-1. ``read_raw_bti`` with various parametrization would consistently label those channels as ``ECG`` instead of ``EOG``:

```py
>>> raw = mne.io.read_raw_bti(pdf_fname, config, hs_file, convert=False,
                              rename_channels=False, ecg_ch=None, 
                              eog_ch=('RVEOGo-1', 'RHEOG-1', 'RVEOGu-1', 'LHEOG-1'))
>>> raw.info
<Info | 9 non-empty values
 bads: []
 ch_names: A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, ...
 chs: 248 Magnetometers, 2 Stimulus, 23 Reference Magnetometers, 1 misc, 4 ECG
 custom_ref_applied: False
 dev_ctf_t: CTF MEG device -> CTF/4D/KIT head transform
 dig: 3 items (3 Cardinal)
 highpass: 0.0 Hz
 lowpass: 508.6 Hz
 meas_date: 2014-04-14 06:40:13 UTC
 nchan: 278
 projs: []
 sfreq: 1017.2 Hz
>>> raw.info['chs'][-4:]
[{'loc': array([0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1.], dtype=float32),
  'ch_name': 'RVEOGo-1',
  'unit_mul': 0 (FIFF_UNITM_NONE),
  'coord_frame': 0 (FIFFV_COORD_UNKNOWN),
  'coil_type': 0 (FIFFV_COIL_NONE),
  'range': 1.0,
  'unit': 107 (FIFF_UNIT_V),
  'cal': 1.0,
  'scanno': 275,
  'kind': 402 (FIFFV_ECG_CH),
  'logno': 385},
 {'loc': array([0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1.], dtype=float32),
  'ch_name': 'RHEOG-1',
  'unit_mul': 0 (FIFF_UNITM_NONE),
  'coord_frame': 0 (FIFFV_COORD_UNKNOWN),
  'coil_type': 0 (FIFFV_COIL_NONE),
  'range': 1.0,
  'unit': 107 (FIFF_UNIT_V),
  'cal': 1.0,
  'scanno': 276,
  'kind': 402 (FIFFV_ECG_CH),
  'logno': 386},
 {'loc': array([0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1.], dtype=float32),
  'ch_name': 'RVEOGu-1',
  'unit_mul': 0 (FIFF_UNITM_NONE),
  'coord_frame': 0 (FIFFV_COORD_UNKNOWN),
  'coil_type': 0 (FIFFV_COIL_NONE),
  'range': 1.0,
  'unit': 107 (FIFF_UNIT_V),
  'cal': 1.0,
  'scanno': 277,
  'kind': 402 (FIFFV_ECG_CH),
  'logno': 387},
 {'loc': array([0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 1.], dtype=float32),
  'ch_name': 'LHEOG-1',
  'unit_mul': 0 (FIFF_UNITM_NONE),
  'coord_frame': 0 (FIFFV_COORD_UNKNOWN),
  'coil_type': 0 (FIFFV_COIL_NONE),
  'range': 1.0,
  'unit': 107 (FIFF_UNIT_V),
  'cal': 1.0,
  'scanno': 278,
  'kind': 402 (FIFFV_ECG_CH),
  'logno': 388}]
```

#### Steps to reproduce

It reproduces on [mne testing data](https://github.com/mne-tools/mne-testing-data), were I to set the ``MISC`` channels starting with an X (``X65``, ``X67``, ``X69``, ``X66``, ``X68``) to be EOG channels:

```py
>>> raw = mne.io.read_raw_bti('BTi/4Dsim/c,rfDC', 'BTi/4Dsim/config', 'BTi/4Dsim/hs_file', convert=False, 
                              rename_channels=False, eog_ch=('X65','X67''X69','X66', 'X68'))
Reading 4D PDF file /home/adina/repos/mne-testing-data/BTi/4Dsim/c,rfDC...
Creating Neuromag info structure ...
... Setting channel info structure.
... Reading digitization points from BTi/4Dsim/hs_file
Currently direct inclusion of 4D weight tables is not supported. For critical use cases please take into account the MNE command "mne_create_comp_data" to include weights as printed out by the 4D "print_table" routine.

>>> raw.info
<Info | 9 non-empty values
 bads: []
 ch_names: A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, ...
 chs: 248 Magnetometers, 2 Stimulus, 23 Reference Magnetometers, 6 misc
 custom_ref_applied: False
 dev_ctf_t: CTF MEG device -> CTF/4D/KIT head transform
 dig: 1125 items (3 Cardinal, 1122 Extra)
 highpass: 0.0 Hz
 lowpass: 508.9 Hz
 meas_date: 2019-03-14 13:20:14 UTC
 nchan: 279
 projs: []
 sfreq: 1017.8 Hz
>
```

#### potential fix

The following patch fixes it for me:

```diff
diff --git a/mne/io/bti/bti.py b/mne/io/bti/bti.py
index 6c90a0f72..2a1f261e3 100644
--- a/mne/io/bti/bti.py
+++ b/mne/io/bti/bti.py
@@ -1194,7 +1194,7 @@ def _get_bti_info(pdf_fname, config_fname, head_shape_fname, rotation_x,
             chan_info['kind'] = FIFF.FIFFV_STIM_CH
         elif chan_4d == 'TRIGGER':
             chan_info['kind'] = FIFF.FIFFV_STIM_CH
-        elif chan_4d.startswith('EOG'):
+        elif chan_4d.startswith('EOG') or chan_4d in eog_ch:
             chan_info['kind'] = FIFF.FIFFV_EOG_CH
         elif chan_4d == ecg_ch:
             chan_info['kind'] = FIFF.FIFFV_ECG_CH
```

<details><summary>output with the patch applied </summary>

```py
>>> raw = mne.io.read_raw_bti('BTi/4Dsim/c,rfDC', 'BTi/4Dsim/config', 'BTi/4Dsim/hs_file', convert=False,
                               rename_channels=False, eog_ch=('X65','X67','X69','X66', 'X68'))
Reading 4D PDF file /home/adina/repos/mne-testing-data/BTi/4Dsim/c,rfDC...
Creating Neuromag info structure ...
... Setting channel info structure.
... Reading digitization points from BTi/4Dsim/hs_file
Currently direct inclusion of 4D weight tables is not supported. For critical use cases please take into account the MNE command "mne_create_comp_data" to include weights as printed out by the 4D "print_table" routine.

>>> raw.info
<Info | 9 non-empty values
 bads: []
 ch_names: A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, ...
 chs: 248 Magnetometers, 2 Stimulus, 23 Reference Magnetometers, 1 misc, 5 EOG
 custom_ref_applied: False
 dev_ctf_t: CTF MEG device -> CTF/4D/KIT head transform
 dig: 1125 items (3 Cardinal, 1122 Extra)
 highpass: 0.0 Hz
 lowpass: 508.9 Hz
 meas_date: 2019-03-14 13:20:14 UTC
 nchan: 279
 projs: []
 sfreq: 1017.8 Hz
>

```
</details>

but I'm not sure if there isn't more to it, for example whether or not ``ecg_ch=None`` should prevent the channels from being labeled as ``ECG``.

I ran this code with the ``0.24.1`` release and today's ``main``.


Discussion:
indeed your fix seems right !

can you send us a PR to fix the issue?

thanks a lot

>


Resolving patch:
diff --git a/mne/io/bti/bti.py b/mne/io/bti/bti.py
--- a/mne/io/bti/bti.py
+++ b/mne/io/bti/bti.py
@@ -1194,7 +1194,7 @@ def _get_bti_info(pdf_fname, config_fname, head_shape_fname, rotation_x,
             chan_info['kind'] = FIFF.FIFFV_STIM_CH
         elif chan_4d == 'TRIGGER':
             chan_info['kind'] = FIFF.FIFFV_STIM_CH
-        elif chan_4d.startswith('EOG'):
+        elif chan_4d.startswith('EOG') or chan_4d in eog_ch:
             chan_info['kind'] = FIFF.FIFFV_EOG_CH
         elif chan_4d == ecg_ch:
             chan_info['kind'] = FIFF.FIFFV_ECG_CH


Test patch:
diff --git a/mne/io/bti/tests/test_bti.py b/mne/io/bti/tests/test_bti.py
--- a/mne/io/bti/tests/test_bti.py
+++ b/mne/io/bti/tests/test_bti.py
@@ -355,3 +355,12 @@ def test_nan_trans():
 def test_bti_ch_data(fname, preload):
     """Test for gh-6048."""
     read_raw_bti(fname, preload=preload)  # used to fail with ascii decode err
+
+
+@testing.requires_testing_data
+def test_bti_set_eog():
+    """Check that EOG channels can be set (gh-10092)."""
+    raw = read_raw_bti(fname_sim,
+                       preload=False,
+                       eog_ch=('X65', 'X67', 'X69', 'X66', 'X68'))
+    assert_equal(len(pick_types(raw.info, eog=True)), 5)