{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Using the coffeine filterbank for dedoding motor imagery\n", "\n", "This notebook is based on the [MNE example](https://mne.tools/dev/auto_examples/decoding/decoding_csp_eeg.html) and illustrates the construction of the filterbank models.\n", "\n", "First we load the data as in the original example." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import ShuffleSplit, cross_val_score\n", "\n", "import mne\n", "from mne import Epochs, pick_types, events_from_annotations\n", "from mne.io import concatenate_raws, read_raw_edf\n", "from mne.datasets import eegbci\n", "\n", "from coffeine import compute_coffeine, make_filter_bank_classifier" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "mne.set_log_level('critical')\n", "pd.set_option(\"large_repr\", \"info\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "tmin, tmax = -1.0, 4.0\n", "event_id = dict(hands=2, feet=3)\n", "subject = 1\n", "runs = [6, 10, 14] # motor imagery: hands vs feet\n", "raw_fnames = eegbci.load_data(subject, runs)\n", "raw = concatenate_raws([read_raw_edf(f, preload=True) for f in raw_fnames])\n", "eegbci.standardize(raw) # set channel names" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Apply band-pass filter\n", "raw.filter(4.0, 35.0, fir_design=\"firwin\", skip_by_annotation=\"edge\")\n", "\n", "events, _ = events_from_annotations(raw, event_id=dict(T1=2, T2=3))\n", "picks = pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude=\"bads\")\n", "\n", "# Read epochs (train will be done only between 1 and 2s)\n", "# Testing will be done with a running classifier\n", "epochs = Epochs(\n", " raw,\n", " events,\n", " event_id,\n", " tmin,\n", " tmax,\n", " proj=True,\n", " picks=picks,\n", " baseline=None,\n", " preload=True,\n", ")\n", "\n", "labels = epochs.events[:, -1] - 2\n", "conditions = ['feet', 'hand']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Building a coffeine data frame of covariances per frequency\n", "\n", "\n", "In the following, we compute covariances based on pre-defined frequencies and show how to make a coffeine data frame from them. This was previously complicated, now coffeine provides the API for it." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As this is event-related data and not subject-level data as in [Sabbagh et al 2020](https://www.sciencedirect.com/science/article/pii/S1053811920303797), we need to loop over epochs. Luckily, coffeine does this for us. We now get the pandas data frame where each columns is an object array of covariances, which is represented as a list of covariances, leading to an object array type." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now make the pandas data frame where each columns is an object array of covariances, which we can represent as a list of covariances." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<class 'pandas.core.frame.DataFrame'>\n", "RangeIndex: 5 entries, 0 to 4\n", "Data columns (total 2 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 alpha1 5 non-null object\n", " 1 alpha2 5 non-null object\n", "dtypes: object(2)\n", "memory usage: 208.0+ bytes\n", "" ], "text/plain": [ "