注意
转到末尾下载完整示例代码。
导入 fNIRS 设备数据#
fNIRS 设备包含两种光极:光源(又称“发射器”或“发送器”)和光探测器(又称“接收器”)。通道定义为光源-探测器对,通道位置定义为光源与探测器的中点。
MNE-Python 提供用于从多种文件格式读取 fNIRS 数据和光极位置的函数。无论设备制造商或文件格式如何,MNE-Python 的 fNIRS 函数都会以相同方式在内部存储测量数据及其元数据(例如,数据值始终转换为 SI 单位)。支持的测量类型包括振幅、光密度、氧合血红蛋白浓度和脱氧血红蛋白浓度(用于连续波 fNIRS),以及 AC 振幅和相位(用于频域 fNIRS)。
警告
MNE-Python 在内部以特定结构存储元数据,内部函数期望特定的命名约定。不建议手动修改通道名称和元数据。
标准化数据#
SNIRF(.snirf)#
共享近红外光谱格式(SNIRF)由 fNIRS 社区设计,旨在促进 fNIRS 数据的共享和分析,并且是功能性近红外光谱学会(SfNIRS)的官方格式。制造商 Gowerlabs、NIRx、Kernel、Artinis 和 Cortivision 均以 SNIRF 格式导出数据,这些文件可以导入 MNE。SNIRF 是向 MNE-Python 读入数据的首选格式。可以使用 mne.io.read_raw_snirf() 读取以 SNIRF 格式存储的数据。
注意
SNIRF 格式对许多不同类型的 fNIRS 记录都作了规定。MNE-Python 目前仅支持读取以 .snirf 格式存储的连续波或血红蛋白数据。
指定坐标系#
用于指定传感器位置的坐标系有多种(详见 源空间对齐与坐标框架)。在读取 SNIRF 文件时,会尽可能自动确定坐标系。但有时无法做到这一点,此时必须手动指定光极所在的坐标系。这可以通过加载数据时的 optode_frame 参数完成。
| 厂商 | 型号 |
|
|---|---|---|
NIRx |
ICBM-152 MNI |
mri |
Kernel |
ICBM 2009b |
mri |
对于 Gowerlabs SNIRF 文件,坐标系会自动检测。
连续波设备#
NIRx(目录或 hdr)#
NIRx 生产连续波 fNIRS 设备。可以使用 mne.io.read_raw_nirx() 读取 NIRx 记录。NIRx 设备将数据直接存储在一个包含多种文件类型的目录中,MNE-Python 会从每个文件中提取相应信息。MNE-Python 仅支持使用 NIRStar 15.0 及以上版本和 Aurora 2021 及以上版本记录的 NIRx 文件。MNE-Python 支持从 NIRScout 和 NIRSport 设备读取数据。
Hitachi(.csv)#
Hitachi 生产连续波 fNIRS 设备。可以使用 mne.io.read_raw_hitachi() 读取 Hitachi fNIRS 记录。由于不存储光极信息,因此需要手动设置蒙太奇,参见 mne.io.read_raw_hitachi() 的 Notes 部分。
频域设备#
BOXY(.txt)#
可以使用 mne.io.read_raw_boxy() 读取 BOXY 记录。BOXY 软件以及 ISS Imagent I 和 II 设备是频域系统,它们将数据存储在单个 .txt 文件中,其中包含以下内容(括号内为 MNE-Python 对相应数据类型的名称):
- DC
- 探测器收集的所有光(
fnirs_cw_amplitude)
- AC
- 高频调制光强度(
fnirs_fd_ac_amplitude)
- 相位
- 调制光的相位(
fnirs_fd_phase)
DC 数据以 fnirs_cw_amplitude 类型存储,因为它同时收集调制光和非调制光,因此类似于 NIRx 等连续波系统所收集的数据。这有助于符合 SNIRF 标准类型。
这些原始数据文件可由采集设备保存为已解析或未解析的 .txt 文件,这会影响文件中数据的组织方式。MNE-Python 会读取任一种文件类型,并提取原始 DC、AC 和相位数据。如果使用记录硬件的 digaux 端口发送触发信号,MNE-Python 还会读取 digaux 数据并为所有触发信号创建注释。
自定义数据导入#
加载 CSV 或 TSV 格式的旧版数据#
警告
不支持此方法,建议用户不要使用。应使用功能性近红外光谱学会提供的工具将数据转换为 SNIRF 格式,然后使用 mne.io.read_raw_snirf() 加载。
fNIRS 测量数据可能以非标准化格式存储,MNE-Python 不支持这种格式,也难以轻松转换为 SNIRF。这类旧版数据通常为 CSV 或 TSV 格式;尽管由于文件格式缺乏标准化(通道的命名和排序、数据的类型和缩放以及传感器位置的指定因厂商而异),MNE-Python 并未正式支持,但这里展示一种加载方法。你可能需要根据 CSV 的来源系统进行调整。
import numpy as np
import pandas as pd
import mne
首先,我们生成一个示例 CSV 文件,随后将其加载到 MNE-Python 中。如果你已有要加载的实际数据,则可跳过此步骤。我们模拟 16 个通道、每个通道 100 个样本的数据,并将其保存到名为 fnirs.csv 的文件中。
pd.DataFrame(np.random.default_rng(97).normal(size=(16, 100))).to_csv("fnirs.csv")
接下来,我们将加载示例 CSV 文件。
data = pd.read_csv("fnirs.csv")
然后,必须手动指定元数据,因为 CSV 文件不包含通道名称、类型、采样率等信息。
警告
在 MNE-Python 中,通道命名必须遵循 S#_D# type 结构,其中 # 替换为相应的光源和探测器编号,type 为 hbo、hbr 或波长。
ch_names = [
"S1_D1 hbo",
"S1_D1 hbr",
"S2_D1 hbo",
"S2_D1 hbr",
"S3_D1 hbo",
"S3_D1 hbr",
"S4_D1 hbo",
"S4_D1 hbr",
"S5_D2 hbo",
"S5_D2 hbr",
"S6_D2 hbo",
"S6_D2 hbr",
"S7_D2 hbo",
"S7_D2 hbr",
"S8_D2 hbo",
"S8_D2 hbr",
]
ch_types = [
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
"hbo",
"hbr",
]
sfreq = 10.0 # in Hz
最后,可以将数据转换为 MNE-Python 数据结构。上述元数据用于创建 mne.Info 数据结构,并将其与数据结合以创建 MNE-Python 的 Raw 对象。有关 info 结构的更多详细信息,请参见 Info 数据结构;有关连续数据在 MNE-Python 中存储方式的更多详细信息,请参见 Raw 数据结构:连续数据。有关如何从原始数组数据创建 MNE-Python 数据结构的更详细说明,请参见 从零创建 MNE-Python 数据结构。
Creating RawArray with float64 data, n_channels=16, n_times=101
Range : 0 ... 100 = 0.000 ... 10.000 secs
Ready.
为导入数据应用标准传感器位置#
拥有光极位置信息可能有助于分析。除了它带来的一般好处(例如创建感兴趣区域等)之外,这对 fNIRS 可能尤为重要,因为将光密度数据转换为血红蛋白浓度估计值需要光极位置信息。MNE-Python 提供了一些方法,可从部分厂商加载标准传感器配置(蒙太奇),下面将进行演示。一些有助于理解传感器位置、坐标系以及如何在 MNE-Python 中存储和查看这些信息的实用教程包括:处理传感器位置、源空间对齐与坐标框架 和 Plotting EEG sensors on the scalp。
以下是如何为 Artinis OctaMon 设备加载光极位置的示例。
注意
还可以通过将 coord_frame 设置为 'mri',使用 mne.channels.read_custom_montage() 从文件为 fNIRS 创建自定义蒙太奇。
montage = mne.channels.make_standard_montage("artinis-octamon")
raw.set_montage(montage)
# View the position of optodes in 2D to confirm the positions are correct.
raw.plot_sensors()

为验证位置加载正确,还可以在三维表示中查看光源(红色)、探测器(黑色)和通道(白线和橙色点)的位置。基准点用蓝色、绿色和红色标记。详情请参见 源空间对齐与坐标框架。
subjects_dir = mne.datasets.sample.data_path() / "subjects"
mne.datasets.fetch_fsaverage(subjects_dir=subjects_dir)
brain = mne.viz.Brain(
"fsaverage", subjects_dir=subjects_dir, alpha=0.5, cortex="low_contrast"
)
brain.add_head()
brain.add_sensors(raw.info, trans="fsaverage")
brain.show_view(azimuth=90, elevation=90, distance=500)

0 files missing from root.txt in /home/circleci/mne_data/MNE-sample-data/subjects
0 files missing from bem.txt in /home/circleci/mne_data/MNE-sample-data/subjects/fsaverage
Using fsaverage-head-dense.fif for head surface.
1 BEM surfaces found
Reading a surface...
[done]
1 BEM surfaces read
Channel types:: hbo: 8, hbr: 8
脚本总运行时间:(0 分钟 6.512 秒)