当前博文未提及该问题,以下是基于C知道的知识内容为您回答
在Python中,您可以使用`nilearn`库加载CC200图谱,并提取和可视化指定的脑区(lPRECU, IFG, lPARAH, lPOST, rLING)。以下是完整的代码实现,包含详细的步骤和注释。
## 1. 环境准备与数据加载
首先,确保已安装`nilearn`、`nibabel`和`matplotlib`库。然后加载CC200图谱及其标签。
```python
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from nilearn import datasets, plotting, image
from nilearn.plotting import plot_roi, plot_stat_map
import pandas as pd
# 加载CC200图谱(nilearn会自动下载或从缓存加载)
craddock_atlas = datasets.fetch_atlas_craddock_2012(n_rois=200, resolution=2) # [ref_2]
# 获取图谱文件路径和标签文件路径
atlas_filename = craddock_atlas['maps'] # .nii.gz文件
labels_filename = craddock_atlas['labels'] # 标签文本文件
print(f"图谱文件路径: {atlas_filename}")
print(f"标签文件路径: {labels_filename}")
# 读取标签信息(假设为CSV或文本格式)
# 注意:实际标签文件格式可能需调整读取方式
try:
# 尝试读取为CSV(逗号分隔)
labels_df = pd.read_csv(labels_filename, header=None)
roi_labels = labels_df[0].tolist() if len(labels_df.columns) > 0 else []
except:
# 尝试读取为纯文本(每行一个标签)
with open(labels_filename, 'r') as f:
roi_labels = [line.strip() for line in f.readlines()]
print(f"共加载 {len(roi_labels)} 个ROI标签")
```
## 2. 识别目标脑区的ROI编号
CC200图谱通常使用数字编号标识每个脑区。您需要根据标签名称查找对应的ROI编号。
```python
# 定义目标脑区名称(根据您的需求)
target_regions = ['lPRECU', 'IFG', 'lPARAH', 'lPOST', 'rLING']
# 创建脑区名称到ROI编号的映射字典
region_to_roi = {}
# 在标签列表中查找目标脑区(注意:实际标签名称可能略有不同)
for idx, label in enumerate(roi_labels, start=1):
label_lower = label.lower()
# 根据常见命名习惯进行匹配(可根据实际标签调整)
if 'precu' in label_lower and 'l' in label_lower[:3]:
region_to_roi['lPRECU'] = idx
elif 'ifg' in label_lower or 'inferior frontal' in label_lower:
region_to_roi['IFG'] = idx
elif 'parah' in label_lower and 'l' in label_lower[:3]:
region_to_roi['lPARAH'] = idx
elif 'post' in label_lower and 'l' in label_lower[:3]:
region_to_roi['lPOST'] = idx
elif 'ling' in label_lower and 'r' in label_lower[:3]:
region_to_roi['rLING'] = idx
# 检查是否找到所有目标脑区
for region in target_regions:
if region in region_to_roi:
print(f"找到脑区 {region}: ROI编号 {region_to_roi[region]}")
else:
print(f"警告: 未找到脑区 {region},尝试模糊匹配或检查标签名称")
# 如果自动匹配失败,可手动指定ROI编号(根据您的图谱版本)
# region_to_roi = {'lPRECU': 45, 'IFG': 67, 'lPARAH': 89, 'lPOST': 112, 'rLING': 156}
```
## 3. 创建目标脑区的二值化图谱
将目标脑区提取出来,创建一个新的NIfTI图像,其中只有这些脑区被标记。
```python
# 加载图谱数据
import nibabel as nib
atlas_img = nib.load(atlas_filename)
atlas_data = atlas_img.get_fdata()
# 创建空的目标脑区掩模
target_mask = np.zeros_like(atlas_data)
# 将目标ROI编号的区域设置为1
for region, roi_id in region_to_roi.items():
target_mask[atlas_data == roi_id] = 1
print(f"已标记脑区 {region} (ROI {roi_id}),体素数: {np.sum(atlas_data == roi_id)}")
# 创建新的NIfTI图像
target_img = nib.Nifti1Image(target_mask, atlas_img.affine, atlas_img.header)
# 保存目标脑区图谱(可选)
# nib.save(target_img, 'target_regions.nii.gz')
```
## 4. 可视化目标脑区
使用`nilearn`的绘图功能可视化提取的脑区。
```python
# 设置绘图风格
plt.style.use('seaborn-whitegrid')
# 创建子图布局
fig = plt.figure(figsize=(16, 10))
# 1. 3D玻璃脑可视化
ax1 = fig.add_subplot(2, 3, 1, projection='3d')
plotting.plot_roi(target_img,
display_mode='ortho', # 三视图显示
cut_coords=(0, 0, 0), # 中心坐标
title='目标脑区 (三视图)',
axes=ax1)
# 2. 单个脑区分别可视化(如果ROI不重叠)
ax2 = fig.add_subplot(2, 3, 2)
for region, roi_id in region_to_roi.items():
region_mask = (atlas_data == roi_id).astype(np.float32)
region_img = nib.Nifti1Image(region_mask, atlas_img.affine)
# 使用不同颜色显示不同脑区
colors = ['red', 'blue', 'green', 'purple', 'orange']
color_idx = list(region_to_roi.keys()).index(region)
plotting.plot_roi(region_img,
display_mode='z',
cut_coords=1,
colorbar=False,
title=region,
axes=ax2,
alpha=0.7,
color=colors[color_idx % len(colors)])
# 3. 表面投影可视化(需要表面模板)
try:
ax3 = fig.add_subplot(2, 3, 3, projection='3d')
fsaverage = datasets.fetch_surf_fsaverage()
plotting.plot_surf_roi(fsaverage['infl_left'],
roi_map=target_mask,
hemi='left',
view='lateral',
title='左侧表面投影',
axes=ax3)
except Exception as e:
print(f"表面可视化失败: {e}")
# 备用:使用统计图显示
plotting.plot_stat_map(target_img,
display_mode='z',
cut_coords=range(-30, 71, 20),
title='轴向切片',
axes=ax3)
# 4. 所有目标脑区叠加显示
ax4 = fig.add_subplot(2, 3, 4)
plotting.plot_roi(target_img,
display_mode='x',
cut_coords=range(-40, 41, 20),
title='矢状位切片',
axes=ax4)
# 5. 冠状位视图
ax5 = fig.add_subplot(2, 3, 5)
plotting.plot_roi(target_img,
display_mode='y',
cut_coords=range(-40, 41, 20),
title='冠状位切片',
axes=ax5)
# 6. 信息总结表格
ax6 = fig.add_subplot(2, 3, 6)
ax6.axis('tight')
ax6.axis('off')
# 创建汇总表格
table_data = []
for region in target_regions:
roi_id = region_to_roi.get(region, '未找到')
voxel_count = np.sum(atlas_data == roi_id) if isinstance(roi_id, int) else 0
table_data.append([region, roi_id, voxel_count])
table = ax6.table(cellText=table_data,
colLabels=['脑区', 'ROI编号', '体素数'],
loc='center',
cellLoc='center',
colWidths=[0.3, 0.3, 0.4])
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 1.5)
ax6.set_title('目标脑区信息汇总', pad=20)
plt.tight_layout()
plt.show()
```
## 5. 高级可视化:交互式3D显示
```python
# 交互式3D可视化(需要安装ipympl或使用Jupyter Notebook)
# %matplotlib widget # 在Jupyter中取消注释以启用交互式
from nilearn import surface
from nilearn.plotting import plot_surf_stat_map
# 将体积数据投影到表面
try:
# 获取表面模板
fsaverage = datasets.fetch_surf_fsaverage()
# 将体积图谱投影到左侧表面
texture_left = surface.vol_to_surf(target_img, fsaverage['pial_left'])
# 绘制表面图
fig, axes = plt.subplots(1, 2, figsize=(12, 5),
subplot_kw={'projection': '3d'})
# 左侧视图
plot_surf_stat_map(fsaverage['infl_left'],
texture_left,
hemi='left',
view='lateral',
title='左侧脑区 (lPRECU, lPARAH, lPOST)',
axes=axes[0],
threshold=0.5,
cmap='autumn')
# 右侧视图
texture_right = surface.vol_to_surf(target_img, fsaverage['pial_right'])
plot_surf_stat_map(fsaverage['infl_right'],
texture_right,
hemi='right',
view='lateral',
title='右侧脑区 (rLING, IFG可能涉及双侧)',
axes=axes[1],
threshold=0.5,
cmap='winter')
plt.tight_layout()
plt.show()
except Exception as e:
print(f"表面投影失败,使用备用体积可视化: {e}")
# 备用:使用plot_glass_brain进行玻璃脑显示
from nilearn.plotting import plot_glass_brain
fig, ax = plt.subplots(figsize=(10, 8))
plot_glass_brain(target_img,
display_mode='lyrz', # 四个视角
title='目标脑区玻璃脑视图',
axes=ax,
colorbar=True)
plt.show()
```
## 6. 提取每个脑区的统计信息
```python
# 计算每个目标脑区的空间统计信息
region_stats = []
for region, roi_id in region_to_roi.items():
if isinstance(roi_id, int):
# 获取该ROI的体素坐标
roi_coords = np.argwhere(atlas_data == roi_id)
if len(roi_coords) > 0:
# 计算质心(中心坐标)
centroid = np.mean(roi_coords, axis=0)
# 将体素坐标转换为MNI坐标
# 注意:这里简化处理,实际需要应用仿射变换
mni_coords = nib.affines.apply_affine(atlas_img.affine, centroid)
region_stats.append({
'Region': region,
'ROI_ID': roi_id,
'Voxel_Count': len(roi_coords),
'Centroid_MNI_X': mni_coords[0],
'Centroid_MNI_Y': mni_coords[1],
'Centroid_MNI_Z': mni_coords[2],
'Volume_mm3': len(roi_coords) * np.abs(np.linalg.det(atlas_img.affine[:3, :3]))
})
# 创建统计表格
stats_df = pd.DataFrame(region_stats)
print("\n目标脑区统计信息:")
print(stats_df.to_string(index=False))
# 可视化统计信息
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 体素数量柱状图
axes[0, 0].bar(stats_df['Region'], stats_df['Voxel_Count'], color='skyblue')
axes[0, 0].set_title('各脑区体素数量')
axes[0, 0].set_ylabel('体素数')
axes[0, 0].tick_params(axis='x', rotation=45)
# 2. 体积分布饼图
axes[0, 1].pie(stats_df['Volume_mm3'], labels=stats_df['Region'], autopct='%1.1f%%')
axes[0, 1].set_title('各脑区相对体积')
# 3. MNI坐标3D散点图
ax3d = fig.add_subplot(2, 2, 3, projection='3d')
scatter = ax3d.scatter(stats_df['Centroid_MNI_X'],
stats_df['Centroid_MNI_Y'],
stats_df['Centroid_MNI_Z'],
c=range(len(stats_df)),
s=stats_df['Voxel_Count']/10,
cmap='viridis',
alpha=0.8)
# 添加标签
for i, row in stats_df.iterrows():
ax3d.text(row['Centroid_MNI_X'],
row['Centroid_MNI_Y'],
row['Centroid_MNI_Z'],
row['Region'], fontsize=9)
ax3d.set_xlabel('MNI X')
ax3d.set_ylabel('MNI Y')
ax3d.set_zlabel('MNI Z')
ax3d.set_title('脑区质心MNI坐标')
# 4. 坐标热图
coords_matrix = stats_df[['Centroid_MNI_X', 'Centroid_MNI_Y', 'Centroid_MNI_Z']].values
im = axes[1, 1].imshow(coords_matrix, aspect='auto', cmap='coolwarm')
axes[1, 1].set_title('脑区坐标热图')
axes[1, 1].set_xlabel('坐标轴 (X,Y,Z)')
axes[1, 1].set_ylabel('脑区')
axes[1, 1].set_xticks([0, 1, 2])
axes[1, 1].set_xticklabels(['X', 'Y', 'Z'])
axes[1, 1].set_yticks(range(len(stats_df)))
axes[1, 0].set_yticklabels(stats_df['Region'])
plt.colorbar(im, ax=axes[1, 1])
plt.tight_layout()
plt.show()
```
## 7. 实用建议与注意事项
1. **标签匹配问题**:CC200图谱的标签命名可能因版本而异。如果上述代码无法找到目标脑区,请先检查实际的标签名称:
```python
# 打印前20个标签查看命名格式
print("前20个ROI标签:")
for i, label in enumerate(roi_labels[:20], 1):
print(f"{i}: {label}")
```
2. **手动指定ROI编号**:如果知道确切的ROI编号,可以直接指定:
```python
region_to_roi = {
'lPRECU': 45, # 示例编号,请根据实际图谱调整
'IFG': 67,
'lPARAH': 89,
'lPOST': 112,
'rLING': 156
}
```
3. **批量处理多个被试**:如果需要处理多个被试的数据,可以将上述代码封装为函数:
```python
def extract_and_visualize_regions(atlas_path, target_regions_dict, output_dir='results'):
"""提取并可视化指定脑区"""
# ... 实现代码 ...
return region_masks, stats_df
```
4. **与功能数据结合**:提取的脑区掩模可用于后续的fMRI时间序列提取:
```python
from nilearn.input_data import NiftiLabelsMasker
# 创建掩模器
masker = NiftiLabelsMasker(labels_img=target_img,
standardize=True,
detrend=True,
low_pass=0.1,
high_pass=0.01,
t_r=2.0) # 根据实际TR调整
# 提取时间序列
# time_series = masker.fit_transform(func_img)
```
此代码提供了从加载CC200图谱到可视化特定脑区的完整流程。您可以根据实际需要调整脑区名称、ROI编号和可视化参数。如果在匹配脑区名称时遇到问题,建议先检查图谱的标签文件,确认目标脑区的确切命名方式。