Beispiel #1
0
def make_age_maps(data_file, info_file, out_name):
    """
    对每个顶点,计算跨同一年龄被试的平均和sem,分别保存在
    out_name-mean.dscalar.nii, out_name-sem.dscalar.nii中

    Args:
        data_file (str): end with .dscalar.nii
            shape=(n_subj, LR_count_32k)
        info_file (str): subject info file
        out_name (str): filename to save
    """
    # prepare
    data_maps = nib.load(data_file).get_fdata()
    info_df = pd.read_csv(info_file)
    ages = np.array(info_df['age in years'])
    ages_uniq = np.unique(ages)
    n_age = len(ages_uniq)

    # calculate
    mean_maps = np.ones((n_age, LR_count_32k)) * np.nan
    sem_maps = np.ones((n_age, LR_count_32k)) * np.nan
    for age_idx, age in enumerate(ages_uniq):
        data = data_maps[ages == age]
        mean_maps[age_idx] = np.mean(data, 0)
        sem_maps[age_idx] = sem(data, 0)

    # save
    map_names = [str(i) for i in ages_uniq]
    reader = CiftiReader(mmp_map_file)
    save2cifti(f'{out_name}-mean.dscalar.nii', mean_maps,
               reader.brain_models(), map_names)
    save2cifti(f'{out_name}-sem.dscalar.nii', sem_maps, reader.brain_models(),
               map_names)
Beispiel #2
0
def vtx_corr_col(data_file1, atlas_name, roi_name, data_file2, column, idx_col,
                 out_file):
    """
    计算data_file1中指定atlas ROI内的所有顶点序列和data_file2中指定column序列的相关

    Args:
        data_file1 (str): end with .dscalar.nii
            shape=(N, LR_count_32k)
        atlas_name (str):
        roi_name (str):
        data_file2 (str): end with .csv
            shape=(N, n_col)
        column (str):
        idx_col (int): specify index column of csv file
            If None, means no index column.
    """
    # prepare
    reader = CiftiReader(data_file1)
    maps = reader.get_data()
    atlas = Atlas(atlas_name)
    assert atlas.maps.shape == (1, LR_count_32k)
    roi_idx_map = atlas.maps[0] == atlas.roi2label[roi_name]
    maps = maps[:, roi_idx_map]

    df = pd.read_csv(data_file2, index_col=idx_col)
    col_vec = np.array(df[column])
    col_vec = np.expand_dims(col_vec, 0)

    # calculate
    data = np.ones((1, LR_count_32k)) * np.nan
    data[0, roi_idx_map] = 1 - cdist(col_vec, maps.T, 'correlation')[0]

    # save
    save2cifti(out_file, data, reader.brain_models())
def merge_smoothed_data(dataset_name, meas_name, sigma):
    """
    合并我平滑过后的cifti文件

    Args:
        dataset_name (str): HCPD | HCPA
        meas_name (str): thickness | myelin
        sigma (float): the size of the gaussian surface smoothing kernel in mm
    """
    # outputs
    out_file = pjoin(work_dir,
                     f'{dataset_name}_{meas_name}_{sigma}mm.dscalar.nii')

    # prepare
    src_dir = pjoin(work_dir, f'{dataset_name}_{meas_name}_{sigma}mm')
    src_file = pjoin(src_dir, '{sid}.dscalar.nii')
    df = pd.read_csv(dataset_name2info[dataset_name])
    n_subj = df.shape[0]
    data = np.zeros((n_subj, LR_count_32k), np.float64)

    # calculate
    for subj_idx, subj_id in enumerate(df['subID']):
        time1 = time.time()
        meas_file = src_file.format(sid=subj_id)
        data[subj_idx] = nib.load(meas_file).get_fdata()[0]
        print(f'Finished: {subj_idx+1}/{n_subj},'
              f'cost: {time.time() - time1} seconds.')

    # save
    mmp_reader = CiftiReader(mmp_map_file)
    save2cifti(out_file, data, mmp_reader.brain_models(), df['subID'])
Beispiel #4
0
def make_non_outlier_map(fpath,
                         thr,
                         roi_name,
                         out_file_mask=None,
                         out_file_prob=None):
    """
    将同时在thr%以上的被试中被认定为outlier的顶点判定为跨被试的outlier
    If out_file_mask is not None, save mask map. (.dlabel.nii or .npy)
    If out_file_prob is not None, save prob map. (.dscalar.nii)
    """
    # prepare
    data = np.load(fpath)
    n_subj, n_vtx = data.shape

    atlas1 = Atlas('Cole_visual_LR')
    atlas2 = Atlas('Cole_visual_ROI')
    assert atlas1.maps.shape == (1, LR_count_32k)
    assert atlas2.maps.shape == (1, LR_count_32k)
    roi_idx_map = atlas1.maps[0] == atlas1.roi2label[roi_name]

    if roi_name == 'R_cole_visual':
        prefix = 'R_'
    elif roi_name == 'L_cole_visual':
        prefix = 'L_'
    else:
        raise ValueError("error roi_name:", roi_name)
    mmp_reader = CiftiReader(mmp_map_file)
    mmp_lbl_tab = mmp_reader.label_tables()[0]

    # calculate
    if out_file_mask is not None:
        data_tmp = np.sum(data, axis=0)
        outlier_vec = data_tmp > thr / 100 * n_subj
        print(f'#outliers/total: {np.sum(outlier_vec)}/{n_vtx}')
        mask_npy = np.zeros(LR_count_32k, bool)
        mask_npy[roi_idx_map] = ~outlier_vec
        if out_file_mask.endswith('.npy'):
            np.save(out_file_mask, mask_npy)
        elif out_file_mask.endswith('.dlabel.nii'):
            mask_cii = atlas2.maps.copy()
            mask_cii[0, ~mask_npy] = np.nan
            lbl_tab = nib.cifti2.cifti2.Cifti2LabelTable()
            for roi, lbl in atlas2.roi2label.items():
                if roi.startswith(prefix):
                    lbl_tab[lbl] = mmp_lbl_tab[lbl]
            save2cifti(out_file_mask,
                       mask_cii,
                       mmp_reader.brain_models(),
                       label_tables=[lbl_tab])
        else:
            raise ValueError("Not supported file name:", out_file_mask)

    if out_file_prob is not None:
        data_tmp = np.mean(data, axis=0)
        prob_map = np.ones((1, LR_count_32k), dtype=np.float64) * np.nan
        prob_map[0, roi_idx_map] = data_tmp
        assert out_file_prob.endswith('.dscalar.nii')
        save2cifti(out_file_prob, prob_map, mmp_reader.brain_models())
Beispiel #5
0
def pca(data_file, atlas_name, roi_name, n_component, axis, out_name):
    """
    对n_subj x n_vtx形状的矩阵进行PCA降维

    Args:
        data_file (str): end with .dscalar.nii
            shape=(n_subj, LR_count_32k)
        atlas_name (str): include ROIs' labels and mask map
        roi_name (str): 决定选用哪个区域内的顶点来参与PCA
        n_component (int): the number of components
        axis (str): vertex | subject
            vertex: 对顶点数量进行降维,得到几个主成分时间序列,
            观察某个主成分在各顶点上的权重,刻画其空间分布。
            subject: 对被试数量进行降维,得到几个主成分map,
            观察某个主成分在各被试上的权重,按年龄排序即可得到时间序列。
        out_name (str): output name
            If axis=vertex, output
            1. n_subj x n_component out_name.csv
            2. n_component x LR_count_32k out_name.dscalar.nii
            3. out_name.pkl with fitted PCA model
    """
    # prepare
    component_names = [f'C{i}' for i in range(1, n_component + 1)]

    meas_maps = nib.load(data_file).get_fdata()
    atlas = Atlas(atlas_name)
    assert atlas.maps.shape == (1, LR_count_32k)
    roi_idx_map = atlas.maps[0] == atlas.roi2label[roi_name]
    meas_maps = meas_maps[:, roi_idx_map]

    bms = CiftiReader(mmp_map_file).brain_models()

    # calculate
    pca = PCA(n_components=n_component)
    data = np.ones((n_component, LR_count_32k), np.float64) * np.nan
    if axis == 'vertex':
        X = meas_maps
        pca.fit(X)
        Y = pca.transform(X)
        df = pd.DataFrame(data=Y, columns=component_names)
        data[:, roi_idx_map] = pca.components_

    elif axis == 'subject':
        X = meas_maps.T
        pca.fit(X)
        Y = pca.transform(X)
        df = pd.DataFrame(data=pca.components_.T, columns=component_names)
        data[:, roi_idx_map] = Y.T

    else:
        raise ValueError('Invalid axis:', axis)

    # save
    df.to_csv(f'{out_name}.csv', index=False)
    save2cifti(f'{out_name}.dscalar.nii', data, bms, component_names)
    pkl.dump(pca, open(f'{out_name}.pkl', 'wb'))
def separate_networks():
    """
    把ColeNetwork的12个网络分到单独的map里。
    每个map的MMP parcel的label保留原来的样子。
    需要注意的是multimodal_glasser的MMP_mpmLR32k.dlabel.nii中,
    ROI label的编号1~180是右脑,181~360是左脑。0对应的是???
    而cortex_parcel_network_assignments.mat中0~359的index是左脑在先
    """
    import numpy as np
    import nibabel as nib
    from scipy.io import loadmat
    from cxy_visual_dev.lib.ColeNet import get_name_label_of_ColeNetwork
    from magicbox.io.io import CiftiReader, save2cifti

    # inputs
    mmp_file = '/nfs/p1/atlases/multimodal_glasser/surface/'\
               'MMP_mpmLR32k.dlabel.nii'
    roi2net_file = pjoin(cole_dir, 'cortex_parcel_network_assignments.mat')

    # outputs
    out_file = pjoin(work_dir, 'networks.dlabel.nii')

    # load
    mmp_reader = CiftiReader(mmp_file)
    mmp_map = mmp_reader.get_data()[0]
    lbl_tab_raw = mmp_reader.label_tables()[0]

    roi2net = loadmat(roi2net_file)['netassignments'][:, 0]
    roi2net = np.r_[roi2net[180:], roi2net[:180]]
    net_labels = np.unique(roi2net)

    # prepare
    data = np.zeros((len(net_labels), len(mmp_map)), dtype=np.uint16)
    map_names = []
    label_tables = []
    net_lbl2name = {}
    for name, lbl in zip(*get_name_label_of_ColeNetwork()):
        net_lbl2name[lbl] = name

    # calculate
    for net_idx, net_lbl in enumerate(net_labels):
        roi_labels = np.where(roi2net == net_lbl)[0] + 1
        lbl_tab = nib.cifti2.cifti2.Cifti2LabelTable()
        lbl_tab[0] = lbl_tab_raw[0]
        for roi_lbl in roi_labels:
            data[net_idx, mmp_map == roi_lbl] = roi_lbl
            lbl_tab[roi_lbl] = lbl_tab_raw[roi_lbl]
        map_names.append(net_lbl2name[net_lbl])
        label_tables.append(lbl_tab)

    # save
    save2cifti(out_file,
               data,
               mmp_reader.brain_models(),
               map_names,
               label_tables=label_tables)
def zscore_data(data_file, out_file):
    """
    对每个被试做全脑zscore

    Args:
        data_file (str): .dscalar.nii
        out_file (str): .dscalar.nii
    """
    reader = CiftiReader(data_file)
    data = reader.get_data()
    data = zscore(data, 1)
    save2cifti(out_file, data, reader.brain_models(), reader.map_names())
Beispiel #8
0
def kendall2cifti(data_file, rois, atlas_name, out_file):
    """
    把指定ROI的Tau值和p值存成cifti格式 方便可视化在大脑上
    """
    # prepare
    df = pd.read_csv(data_file, index_col=0)
    atlas = Atlas(atlas_name)
    assert atlas.maps.shape == (1, LR_count_32k)
    out_data = np.ones((2, LR_count_32k)) * np.nan

    # calculate
    for roi in rois:
        mask = atlas.maps[0] == atlas.roi2label[roi]
        out_data[0, mask] = df.loc['tau', roi]
        out_data[1, mask] = -np.log10(df.loc['p', roi])

    # save
    save2cifti(out_file, out_data,
               CiftiReader(mmp_map_file).brain_models(), ['tau', '-lg(p)'])
Beispiel #9
0
def polyfit(data_file, info_file, deg, out_file):
    """
    对时间序列进行多项式拟合

    Args:
        data_file (str): .csv | .dscalar.nii
            If is .csv, fit each column with ages.
            If is .dscalar.nii, fit each vertex with ages.
        info_file (str): .csv
        deg (int): degree of polynomial
        out_file (str): file to output
            same postfix with data_file
    """
    # prepare
    if data_file.endswith('.csv'):
        assert out_file.endswith('.csv')
        reader = pd.read_csv(data_file)
        data = np.array(reader)
    elif data_file.endswith('.dscalar.nii'):
        assert out_file.endswith('.dscalar.nii')
        reader = CiftiReader(data_file)
        data = reader.get_data()
    else:
        raise ValueError(1)

    # calculate
    ages = np.array(pd.read_csv(info_file)['age in years'])
    coefs = np.polyfit(ages, data, deg)
    n_row = coefs.shape[0]
    if deg == 1:
        assert n_row == 2
        row_names = ['coef', 'intercept']
    else:
        row_names = [''] * n_row
        raise Warning("Can't provide row names for degree:", deg)

    # save
    if out_file.endswith('.csv'):
        df = pd.DataFrame(coefs, row_names, reader.columns)
        df.to_csv(out_file)
    else:
        save2cifti(out_file, coefs, reader.brain_models(), row_names)
def separate_networks():
    """
    把ColeNetwork的12个网络分到单独的map里。
    每个map的MMP parcel的label保留原来的样子。
    需要注意的是multimodal_glasser的MMP_mpmLR32k.dlabel.nii中,
    ROI label的编号1~180是右脑,181~360是左脑。0对应的是???
    而cortex_parcel_network_assignments.mat中0~359的index是左脑在先
    """
    # outputs
    out_file = pjoin(work_dir, 'networks.dlabel.nii')

    # load
    mmp_reader = CiftiReader(mmp_map_file)
    mmp_map = mmp_reader.get_data()[0]
    lbl_tab_raw = mmp_reader.label_tables()[0]

    roi2net = loadmat(cole_net_assignment_file)['netassignments'][:, 0]
    roi2net = np.r_[roi2net[180:], roi2net[:180]]
    net_labels = np.unique(roi2net)

    # prepare
    data = np.zeros((len(net_labels), len(mmp_map)), dtype=np.uint16)
    map_names = []
    label_tables = []

    # calculate
    for net_idx, net_lbl in enumerate(net_labels):
        roi_labels = np.where(roi2net == net_lbl)[0] + 1
        lbl_tab = nib.cifti2.cifti2.Cifti2LabelTable()
        lbl_tab[0] = lbl_tab_raw[0]
        for roi_lbl in roi_labels:
            data[net_idx, mmp_map == roi_lbl] = roi_lbl
            lbl_tab[roi_lbl] = lbl_tab_raw[roi_lbl]
        map_names.append(cole_label2name[net_lbl])
        label_tables.append(lbl_tab)

    # save
    save2cifti(out_file,
               data,
               mmp_reader.brain_models(),
               map_names,
               label_tables=label_tables)
def merge_data(dataset_name, meas_name):
    """
    把所有被试的数据合并到一个cifti文件里

    Args:
        dataset_name (str): HCPD | HCPA
        meas_name (str): thickness | myelin
    """
    # outputs
    out_file = pjoin(work_dir, f'{dataset_name}_{meas_name}.dscalar.nii')

    # prepare
    dataset_dir = dataset_name2dir[dataset_name]
    meas2file = {
        'myelin':
        pjoin(
            dataset_dir,
            'fmriresults01/{sid}_V1_MR/MNINonLinear/fsaverage_LR32k/'
            '{sid}_V1_MR.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii'),
        'thickness':
        pjoin(
            dataset_dir,
            'fmriresults01/{sid}_V1_MR/MNINonLinear/fsaverage_LR32k/'
            '{sid}_V1_MR.thickness_MSMAll.32k_fs_LR.dscalar.nii')
    }

    df = pd.read_csv(dataset_name2info[dataset_name])
    n_subj = df.shape[0]

    data = np.zeros((n_subj, LR_count_32k), np.float64)

    # calculate
    for subj_idx, subj_id in enumerate(df['subID']):
        time1 = time.time()
        meas_file = meas2file[meas_name].format(sid=subj_id)
        data[subj_idx] = nib.load(meas_file).get_fdata()[0]
        print(f'Finished: {subj_idx+1}/{n_subj},'
              f'cost: {time.time() - time1} seconds.')

    # save
    mmp_reader = CiftiReader(mmp_map_file)
    save2cifti(out_file, data, mmp_reader.brain_models(), df['subID'])
Beispiel #12
0
def mask_maps(data_file, atlas_name, roi_name, out_file):
    """
    把data map在指定atlas的ROI以外的部分全赋值为nan

    Args:
        data_file (str): end with .dscalar.nii
            shape=(n_map, LR_count_32k)
        atlas_name (str):
        roi_name (str):
        out_file (str):
    """
    # prepare
    reader = CiftiReader(data_file)
    data = reader.get_data()
    atlas = Atlas(atlas_name)
    assert atlas.maps.shape == (1, LR_count_32k)
    roi_idx_map = atlas.maps[0] == atlas.roi2label[roi_name]

    # calculate
    data[:, ~roi_idx_map] = np.nan

    # save
    save2cifti(out_file, data, reader.brain_models(), reader.map_names())