-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9e14ec4
commit 84b9fef
Showing
232 changed files
with
29,353 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"\n# FBrCCA\nThis script shows how to use FBrCCA from PyntBCI for decoding c-VEP trials. The FBrCCA method uses a template matching\nclassifier where templates are estimated using reconvolution and canonical correlation analysis (CCA). Additionally,\nFBrCCA uses a filterbank (FB).\n\nThe data used in this script come from Thielen et al. (2021), see references [1]_ and [2]_.\n\n## References\n.. [1] Thielen et al. (2021) From full calibration to zero training for a code-modulated visual evoked potentials brain\n computer interface. DOI: https://doi.org/10.34973/9txv-z787\n.. [2] Thielen, J., Marsman, P., Farquhar, J., & Desain, P. (2021). From full calibration to zero training for a\n code-modulated visual evoked potentials for brain\u2013computer interface. Journal of Neural Engineering, 18(5),\n 056007. DOI: https://doi.org/10.1088/1741-2552/abecef\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn\n\nimport pyntbci\n\nseaborn.set_context(\"paper\", font_scale=1.5)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Set the data path\nThe cell below specifies where the dataset has been downloaded to. Please, make sure it is set correctly according to\nthe specification of your device. If none of the folder structures in the dataset were changed, the cells below should\nwork just as fine.\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"path = os.path.join(os.path.dirname(pyntbci.__file__)) # path to the dataset\nn_subjects = 5\nsubjects = [f\"sub-{1 + i:02d}\" for i in range(n_subjects)]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Analyse multiple participants\nIn this section, we directly apply FBrCCA and compare it to a single-band rCCA using the pass-bands defined in the\nfilterbank.\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"# Set trial duration\ntrialtime = 4.2 # limit trials to a certain duration in seconds\nn_trials = 100 # limit the number of trials in the dataset\n\n# Set rCCA (see pyntbci.classifiers.rCCA)\nevent = \"duration\" # event definition type\ntransient_size = 0.3 # length of a transient response in seconds\nonset_event = True\n\n# Set folds for chronological cross-validation\nn_folds = 5\nfolds = np.repeat(np.arange(n_folds), int(n_trials / n_folds))\n\n# Set filterbank (see pyntbci.utilities.filterbank)\ntmin = 0 # seconds before trial onset that could catch filter artefacts and is cut off after the filterbank\nfilterbank = [ # passbands with lower and higher cutoffs in Hz\n [1.0, 60.0],\n [12.0, 60.0],\n [30.0, 60.0]]\nftype = \"chebyshev1\" # filter type\ngpass = 3 # maximum attenuation in the passband in dB\ngstop = 20 # minimum attenuation in the stopband in dB\nn_bands = len(filterbank)\n\n# Loop participants\naccuracy_rcca = np.zeros((n_subjects, n_folds, n_bands))\naccuracy_fbrcca = np.zeros((n_subjects, n_folds))\nfor i_subject in range(n_subjects):\n subject = subjects[i_subject]\n\n # Load data\n fn = os.path.join(path, \"data\", f\"thielen2021_{subject}.npz\")\n tmp = np.load(fn)\n fs = tmp[\"fs\"]\n X = tmp[\"X\"][:n_trials, :, :int(trialtime * fs)]\n y = tmp[\"y\"][:n_trials]\n V = tmp[\"V\"]\n\n # Apply filterbank\n X = pyntbci.utilities.filterbank(X, filterbank, fs, tmin=tmin, ftype=ftype, gpass=gpass, gstop=gstop)\n\n # Cross-validation\n for i_fold in range(n_folds):\n\n # Split data to train and test set\n X_trn, y_trn = X[folds != i_fold, :, :, :], y[folds != i_fold]\n X_tst, y_tst = X[folds == i_fold, :, :, :], y[folds == i_fold]\n\n # Setup classifier\n rcca = pyntbci.classifiers.rCCA(codes=V, fs=fs, event=event, transient_size=transient_size,\n onset_event=onset_event)\n fbrcca = pyntbci.classifiers.FilterBank(estimator=rcca, gating=\"mean\")\n\n # Train classifier\n fbrcca.fit(X_trn, y_trn)\n\n # Apply classifier\n yh_tst = fbrcca.predict(X_tst)\n\n # Compute accuracy\n accuracy_fbrcca[i_subject, i_fold] = np.mean(yh_tst == y_tst)\n\n # Loop individual pass-bands\n for i_band in range(n_bands):\n # Setup classifier\n rcca = pyntbci.classifiers.rCCA(codes=V, fs=fs, event=event, transient_size=transient_size,\n onset_event=onset_event)\n\n # Train classifier\n rcca.fit(X_trn[:, :, :, i_band], y_trn)\n\n # Apply classifier\n yh_tst = rcca.predict(X_tst[:, :, :, i_band])\n\n # Compute accuracy\n accuracy_rcca[i_subject, i_fold, i_band] = np.mean(yh_tst == y_tst)\n\n# Stack results\naccuracy = np.concatenate((accuracy_fbrcca[:, :, np.newaxis], accuracy_rcca), axis=2)\n\n# Plot accuracy\nplt.figure(figsize=(15, 4))\nfor i in range(1 + len(filterbank)):\n if i == 0:\n label = \"FBrCCA\"\n else:\n label = f\"rCCA {filterbank[i - 1][0]:>4}-{filterbank[i - 1][1]:>4}\"\n width = 0.9 / (1 + len(filterbank))\n plt.bar(i * width + np.arange(n_subjects), accuracy[:, :, i].mean(axis=1), width,\n yerr=accuracy[:, :, i].std(axis=1), label=label)\nplt.axhline(1 / V.shape[0], linestyle=\"--\", color=\"k\", alpha=0.5, label=\"chance\")\nplt.xticks(width * (len(filterbank) / 2) + np.arange(n_subjects), subjects, rotation=45)\nplt.legend(bbox_to_anchor=(1.0, 1.0))\nplt.ylabel(\"accuracy\")\nplt.title(\"Decoding performance full dataset\")\nplt.tight_layout()\n\n# Print accuracy\nfor i in range(1 + len(filterbank)):\n if i == 0:\n label = \"FBrCCA\"\n else:\n label = f\"rCCA {filterbank[i - 1][0]:>4}-{filterbank[i - 1][1]:>4}\"\n print(f\"{label}: {np.mean(accuracy[-1, :, i]):.2f} +/- {np.std(accuracy[-1, :, i]):.2f}\")\n\n# plt.show()" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.12" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |
Oops, something went wrong.