Note
Go to the end to download the full example code
02. Detect HFOs on BIDS Dataset#
MNE-HFO requires strict adherence to the BIDS specification for EEG/iEEG data.
It currently depends on the data structures defined by MNE-Python
and
MNE-BIDS
.
In this example, we use MNE-BIDS to load real raw data and then use MNE-HFO to detect HFOs. Specifically, we will follow these steps:
1. Load data via mne_bids.read_raw_bids()
. We will load a sample subject
from the Fedele dataset [1].
Run a few
mne_hfo.base.Detector
instances to detect HFOsFormat the detected HFOs as a
pandas.DataFrame
Write to disk according to BEP-021 and read it in again.
References#
- [1] Fedele T, Burnos S, Boran E, Krayenbühl N, Hilfiker P, Grunwald T, Sarnthein J.
Resection of high frequency oscillations predicts seizure outcome in the individual patient. Scientific Reports. 2017;7(1):13836. https://www.nature.com/articles/s41598-017-13064-1. doi:10.1038/s41598-017-13064-1
# Authors: Adam Li <adam2392@gmail.com>
#
We are importing everything we need for this example:
from pathlib import Path
from mne_bids import BIDSPath, read_raw_bids, make_report, print_dir_tree
from mne_hfo import (RMSDetector, write_annotations,
read_annotations)
Load the data#
First, we need some data to work with. We will use the test dataset
available with the repository under data/
directory.
show the contents of the BIDS dataset
|data/
|--- .bidsignore
|--- README
|--- dataset_description.json
|--- participants.json
|--- participants.tsv
|--- derivatives/
|------ sub-01/
|--------- ieeg/
|------------ sub-01_task-interictalsleep_run-01_annotations.json
|------------ sub-01_task-interictalsleep_run-01_annotations.tsv
|--- sub-01/
|------ sub-01_scans.tsv
|------ ieeg/
|--------- sub-01_task-interictalsleep_run-01_channels.tsv
|--------- sub-01_task-interictalsleep_run-01_events.tsv
|--------- sub-01_task-interictalsleep_run-01_ieeg.eeg
|--------- sub-01_task-interictalsleep_run-01_ieeg.json
|--------- sub-01_task-interictalsleep_run-01_ieeg.vhdr
|--------- sub-01_task-interictalsleep_run-01_ieeg.vmrk
The Fedele-epilepsy-HFO-iEEG Dataset dataset was created by Fedele T, Burnos S,
Boran E, Krayenbühl N, Hilfiker P, Grunwald T, and Sarnthein J and conforms to
BIDS version 1.4.0. This report was generated with MNE-BIDS
(https://doi.org/10.21105/joss.01896). The dataset consists of 1 participants
(comprised of 1 male and 0 female participants; handedness were all unknown;
ages ranged from 25.0 to 25.0 (mean = 25.0, std = 0.0)) . Data was recorded
using an iEEG system (Elekta) sampled at 2000.0 Hz with line noise at 50.0 Hz.
There was 1 scan in total. Recording durations ranged from 5.0 to 5.0 seconds
(mean = 5.0, std = 0.0), for a total of 5.0 seconds of data recorded over all
scans. For each dataset, there were on average 50.0 (std = 0.0) recording
channels per scan, out of which 50.0 (std = 0.0) were used in analysis (0.0 +/-
0.0 were removed from analysis).
Load the dataset.
Extracting parameters from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_ieeg.vhdr...
Setting channel info structure...
Reading events from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_events.tsv.
Reading channel info from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_channels.tsv.
/home/circleci/project/examples/01_working_with_bids.py:73: RuntimeWarning: Did not find any electrodes.tsv associated with sub-01_task-interictalsleep_run-01.
The search_str was "../mne_hfo/tests/data/sub-01/**/ieeg/sub-01*electrodes.tsv"
raw = read_raw_bids(bids_path)
/home/circleci/project/examples/01_working_with_bids.py:73: RuntimeWarning: Did not find any coordsystem.json associated with sub-01_task-interictalsleep_run-01.
The search_str was "../mne_hfo/tests/data/sub-01/**/ieeg/sub-01*coordsystem.json"
raw = read_raw_bids(bids_path)
Let’s plot the data and see what it looks like raw.plot()
Detect HFOs#
All detectors inherit from the base class mne_hfo.base.Detector
,
which inherits from the sklearn.base.BaseEstimator
class.
To run any estimator, one instantiates it along with the hyper-parameters,
and then calls the fit
function. Afterwards, detected HFOs are available
in the various data structures. The recommended usage is the DataFrame, which
is accessible via the mne_hfo.base.Detector.to_data_frame
property.
kwargs = {
'threshold': 3, # threshold for "significance"
'win_size': 100, # window size in samples
'overlap': 0.25 # overlap in percentage relative to the window size
}
detector = RMSDetector(**kwargs)
# run detector
detector.fit(X=raw)
# get the HFO results as an annotations.tsv DataFrame
annot_df = detector.to_data_frame(format='bids')
print(annot_df.head())
0%| | 0/50 [00:00<?, ?it/s]
32%|███▏ | 16/50 [00:00<00:00, 156.21it/s]
64%|██████▍ | 32/50 [00:00<00:00, 137.09it/s]
92%|█████████▏| 46/50 [00:00<00:00, 94.32it/s]
100%|██████████| 50/50 [00:00<00:00, 113.39it/s]
onset ... sfreq
0 0.0 ... 2000.0
1 0.0 ... 2000.0
2 0.0 ... 2000.0
3 0.0 ... 2000.0
4 0.0 ... 2000.0
[5 rows x 6 columns]
onset ... sfreq
0 0.0 ... 2000.0
1 0.0 ... 2000.0
2 0.0 ... 2000.0
3 0.0 ... 2000.0
4 0.0 ... 2000.0
[5 rows x 6 columns]
Convert HFO events to annotations#
Detectors output HFO events detected as a DataFrame fashioned after the
*_events.tsv
files in BIDS-iEEG. Instead, HFO events are indeed
Derivatives of the Raw data, that are estimated/detected using mne-hfo.
The correct way to store them is in terms of an *_annotations.tsv
,
according to the BIDS-Derivatives specification.
# alternatively save annotation dataframe to disc
annot_path = bids_path.copy().update(suffix='annotations',
root=root / 'derivatives',
extension='.tsv',
check=False)
intended_for = raw.filenames[0]
write_annotations(annot_df, fname=annot_path,
intended_for=intended_for, root=root)
print(annot_df.head())
inside write... sub-01_task-interictalsleep_run-01_ieeg.vhdr
onset ... sfreq
0 0.0 ... 2000.0
1 0.0 ... 2000.0
2 0.0 ... 2000.0
3 0.0 ... 2000.0
4 0.0 ... 2000.0
[5 rows x 6 columns]
Read data back in#
The data will match what was written. In addition, you can check for overlapping HFOs.
annot_df = read_annotations(annot_path)
print(annot_df.head())
sub-01_task-interictalsleep_run-01_ieeg.vhdr
raw fpath: ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_ieeg.vhdr
Extracting parameters from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_ieeg.vhdr...
Setting channel info structure...
Reading events from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_events.tsv.
Reading channel info from ../mne_hfo/tests/data/sub-01/ieeg/sub-01_task-interictalsleep_run-01_channels.tsv.
onset ... sfreq
0 0.0 ... 2000.0
1 0.0 ... 2000.0
2 0.0 ... 2000.0
3 0.0 ... 2000.0
4 0.0 ... 2000.0
[5 rows x 6 columns]
Total running time of the script: (0 minutes 2.416 seconds)
Estimated memory usage: 14 MB