Skip to content

Commit

Permalink
"GFP" trace in STC time viewer is actually RMS
Browse files Browse the repository at this point in the history
I've also rearranged the formula such that it becomes
immediately obvious that we're dealing with RMS values.

See mne-tools#8775 for our lengthy discussion on this for sensor-level
data.
  • Loading branch information
hoechenberger committed Feb 26, 2021
1 parent 8e3bcef commit 300bc18
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
2 changes: 2 additions & 0 deletions doc/changes/latest.inc
Expand Up @@ -158,6 +158,8 @@ Bugs

- `~mne.io.read_raw_bti` erroneously treated response channels as respiratory channels (:gh:`8855` by `Richard Höchenberger`_)

- The RMS trace shown in the time viewer of `~mne.SourceEstimate` plots is now correctly labeled as ``RMS`` (was ``GFP`` before) (:gh:`8965` by `Richard Höchenberger`_)

API changes
~~~~~~~~~~~
- ``mne.read_selection`` has been deprecated in favor of `mne.read_vectorview_selection`. ``mne.read_selection`` will be removed in MNE-Python 0.24 (:gh:`8870` by `Richard Höchenberger`_)
20 changes: 11 additions & 9 deletions mne/viz/_brain/_brain.py
Expand Up @@ -602,7 +602,7 @@ def setup_time_viewer(self, time_viewer=True, show_traces=True):
self.color_list.remove("#7f7f7f")
self.color_cycle = _ReuseCycle(self.color_list)
self.mpl_canvas = None
self.gfp = None
self.rms = None
self.picked_patches = {key: list() for key in all_keys}
self.picked_points = {key: list() for key in all_keys}
self.pick_table = dict()
Expand Down Expand Up @@ -1130,13 +1130,15 @@ def _configure_vertex_time_course(self):
else:
self.clear_glyphs()

# plot the GFP
# plot RMS of the activation
y = np.concatenate(list(v[0] for v in self.act_data_smooth.values()
if v[0] is not None))
y = np.linalg.norm(y, axis=0) / np.sqrt(len(y))
self.gfp, = self.mpl_canvas.axes.plot(
self._data['time'], y,
lw=3, label='GFP', zorder=3, color=self._fg_color,
rms = np.sqrt((y ** 2).mean(axis=0))
del y

self.rms = self.mpl_canvas.axes.plot(
self._data['time'], rms,
lw=3, label='RMS', zorder=3, color=self._fg_color,
alpha=0.5, ls=':')

# now plot the time line
Expand Down Expand Up @@ -1695,9 +1697,9 @@ def clear_glyphs(self):
for label_id in list(self.picked_patches[hemi]):
self._remove_label_glyph(hemi, label_id)
assert sum(len(v) for v in self.picked_patches.values()) == 0
if self.gfp is not None:
self.gfp.remove()
self.gfp = None
if self.rms is not None:
self.rms.remove()
self.rms = None
self._update()

def plot_time_course(self, hemi, vertex_id, color):
Expand Down
Expand Up @@ -8,6 +8,8 @@
minimum-norm inverse method on evoked/raw/epochs data.
"""

import os.path as op

import numpy as np
import matplotlib.pyplot as plt

Expand All @@ -19,7 +21,8 @@
# Process MEG data

data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
raw_fname = op.join(data_path, 'MEG', 'sample',
'sample_audvis_filt-0-40_raw.fif')

raw = mne.io.read_raw_fif(raw_fname) # already has an average reference
events = mne.find_events(raw, stim_channel='STI 014')
Expand Down

0 comments on commit 300bc18

Please sign in to comment.