说明
转到末尾下载完整示例代码。
提取并可视化受试者头部运动#
在 MEG 记录过程中,可以利用持续发出正弦信号的 HPI 线圈来编码连续的头部运动。随后可以从记录中提取这些信号,并用其估计随时间变化的头部位置。下面我们通过一个示例展示具体做法,以及如何可视化结果。
HPI 频率#
首先,我们加载一小段原始数据,其中受试者在记录过程中有意移动了头部。其功率谱密度显示出五个峰值(在梯度计中最为清晰),分别对应 HPI 线圈频率;此外还有其他与工频干扰相关的峰值(60 Hz 及其谐波)。
# Authors: Eric Larson <larson.eric.d@gmail.com>
# Richard Höchenberger <richard.hoechenberger@gmail.com>
# Daniel McCloy <dan@mccloy.info>
#
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
from os import path as op
import mne
data_path = op.join(mne.datasets.testing.data_path(verbose=True), "SSS")
fname_raw = op.join(data_path, "test_move_anon_raw.fif")
raw = mne.io.read_raw_fif(fname_raw, allow_maxshield="yes").load_data()
raw.compute_psd().plot(picks="data", exclude="bads", amplitude=False)

Opening raw data file /home/circleci/mne_data/MNE-testing-data/SSS/test_move_anon_raw.fif...
Read a total of 12 projection items:
mag.fif : PCA-v1 (1 x 306) idle
mag.fif : PCA-v2 (1 x 306) idle
mag.fif : PCA-v3 (1 x 306) idle
mag.fif : PCA-v4 (1 x 306) idle
mag.fif : PCA-v5 (1 x 306) idle
mag.fif : PCA-v6 (1 x 306) idle
mag.fif : PCA-v7 (1 x 306) idle
grad.fif : PCA-v1 (1 x 306) idle
grad.fif : PCA-v2 (1 x 306) idle
grad.fif : PCA-v3 (1 x 306) idle
grad.fif : PCA-v4 (1 x 306) idle
Average EEG reference (1 x 60) idle
Range : 10800 ... 31199 = 9.000 ... 25.999 secs
Ready.
Reading 0 ... 20399 = 0.000 ... 16.999 secs...
Effective window size : 1.707 (s)
Plotting power spectral density (dB=True).
我们可以使用 mne.chpi.get_chpi_info 获取线圈频率、指示每个线圈何时开启的 STIM 通道索引,以及各线圈活动对应的“事件代码”(event codes)。
chpi_freqs, ch_idx, chpi_codes = mne.chpi.get_chpi_info(info=raw.info)
print(f"cHPI coil frequencies extracted from raw: {chpi_freqs} Hz")
Using 5 HPI coils: 83 143 203 263 323 Hz
cHPI coil frequencies extracted from raw: [ 83. 143. 203. 263. 323.] Hz
估计连续头部位置#
首先,让我们提取随时间变化的 HPI 线圈幅度:
Using 5 HPI coils: 83 143 203 263 323 Hz
Line interference frequencies: 60.0 120.0 180.0 240.0 300.0 360.0 Hz
Using time window: 83.3 ms
Fitting 5 HPI coil locations at up to 1696 time points (17.0 s duration)
0%| | cHPI amplitudes : 0/1696 [00:00<?, ?it/s]
0%| | cHPI amplitudes : 1/1696 [00:02<1:18:24, 2.78s/it]
2%|▏ | cHPI amplitudes : 41/1696 [00:02<01:47, 15.44it/s]
5%|▍ | cHPI amplitudes : 84/1696 [00:02<00:49, 32.29it/s]
7%|▋ | cHPI amplitudes : 127/1696 [00:02<00:31, 49.80it/s]
10%|█ | cHPI amplitudes : 170/1696 [00:02<00:22, 67.98it/s]
13%|█▎ | cHPI amplitudes : 213/1696 [00:02<00:17, 86.85it/s]
15%|█▌ | cHPI amplitudes : 256/1696 [00:02<00:13, 106.40it/s]
18%|█▊ | cHPI amplitudes : 299/1696 [00:02<00:11, 126.67it/s]
20%|██ | cHPI amplitudes : 341/1696 [00:02<00:09, 147.16it/s]
23%|██▎ | cHPI amplitudes : 384/1696 [00:02<00:07, 168.89it/s]
25%|██▌ | cHPI amplitudes : 427/1696 [00:02<00:06, 191.34it/s]
28%|██▊ | cHPI amplitudes : 470/1696 [00:02<00:05, 214.57it/s]
30%|███ | cHPI amplitudes : 513/1696 [00:02<00:04, 238.53it/s]
33%|███▎ | cHPI amplitudes : 556/1696 [00:02<00:04, 263.25it/s]
35%|███▌ | cHPI amplitudes : 599/1696 [00:03<00:03, 288.75it/s]
38%|███▊ | cHPI amplitudes : 642/1696 [00:03<00:03, 314.97it/s]
40%|████ | cHPI amplitudes : 684/1696 [00:03<00:02, 341.30it/s]
43%|████▎ | cHPI amplitudes : 727/1696 [00:03<00:02, 369.05it/s]
45%|████▌ | cHPI amplitudes : 769/1696 [00:03<00:02, 396.86it/s]
48%|████▊ | cHPI amplitudes : 812/1696 [00:03<00:02, 426.13it/s]
50%|█████ | cHPI amplitudes : 855/1696 [00:03<00:01, 456.16it/s]
53%|█████▎ | cHPI amplitudes : 898/1696 [00:03<00:01, 486.95it/s]
55%|█████▌ | cHPI amplitudes : 941/1696 [00:03<00:01, 518.43it/s]
58%|█████▊ | cHPI amplitudes : 984/1696 [00:03<00:01, 550.62it/s]
61%|██████ | cHPI amplitudes : 1027/1696 [00:03<00:01, 583.42it/s]
63%|██████▎ | cHPI amplitudes : 1070/1696 [00:03<00:01, 616.94it/s]
66%|██████▌ | cHPI amplitudes : 1113/1696 [00:03<00:00, 651.02it/s]
68%|██████▊ | cHPI amplitudes : 1156/1696 [00:03<00:00, 685.78it/s]
71%|███████ | cHPI amplitudes : 1200/1696 [00:03<00:00, 722.03it/s]
73%|███████▎ | cHPI amplitudes : 1243/1696 [00:03<00:00, 757.78it/s]
76%|███████▌ | cHPI amplitudes : 1286/1696 [00:03<00:00, 793.99it/s]
78%|███████▊ | cHPI amplitudes : 1330/1696 [00:03<00:00, 831.70it/s]
81%|████████ | cHPI amplitudes : 1374/1696 [00:03<00:00, 869.88it/s]
84%|████████▎ | cHPI amplitudes : 1417/1696 [00:03<00:00, 907.37it/s]
86%|████████▌ | cHPI amplitudes : 1460/1696 [00:03<00:00, 944.97it/s]
89%|████████▊ | cHPI amplitudes : 1503/1696 [00:03<00:00, 983.05it/s]
91%|█████████ | cHPI amplitudes : 1546/1696 [00:03<00:00, 1021.27it/s]
94%|█████████▎| cHPI amplitudes : 1589/1696 [00:03<00:00, 1059.59it/s]
96%|█████████▌| cHPI amplitudes : 1632/1696 [00:03<00:00, 1098.01it/s]
99%|█████████▉| cHPI amplitudes : 1675/1696 [00:03<00:00, 1136.20it/s]
100%|██████████| cHPI amplitudes : 1696/1696 [00:03<00:00, 496.65it/s]
其次,根据这些幅度计算随时间变化的 HPI 线圈位置:
Computing 4385 HPI location guesses (1 cm grid in a 10.7 cm sphere)
HPIFIT: 5 coils digitized in order 5 1 4 3 2
HPI consistency of isotrak and hpifit is OK.
0%| | cHPI locations : 0/1696 [00:00<?, ?it/s]
0%| | cHPI locations : 1/1696 [00:01<44:47, 1.59s/it]
6%|▌ | cHPI locations : 101/1696 [00:01<00:25, 63.33it/s]
12%|█▏ | cHPI locations : 201/1696 [00:01<00:12, 122.36it/s]
18%|█▊ | cHPI locations : 301/1696 [00:01<00:07, 179.45it/s]
24%|██▎ | cHPI locations : 401/1696 [00:01<00:05, 233.70it/s]
30%|██▉ | cHPI locations : 501/1696 [00:01<00:04, 282.96it/s]
33%|███▎ | cHPI locations : 559/1696 [00:02<00:03, 293.05it/s]
33%|███▎ | cHPI locations : 568/1696 [00:02<00:04, 277.46it/s]
34%|███▍ | cHPI locations : 573/1696 [00:02<00:04, 260.80it/s]
34%|███▍ | cHPI locations : 577/1696 [00:02<00:04, 246.77it/s]
34%|███▍ | cHPI locations : 581/1696 [00:02<00:04, 230.20it/s]
35%|███▍ | cHPI locations : 587/1696 [00:02<00:05, 215.80it/s]
35%|███▌ | cHPI locations : 600/1696 [00:02<00:05, 208.81it/s]
41%|████▏ | cHPI locations : 700/1696 [00:03<00:03, 249.05it/s]
47%|████▋ | cHPI locations : 789/1696 [00:03<00:03, 277.37it/s]
47%|████▋ | cHPI locations : 794/1696 [00:03<00:03, 262.80it/s]
47%|████▋ | cHPI locations : 800/1696 [00:03<00:03, 250.17it/s]
47%|████▋ | cHPI locations : 805/1696 [00:03<00:03, 237.51it/s]
48%|████▊ | cHPI locations : 810/1696 [00:03<00:03, 225.53it/s]
48%|████▊ | cHPI locations : 815/1696 [00:03<00:04, 212.93it/s]
48%|████▊ | cHPI locations : 819/1696 [00:03<00:04, 202.36it/s]
49%|████▊ | cHPI locations : 823/1696 [00:04<00:04, 192.33it/s]
49%|████▉ | cHPI locations : 827/1696 [00:04<00:04, 182.26it/s]
49%|████▉ | cHPI locations : 833/1696 [00:04<00:04, 173.97it/s]
50%|█████ | cHPI locations : 848/1696 [00:04<00:04, 169.67it/s]
56%|█████▌ | cHPI locations : 948/1696 [00:04<00:03, 206.36it/s]
61%|██████▏ | cHPI locations : 1040/1696 [00:04<00:02, 236.88it/s]
62%|██████▏ | cHPI locations : 1051/1696 [00:04<00:02, 228.09it/s]
63%|██████▎ | cHPI locations : 1062/1696 [00:04<00:02, 218.93it/s]
63%|██████▎ | cHPI locations : 1072/1696 [00:05<00:02, 211.22it/s]
64%|██████▍ | cHPI locations : 1086/1696 [00:05<00:02, 205.78it/s]
70%|██████▉ | cHPI locations : 1186/1696 [00:05<00:02, 237.04it/s]
76%|███████▌ | cHPI locations : 1286/1696 [00:05<00:01, 269.09it/s]
76%|███████▋ | cHPI locations : 1296/1696 [00:05<00:01, 260.22it/s]
77%|███████▋ | cHPI locations : 1301/1696 [00:05<00:01, 249.08it/s]
77%|███████▋ | cHPI locations : 1306/1696 [00:05<00:01, 237.38it/s]
77%|███████▋ | cHPI locations : 1311/1696 [00:05<00:01, 226.39it/s]
78%|███████▊ | cHPI locations : 1315/1696 [00:06<00:01, 217.55it/s]
78%|███████▊ | cHPI locations : 1319/1696 [00:06<00:01, 208.40it/s]
78%|███████▊ | cHPI locations : 1325/1696 [00:06<00:01, 199.20it/s]
78%|███████▊ | cHPI locations : 1331/1696 [00:06<00:01, 191.40it/s]
79%|███████▉ | cHPI locations : 1341/1696 [00:06<00:01, 185.21it/s]
85%|████████▍ | cHPI locations : 1441/1696 [00:06<00:01, 219.06it/s]
91%|█████████ | cHPI locations : 1541/1696 [00:06<00:00, 251.18it/s]
92%|█████████▏| cHPI locations : 1565/1696 [00:06<00:00, 247.80it/s]
93%|█████████▎| cHPI locations : 1573/1696 [00:07<00:00, 236.26it/s]
93%|█████████▎| cHPI locations : 1580/1696 [00:07<00:00, 227.99it/s]
94%|█████████▎| cHPI locations : 1586/1696 [00:07<00:00, 217.82it/s]
94%|█████████▍| cHPI locations : 1590/1696 [00:07<00:00, 207.19it/s]
94%|█████████▍| cHPI locations : 1594/1696 [00:07<00:00, 197.58it/s]
94%|█████████▍| cHPI locations : 1599/1696 [00:07<00:00, 188.85it/s]
95%|█████████▍| cHPI locations : 1609/1696 [00:07<00:00, 182.79it/s]
97%|█████████▋| cHPI locations : 1652/1696 [00:07<00:00, 190.67it/s]
100%|██████████| cHPI locations : 1696/1696 [00:07<00:00, 214.08it/s]
最后,根据线圈位置计算头部位置:
head_pos = mne.chpi.compute_head_pos(raw.info, chpi_locs, weighted=True, verbose=True)
t=9.000: 5/5 good HPI fits, movements [mm/s] = 0.1 / 0.2 / 0.5 / 0.2 / 0.3
t=10.000: 5/5 good HPI fits, movements [mm/s] = 0.1 / 0.2 / 0.0 / 0.1 / 0.1
t=11.000: 5/5 good HPI fits, movements [mm/s] = 0.1 / 0.1 / 0.1 / 0.0 / 0.1
t=12.000: 5/5 good HPI fits, movements [mm/s] = 0.0 / 0.0 / 0.1 / 0.0 / 0.0
t=13.000: 5/5 good HPI fits, movements [mm/s] = 0.0 / 0.1 / 0.0 / 0.0 / 0.0
t=14.000: 5/5 good HPI fits, movements [mm/s] = 0.1 / 0.1 / 0.1 / 0.1 / 0.1
t=14.580: 5/5 good HPI fits, movements [mm/s] = 5.0 / 4.8 / 6.1 / 5.5 / 4.9
t=14.670: 5/5 good HPI fits, movements [mm/s] = 33.4 / 34.2 / 39.7 / 37.9 / 30.6
t=14.720: 5/5 good HPI fits, movements [mm/s] = 48.8 / 47.1 / 60.4 / 59.3 / 44.0
t=14.760: 5/5 good HPI fits, movements [mm/s] = 65.6 / 63.2 / 73.1 / 71.0 / 56.5
t=14.800: 5/5 good HPI fits, movements [mm/s] = 66.3 / 59.3 / 83.1 / 77.8 / 61.0
t=14.860: 5/5 good HPI fits, movements [mm/s] = 55.2 / 52.3 / 57.7 / 62.2 / 47.2
t=14.990: 5/5 good HPI fits, movements [mm/s] = 22.9 / 22.5 / 24.0 / 27.1 / 19.9
t=15.990: 5/5 good HPI fits, movements [mm/s] = 0.7 / 0.9 / 0.8 / 0.8 / 0.9
t=16.880: 5/5 good HPI fits, movements [mm/s] = 2.6 / 3.4 / 2.9 / 3.8 / 3.3
t=16.930: 5/5 good HPI fits, movements [mm/s] = 51.6 / 55.4 / 58.1 / 66.9 / 59.1
t=16.990: 5/5 good HPI fits, movements [mm/s] = 57.3 / 54.0 / 62.1 / 65.0 / 57.7
t=17.040: 5/5 good HPI fits, movements [mm/s] = 53.4 / 49.5 / 60.0 / 61.9 / 49.2
t=17.090: 5/5 good HPI fits, movements [mm/s] = 58.2 / 50.5 / 66.5 / 65.0 / 51.5
t=17.140: 5/5 good HPI fits, movements [mm/s] = 60.1 / 54.3 / 72.9 / 67.3 / 57.5
t=17.180: 5/5 good HPI fits, movements [mm/s] = 63.5 / 60.1 / 74.4 / 72.1 / 61.9
t=17.220: 5/5 good HPI fits, movements [mm/s] = 61.2 / 56.4 / 75.2 / 71.4 / 63.7
t=17.260: 5/5 good HPI fits, movements [mm/s] = 67.8 / 66.8 / 73.2 / 68.8 / 69.0
t=17.320: 5/5 good HPI fits, movements [mm/s] = 49.5 / 51.7 / 54.9 / 54.9 / 52.5
t=17.470: 5/5 good HPI fits, movements [mm/s] = 18.5 / 21.2 / 19.3 / 20.5 / 17.3
t=18.470: 5/5 good HPI fits, movements [mm/s] = 1.9 / 2.7 / 2.0 / 2.4 / 1.9
t=19.390: 5/5 good HPI fits, movements [mm/s] = 2.5 / 2.7 / 1.9 / 2.9 / 2.5
t=19.500: 5/5 good HPI fits, movements [mm/s] = 22.9 / 25.1 / 19.4 / 28.8 / 27.7
t=19.610: 5/5 good HPI fits, movements [mm/s] = 21.3 / 25.6 / 21.8 / 31.7 / 31.4
t=19.710: 5/5 good HPI fits, movements [mm/s] = 21.7 / 20.6 / 23.2 / 29.7 / 27.8
t=19.850: 5/5 good HPI fits, movements [mm/s] = 16.6 / 14.7 / 18.6 / 21.8 / 20.2
t=20.850: 5/5 good HPI fits, movements [mm/s] = 2.3 / 1.9 / 2.0 / 2.5 / 2.2
t=21.850: 5/5 good HPI fits, movements [mm/s] = 0.6 / 1.7 / 1.7 / 2.0 / 1.9
t=21.950: 5/5 good HPI fits, movements [mm/s] = 26.0 / 27.2 / 24.1 / 32.0 / 26.3
t=22.000: 5/5 good HPI fits, movements [mm/s] = 65.7 / 58.8 / 46.3 / 64.4 / 52.2
t=22.050: 5/5 good HPI fits, movements [mm/s] = 60.1 / 62.4 / 51.2 / 69.5 / 57.9
t=22.100: 5/5 good HPI fits, movements [mm/s] = 61.3 / 65.6 / 58.4 / 74.8 / 64.5
t=22.140: 5/5 good HPI fits, movements [mm/s] = 74.3 / 73.6 / 62.3 / 79.9 / 68.0
t=22.180: 5/5 good HPI fits, movements [mm/s] = 63.9 / 59.6 / 53.1 / 67.7 / 53.5
t=22.240: 5/5 good HPI fits, movements [mm/s] = 38.5 / 39.2 / 36.6 / 47.8 / 42.1
t=22.300: 5/5 good HPI fits, movements [mm/s] = 41.8 / 40.2 / 33.6 / 47.4 / 39.2
t=22.400: 5/5 good HPI fits, movements [mm/s] = 31.9 / 28.3 / 22.1 / 30.8 / 25.0
t=23.400: 5/5 good HPI fits, movements [mm/s] = 1.8 / 1.8 / 1.1 / 1.5 / 1.2
t=24.400: 5/5 good HPI fits, movements [mm/s] = 1.3 / 0.8 / 0.7 / 0.8 / 0.7
t=24.640: 5/5 good HPI fits, movements [mm/s] = 12.5 / 11.5 / 11.5 / 13.1 / 10.9
t=24.720: 5/5 good HPI fits, movements [mm/s] = 30.4 / 33.1 / 31.7 / 39.0 / 35.2
t=24.790: 5/5 good HPI fits, movements [mm/s] = 31.0 / 36.0 / 33.0 / 42.7 / 41.1
t=24.850: 5/5 good HPI fits, movements [mm/s] = 37.4 / 40.9 / 35.5 / 45.1 / 42.1
t=24.890: 5/5 good HPI fits, movements [mm/s] = 50.3 / 51.9 / 50.0 / 59.8 / 53.0
t=24.930: 5/5 good HPI fits, movements [mm/s] = 56.2 / 54.7 / 59.0 / 68.6 / 62.0
t=24.980: 5/5 good HPI fits, movements [mm/s] = 47.0 / 47.6 / 51.1 / 58.5 / 53.8
t=25.080: 5/5 good HPI fits, movements [mm/s] = 23.9 / 19.2 / 23.1 / 28.1 / 26.4
t=25.510: 5/5 good HPI fits, movements [mm/s] = 2.4 / 6.5 / 7.4 / 6.5 / 7.8
请注意,之后可以分别使用 mne.chpi.write_head_pos() 和 mne.chpi.read_head_pos() 将其写入磁盘或从磁盘读取。
可视化连续头部位置#
我们可以将其绘制为轨迹曲线,这对长时间记录尤其有用:
mne.viz.plot_head_positions(head_pos, mode="traces", totals=True)

也可以将其可视化为连续场(向量指向头顶方向):
mne.viz.plot_head_positions(head_pos, mode="field")

随后,这些头部位置可以与 mne.preprocessing.maxwell_filter() 配合使用来补偿运动,或与 mne.preprocessing.annotate_movement() 配合使用,将偏离平均头部位置过多的数据段标记为坏段。
计算 HPI 信号的 SNR#
也可以计算连续 HPI 测量的信噪比(SNR)。它可以作为垂直方向上头部位置的有用替代指标,即能够指示 HPI 线圈与 MEG 传感器之间的距离。使用 compute_chpi_snr 时,会针对每种 MEG 传感器类型和每个 HPI 线圈(频率)分别计算 HPI 功率与 SNR,同时计算每种传感器类型的残余功率。结果随后可用 plot_chpi_snr 可视化。为加快速度,这里只展示几秒钟的数据:
raw.crop(tmin=5, tmax=10)
snr_dict = mne.chpi.compute_chpi_snr(raw)
fig = mne.viz.plot_chpi_snr(snr_dict)

Using 5 HPI coils: 83 143 203 263 323 Hz
Line interference frequencies: 60.0 120.0 180.0 240.0 300.0 360.0 Hz
Using time window: 83.3 ms
Fitting 5 HPI coil locations at up to 496 time points (5.0 s duration)
0%| | cHPI SNRs : 0/496 [00:00<?, ?it/s]
0%| | cHPI SNRs : 1/496 [00:01<12:32, 1.52s/it]
11%|█ | cHPI SNRs : 55/496 [00:01<00:11, 37.63it/s]
23%|██▎ | cHPI SNRs : 112/496 [00:01<00:04, 77.80it/s]
34%|███▍ | cHPI SNRs : 169/496 [00:01<00:02, 119.09it/s]
46%|████▌ | cHPI SNRs : 226/496 [00:01<00:01, 161.50it/s]
57%|█████▋ | cHPI SNRs : 283/496 [00:01<00:01, 205.01it/s]
69%|██████▊ | cHPI SNRs : 340/496 [00:01<00:00, 249.64it/s]
80%|████████ | cHPI SNRs : 397/496 [00:01<00:00, 295.35it/s]
92%|█████████▏| cHPI SNRs : 454/496 [00:01<00:00, 342.09it/s]
100%|██████████| cHPI SNRs : 496/496 [00:01<00:00, 298.46it/s]
脚本总运行时间:(0 分钟 23.029 秒)