Skip to content

Commit 252b6f3

Browse files
authored
Merge pull request #141 from LuyandaMdanda/master
1st draft of mne example
2 parents 3a312e6 + bf3618d commit 252b6f3

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
# Ignore Mac folder profile files
1717
*DS_Store*
18+
.vs*
1819

1920
# Ignore coverage file
2021
.coverage

examples/plot_mne_example.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
"""
2+
Using fooof with MNE
3+
====================
4+
5+
This examples illustrates how to use fooof with MNE and create topographical plots.
6+
7+
This tutorial does require that you have `MNE
8+
<https://mne-tools.github.io/>`_ installed. If you don't already have
9+
MNE, you can follow instructions to get it `here
10+
<https://mne-tools.github.io/stable/getting_started.html>`_.
11+
"""
12+
13+
###################################################################################################
14+
15+
# General imports
16+
import numpy as np
17+
import pandas as pd
18+
from matplotlib import cm, colors, colorbar
19+
import matplotlib.pyplot as plt
20+
21+
# Import MNE, as well as the MNE sample dataset
22+
import mne
23+
from mne import io
24+
from mne.datasets import sample
25+
from mne.viz import plot_topomap
26+
27+
# FOOOF imports
28+
from fooof import FOOOF, FOOOFGroup
29+
from fooof.analysis import *
30+
31+
###################################################################################################
32+
# Load & Check MNE Data
33+
# ---------------------
34+
#
35+
# First, we will load the example dataset from MNE, and have a quick look at the data.
36+
#
37+
# The MNE sample dataset is a combined MEG/EEG recording with an audiovisual task, as
38+
# described `here <https://martinos.org/mne/stable/manual/sample_dataset.html>`_.
39+
#
40+
# For the current example, we are going to sub-select only the EEG data,
41+
# and analyze it as continuous (non-epoched) data.
42+
#
43+
44+
###################################################################################################
45+
46+
# Get the data path for the MNE example data
47+
raw_fname = sample.data_path() + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
48+
event_fname = sample.data_path() + '/MEG/sample/sample_audvis_filt-0-40_raw-eve.fif'
49+
50+
# Load the file of example MNE data
51+
raw = mne.io.read_raw_fif(raw_fname, preload=True, verbose=False)
52+
53+
###################################################################################################
54+
55+
# Select EEG channels from the dataset
56+
raw = raw.pick_types(meg=False, eeg=True, eog=False, exclude='bads')
57+
58+
###################################################################################################
59+
60+
# Explicitly adding a default EEG average reference required for source localization
61+
raw.set_eeg_reference()
62+
63+
###################################################################################################
64+
65+
# Plot the channel locations and labels
66+
raw.plot_sensors(show_names=True)
67+
68+
###################################################################################################
69+
70+
# Creating epochs
71+
reject = dict(eeg=180e-6)
72+
event_id = {'left/auditory': 1}
73+
events = mne.read_events(event_fname)
74+
epochs = mne.Epochs(raw, events=events, event_id=event_id, tmin=5, tmax=125,
75+
baseline=None, preload=True, verbose=False)
76+
77+
###################################################################################################
78+
79+
# Creating Power Spectra Densities
80+
spectra, freqs = mne.time_frequency.psd_welch(epochs, fmin=1., fmax=50., n_fft=2000,
81+
n_overlap=250, n_per_seg=500)
82+
83+
###################################################################################################
84+
# FOOOFGroup
85+
# ----------
86+
#
87+
# The FOOOFGroup object is used to fit FOOOF models across the power spectra.
88+
#
89+
90+
###################################################################################################
91+
92+
# Initialize a FOOOFGroup object, with desired settings
93+
fg = FOOOFGroup(peak_width_limits=[1, 6], min_peak_height=0.075,
94+
max_n_peaks=6, peak_threshold=1, verbose=False)
95+
96+
###################################################################################################
97+
98+
# Selecting the first epoch of data to FOOOF
99+
spectra = np.squeeze(spectra[0,:,:])
100+
n_channels, n_freq = spectra.shape
101+
num_blocks = len(mne.read_events(event_fname))
102+
103+
# Setting frequency range
104+
freq_range = [3, 35]
105+
106+
# Fit the FOOOF model across all channels
107+
fg.fit(freqs, spectra, freq_range)
108+
fg.plot()
109+
110+
###################################################################################################
111+
112+
# Define labels for periodic & aperiodic features
113+
feats = ["CFS", "PWS", "BWS"]
114+
aperiodic_feats = ["Offset","Exponent"]
115+
116+
# Define bands of interest
117+
bands = {'theta': [3, 7],
118+
'alpha': [7, 14],
119+
'beta': [15, 30]}
120+
121+
# Create dictionaries to store all the periodic properties across frequencies
122+
results = {}
123+
for band_name in bands.keys():
124+
results[band_name] = np.zeros(shape=[num_blocks, n_channels, len(feats)])
125+
126+
# Creating dictionaries to store all the aperiodic properties across frequencies
127+
exponent_results = np.zeros(shape=[num_blocks, n_channels, len(aperiodic_feats)])
128+
129+
###################################################################################################
130+
131+
# Populating periodic and aperiodic values
132+
for block in range(0, num_blocks):
133+
for ind, res in enumerate(fg):
134+
exponent_results[block, ind, :] = res.aperiodic_params
135+
for band_label, band_range in bands.items():
136+
results[band_label][block, ind, :] = get_band_peak(res.peak_params, band_range, True)
137+
138+
###################################################################################################
139+
# Plotting Topographies
140+
# ---------------------
141+
#
142+
# Now we can plot the extracted FOOOF features across all channels.
143+
#
144+
145+
###################################################################################################
146+
147+
def plot_topo_colorbar(vmin, vmax, label):
148+
"""Helper function to create colorbars for the topography plots."""
149+
150+
fig = plt.figure(figsize=(2, 3))
151+
ax1 = fig.add_axes([0.9, 0.25, 0.15, 0.9])
152+
153+
cmap = cm.viridis
154+
norm = colors.Normalize(vmin=vmin, vmax=vmax)
155+
156+
cb1 = colorbar.ColorbarBase(plt.gca(), cmap=cmap,
157+
norm=norm, orientation='vertical')
158+
159+
###################################################################################################
160+
#
161+
# In this example, we will be plotting the alpha center frequency and oscillatory exponent.
162+
163+
###################################################################################################
164+
165+
# Settings to grab the alpha center frequency
166+
band = 'alpha'
167+
cur_data = results[band]
168+
169+
topo_dat = np.mean(cur_data,0)
170+
171+
###################################################################################################
172+
173+
# Looking at the alpha center frequeuncy
174+
print('CURRENT FEATURE:', feats[0])
175+
disp_dat = topo_dat[:,0]
176+
177+
inds = np.where(np.isnan(disp_dat))
178+
disp_dat[inds] = np.nanmean(disp_dat)
179+
180+
vbuffer = 0.1 * (disp_dat.max() - disp_dat.min())
181+
vmin, vmax, = disp_dat.min() - vbuffer, disp_dat.max() + vbuffer
182+
183+
fig, ax = plt.subplots()
184+
plot_topo_colorbar(vmin, vmax, feats[0])
185+
mne.viz.plot_topomap(disp_dat, raw.info, vmin=vmin, vmax=vmax, cmap=cm.viridis, contours=0, axes=ax)
186+
187+
###################################################################################################
188+
189+
# Looking at the aperiodic exponent
190+
cur_data = exponent_results
191+
192+
topo_dat = np.mean(cur_data,0)
193+
194+
print('CURRENT FEATURE:', aperiodic_feats[1])
195+
disp_dat = topo_dat[:,1]
196+
197+
inds = np.where(np.isnan(disp_dat))
198+
disp_dat[inds] = np.nanmean(disp_dat)
199+
200+
vbuffer = 0.1 * (disp_dat.max() - disp_dat.min())
201+
vmin, vmax, = disp_dat.min() - vbuffer, disp_dat.max() + vbuffer
202+
203+
fig, ax = plt.subplots()
204+
plot_topo_colorbar(vmin, vmax, exponent_results[1])
205+
mne.viz.plot_topomap(disp_dat, raw.info, vmin=vmin, vmax=vmax, cmap=cm.viridis, contours=0, axes=ax)

0 commit comments

Comments
 (0)