Human Connectome Project (HCP) Dataset loader网址翻译

地址:
https://nbviewer.jupyter.org/github/NeuromatchAcademy/course-content/blob/master/projects/load_hcp.ipynb

人类Connectome Project(HCP)数据集

  • HCP数据集包括大量的被试样本,包括静息态和基于任务的功能磁共振成像。
  • NMA整理的数据集包括时间序列数据,这些数据已通过在360个感兴趣的区域内进行汇总而进行了预处理和空间降采样。
#导入相应的包
import os
import numpy as np
import matplotlib.pyplot as plt
# 可视化需要
!pip install nilearn --quiet
from nilearn import plotting, datasets
#设置风格
#@title Figure settings
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
plt.style.use("https://raw.githubusercontent.com/NeuromatchAcademy/course-content/master/nma.mplstyle")

基本参数

# 数据存储目录
HCP_DIR = "./hcp"
if not os.path.isdir(HCP_DIR):
  os.mkdir(HCP_DIR)

# NMA项目共享的数据是HCP数据集的完整子集
N_SUBJECTS = 339

# 数据已经从Glasesr分解汇总到ROI中
N_PARCELS = 360

# 所有任务的采集参数相同
TR = 0.72  # 时间分辨率,以秒为单位

# The parcels 在半球上的匹配顺序相同
HEMIS = ["Right", "Left"]

# 每个实验在每个主题中重复多次
N_RUNS_REST = 4
N_RUNS_TASK = 2

# 时间序列数据是按实验组织的,每个实验
#具有LR和RL(相位编码方向)采集
BOLD_NAMES = [
  "rfMRI_REST1_LR", "rfMRI_REST1_RL",
  "rfMRI_REST2_LR", "rfMRI_REST2_RL",
  "tfMRI_MOTOR_RL", "tfMRI_MOTOR_LR",
  "tfMRI_WM_RL", "tfMRI_WM_LR",
  "tfMRI_EMOTION_RL", "tfMRI_EMOTION_LR",
  "tfMRI_GAMBLING_RL", "tfMRI_GAMBLING_LR",
  "tfMRI_LANGUAGE_RL", "tfMRI_LANGUAGE_LR",
  "tfMRI_RELATIONAL_RL", "tfMRI_RELATIONAL_LR",
  "tfMRI_SOCIAL_RL", "tfMRI_SOCIAL_LR"
]

# 您可能希望代码开发期间限制使用的主题。You may want to limit the subjects used during code development.
# 他将使用所有主题:
subjects = range(N_SUBJECTS)

下载资料
其余数据和任务数据在不同的文件中共享,但是它们将解压缩到相同的目录结构中。

每个文件都很大,需要一些时间来下载。如果仅关注静息或任务分析,则可能不希望仅下载该数据集。

我们还分别提供了一些可能有用的行为协变量信息。

#静息态
fname = "hcp_rest.tgz"
if not os.path.exists(fname):
  !wget -qO $fname https://osf.io/bqp7m/download/
  !tar -xzf $fname -C $HCP_DIR --strip-components=1
 #任务态
 fname = "hcp_task.tgz"
if not os.path.exists(fname):
  !wget -qO $fname https://osf.io/s4h8j/download/
  !tar -xzf $fname -C $HCP_DIR --strip-components=1
 #行为协变量
 fname = "hcp_covariates.tgz"
if not os.path.exists(fname):
  !wget -qO $fname https://osf.io/x5p4g/download/
  !tar -xzf $fname -C $HCP_DIR --strip-components=1
#脑区模板
fname = f"{HCP_DIR}/atlas.npz"
if not os.path.exists(fname):
  !wget -qO $fname https://osf.io/j5kuc/download

加载区域信息

  • 下载任意一个数据集都会创建region.npy文件,其中包含每个parcel的区域名称和网络分配。

  • Glasser等人的补编中提供了有关每个区域使用的名称的详细信息。 2016。Ji等人,2019年提供了有关网络分割的信息。

#脑区信息
regions = np.load(f"{HCP_DIR}/regions.npy").T
region_info = dict(
    name=regions[0].tolist(),
    network=regions[1],
    myelin=regions[2].astype(np.float),
)

我们还提供了fsaverage5表面上的分割和每个区域的近似MNI坐标,这对于可视化很有用:

with np.load(f"{HCP_DIR}/atlas.npz") as dobj:
  atlas = dict(**dobj)

帮助函数
数据导入

def get_image_ids(name):
  """获取给定实验中基于1的图像索引
    Args:
      name (str) :要加载的实验名称(“静息”或任务名称)
    Returns:
      run_ids (list of int) :实验图像文件的ID

  """
  run_ids = [
    i for i, code in enumerate(BOLD_NAMES, 1) if name.upper() in code
  ]
  if not run_ids:
    raise ValueError(f"Found no data for '{name}''")
  return run_ids

def load_timeseries(subject, name, runs=None, concat=True, remove_mean=True):
  """加载单个主题的时间序列数据
  
  Args:
    subject (int): 从0开始的加载主题ID
    name (str) : 要加载的实验名称(“静息”或任务名称)
    run (None or int or list of ints):要加载的任务的基于0的运行,或无以加载所有运行
    concat (bool) : 如果为True,则连接多个一起运行
    remove_mean (bool) : 如果为True,则减去parcal均值

  Returns
    ts (n_parcel x n_tp array): BOLD数据值的数组

  """
  # 获取列表的相对于0的索引
  if runs is None:
    runs = range(N_RUNS_REST) if name == "rest" else range(N_RUNS_TASK)
  elif isinstance(runs, int):
    runs = [runs]

  # 获取此实验的第一个(从1开始)运行ID
  offset = get_image_ids(name)[0]

  # 加载每次运行的数据
  bold_data = [
      load_single_timeseries(subject, offset + run, remove_mean) for run in runs
  ]

  # 选择连接
  if concat:
    bold_data = np.concatenate(bold_data, axis=-1)

  return bold_data


def load_single_timeseries(subject, bold_run, remove_mean=True):
  """加载单个主题和单个运行的时间序列数据
  
  Args:
    subject (int): 从0开始的主题ID加载
    bold_run (int): 所有任务均基于1的运行索引
    remove_mean (bool): 如果为True,则减去parcel均值

  Returns
    ts (n_parcel x n_timepoint array): BOLD数组

  """
  bold_path = f"{HCP_DIR}/subjects/{subject}/timeseries"
  bold_file = f"bold{bold_run}_Atlas_MSMAll_Glasser360Cortical.npy"
  ts = np.load(f"{bold_path}/{bold_file}")
  if remove_mean:
    ts -= ts.mean(axis=1, keepdims=True)
  return ts

def load_evs(subject, name, condition):
  """加载一个任务条件的EV(解释性变量)数据

  Args:
    subject (int): 从0开始的主题ID加载
    name (str) : 任务名称
    condition (str) : 条件名称

  Returns
    evs (list of dicts): 每次运行的条件具有开始,持续时间和幅度的字典.

  """
  evs = []
  for id in get_image_ids(name):
    task_key = BOLD_NAMES[id - 1]
    ev_file = f"{HCP_DIR}/subjects/{subject}/EVs/{task_key}/{condition}.txt"
    ev_array = np.loadtxt(ev_file, ndmin=2, unpack=True)
    ev = dict(zip(["onset", "duration", "amplitude"], ev_array))
    evs.append(ev)
  return evs

基于任务的分析

def condition_frames(run_evs, skip=0):
  """确定每次运行中与给定条件相对应的时间点

  Args:
    run_evs (list of dicts) : 每次运行的事件的开始和持续时间
    skip (int) : 在每次试用开始时忽略这么多帧,血流动力学滞后

  Returns:
    frames_list (list of 1D arrays): 每次运行的帧索引的平面数组

  """
  frames_list = []
  for ev in run_evs:

    # 确定何时开始试用,四舍五入
    start = np.floor(ev["onset"] / TR).astype(int)

    # 使用试验持续时间来确定试验要包括多少帧
    duration = np.ceil(ev["duration"] / TR).astype(int)

    # 取与这个特定试验相对应的帧的范围
    frames = [s + np.arange(skip, d) for s, d in zip(start, duration)]

    frames_list.append(np.concatenate(frames))

  return frames_list


def selective_average(timeseries_data, ev, skip=0):
  """取给定条件下帧间的时间平均值

  Args:
    timeseries_data (array or list of arrays): n_parcel x n_tp arrays
    ev (dict or list of dicts): 条件时间信息
    skip (int) : 在每次试验开始时忽略这许多帧,以说明血流动力学滞后

  Returns:
    avg_data (1D array): 基于条件时序在选定图像帧间平均的数据
  """
  # 确保我们有相同长度的列表
  if not isinstance(timeseries_data, list):
    timeseries_data = [timeseries_data]
  if not isinstance(ev, list):
    ev = [ev]
  if len(timeseries_data) != len(ev):
    raise ValueError("Length of `timeseries_data` and `ev` must match.")

  # 识别相关帧的索引
  frames = condition_frames(ev, skip)

  # 从每个图像中选择帧
  selected_data = []
  for run_data, run_frames in zip(timeseries_data, frames):
    run_frames = run_frames[run_frames < run_data.shape[1]]
    selected_data.append(run_data[:, run_frames])

  # 取每个parcel的平均值
  avg_data = np.concatenate(selected_data, axis=-1).mean(axis=-1)

  return avg_data

静止态分析
加载一次静态态数据:

help(load_timeseries)
#为单个subject加载时间序列数据
timeseries = load_timeseries(subject=0, name="rest", runs=1)
print(timeseries.shape)  # n_parcel x n_timepoint

#加载为每个被试的静息态时间序列(使用所有运行数据):
timeseries_rest = []
for subject in subjects:
  ts_concat = load_timeseries(subject, "rest")
  timeseries_rest.append(ts_concat)

运行简单的基于相关性的“功能连接”分析
为每个受试者生成一个相关矩阵(显示“功能连接性”或功能系数),并绘制组平均值:

fc = np.zeros((N_SUBJECTS, N_PARCELS, N_PARCELS))
for sub, ts in enumerate(timeseries_rest):
  fc[sub] = np.corrcoef(ts)

group_fc = fc.mean(axis=0)

plt.imshow(group_fc, interpolation="none", cmap="bwr", vmin=-1, vmax=1)
plt.colorbar()
plt.show()

绘制特定“种子”parcel和数据集中每个parcel之间的FC值分布图,用半球分隔:

seed_roi = "R_FEF"  # name of seed parcel
ind = region_info["name"].index(seed_roi)

hemi_fc = np.split(group_fc, 2)

# 绘制右半球和左半球目标区域的功能曲线
for i, hemi_fc in enumerate(hemi_fc):
  plt.plot(hemi_fc[:, ind], label=f"{HEMIS[i]} hemisphere")
plt.title(f"FC for region {seed_roi}")
plt.xlabel("Target region")
plt.ylabel("Correlation (FC)")
plt.legend()
plt.show()

你可能感兴趣的:(核磁数据,数据分析)