Repository: mne-tools/mne-python

Issue:
How to apply ica on brainvision raw data
I am getting this error when trying to fit the data:

ValueError: picks (NoneNone, treated as "data") yielded no channels, consider passing picks explicitly

How to resolve this issue?


Discussion:
Hello @arthurlgk, we'd need a little more information how you got there.

- Which version of `mne-python` are you running?
- Could you share the code that leads to this problem?

Thanks!
I am currently using mne 0.21.0.
And the code is the following:
```
fname = "demo_3.vhdr"
bv_raw = mne.io.read_raw_brainvision(dirname+fname)
ica = ICA(n_components=63, random_state=97)
ica.fit(bv_raw)
```
Thank you.
@arthurlgk Ok, this seems a little odd to me (the behavior you're seeing, not your code, which looks ok) @cbrnr Maybe you have an idea?

@arthurlgk Could you (privately) share with me one of the datasets that produces this problem? So I can try look into this myself. My email address is richard.hoechenberger@gmail.com
@hoechenberger Sent. Did you receive it?
Not sure, but maybe the channel types are not EEG/MEG? @arthurlgk can you post the output of `bv_raw.info`?
> @hoechenberger Sent. Did you receive it?

Thank you, I received the email. Will look into this within the next 2 hours.
@arthurlgk I just looked at the `.vhdr` file you included, and there's something off.

Your file looks something like this:
```
...
Ch1=Channel 1,,1,
Ch2=Channel 2,,1,
Ch3=Channel 3,,1,
...
```

while it's supposed to look like this:
```
...
Ch1=FP1,,0.5,µV
Ch2=FP2,,0.5,µV
Ch3=F3,,0.5,µV
...
```
i.e., there are no units specified in your file. I'm not sure if that's even valid (but I'm not an expert on BV data). How did you generate those files?

@sappelhoff Maybe you would know which unit is the default if not explicitly specified in the `vhdr` file? µV, I suppose?
yep, seems to me like that.

pdf source: https://www.brainproducts.com/filedownload.php?path=products/more/BVCDF-1.0_DocVersion-2.5_2019-12-12.pdf

See screenshot:

![image](https://user-images.githubusercontent.com/9084751/97286139-6c131f00-1843-11eb-8806-51916d607441.png)

Yes just found out the same. Thanks for looking. I will now try to figure out whether `pybv` or MNE is doing something wrong when reading @arthurlgk's file.
… just to realize that [pybv](https://github.com/bids-standard/pybv) only **writes**, apparently ;) So it must be something in MNE
Ok found it. Working on a fix.
> … just to realize that pybv only writes, apparently

yes :-) better to make the MNE reader great, than have a second and less complete/battle-tested version in pybv.
(strictly speaking, @abramhindle's file does not follow the specification. Because as I read the specs: if you don't have a unit, also the comma separating unit from the rest of props must go. but it's easy to deal with this, so… still it would be interesting to know which software @abramhindle used to create this file, because either it's buggy or the specs need to be amended)
(Am I right? Or am I reading this incorrectly? it says `...[,<unit>]`, so the comma should only be there if there's a unit, right?)
> Am I right?

I agree. it might be a typo :-/ coul be worth looking into how they handle the remaining *optional* trailing fields ... if they all go away including the comma, it may be legit.

To me it'd make much more sense to leave the comma in any case (even when unit is empty)
We have the same for "markers" -> the last (trailing) optional parameter seems to remove the final comma if it's not present:

![image](https://user-images.githubusercontent.com/9084751/97296347-d5e5f580-1850-11eb-969b-53456974683f.png)

I wouldn't trust these specs too much but try to catch as many cases as possible (so in this case I'd try to handle a trailing comma even though it's technically invalid).
> We have the same for "markers" -> the last (trailing) optional parameter seems to remove the final comma if it's not present:

Ok so this seems to be a conscious decision in the specs, then.
I am still interest in how @arthurlgk obtained the file
> I am still interest in how @arthurlgk obtained the file

The header they sent me starts with

```
Brain Vision Data Exchange Header File Version 1.0
; Data created by the Vision Recorder
```

I wonder which version of BV Recorder that was.

Resolving patch:
diff --git a/mne/io/brainvision/brainvision.py b/mne/io/brainvision/brainvision.py
--- a/mne/io/brainvision/brainvision.py
+++ b/mne/io/brainvision/brainvision.py
@@ -498,11 +498,16 @@ def _get_vhdr_info(vhdr_fname, eog, misc, scale):
     for chan, props in cfg.items('Channel Infos'):
         n = int(re.findall(r'ch(\d+)', chan)[0]) - 1
         props = props.split(',')
-        # default to microvolts because that's what the older brainvision
-        # standard explicitly assumed; the unit is only allowed to be
+
+        # default to µV, following the BV specs; the unit is only allowed to be
         # something else if explicitly stated (cf. EEGLAB export below)
         if len(props) < 4:
-            props += (u'µV',)
+            # deal with older files, which have no unit property
+            props += ('µV',)
+        elif props[3] == '':
+            # deal with files where the unit property is simply empty
+            props[3] = 'µV'
+
         name, _, resolution, unit = props[:4]
         ch_dict[chan] = name
         ch_names[n] = name


Test patch:
diff --git a/mne/io/brainvision/tests/data/test.vhdr b/mne/io/brainvision/tests/data/test.vhdr
--- a/mne/io/brainvision/tests/data/test.vhdr
+++ b/mne/io/brainvision/tests/data/test.vhdr
@@ -21,8 +21,8 @@ BinaryFormat=INT_16
 ; Fields are delimited by commas, some fields might be omitted (empty).
 ; Commas in channel names are coded as "\1".
 Ch1=FP1,,0.5,µV
-Ch2=FP2,,0.5,µV
-Ch3=F3,,0.5,µV
+Ch2=FP2,,0.5,
+Ch3=F3,,0.5
 Ch4=F4,,0.5,µV
 Ch5=C3,,0.5,µV
 Ch6=C4,,0.5,µV
diff --git a/mne/io/brainvision/tests/test_brainvision.py b/mne/io/brainvision/tests/test_brainvision.py
--- a/mne/io/brainvision/tests/test_brainvision.py
+++ b/mne/io/brainvision/tests/test_brainvision.py
@@ -72,9 +72,16 @@ def test_orig_units(recwarn):
     raw = read_raw_brainvision(vhdr_path)
     orig_units = raw._orig_units
     assert len(orig_units) == 32
-    assert orig_units['FP1'] == u'µV'
+    assert orig_units['FP1'] == 'µV'
+
+    # no unit specified in the vhdr, ensure we default to µV here
+    assert orig_units['FP2'] == 'µV'
+    assert orig_units['F3'] == 'µV'
+
+    sum([v == 'µV' for v in orig_units.values()]) == 26
+
     assert orig_units['CP5'] == 'n/a'  # originally BS, not a valid unit
-    assert orig_units['CP6'] == u'µS'
+    assert orig_units['CP6'] == 'µS'
     assert orig_units['HL'] == 'n/a'  # originally ARU, not a valid unit
     assert orig_units['HR'] == 'n/a'  # originally uS ...
     assert orig_units['Vb'] == 'S'