Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: write_raw_bids() got an unexpected keyword argument 'events_data'" #175

Closed
christian-oreilly opened this issue Nov 11, 2024 · 9 comments · Fixed by #176
Closed

Comments

@christian-oreilly
Copy link
Collaborator

Error reported by @Deepa-Tilwani on Discord.

{
	"name": "TypeError",
	"message": "write_raw_bids() got an unexpected keyword argument 'events_data'",
	"stack": "---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[10], line 19
     16 bids_path_args = [{'subject': subject, 'session': '01', \"task\": \"narative\"} for subject in df_paths.index]
     18 if recompute:
---> 19     bids_paths = ll.bids.convert_dataset_to_bids(import_fct, import_args, bids_path_args,
     20                                                  bids_root=path_eegp / \"bids_dataset\", overwrite=True)
     21 else:
     22     bids_paths = ll.bids.get_dataset_bids_path(bids_path_args, bids_root=path_eegp / \"bids_dataset\")

File ~/Documents/Projects/ABC/.venv/lib/python3.10/site-packages/pylossless/bids.py:140, in convert_dataset_to_bids(import_funcs, import_args, bids_path_args, datatype, bids_root, import_events, **write_kwargs)
    135 bids_paths = []
    136 for import_kwargs, bids_path_kwargs, func in zip(
    137     import_args, bids_path_args, import_funcs
    138 ):
    139     bids_paths.append(
--> 140         convert_recording_to_bids(
    141             func,
    142             import_kwargs,
    143             bids_path_kwargs,
    144             datatype=datatype,
    145             bids_root=bids_root,
    146             import_events=import_events,
    147             **write_kwargs
    148         )
    149     )
    151 return bids_paths

File ~/Documents/Projects/ABC/.venv/lib/python3.10/site-packages/pylossless/bids.py:80, in convert_recording_to_bids(import_func, import_kwargs, bids_path_kwargs, datatype, bids_root, import_events, **write_kwargs)
     77 if \"allow_preload\" not in write_kwargs:
     78     write_kwargs[\"allow_preload\"] = True
---> 80 write_raw_bids(
     81     raw, bids_path=bids_path, events_data=events, event_id=event_id, **write_kwargs
     82 )
     84 return bids_path

TypeError: write_raw_bids() got an unexpected keyword argument 'events_data'"
}
@christian-oreilly
Copy link
Collaborator Author

I think MNE-BIDS renamed the events_data arguments to events in MNE-BIDS version 0.11+. @Deepa-Tilwani Could you check if you rename events_data to events on line 80 of the bids.py file if it works fine?

@christian-oreilly
Copy link
Collaborator Author

Could you check if you rename events_data to events on line 80 of the bids.py file if it works fine?

Confirmed.

@scott-huberty
Copy link
Member

scott-huberty commented Nov 11, 2024

Thanks @christian-oreilly Seems you are right 🙏 . Maybe we just pin to MNE-BIDS>=0.11? it was released 2 years ago.

Nevermind.. We already pin to MNE-BIDS 0.14. As @christian-oreilly said, looks like we are lacking a test for convert_dataset_to_bids

@christian-oreilly
Copy link
Collaborator Author

Yeah. I'll fish some old code. I was using this in the README some time back... so maybe this can be put in a test with the PR solving this.

@christian-oreilly
Copy link
Collaborator Author

Fetched from the history...

BIDSification

PyLossless provides some functions to help the user import non-BIDS recordings. Since the code to import datasets recorded in different formats and with different properties can vary much from one project to the next, the user must provide a function that can load and return a raw object along with the standard MNE events array and event_id dictionary. For example, in the case of our dataset

# Example of importing function
import tempfile
def egi_import_fct(path_in, stim_channel):
    # read in a file
    raw = mne.io.read_raw_egi(path_in, preload=True)
    # events and event IDs for events sidecar
    events = mne.find_events(raw, stim_channel=['STI 014'])
    event_id = raw.event_id
    # MNE-BIDS doesn't currently support RawMFF objects.
    with tempfile.TemporaryDirectory() as temp_dir:
        raw.save(Path(temp_dir) / "tmp_raw.fif")
        # preload=True is important since this file is volatile
        raw = mne.io.read_raw_fif(Path(temp_dir) / 'tmp_raw.fif', preload=True)
    # we only want EEG channels in the channels sidecar
    raw.pick_types(eeg=True, stim=False)
    raw.rename_channels({'E129': 'Cz'})  # to make compatible with montage
    return raw, events, event_id

Then, the dataset can be converted to BIDS as follows

import_args = [{"stim_channel": 'STI 014', "path_in": './sub-s004-ses_07_task-MMN_20220218_022348.mff'},
               {"stim_channel": 'STI 014', "path_in": './sub-s004-ses_07_task-MMN_20220218_022348.mff'}]
bids_path_args = [{'subject': '001', 'run': '01', 'session': '01', "task": "mmn"},
                  {'subject': '002', 'run': '01', 'session': '01', "task": "mmn"}]
bids_paths = ll.bids.convert_to_bids(egi_import_fct, import_args, bids_path_args, overwrite=True)

Note that, in this case, we used twice the same input file just to demonstrate how this function can be used for multiple recordings. In practice, a user may want to have this information stored in CSV files that can be readily used. For example, if we create such files for the demonstration:

import pandas as pd
pd.DataFrame(import_args).to_csv("import_args.csv", index=False)
pd.DataFrame(bids_path_args).to_csv("bids_path_args.csv", index=False)

Now, regardless of how such files have been produced (e.g., from Excel), these can be used directly to process the whole dataset:

import_args = list(pd.read_csv("import_args.csv").T.to_dict().values())
bids_path_args = list(pd.read_csv("bids_path_args.csv").T.to_dict().values())
bids_paths = ll.bids.convert_to_bids(egi_import_fct, import_args, bids_path_args, overwrite=True)
pipeline.run_dataset(bids_paths)

@christian-oreilly
Copy link
Collaborator Author

@scott-huberty I think the only challenge is that we don't have such a test file in the repo. Apparently, that file was also not part of the repo at this point in time... I am not sure if it was ever included.

@christian-oreilly
Copy link
Collaborator Author

I did find it in some old code archive on my local computer, though. That file was 761.1 MB. Maybe it can be cropped to a more reasonable size (~1MB?) and included? I suppose this was one of our internal Q1k piloting on you or me.

@scott-huberty
Copy link
Member

@christian-oreilly Maybe we can just use one of MNE's test files to create a "dummy" dataset (repeatedly using one file) like your previous example did?

import mne

raw_fname = mne.datasets.testing.data_path() / "EGI" / "test_egi.mff"

...

christian-oreilly added a commit that referenced this issue Nov 11, 2024
@christian-oreilly christian-oreilly linked a pull request Nov 11, 2024 that will close this issue
@christian-oreilly
Copy link
Collaborator Author

Yeah... I ended up doing something like that. I copied a snippet from another test and used

    testing_path = mne.datasets.testing.data_path()
    fname = testing_path / "EDF" / "test_edf_overlapping_annotations.edf"

Test written and successful locally.

christian-oreilly added a commit that referenced this issue Nov 11, 2024
* Fix bug issue #175

* Code linting.

* Update pylossless/tests/test_bids.py

Co-authored-by: Scott Huberty <[email protected]>

* Update pylossless/tests/test_bids.py

Co-authored-by: Scott Huberty <[email protected]>

* Update pylossless/tests/test_bids.py

Co-authored-by: Scott Huberty <[email protected]>

* Remove print, clean test files, rename test.

---------

Co-authored-by: Scott Huberty <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants