lina-usc / pylossless

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

Saving the processed data from the pylossless #170

Closed Deepa-Tilwani closed 1 week ago

Deepa-Tilwani commented 2 weeks ago

My code crash is happening while exporting it to bids format. I defined a bids path like this :

from mne_bids import BIDSPath
output_path = '/Users/deepatilwani/Documents/Projects/ABC/bids'
bids_path = BIDSPath(subject=df_paths["eeg_fname"][1].split(".")[0], task='annotation',
                 extension= '.edf', datatype='eeg', root=output_path)

It creates a path like this :
BIDSPath(
root: /Users/deepatilwani/Documents/Projects/ABC/bids
datatype: eeg
basename: sub-ABC1064_task-annotation)

When I do pipeline.save(bids_path)

It crashes error message

It says :

{
    "name": "FileExistsError",
    "message": "\"/Users/deepatilwani/Documents/Projects/ABC/bids/sub-ABC1064/eeg/sub-ABC1064_task-annotation_events.tsv\" already exists. Please set overwrite to True.",
    "stack": "---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
Input In [123], in <cell line: 1>()
----> 1 pipeline.save(bids_path)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/pylossless/pipeline.py:1041, in LosslessPipeline.save(self, derivatives_path, overwrite)
   1031 def save(self, derivatives_path, overwrite=False):
   1032     \"\"\"Save the file at the end of the pipeline.
   1033 
   1034     Parameters
   (...)
   1039         whether to overwrite existing files with the same name.
   1040     \"\"\"
-> 1041     mne_bids.write_raw_bids(
   1042         self.raw,
   1043         derivatives_path,
   1044         overwrite=overwrite,
   1045         format=\"EDF\",
   1046         allow_preload=True,
   1047     )
   1048     # TODO: address derivatives support in MNE bids.
   1049     # use shutils ( or pathlib?) to rename file with ll suffix
   1050 
   1051     # Save ICAs
   1052     bpath = derivatives_path.copy()

File <decorator-gen-464>:12, in write_raw_bids(raw, bids_path, events, event_id, anonymize, format, symlink, empty_room, allow_preload, montage, acpc_aligned, overwrite, verbose)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne_bids/write.py:1983, in write_raw_bids(raw, bids_path, events, event_id, anonymize, format, symlink, empty_room, allow_preload, montage, acpc_aligned, overwrite, verbose)
   1979 events_array, event_dur, event_desc_id_map = _read_events(
   1980     events, event_id, raw, bids_path=bids_path
   1981 )
   1982 if events_array.size != 0:
-> 1983     _events_tsv(
   1984         events=events_array,
   1985         durations=event_dur,
   1986         raw=raw,
   1987         fname=events_tsv_path.fpath,
   1988         trial_type=event_desc_id_map,
   1989         overwrite=overwrite,
   1990     )
   1991     _events_json(fname=events_json_path.fpath, overwrite=overwrite)
   1992 # Kepp events_array around for BrainVision writing below.

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne_bids/write.py:327, in _events_tsv(events, durations, raw, fname, trial_type, overwrite)
    324 else:
    325     del data[\"trial_type\"]
--> 327 _write_tsv(fname, data, overwrite)

File <decorator-gen-306>:12, in _write_tsv(fname, dictionary, overwrite, verbose)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne_bids/utils.py:245, in _write_tsv(fname, dictionary, overwrite, verbose)
    243 \"\"\"Write an ordered dictionary to a .tsv file.\"\"\"
    244 if op.exists(fname) and not overwrite:
--> 245     raise FileExistsError(
    246         f'\"{fname}\" already exists. ' \"Please set overwrite to True.\"
    247     )
    248 _to_tsv(dictionary, fname)
    250 logger.info(f\"Writing '{fname}'...\")

FileExistsError: \"/Users/deepatilwani/Documents/Projects/ABC/bids/sub-ABC1064/eeg/sub-ABC1064_task-annotation_events.tsv\" already exists. Please set overwrite to True."
}

When I do overwrite = True

{
    "name": "ValueError",
    "message": "Signal range [0.0, 0.137605265721] out of physical range: [0.001804231242, 0.137605265721]",
    "stack": "---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [124], in <cell line: 1>()
----> 1 pipeline.save(bids_path, overwrite=True )

File ~/Documents/Projects/venv/lib/python3.9/site-packages/pylossless/pipeline.py:1041, in LosslessPipeline.save(self, derivatives_path, overwrite)
   1031 def save(self, derivatives_path, overwrite=False):
   1032     \"\"\"Save the file at the end of the pipeline.
   1033 
   1034     Parameters
   (...)
   1039         whether to overwrite existing files with the same name.
   1040     \"\"\"
-> 1041     mne_bids.write_raw_bids(
   1042         self.raw,
   1043         derivatives_path,
   1044         overwrite=overwrite,
   1045         format=\"EDF\",
   1046         allow_preload=True,
   1047     )
   1048     # TODO: address derivatives support in MNE bids.
   1049     # use shutils ( or pathlib?) to rename file with ll suffix
   1050 
   1051     # Save ICAs
   1052     bpath = derivatives_path.copy()

File <decorator-gen-464>:12, in write_raw_bids(raw, bids_path, events, event_id, anonymize, format, symlink, empty_room, allow_preload, montage, acpc_aligned, overwrite, verbose)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne_bids/write.py:2110, in write_raw_bids(***failed resolving arguments***)
   2108 elif bids_path.datatype in [\"eeg\", \"ieeg\"] and format == \"EDF\":
   2109     warn(\"Converting data files to EDF format\")
-> 2110     _write_raw_edf(raw, bids_path.fpath, overwrite=overwrite)
   2111 elif bids_path.datatype in [\"eeg\", \"ieeg\"] and format == \"EEGLAB\":
   2112     warn(\"Converting data files to EEGLAB format\")

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne_bids/write.py:1175, in _write_raw_edf(raw, bids_fname, overwrite)
   1163 \"\"\"Store data as EDF.
   1164 
   1165 Parameters
   (...)
   1172     Whether to overwrite an existing file or not.
   1173 \"\"\"
   1174 assert str(bids_fname).endswith(\".edf\")
-> 1175 raw.export(bids_fname, overwrite=overwrite)

File <decorator-gen-267>:12, in export(self, fname, fmt, physical_range, add_ch_type, overwrite, verbose)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne/io/base.py:1792, in BaseRaw.export(self, fname, fmt, physical_range, add_ch_type, overwrite, verbose)
   1765 \"\"\"Export Raw to external formats.
   1766 
   1767 %(export_fmt_support_raw)s
   (...)
   1788 %(export_edf_note)s
   1789 \"\"\"
   1790 from ..export import export_raw
-> 1792 export_raw(
   1793     fname,
   1794     self,
   1795     fmt,
   1796     physical_range=physical_range,
   1797     add_ch_type=add_ch_type,
   1798     overwrite=overwrite,
   1799     verbose=verbose,
   1800 )

File <decorator-gen-517>:12, in export_raw(fname, raw, fmt, physical_range, add_ch_type, overwrite, verbose)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne/export/_export.py:76, in export_raw(fname, raw, fmt, physical_range, add_ch_type, overwrite, verbose)
     73 elif fmt == \"edf\":
     74     from ._edf import _export_raw
---> 76     _export_raw(fname, raw, physical_range, add_ch_type)
     77 elif fmt == \"brainvision\":
     78     from ._brainvision import _export_raw

File ~/Documents/Projects/venv/lib/python3.9/site-packages/mne/export/_edf.py:139, in _export_raw(fname, raw, physical_range, add_ch_type)
    135         pmax = ch_types_phys_max[ch_type]
    136         prange = pmin, pmax
    138     signals.append(
--> 139         EdfSignal(
    140             data[idx],
    141             out_sfreq,
    142             label=signal_label,
    143             transducer_type=\"\",
    144             physical_dimension=\"\" if ch_type == \"stim\" else \"uV\",
    145             physical_range=prange,
    146             digital_range=(digital_min, digital_max),
    147             prefiltering=filter_str_info,
    148         )
    149     )
    151 # set patient info
    152 subj_info = raw.info.get(\"subject_info\")

File ~/Documents/Projects/venv/lib/python3.9/site-packages/edfio/edf_signal.py:124, in EdfSignal.__init__(self, data, sampling_frequency, label, transducer_type, physical_dimension, physical_range, digital_range, prefiltering)
    122 if not np.all(np.isfinite(data)):
    123     raise ValueError(\"Signal data must contain only finite values\")
--> 124 self._set_physical_range(physical_range, data)
    125 self._set_digital_range(digital_range)
    126 self._set_data(data)

File ~/Documents/Projects/venv/lib/python3.9/site-packages/edfio/edf_signal.py:427, in EdfSignal._set_physical_range(self, physical_range, data)
    425     data_max = data.max()
    426     if data_min < physical_range.min or data_max > physical_range.max:
--> 427         raise ValueError(
    428             f\"Signal range [{data_min}, {data_max}] out of physical range: [{physical_range.min}, {physical_range.max}]\"
    429         )
    430 self._physical_min = encode_float(
    431     _round_float_to_8_characters(physical_range.min, math.floor)
    432 )
    433 self._physical_max = encode_float(
    434     _round_float_to_8_characters(physical_range.max, math.ceil)
    435 )

ValueError: Signal range [0.0, 0.137605265721] out of physical range: [0.001804231242, 0.137605265721]"
}
scott-huberty commented 2 weeks ago
  1. For the first error, maybe we can improve our error message so that it is more clear to users what they need to do. I think that 'Please pass overwrite=True to the save method', might be better than 'Please set overwrite to True' EDIT: However, this error derives from MNE-BIDS. so maybe the improvement should be made upstream.
scott-huberty commented 1 week ago

This issue was fixed by updating to the current stable version of MNE-Python (version 1.8).

The reason this resolved the issue is because the bug that @Deepa-Tilwani was hitting originated from MNE-Python, not PyLossless, and that bug was fixed by MNE-Python in https://github.com/mne-tools/mne-python/pull/12676 , which was included in the 1.8 release.