Saved using eeglab. The set file cannot be opened

Hello, I added a re reference to “A2” in the eeglab script file, and the Python error that could have been used was not resolved. I kindly ask for your help to take a look

:backhand_index_pointing_down:

Cell In[12], line 23
     21     os.makedirs(output_dir)
     22 files_dict = group_files_by_number(relative_gdf_file_path)
---> 23 process_files_in_batches(files_dict) 

Cell In[11], line 26, in process_files_in_batches(files_dict)
     23             print('file_name', file_name)
     24             print(f"Loading {file_path}...")
---> 26             epochs = mne.io.read_epochs_eeglab(file_path, uint16_codec='latin1')
     27 #             epochs = safe_read_epochs_eeglab(file_path)
     28 #             epochs.plot(n_epochs=5, title="Raw Epochs", scalings='auto')  # 默认展示前 5 个 trial
     29             # 同样对epochs应用带通滤波
     30             epochs.filter(l_freq=1, h_freq=40, verbose=False)

File D:\Anaconda3\envs\mner\lib\site-packages\mne\io\eeglab\eeglab.py:396, in read_epochs_eeglab(input_fname, events, event_id, eog, uint16_codec, montage_units, verbose)
    337 @fill_doc
    338 def read_epochs_eeglab(
    339     input_fname,
   (...)
    346     verbose=None,
    347 ) -> "EpochsEEGLAB":
    348     r"""Reader function for EEGLAB epochs files.
    349 
    350     Parameters
   (...)
    394     .. versionadded:: 0.11.0
    395     """
--> 396     epochs = EpochsEEGLAB(
    397         input_fname=input_fname,
    398         events=events,
    399         eog=eog,
    400         event_id=event_id,
    401         uint16_codec=uint16_codec,
    402         montage_units=montage_units,
    403         verbose=verbose,
    404     )
    405     return epochs

File <decorator-gen-265>:12, in __init__(self, input_fname, events, event_id, tmin, baseline, reject, flat, reject_tmin, reject_tmax, eog, uint16_codec, montage_units, verbose)

File D:\Anaconda3\envs\mner\lib\site-packages\mne\io\eeglab\eeglab.py:669, in EpochsEEGLAB.__init__(self, input_fname, events, event_id, tmin, baseline, reject, flat, reject_tmin, reject_tmax, eog, uint16_codec, montage_units, verbose)
    666     events = read_events(events)
    668 logger.info(f"Extracting parameters from {input_fname}...")
--> 669 info, eeg_montage, _ = _get_info(eeg, eog=eog, montage_units=montage_units)
    671 for key, val in event_id.items():
    672     if val not in events[:, 2]:

File D:\Anaconda3\envs\mner\lib\site-packages\mne\io\eeglab\eeglab.py:229, in _get_info(eeg, eog, montage_units)
    227 if eeg_has_ch_names_info:
    228     has_pos = _eeg_has_montage_information(eeg)
--> 229     ch_names, ch_types, eeg_montage = _get_montage_information(
    230         eeg, has_pos, montage_units=montage_units
    231     )
    232     update_ch_names = False
    233 else:  # if eeg.chanlocs is empty, we still need default chan names

File D:\Anaconda3\envs\mner\lib\site-packages\mne\io\eeglab\eeglab.py:172, in _get_montage_information(eeg, get_pos, montage_units)
    169 ys = nodatchans.get("Y", [])
    170 zs = nodatchans.get("Z", [])
--> 172 for type_, description, x, y, z in zip(types, descriptions, xs, ys, zs):
    173     if type_ != "FID":
    174         continue

TypeError: 'float' object is not iterable

Could it be that sensor A2 does not have a position and the other sensors do? This looks like a bug in MNE-Python’s EEGLAB reading code. Would it be possible for you to share the datafile so we could have a look?

1 Like

I’ve had a similar issue with the data from https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/PX8PND, fails on every subject so you can try any one of them.

I did not collect the data so I am not sure about the specifics, but the “nodatchans” attr of the EEG was like the following,

{'labels': 'TP9',
 'type': array([], dtype='<U1'),
 'theta': -108.393,
 'radius': 0.664888888888889,
 'X': -23.301607180511102,
 'Y': 70.07579868220873,
 'Z': -42.08821143569428,
 'sph_theta': 108.393,
 'sph_phi': -29.680000000000014,
 'sph_radius': 85,
 'urchan': 10,
 'ref': 'TP9 TP10 ',
 'datachan': 0}

So xs, ys, zs in the _get_montage_information function were floats instead of iterables. I installed locally and made sure they were iterables by modifying lines 165-181 from io/eeglab/eeglab.py.

    lpa, rpa, nasion = None, None, None
    if hasattr(eeg, "chaninfo") and isinstance(eeg.chaninfo.get("nodatchans"), dict):

        def ensure_iterable(obj):
            try:
                iter(obj)
            except TypeError:
                return [obj]
            return obj

        nodatchans = eeg.chaninfo["nodatchans"]
        types = nodatchans.get("type", [])
        descriptions = nodatchans.get("description", [])
        xs = ensure_iterable(nodatchans.get("X", []))
        ys = ensure_iterable(nodatchans.get("Y", []))
        zs = ensure_iterable(nodatchans.get("Z", []))

        for type_, description, x, y, z in zip(types, descriptions, xs, ys, zs):
            if type_ != "FID":
                continue
            if description == "Nasion":
                nasion = np.array([x, y, z])
            elif description == "Right periauricular point":
                rpa = np.array([x, y, z])
            elif description == "Left periauricular point":
                lpa = np.array([x, y, z])

Tested pytest mne/io/eeglab/tests/test_eeglab.py --verbose and it passes all eeglab io tests. I can make a pull request if you think this makes sense? I did not work with EEG data extensively so not sure if this modification is OK.

1 Like

Great work tracking down the bug! Yes, please open a PR :hugs:

You could use np.atleast_1d instead of ensure_iterable.

1 Like

Hi @emrecncelik, your fix would be very useful to include in MNE-Python. Do you want to open a PR (do you need any help doing so?) or shall I?

Hi @wmvanvliet ! I’ve already opened a PR but forgot to link it here, waiting for the merge but there seems to be some workflows awaiting approval?

Thanks for the tip by the way!

PR: Fix eeglab loading issue while calling `_get_montage_information` due to scalar `x,y,z` in 'nodatchans' by emrecncelik · Pull Request #13395 · mne-tools/mne-python · GitHub

oh, I missed that. Pressed the “run workflows” button… if green than it should merge automatically. Thanks!

1 Like

Hello again, @wmvanvliet . Looks like it passed all tests now, anything else I can do for the merge?

merged. Thanks for the PR!