Repository: mne-tools/mne-bids

Issue:
If available, write impedance values to "electrodes.tsv"
With https://github.com/mne-tools/mne-python/pull/7974 MNE-Python is getting some functionality to parse electrode impedance values from raw data files. 

For now this is only implemented for BrainVision files, and the data is then available from `raw.impedances`.

Whenever impedances are available, we could try to write them to `electrodes.tsv`, because [these are RECOMMENDED values in BIDS](https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/03-electroencephalography.html#electrodes-description-_electrodestsv)


Discussion:

Resolving patch:
diff --git a/mne_bids/dig.py b/mne_bids/dig.py
--- a/mne_bids/dig.py
+++ b/mne_bids/dig.py
@@ -1,5 +1,6 @@
 """Read/write BIDS compatible electrode/coords structures from MNE."""
 # Authors: Adam Li <adam2392@gmail.com>
+#          Stefan Appelhoff <stefan.appelhoff@mailbox.org>
 #
 # License: BSD (3-clause)
 import json
@@ -132,6 +133,21 @@ def _handle_coordsystem_reading(coordsystem_fpath, kind, verbose=True):
     return coord_frame, coord_unit
 
 
+def _get_impedances(raw, names):
+    """Get the impedance values in kOhm from raw.impedances."""
+    if not hasattr(raw, 'impedances'):  # pragma: no cover
+        return ['n/a'] * len(names)
+    no_info = {'imp': 'n/a', 'imp_unit': 'kOhm'}
+    impedance_dicts = [raw.impedances.get(name, no_info) for name in names]
+    # If we encounter a unit not defined in `scalings`, return NaN
+    scalings = {'kOhm': 1, 'Ohm': 0.001}
+    impedances = [
+        imp_dict['imp'] * scalings.get(imp_dict['imp_unit'], np.nan)
+        for imp_dict in impedance_dicts
+    ]
+    return impedances
+
+
 def _electrodes_tsv(raw, fname, kind, overwrite=False, verbose=True):
     """Create an electrodes.tsv file and save it.
 
@@ -183,6 +199,11 @@ def _electrodes_tsv(raw, fname, kind, overwrite=False, verbose=True):
     else:  # pragma: no cover
         raise RuntimeError("kind {} not supported.".format(kind))
 
+    # Add impedance values if available, currently only BrainVision:
+    # https://github.com/mne-tools/mne-python/pull/7974
+    if hasattr(raw, 'impedances'):
+        data['impedance'] = _get_impedances(raw, names)
+
     _write_tsv(fname, data, overwrite=overwrite, verbose=verbose)
 
 


Test patch:
diff --git a/mne_bids/tests/test_write.py b/mne_bids/tests/test_write.py
--- a/mne_bids/tests/test_write.py
+++ b/mne_bids/tests/test_write.py
@@ -708,9 +708,8 @@ def test_bti(_bids_validate):
 
 
 # XXX: vhdr test currently passes only on MNE master. Skip until next release.
-# see: https://github.com/mne-tools/mne-python/pull/6558
-@pytest.mark.skipif(LooseVersion(mne.__version__) < LooseVersion('0.19'),
-                    reason='requires mne 0.19.dev0 or higher')
+@pytest.mark.skipif(LooseVersion(mne.__version__) < LooseVersion('0.21'),
+                    reason='requires mne 0.21.dev0 or higher')
 @pytest.mark.filterwarnings(warning_str['channel_unit_changed'])
 def test_vhdr(_bids_validate):
     """Test write_raw_bids conversion for BrainVision data."""
@@ -777,6 +776,26 @@ def test_vhdr(_bids_validate):
     write_raw_bids(raw, bids_basename, bids_root, overwrite=False)
     _bids_validate(bids_root)
 
+    # Test coords and impedance writing
+    # first read the data and set a montage
+    data_path = op.join(testing.data_path(), 'montage')
+    fname_vhdr = op.join(data_path, 'bv_dig_test.vhdr')
+    raw = mne.io.read_raw_brainvision(fname_vhdr, preload=False)
+    raw.set_channel_types({'HEOG': 'eog', 'VEOG': 'eog', 'ECG': 'ecg'})
+    fname_bvct = op.join(data_path, 'captrak_coords.bvct')
+    montage = mne.channels.read_dig_captrak(fname_bvct)
+    raw.set_montage(montage)
+
+    # convert to BIDS and check impedances
+    bids_root = _TempDir()
+    write_raw_bids(raw, bids_basename, bids_root)
+    electrodes_fpath = _find_matching_sidecar(bids_basename, bids_root,
+                                              suffix='electrodes.tsv')
+    tsv = _from_tsv(electrodes_fpath)
+    assert len(tsv.get('impedance', {})) > 0
+    assert tsv['impedance'][-3:] == ['n/a', 'n/a', 'n/a']
+    assert tsv['impedance'][:3] == ['5.0', '2.0', '4.0']
+
 
 @pytest.mark.filterwarnings(warning_str['nasion_not_found'])
 def test_edf(_bids_validate):