lina-usc / pylossless

🧠 EEG Processing pipeline that annotates continuous data
https://pylossless.readthedocs.io/en/latest/
MIT License
25 stars 10 forks source link

`load_ll_derivative` fails to load our example files in `Pylossless/assets`. #185

Open scott-huberty opened 8 hours ago

scott-huberty commented 8 hours ago

load_ll_derivative fails to load the Pylossless derivatives that we previously created and saved to pylossless/assets:

Assuming you are in the Pylossless repository directory

from pathlib import Path
import mne_bids
import pylossless as ll

root = Path("./pylossless/assets/test_data").resolve()

bpath = mne_bids.BIDSPath(root=root, subject="s01", datatype="eeg", task="faceO")

config = ll.config.Config().load_default()
pipeline = ll.LosslessPipeline(config=config)
pipeline.load_ll_derivative(bpath)

The error emanates from MNE (I am using MNE version 1.8.0).

Since this is not coming up in our tests, I imagine that this is specific to the asset files. But since these files are used to demo the dashboard, until we fix it, the dashboard demo won't work.

File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:829, in _read_edf_header(fname, exclude, infer_types, include, exclude_after_unique)
    827     patient[key] = float(value)
    828 elif key in ["hand"]:
--> 829     patient[key] = int(value)
    830 else:
    831     warn(f"Invalid patient information {key}")

ValueError: invalid literal for int() with base 10: 'None'
stack trace ``` --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[1], line 11 9 config = ll.config.Config().load_default() 10 pipeline = ll.LosslessPipeline(config=config) ---> 11 pipeline.load_ll_derivative(bpath) File ~/devel/repos/pylossless/pylossless/pipeline.py:1248, in LosslessPipeline.load_ll_derivative(self, derivatives_path) 1246 if not isinstance(derivatives_path, BIDSPath): 1247 derivatives_path = get_bids_path_from_fname(derivatives_path) -> 1248 self.raw = mne_bids.read_raw_bids(derivatives_path) 1249 bpath = derivatives_path.copy() 1250 # Load ICAs File :12, in read_raw_bids(bids_path, extra_params, verbose) File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne_bids/read.py:857, in read_raw_bids(bids_path, extra_params, verbose) 855 if raw_path.suffix == ".fif" and "allow_maxshield" not in extra_params: 856 extra_params["allow_maxshield"] = True --> 857 raw = _read_raw( 858 raw_path, 859 electrode=None, 860 hsp=None, 861 hpi=None, 862 config_path=config_path, 863 **extra_params, 864 ) 866 # Try to find an associated events.tsv to get information about the 867 # events in the recorded data 868 if ( 869 bids_path.subject == "emptyroom" and bids_path.task == "noise" 870 ) or bids_path.task.startswith("rest"): File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne_bids/read.py:76, in _read_raw(raw_path, electrode, hsp, hpi, allow_maxshield, config_path, **kwargs) 74 elif ext in [".ds", ".vhdr", ".set", ".edf", ".bdf", ".EDF", ".snirf", ".cdt"]: 75 raw_path = Path(raw_path) ---> 76 raw = reader[ext](raw_path, **kwargs) 78 # MEF and NWB are allowed, but not yet implemented 79 elif ext in [".mef", ".nwb"]: File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:1689, in read_raw_edf(input_fname, eog, misc, stim_channel, exclude, infer_types, include, preload, units, encoding, exclude_after_unique, verbose) 1687 if ext != "edf": 1688 raise NotImplementedError(f"Only EDF files are supported, got {ext}.") -> 1689 return RawEDF( 1690 input_fname=input_fname, 1691 eog=eog, 1692 misc=misc, 1693 stim_channel=stim_channel, 1694 exclude=exclude, 1695 infer_types=infer_types, 1696 preload=preload, 1697 include=include, 1698 units=units, 1699 encoding=encoding, 1700 exclude_after_unique=exclude_after_unique, 1701 verbose=verbose, 1702 ) File :12, in __init__(self, input_fname, eog, misc, stim_channel, exclude, infer_types, preload, include, units, encoding, exclude_after_unique, verbose) File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:151, in RawEDF.__init__(self, input_fname, eog, misc, stim_channel, exclude, infer_types, preload, include, units, encoding, exclude_after_unique, verbose) 149 logger.info(f"Extracting EDF parameters from {input_fname}...") 150 input_fname = os.path.abspath(input_fname) --> 151 info, edf_info, orig_units = _get_info( 152 input_fname, 153 stim_channel, 154 eog, 155 misc, 156 exclude, 157 infer_types, 158 preload, 159 include, 160 exclude_after_unique, 161 ) 162 logger.info("Creating raw.info structure...") 164 _validate_type(units, (str, None, dict), "units") File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:537, in _get_info(fname, stim_channel, eog, misc, exclude, infer_types, preload, include, exclude_after_unique) 534 eog = eog if eog is not None else [] 535 misc = misc if misc is not None else [] --> 537 edf_info, orig_units = _read_header( 538 fname, exclude, infer_types, include, exclude_after_unique 539 ) 541 # XXX: `tal_ch_names` to pass to `_check_stim_channel` should be computed 542 # from `edf_info['ch_names']` and `edf_info['tal_idx']` but 'tal_idx' 543 # contains stim channels that are not TAL. 544 stim_channel_idxs, _ = _check_stim_channel(stim_channel, edf_info["ch_names"]) File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:511, in _read_header(fname, exclude, infer_types, include, exclude_after_unique) 509 logger.info(f"{ext.upper()} file detected") 510 if ext in ("bdf", "edf"): --> 511 return _read_edf_header( 512 fname, exclude, infer_types, include, exclude_after_unique 513 ) 514 elif ext == "gdf": 515 return _read_gdf_header(fname, exclude, include), None File ~/miniforge3/envs/lossless/lib/python3.10/site-packages/mne/io/edf/edf.py:829, in _read_edf_header(fname, exclude, infer_types, include, exclude_after_unique) 827 patient[key] = float(value) 828 elif key in ["hand"]: --> 829 patient[key] = int(value) 830 else: 831 warn(f"Invalid patient information {key}") ValueError: invalid literal for int() with base 10: 'None' ```
scott-huberty commented 5 hours ago

I submitted a bug fix to MNE, but still it would be annoying for us to have to pin to the development version of MNE.

Maybe I can inspect the EDF files and just fix the root of the issue. It just has something to do with the participant info in the EDF file.