非官方中文翻译
本页译自 MNE-Python 官方文档:
查看英文原文 ↗。
文档版权归 MNE Developers 所有(BSD-3-Clause)。
说明
转到末尾下载完整示例代码。
通过子类化 MNEBrowseFigure 进行高级绘图定制#
本示例展示如何通过子类化 MNEBrowseFigure 并使用 figure_class 参数来定制 plot_epochs(…) 与 plot_raw(…)。它把一条 EEG 曲线叠加(“洋葱皮”式)在另一条之上。
本示例在若干方面属于“糟糕的代码”:
由于
MNEBrowseFigure的接口并非公开接口,它可能在 MNE 的次版本甚至补丁版本之间无警告地失效部分功能以近乎复制粘贴的方式从
MNEBrowseFigure重新实现代码与后端相关,尤其仅限 matplotlib 后端,无法用于 qt 浏览器
由于无法把另一份 EEG 直接传给
MNEBrowseFigure,这里通过全局变量传入
尽管如此,本示例说明当 MNE 提供的其他定制方式不足时,可以使用子类化这一“逃生通道”。
Using matplotlib as 2D backend.
Extracting EDF parameters from /home/circleci/mne_data/MNE-eegbci-data/files/eegmmidb/1.0.0/S001/S001R01.edf...
Setting channel info structure...
Creating raw.info structure...
Reading 0 ... 9759 = 0.000 ... 60.994 secs...
Extracting EDF parameters from /home/circleci/mne_data/MNE-eegbci-data/files/eegmmidb/1.0.0/S001/S001R02.edf...
Setting channel info structure...
Creating raw.info structure...
Reading 0 ... 9759 = 0.000 ... 60.994 secs...
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
from mne.datasets import eegbci
from mne.io import read_raw_edf
from mne.viz import set_browser_backend
from mne.viz._mpl_figure import MNEBrowseFigure as MNEBrowseFigureOrig
set_browser_backend("matplotlib")
onionskin_eeg = None
def _set_onionskin_eeg(eeg):
global onionskin_eeg
onionskin_eeg = eeg
class OnionskinMNEBrowseFigure(MNEBrowseFigureOrig):
"""
Subclass of MNEBrowseFigure adding in onion-skin functionality,
i.e. plotting one EEG trace overlaid on top of another.
"""
def __init__(self, *args, **kwargs):
import numpy as np
super().__init__(*args, **kwargs)
onionskin_kwargs = {
**self.mne.trace_kwargs,
}
self.mne.onionskins = self.mne.ax_main.plot(
np.full((1, self.mne.n_channels), np.nan), **onionskin_kwargs
)
def _update_data(self):
import numpy as np
from mne.io.base import BaseRaw
super()._update_data()
if not onionskin_eeg:
self.mne.onionskin_data = None
return
start, stop = self._get_start_stop()
if isinstance(onionskin_eeg, BaseRaw):
if stop is None:
data = onionskin_eeg[:, start:]
else:
data = onionskin_eeg[:, start:stop]
data = data[0]
else:
ix_start = np.searchsorted(
self.mne.boundary_times, self.mne.t_start - self.mne.sampling_period
)
ix_stop = ix_start + self.mne.n_epochs
item = slice(ix_start, ix_stop)
print(type(onionskin_eeg))
data = np.concatenate(
onionskin_eeg.get_data(item=item, copy=False), axis=-1
)
data = self._process_data(data, start, stop, picks=self.mne.picks)
self.mne.onionskin_data = data
def _draw_traces(self):
import numpy as np
from matplotlib.colors import to_rgba_array
from matplotlib.patches import Rectangle
super()._draw_traces()
if self.mne.onionskin_data is None:
return
picks = self.mne.picks
offset_ixs = (
picks
if self.mne.butterfly and self.mne.ch_selections is None
else slice(None)
)
offsets = self.mne.trace_offsets[offset_ixs]
ch_colors = to_rgba_array(self.mne.ch_colors)
ch_colors[:, 3] *= 0.5
decim = np.ones_like(picks)
data_picks_mask = np.isin(picks, self.mne.picks_data)
decim[data_picks_mask] = self.mne.decim
# decim can vary by channel type, so compute different `times` vectors
decim_times = {
decim_value: self.mne.times[::decim_value] + self.mne.first_time
for decim_value in set(decim)
}
time_range = (self.mne.times + self.mne.first_time)[[0, -1]]
ylim = self.mne.ax_main.get_ylim()
for ii, line in enumerate(self.mne.onionskins):
this_offset = offsets[ii]
this_times = decim_times[decim[ii]]
this_data = (
this_offset - self.mne.onionskin_data[ii] * self.mne.scale_factor
)
this_data = this_data[..., :: decim[ii]]
clip = 0.2 if self.mne.butterfly else 0.5
bottom = max(this_offset - clip, ylim[1])
height = min(2 * clip, ylim[0] - bottom)
rect = Rectangle(
xy=np.array([time_range[0], bottom]),
width=time_range[1] - time_range[0],
height=height,
transform=self.mne.ax_main.transData,
)
line.set_clip_path(rect)
line.set_xdata(this_times)
line.set_ydata(this_data)
color = ch_colors[ii]
line.set_color(color)
line.set_zorder(self.mne.zorder["data"] - 1)
subjects = [1]
runs = [1, 2]
raw_fnames = eegbci.load_data(subjects, runs)
first_data = read_raw_edf(raw_fnames[0], preload=True)
second_data = read_raw_edf(raw_fnames[1], preload=True)
first_data.plot(title="First plot", n_channels=3)
second_data.plot(title="Second plot", n_channels=3)
_set_onionskin_eeg(first_data)
second_data.plot(
title="Onionskinned plot",
n_channels=3,
block=True,
figure_class=OnionskinMNEBrowseFigure,
)
脚本总运行时间:(0 分 6.588 秒)


