Repository: mne-tools/mne-python

Issue:
support latin1 encoding for channels in read_raw_nihon
When opening Nihon-Kohden files with `read_raw_nihon` I get the error

```
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 1070: invalid continuation byte
```
raised in [this line](https://github.com/mne-tools/mne-python/blob/1b14d458cbcd391a6907032b809ec37410b60592/mne/io/nihon/nihon.py#L111).

I guess it is similar to [this issue](https://github.com/mne-tools/mne-python/issues/9267) which was already solved [here](https://github.com/mne-tools/mne-python/pull/9384), as replacing the above mentioned line with 
```
with open(e_fname, 'r', encoding='latin1') as fid:
```

fixed the issue.

Maybe we could add a similar [loop over different encodings](https://github.com/mne-tools/mne-python/pull/9384/files#diff-800fa074fc54d9bab7e81ae7d9f3239321fdf53d127bf6bbea3935a3095586e5R252) in [_read_21e_file](https://github.com/mne-tools/mne-python/blob/1b14d458cbcd391a6907032b809ec37410b60592/mne/io/nihon/nihon.py#L102)?


Discussion:
Hello! 👋 Thanks for opening your first issue here! ❤️ We will try to get back to you soon. 🚴🏽‍♂️

No objection, can you make a PR?
I'll have to see how this works, but I'll try

Resolving patch:
diff --git a/mne/io/nihon/nihon.py b/mne/io/nihon/nihon.py
--- a/mne/io/nihon/nihon.py
+++ b/mne/io/nihon/nihon.py
@@ -98,6 +98,8 @@ def _read_nihon_metadata(fname):
 _default_chan_labels += [f'X{i}' for i in range(16, 166)]
 _default_chan_labels += ['NA28', 'Z']
 
+_encodings = ('utf-8', 'latin1')
+
 
 def _read_21e_file(fname):
     fname = _ensure_path(fname)
@@ -106,21 +108,31 @@ def _read_21e_file(fname):
     if e_fname.exists():
         # Read the 21E file and update the labels accordingly.
         logger.info('Found 21E file, reading channel names.')
-        with open(e_fname, 'r') as fid:
-            keep_parsing = False
-            for line in fid:
-                if line.startswith('['):
-                    if 'ELECTRODE' in line or 'REFERENCE' in line:
-                        keep_parsing = True
-                    else:
-                        keep_parsing = False
-                elif keep_parsing is True:
-                    idx, name = line.split('=')
-                    idx = int(idx)
-                    if idx >= len(_chan_labels):
-                        n = idx - len(_chan_labels) + 1
-                        _chan_labels.extend(['UNK'] * n)
-                    _chan_labels[idx] = name.strip()
+        for enc in _encodings:
+            try:
+                with open(e_fname, 'r', encoding=enc) as fid:
+                    keep_parsing = False
+                    for line in fid:
+                        if line.startswith('['):
+                            if 'ELECTRODE' in line or 'REFERENCE' in line:
+                                keep_parsing = True
+                            else:
+                                keep_parsing = False
+                        elif keep_parsing is True:
+                            idx, name = line.split('=')
+                            idx = int(idx)
+                            if idx >= len(_chan_labels):
+                                n = idx - len(_chan_labels) + 1
+                                _chan_labels.extend(['UNK'] * n)
+                            _chan_labels[idx] = name.strip()
+            except UnicodeDecodeError:
+                pass
+            else:
+                break
+        else:
+            warn(f'Could not decode 21E file as one of {_encodings}; '
+                 f'Default channel names are chosen.')
+
     return _chan_labels
 
 
@@ -253,7 +265,6 @@ def _read_nihon_annotations(fname):
         n_logblocks = np.fromfile(fid, np.uint8, 1)[0]
         all_onsets = []
         all_descriptions = []
-        encodings = ('utf-8', 'latin1')
         for t_block in range(n_logblocks):
             fid.seek(0x92 + t_block * 20)
             t_blk_address = np.fromfile(fid, np.uint32, 1)[0]
@@ -262,7 +273,7 @@ def _read_nihon_annotations(fname):
             fid.seek(t_blk_address + 0x14)
             t_logs = np.fromfile(fid, '|S45', n_logs)
             for t_log in t_logs:
-                for enc in encodings:
+                for enc in _encodings:
                     try:
                         t_log = t_log.decode(enc)
                     except UnicodeDecodeError:
@@ -270,7 +281,7 @@ def _read_nihon_annotations(fname):
                     else:
                         break
                 else:
-                    warn(f'Could not decode log as one of {encodings}')
+                    warn(f'Could not decode log as one of {_encodings}')
                     continue
                 t_desc = t_log[:20].strip('\x00')
                 t_onset = datetime.strptime(t_log[20:26], '%H%M%S')


Test patch: