MNE est une librairie python open-source offrant des fonctionnalités spécialisées pour toute sorte de traitements de données MEG, EEG, sEEG, ECoG ou encore NIRS.
Dans le cadre de notre projet, elle peut servir à traiter le signal EEG, le visualiser sous différentes formes, extraire des graphiques complexes et intéressants pour analyser le signal et classifier des essais.
Dans cette documentation, nous avons utilisé le dataset BCI Competition 2a dont le fichier .gdf (contenant les données du signal et les annotations concernant les signaux EEG récoltés lors de la constitution du dataset) et le fichier .mat (contenant les labels) sont téléchargeables sur la page web de BCI Competiton.
Les données du dataset peuvent être importées du fichier gdf en utilisant la fonction mne.io.read_raw_gdf(pathname, eog=None, misc=None, preload=True). Le paramètre pathname décrit le chemin d'accès au fichier gdf. Le paramètre preload = True est particulièrement important : il permet d'activer le chargement en mémoire des données lors de l'importation.
Le retour de cette fonction est une instance de la classe Raw qui va nous permettre de récupérer les données du dataset mais aussi des informations dessus (par exemple les différents événements survenant au cours de l'expérimentation tels que le démarrage d'un nouvel essai).
En ce qui concerne les labels, ils peuvent être chargés dans le programme à l'aide de la fonction scipy.io.loadmat(mat_fname) où mat_fname est le chemin d'accès vers le fichier .mat fourni par BCI Competition 2008.
L'instance de Raw récupérée précédemment doit être configurée avant d'être utilisée convenablement.
La première étape est d'éventuellement préciser la nature de certains canaux avec la fonction raw.set_channel_types({'EOG-left': 'eog','EOG-central': 'eog','EOG-right': 'eog'}). Ici, certains canaux du fichier gdf sont définis comme des canaux EOG (et non EEG qui est leur statut par défaut).
Une deuxième étape, très importante notamment dans le cas de l'affichage en deux ou trois dimensions du signal sur une représentation du cerveau humain, est de définir un montage. Le montage précise le nom de chacune des électrodes de notre objet Raw et leur attribue une position dans l'espace.
Dans le cas de ce dataset, la norme de placement utilisée est le système 10-20 décrit dans les pages précédentes. Il est possible de récupérer le montage par défaut de la norme 10-20 à l'aide de la fonction mne.channels.make_standard_montage(kind='standard_1020').
Cependant, ce montage par défaut doit être paramétré puisque le nom des électrodes définis dans le fichier gdf (sous la forme EEG-n°electrode) ne correspond pas à la norme 10-20. Nous avons nous-mêmes réalisé la conversion des noms d'électrode vers la norme 10-20 : il s'agit ainsi d'utiliser la fonction
montage.rename_channels({'Fz':'EEG-Fz','FC3':'EEG-0','FC1':'EEG-1','FCz':'EEG-2','FC2':'EEG-3','FC4':'EEG-4','C5':'EEG-5','C1':'EEG-6','C2':'EEG-7','C6':'EEG-8','CP3':'EEG-9','CP1':'EEG-10','CPz':'EEG-11','CP2':'EEG-12','CP4':'EEG-13','P1':'EEG-14','P2':'EEG-15','Oz':'EEG-16','C3':'EEG-C3','C4':'EEG-C4','Pz':'EEG-Pz','Cz':'EEG-Cz'})
Le montage est alors prêt à être associé au fichier raw avec la fonction raw.set_montage(montage,match_case = False).
La classe Raw contient une méthode permettant de réaliser directement le filtrage numérique fréquentiel du signal via un filtre passe-bande. Ainsi, la fonction raw.filter(7.,30.,fir_design='firwin',skip_by_annotation='edge') permet de filtrer le signal EEG dans la bande de fréquence 7-30 Hz.
Ensuite, les différents événements survenant lors de l'expérimentation peuvent être récupérés avec la méthode mne.events_from_annotations(raw). Celle-ci renvoie un dictionnaire permettant d'accéder aux identifiants uniques de chaque événement. Par exemple, l'identifiant de l'événement 768 correspondant au début d'un nouvel essai se fait de la manière suivante : event_id = events[1]['768'].
Il faut ensuite préciser les types de canaux que l'on souhaite utiliser dans le dataset avec la fonction mne.pick_types(raw.info, meg=False, eeg=True, stim=False, eog=True,exclude='bads'). Dans cet exemple, les canaux EEG et EOG pertinents sont conservés. La fonction renvoie un objet qui servira à réaliser la sélection des canaux ultérieurement.
Un élément très important de la librairie MNE est la classe Epochs. Les Epochs sont des extraits d'enregistrement EEG de taille similaire contenant un événement donné. Classiquement, il s'agit des essais réalisés lors de l'enregistrement.
Les Epochs de l'objet Raw peuvent être extraits via la fonction mne.Epochs(raw, events[0], event_id, tmin, tmax, picks=picks,baseline=(0, 0), preload=True). events[0] est le dictionnaire des événements récupéré précédemment. event_id décrit l'identifiant de l'événement servant à distinguer les Epochs (ici l'événément 768). tmin et tmax sont les bornes inférieures et supérieures de temps de chaque Epoch. Enfin, preload = True est important car il permettra de réaliser des traitements sur les données (par exemple copie ou réalisation d'un sous-ensemble du dataset) mais il nécessite le chargement complet des données en mémoire et consomme dont d'importantes ressources.
Les données EEG d'un objet Epochs peuvent être récupérées en utilisant la fonction epochs.get_data().
Il est possible grâce à MNE de représenter graphiquement l'activité cérébrale d'un sujet. Pour cela, nous devons utiliser la notion d'evoked. Il s'agit du moyennage temporel des Epochs pour un sujet donné.
L'evoked correspondant à un objet Epochs peut être constitué avec la méthode epochs.average().
Le bruit d'origine physiologique (par exemple les clignements ou mouvements des yeux) peuvent être supprimés grâce aux méthodes evoked.add_proj(mne.compute_proj_evoked(evoked.copy().crop(tmax=0))) et evoked.apply_proj().
Enfin, les graphiques peuvent être affichés grâce à la fonction evoked.plot_topomap(times). Dans cette fonction, le paramètre times est un tableau regroupant les différents instants pour lequel on souhaite afficher l'activité cérébrale.
Voici ci-dessous un exemple de graphique généré avec le dataset BCI Competition 2a sur les données en évaluation du sujet A01.
Le filtre CSP (pour Common Spatial Patterns) est un filtre dit adaptatif, c'est-à-dire qu'il va chercher à personnaliser le filtrage spatial pour chaque personne en sélectionnant les électrodes qui semblent les plus adaptées pour une personne données. En effet, bien que les activités cérébrales soient souvent concentrées dans certaines zones (par exemple le cortex moteur pour un mouvement), les électrodes pertinentes peuvent varier fortement selon les individus : il peut alors être très intéressant de sélectionner les canaux pertinents pour chaque personne.
Ce type de filtre nécessite un entraînement basé sur des données. MNE permet la mise en place d'un tel filtre grâce aux Epochs.
L'initialisation d'un filtre CSP se fait grâce à la fonction CSP(n_components=4, reg=None, log=True, norm_trace=False) retournant une instance de la classe CSP. Il est alors possible d'entraîner le CSP avec la fonction csp.fit_transform(epochs_data, labels) où epochs_data est la matrice de données issues d'un objet de la classe Epochs et labels et la matrice contenant les labels pour chaque essai.
Il peut alors être intéressant d'afficher les patternes CSP calculées après cet entraînement grâce à la fonction csp.plot_patterns(epochs.info, ch_type='eeg', units='Patterns (AU)', size=1.5).
Les graphiques ci-dessous montrent les patternes CSP calculés respectivement pour les sujets A01 et A02.