def calc_map_corr(data_file1, data_file2, atlas_name, roi_name, out_file, map_names1=None, map_names2=None, index=False): """ 计算指定atlas的ROI内的data1 maps和data2 maps的相关 存出的CSV文件的index是map_names1, column是map_names2 Args: data_file1 (str): end with .dscalar.nii shape=(n_map1, LR_count_32k) data_file2 (str): end with .dscalar.nii shape=(n_map2, LR_count_32k) atlas_name (str): roi_name (str): out_file (str): map_names1 (list, optional): Defaults to None. If is None, use map names in data1_file. map_names2 (list, optional): Defaults to None. If is None, use map names in data2_file. index (bool, optional): Defaults to False. Save index of DataFrame or not """ # prepare reader1 = CiftiReader(data_file1) reader2 = CiftiReader(data_file2) data_maps1 = reader1.get_data() data_maps2 = reader2.get_data() atlas = Atlas(atlas_name) assert atlas.maps.shape == (1, LR_count_32k) roi_idx_map = atlas.maps[0] == atlas.roi2label[roi_name] data_maps1 = data_maps1[:, roi_idx_map] data_maps2 = data_maps2[:, roi_idx_map] if map_names1 is None: map_names1 = reader1.map_names() else: assert len(map_names1) == data_maps1.shape[0] if map_names2 is None: map_names2 = reader2.map_names() else: assert len(map_names2) == data_maps2.shape[0] # calculate corrs = 1 - cdist(data_maps1, data_maps2, 'correlation') # save df = pd.DataFrame(corrs, map_names1, map_names2) df.to_csv(out_file, index=index)
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 calc_meas_individual(hemi='lh'): import nibabel as nib import numpy as np import pickle as pkl from magicbox.io.io import CiftiReader from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label # inputs work_dir = pjoin(proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/tfMRI') rois_file = pjoin(proj_dir, 'analysis/s2/1080_fROI/' f'refined_with_Kevin/rois_v3_{hemi}.nii.gz') meas_file = pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') # outputs out_file = pjoin(work_dir, f'individual_activ_{hemi}.pkl') rois = nib.load(rois_file).get_data().squeeze().T n_roi = len(roi2label) meas_reader = CiftiReader(meas_file) meas = meas_reader.get_data(hemi2stru[hemi], True) n_subj = meas.shape[0] roi_meas = {'shape': 'n_roi x n_subj', 'roi': list(roi2label.keys()), 'meas': np.ones((n_roi, n_subj)) * np.nan} for roi_idx, roi in enumerate(roi_meas['roi']): lbl_idx_arr = rois == roi2label[roi] for subj_idx in range(n_subj): lbl_idx_vec = lbl_idx_arr[subj_idx] if np.any(lbl_idx_vec): roi_meas['meas'][roi_idx, subj_idx] = np.mean( meas[subj_idx][lbl_idx_vec]) pkl.dump(roi_meas, open(out_file, 'wb'))
def calc_meas_test(roi_type): """ 用45个被试在test或retest中定出的个体FFA去提取各自在test的face selectivity。 Args: roi_type (str): ROI-test or ROI-retest """ import numpy as np import pandas as pd import nibabel as nib from magicbox.io.io import CiftiReader from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label # inputs hemis = ('lh', 'rh') rois = ('pFus-face', 'mFus-face') subj_file_45 = pjoin(proj_dir, 'data/HCP/wm/analysis_s2/' 'retest/subject_id') subj_file_1080 = pjoin(proj_dir, 'analysis/s2/subject_id') meas_file = pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') roi_type2file = { 'ROI-test': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'rois_v3_{hemi}.nii.gz'), 'ROI-retest': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'retest/rois_{hemi}_v2.nii.gz') } roi_file = roi_type2file[roi_type] # outputs out_file = pjoin(work_dir, f'activ-test_{roi_type}.csv') # prepare subj_ids_45 = open(subj_file_45).read().splitlines() subj_ids_1080 = open(subj_file_1080).read().splitlines() retest_idx_in_1080 = [subj_ids_1080.index(i) for i in subj_ids_45] n_subj = len(subj_ids_45) out_df = pd.DataFrame(index=range(n_subj)) # calculate meas_reader = CiftiReader(meas_file) for hemi in hemis: meas_maps = meas_reader.get_data(hemi2stru[hemi], True)[retest_idx_in_1080] roi_maps = nib.load(roi_file.format(hemi=hemi)).get_fdata().squeeze().T if roi_type == 'ROI-test': roi_maps = roi_maps[retest_idx_in_1080] for roi in rois: col = f"{hemi}_{roi.split('-')[0]}" for idx in range(n_subj): roi_idx_map = roi_maps[idx] == roi2label[roi] if np.any(roi_idx_map): out_df.loc[idx, col] = np.mean(meas_maps[idx][roi_idx_map]) # save out_df.to_csv(out_file, index=False)
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 calc_meas_individual(hemi='lh', meas='thickness'): import nibabel as nib import numpy as np import pickle as pkl from magicbox.io.io import CiftiReader from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label rois = ('IOG-face', 'pFus-face', 'mFus-face') rois_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/' f'refined_with_Kevin/rois_v3_{hemi}.nii.gz') subj_file = pjoin(proj_dir, 'analysis/s2/subject_id') meas_id_file = pjoin(proj_dir, 'data/HCP/subject_id_1096') meas2file = { 'thickness': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.thickness_MSMAll.32k_fs_LR.dscalar.nii', 'myelin': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii', 'va': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.midthickness_MSMAll_va.32k_fs_LR.dscalar.nii' } meas_file = meas2file[meas] trg_file = pjoin(work_dir, f'rois_v3_{hemi}_{meas}.pkl') roi_maps = nib.load(rois_file).get_fdata().squeeze().T n_roi = len(rois) subj_ids = open(subj_file).read().splitlines() n_subj = len(subj_ids) meas_reader = CiftiReader(meas_file) meas_ids = open(meas_id_file).read().splitlines() meas_indices = [meas_ids.index(i) for i in subj_ids] meas_maps = meas_reader.get_data(hemi2stru[hemi], True)[meas_indices] roi_meas = { 'shape': 'n_roi x n_subj', 'roi': rois, 'meas': np.ones((n_roi, n_subj)) * np.nan } for roi_idx, roi in enumerate(roi_meas['roi']): lbl_idx_arr = roi_maps == roi2label[roi] for subj_idx in range(n_subj): lbl_idx_vec = lbl_idx_arr[subj_idx] meas_map = meas_maps[subj_idx] if np.any(lbl_idx_vec): if meas == 'va': tmp = np.sum(meas_map[lbl_idx_vec]) else: tmp = np.mean(meas_map[lbl_idx_vec]) roi_meas['meas'][roi_idx, subj_idx] = tmp pkl.dump(roi_meas, open(trg_file, 'wb'))
def calc_pattern_corr_between_twins(meas_name='thickness'): """ Calculate spatial pattern correlation between each twin pair. """ import pandas as pd import nibabel as nib from magicbox.io.io import CiftiReader from scipy.stats import pearsonr twins_id_file = pjoin(work_dir, 'twins_id_1080.csv') meas2file = { 'thickness': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.thickness_MSMAll.32k_fs_LR.dscalar.nii', 'myelin': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii', 'activ': pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') } hemis = ('lh', 'rh') hemi2stru = { 'lh': 'CIFTI_STRUCTURE_CORTEX_LEFT', 'rh': 'CIFTI_STRUCTURE_CORTEX_RIGHT' } mpm_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'MPM_v3_{hemi}_0.25.nii.gz') roi2label = {'IOG-face': 1, 'pFus-face': 2, 'mFus-face': 3} zyg2label = {'MZ': 1, 'DZ': 2} out_file = pjoin(work_dir, f'twins_pattern-corr_{meas_name}.csv') df = pd.read_csv(twins_id_file) meas_reader = CiftiReader(meas2file[meas_name]) meas_ids = [int(name.split('_')[0]) for name in meas_reader.map_names()] twin1_indices = [meas_ids.index(i) for i in df['twin1']] twin2_indices = [meas_ids.index(i) for i in df['twin2']] out_df = pd.DataFrame() out_df['zygosity'] = df['zygosity'] out_df['zyg'] = [zyg2label[zyg] for zyg in df['zygosity']] for hemi in hemis: meas1 = meas_reader.get_data(hemi2stru[hemi], True)[twin1_indices] meas2 = meas_reader.get_data(hemi2stru[hemi], True)[twin2_indices] mpm = nib.load(mpm_file.format(hemi=hemi)).get_data().squeeze() for roi, lbl in roi2label.items(): idx_vec = mpm == lbl out_df[f"{hemi}_{roi.split('-')[0]}"] = [ pearsonr(i[idx_vec], j[idx_vec])[0] for i, j in zip(meas1, meas2) ] out_df.to_csv(out_file, index=False)
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())
def calc_meas_MPM(hemi='lh'): """ 用一半被试的MPM去提取另一半被试的激活值 如果某个被试没有某个ROI,就不提取该被试该ROI的信号 Args: hemi (str, optional): hemisphere. Defaults to 'lh'. """ import numpy as np import pickle as pkl import nibabel as nib from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label from magicbox.io.io import CiftiReader hids = (1, 2) hid_file = pjoin(split_dir, 'half_id.npy') mpm_file = pjoin(split_dir, 'MPM_half{hid}_{hemi}.nii.gz') roi_file = pjoin(proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' f'rois_v3_{hemi}.nii.gz') src_file = pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') trg_file = pjoin(work_dir, f'activ_{hemi}.pkl') hid_vec = np.load(hid_file) n_subj = len(hid_vec) roi_maps = nib.load(roi_file).get_data().squeeze().T n_roi = len(roi2label) meas_reader = CiftiReader(src_file) meas = meas_reader.get_data(hemi2stru[hemi], True) out_dict = {'shape': 'n_roi x n_subj', 'roi': list(roi2label.keys()), 'meas': np.ones((n_roi, n_subj)) * np.nan} for hid in hids: hid_idx_vec = hid_vec == hid mpm = nib.load(mpm_file.format(hid=hid, hemi=hemi) ).get_data().squeeze() for roi_idx, roi in enumerate(out_dict['roi']): roi_idx_vec = np.any(roi_maps == roi2label[roi], 1) valid_idx_vec = np.logical_and(~hid_idx_vec, roi_idx_vec) mpm_idx_vec = mpm == roi2label[roi] meas_masked = meas[valid_idx_vec][:, mpm_idx_vec] out_dict['meas'][roi_idx][valid_idx_vec] = np.mean(meas_masked, 1) pkl.dump(out_dict, open(trg_file, 'wb'))
def calc_mean_meas_map(meas='thickness'): """ 得到1080个被试的平均map """ import numpy as np from magicbox.io.io import CiftiReader, save2nifti from cxy_hcp_ffa.lib.predefine import hemi2stru # inputs hemis = ('lh', 'rh') subj_file = pjoin(proj_dir, 'analysis/s2/subject_id') meas_id_file = pjoin(proj_dir, 'data/HCP/subject_id_1096') meas2file = { 'thickness': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.thickness_MSMAll.32k_fs_LR.dscalar.nii', 'myelin': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii', 'va': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.midthickness_MSMAll_va.32k_fs_LR.dscalar.nii' } # outputs out_file = pjoin(work_dir, '{meas}_mean-1080_{hemi}.nii.gz') # prepare subj_ids = open(subj_file).read().splitlines() meas_reader = CiftiReader(meas2file[meas]) meas_ids = open(meas_id_file).read().splitlines() meas_indices = [meas_ids.index(i) for i in subj_ids] # calculate for hemi in hemis: meas_maps = meas_reader.get_data(hemi2stru[hemi], True)[meas_indices] meas_mean = np.mean(meas_maps, 0) meas_mean = np.expand_dims(meas_mean, (1, 2)) save2nifti(out_file.format(meas=meas, hemi=hemi), meas_mean)
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 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 get_curvature(hemi='lh'): """ 把45个retest被试在retest session的curvature合并成左右脑两个nifti文件, 主要是为了我那个程序在标定个体ROI的时候读取和显示曲率。 之前服务器上没有retest的结构数据,我想当然地认为同一个被试的沟回曲率在 两次测量应该是一模一样的,所以在标定v1和v2版ROI的时候参照的是test session的曲率; 这次我下了retest的结构数据,决定用retest session的曲率校对一下retest个体ROI。 """ import numpy as np from magicbox.io.io import CiftiReader, save2nifti from cxy_hcp_ffa.lib.predefine import hemi2stru # inputs hemis = ('lh', 'rh') fpath = '/nfs/m1/hcp/retest/{0}/MNINonLinear/fsaverage_LR32k/'\ '{0}.curvature_MSMAll.32k_fs_LR.dscalar.nii' subj_id_file = pjoin(work_dir, 'subject_id') # outputs out_file = pjoin(work_dir, 'curvature_{hemi}.nii.gz') # prepare subj_ids = open(subj_id_file).read().splitlines() n_subj = len(subj_ids) hemi2data = {} for hemi in hemis: hemi2data[hemi] = np.zeros((32492, 1, 1, n_subj), np.float64) # calculate for subj_idx, subj_id in enumerate(subj_ids): reader = CiftiReader(fpath.format(subj_id)) for hemi in hemis: data_tmp = reader.get_data(hemi2stru[hemi], True)[0] hemi2data[hemi][:, 0, 0, subj_idx] = data_tmp print(f'Finished: {subj_idx+1}/{n_subj}') # save for hemi in hemis: save2nifti(out_file.format(hemi=hemi), hemi2data[hemi])
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())
def calc_meas(meas_name='activ', atlas_name='MPM'): import time import numpy as np import pickle as pkl import nibabel as nib from magicbox.io.io import CiftiReader from cxy_hcp_ffa.lib.predefine import roi2label, hemi2stru # inputs hemis = ('lh', 'rh') rois = ('pFus-face', 'mFus-face') subj_file_45 = pjoin(proj_dir, 'data/HCP/wm/analysis_s2/' 'retest/subject_id') subj_file_1080 = pjoin(proj_dir, 'analysis/s2/subject_id') subj_file_1096 = pjoin(proj_dir, 'data/HCP/subject_id_1096') meas2file_test = { 'thickness': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.thickness_MSMAll.32k_fs_LR.dscalar.nii', 'myelin': '/nfs/p1/public_dataset/datasets/hcp/DATA/' 'HCP_S1200_GroupAvg_v1/HCP_S1200_GroupAvg_v1/' 'S1200.All.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii', 'activ': pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') } retest_dir = '/nfs/m1/hcp/retest' meas2file_retest = { 'thickness': pjoin( retest_dir, '{0}/MNINonLinear/fsaverage_LR32k/' '{0}.thickness_MSMAll.32k_fs_LR.dscalar.nii'), 'myelin': pjoin( retest_dir, '{0}/MNINonLinear/fsaverage_LR32k/' '{0}.MyelinMap_BC_MSMAll.32k_fs_LR.dscalar.nii'), 'activ': pjoin( retest_dir, '{0}/MNINonLinear/Results/tfMRI_WM/' 'tfMRI_WM_hp200_s2_level2_MSMAll.feat/GrayordinatesStats/' 'cope20.feat/zstat1.dtseries.nii') } atlas2file = { 'MPM': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'MPM_v3_{hemi}_0.25.nii.gz'), 'ROIv3': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'rois_v3_{hemi}.nii.gz') } # outputs out_file = pjoin(work_dir, f'{meas_name}_{atlas_name}.pkl') # prepare subject IDs subj_ids_45 = open(subj_file_45).read().splitlines() subj_ids_1080 = open(subj_file_1080).read().splitlines() subj_ids_1096 = open(subj_file_1096).read().splitlines() retest_idx_in_1080 = [subj_ids_1080.index(i) for i in subj_ids_45] retest_idx_in_1096 = [subj_ids_1096.index(i) for i in subj_ids_45] n_subj = len(subj_ids_45) # prepare atlas hemi2atlas = {} for hemi in hemis: atlas_tmp = nib.load(atlas2file[atlas_name].format(hemi=hemi)) atlas_tmp = atlas_tmp.get_fdata().squeeze() if atlas_name == 'MPM': atlas_tmp = np.expand_dims(atlas_tmp, 0) hemi2atlas[hemi] = np.repeat(atlas_tmp, n_subj, 0) elif atlas_name == 'ROIv3': hemi2atlas[hemi] = atlas_tmp.T[retest_idx_in_1080] else: raise ValueError('Not supported atlas name:', atlas_name) # prepare test measurement maps if meas_name == 'activ': retest_idx_vec = retest_idx_in_1080 else: retest_idx_vec = retest_idx_in_1096 meas_reader_test = CiftiReader(meas2file_test[meas_name]) hemi2maps_test = {} for hemi in hemis: hemi2maps_test[hemi] = meas_reader_test.get_data( hemi2stru[hemi], True)[retest_idx_vec] # prepare out data data = {} for hemi in hemis: for roi in rois: roi_name = roi.split('-')[0] data[f"{hemi}_{roi_name}_test"] = np.ones(n_subj) * np.nan data[f"{hemi}_{roi_name}_retest"] = np.ones(n_subj) * np.nan # calculate for subj_idx, subj_id in enumerate(subj_ids_45): time1 = time.time() meas_reader_retest = CiftiReader( meas2file_retest[meas_name].format(subj_id)) for hemi in hemis: meas_map_test = hemi2maps_test[hemi][subj_idx] meas_map_retest = meas_reader_retest.get_data( hemi2stru[hemi], True)[0] atlas_map = hemi2atlas[hemi][subj_idx] for roi in rois: idx_vec = atlas_map == roi2label[roi] if np.any(idx_vec): roi_name = roi.split('-')[0] data[f"{hemi}_{roi_name}_test"][subj_idx] =\ np.mean(meas_map_test[idx_vec]) data[f"{hemi}_{roi_name}_retest"][subj_idx] =\ np.mean(meas_map_retest[idx_vec]) print( f'Finished {subj_idx+1}/{n_subj}: cost {time.time()-time1} seconds' ) # save pkl.dump(data, open(out_file, 'wb'))
def prepare_series_ind(sess=1, run='LR'): import numpy as np import nibabel as nib import pickle as pkl from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label from magicbox.io.io import CiftiReader # prepare subjects info subj_id_file = pjoin(work_dir, 'rfMRI_REST_id') subj_file_1080 = pjoin(proj_dir, 'analysis/s2/subject_id') subj_ids = open(subj_id_file).read().splitlines() subj_ids_1080 = open(subj_file_1080).read().splitlines() subj_idx_in_1080 = [subj_ids_1080.index(i) for i in subj_ids] n_subj = len(subj_ids) # prepare seeds seeds = ('IOG-face', 'pFus-face', 'mFus-face') n_seed = len(seeds) seed_mask_lh_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/' 'refined_with_Kevin/rois_v3_lh.nii.gz') seed_mask_rh_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/' 'refined_with_Kevin/rois_v3_rh.nii.gz') hemi2seed_mask = { 'lh': nib.load(seed_mask_lh_file).get_fdata().squeeze().T[subj_idx_in_1080], 'rh': nib.load(seed_mask_rh_file).get_fdata().squeeze().T[subj_idx_in_1080] } # prepare series dictionary n_tp = 1200 # the number of time points seed_lh_dict = { 'shape': 'n_subject x n_seed x n_time_point', 'subject': subj_ids, 'seed': seeds, 'rfMRI': np.ones((n_subj, n_seed, n_tp)) * np.nan } seed_rh_dict = { 'shape': 'n_subject x n_seed x n_time_point', 'subject': subj_ids, 'seed': seeds, 'rfMRI': np.ones((n_subj, n_seed, n_tp)) * np.nan } hemi2seed_dict = {'lh': seed_lh_dict, 'rh': seed_rh_dict} # prepare outputs out_seed_lh = pjoin(work_dir, f'rfMRI{sess}_{run}_ROIv3_lh.pkl') out_seed_rh = pjoin(work_dir, f'rfMRI{sess}_{run}_ROIv3_rh.pkl') # start maps_files = '/nfs/m1/hcp/retest/{0}/MNINonLinear/Results/rfMRI_REST{1}_{2}/'\ 'rfMRI_REST{1}_{2}_Atlas_MSMAll_hp2000_clean.dtseries.nii' for subj_idx, subj_id in enumerate(subj_ids): print('Progress: {}/{}'.format(subj_idx + 1, n_subj)) # prepare maps maps_file = maps_files.format(subj_id, sess, run) maps_reader = CiftiReader(maps_file) hemi2maps = { 'lh': maps_reader.get_data(hemi2stru['lh'], True), 'rh': maps_reader.get_data(hemi2stru['rh'], True) } for hemi in ['lh', 'rh']: maps = hemi2maps[hemi] # seed dict seed_mask = hemi2seed_mask[hemi] for seed_idx, seed in enumerate(seeds): idx_vec = seed_mask[subj_idx] == roi2label[seed] if np.any(idx_vec): hemi2seed_dict[hemi]['rfMRI'][subj_idx, seed_idx] =\ np.mean(maps[:, idx_vec], 1) # save pkl.dump(hemi2seed_dict['lh'], open(out_seed_lh, 'wb')) pkl.dump(hemi2seed_dict['rh'], open(out_seed_rh, 'wb'))
def calc_gdist(method='peak'): """Calculate geodesic distance between each two ROIs. Args: method (str, optional): 'peak' or 'min' If 'peak', use the distance between two vertices with peak activation values in two ROIs respectively. If 'min', use the minimum distance of pair-wise vertices between the two ROIs. Defaults to 'peak'. """ import os import time import gdist import numpy as np import pandas as pd import nibabel as nib from cxy_hcp_ffa.lib.predefine import roi2label, hemi2stru from magicbox.io.io import CiftiReader # inputs rois = ('IOG-face', 'pFus-face', 'mFus-face') hemis = ('lh', 'rh') hemi2Hemi = {'lh': 'L', 'rh': 'R'} subj_file = pjoin(proj_dir, 'analysis/s2/subject_id') roi_file = pjoin(work_dir, 'rois_v3_{}.nii.gz') geo_file = '/nfs/m1/hcp/{sid}/T1w/fsaverage_LR32k/' \ '{sid}.{Hemi}.midthickness_MSMAll.32k_fs_LR.surf.gii' activ_file = pjoin(proj_dir, 'analysis/s2/activation.dscalar.nii') # outputs log_file = pjoin(work_dir, f'gdist_{method}_log') out_file = pjoin(work_dir, f'gdist_{method}.csv') # preparation subj_ids = open(subj_file).read().splitlines() n_subj = len(subj_ids) activ_reader = CiftiReader(activ_file) out_dict = {} for hemi in hemis: for roi1_idx, roi1 in enumerate(rois[:-1]): for roi2 in rois[roi1_idx + 1:]: k = f"{hemi}_{roi1.split('-')[0]}-{roi2.split('-')[0]}" out_dict[k] = np.ones(n_subj, dtype=np.float64) * np.nan log_lines = [] # calculation for hemi in hemis: roi_maps = nib.load(roi_file.format(hemi)).get_fdata().squeeze().T activ_maps = activ_reader.get_data(hemi2stru[hemi], True) assert roi_maps.shape == activ_maps.shape for subj_idx, subj_id in enumerate(subj_ids): time1 = time.time() roi_map = roi_maps[subj_idx] activ_map = activ_maps[subj_idx] g_file = geo_file.format(sid=subj_id, Hemi=hemi2Hemi[hemi]) if not os.path.exists(g_file): log_lines.append(f'{g_file} does not exist.') continue geo = nib.load(g_file) coords = geo.get_arrays_from_intent('NIFTI_INTENT_POINTSET')[0] coords = coords.data.astype(np.float64) faces = geo.get_arrays_from_intent('NIFTI_INTENT_TRIANGLE')[0] faces = faces.data.astype(np.int32) for roi1_idx, roi1 in enumerate(rois[:-1]): roi1_idx_map = roi_map == roi2label[roi1] if np.any(roi1_idx_map): for roi2 in rois[roi1_idx + 1:]: roi2_idx_map = roi_map == roi2label[roi2] if np.any(roi2_idx_map): k = f"{hemi}_{roi1.split('-')[0]}-"\ f"{roi2.split('-')[0]}" if method == 'peak': roi1_max = np.max(activ_map[roi1_idx_map]) roi2_max = np.max(activ_map[roi2_idx_map]) roi1_idx_map =\ np.logical_and(roi1_idx_map, activ_map == roi1_max) roi2_idx_map =\ np.logical_and(roi2_idx_map, activ_map == roi2_max) roi1_vertices = np.where(roi1_idx_map)[0] roi1_vertices = roi1_vertices.astype(np.int32) n_vtx1 = len(roi1_vertices) roi2_vertices = np.where(roi2_idx_map)[0] roi2_vertices = roi2_vertices.astype(np.int32) n_vtx2 = len(roi2_vertices) if n_vtx1 > 1 or n_vtx2 > 1: msg = f'{subj_id}: {roi1} vs {roi2} '\ f'has multiple peaks.' log_lines.append(msg) ds = [] for src_vtx in roi1_vertices: src_vtx = np.array([src_vtx], np.int32) ds_tmp = \ gdist.compute_gdist(coords, faces, src_vtx, roi2_vertices) ds.extend(ds_tmp) out_dict[k][subj_idx] = np.mean(ds) elif n_vtx1 == 1 and n_vtx2 == 1: ds = gdist.compute_gdist( coords, faces, roi1_vertices, roi2_vertices) assert len(ds) == 1 out_dict[k][subj_idx] = ds[0] else: raise RuntimeError("Impossible!") elif method == 'min': roi1_vertices = np.where(roi1_idx_map)[0] roi1_vertices = roi1_vertices.astype(np.int32) roi2_vertices = np.where(roi2_idx_map)[0] roi2_vertices = roi2_vertices.astype(np.int32) ds = gdist.compute_gdist( coords, faces, roi1_vertices, roi2_vertices) out_dict[k][subj_idx] = np.min(ds) else: raise ValueError(f'Not supported method: ' f'{method}') print(f'Finished: {subj_idx+1}/{n_subj}, ' f'cost {time.time()-time1} seconds.') # save out out_df = pd.DataFrame(out_dict) out_df.to_csv(out_file, index=False) out_log = '\n'.join(log_lines) open(log_file, 'w').write(out_log)
def calc_meas_retest(roi_type): """ 用45个被试在test或retest中定出的个体FFA去提取各自在retest的face selectivity。 Args: roi_type (str): ROI-test or ROI-retest """ import time import numpy as np import pandas as pd import nibabel as nib from magicbox.io.io import CiftiReader from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label # inputs hemis = ('lh', 'rh') rois = ('pFus-face', 'mFus-face') subj_file_45 = pjoin(proj_dir, 'data/HCP/wm/analysis_s2/' 'retest/subject_id') subj_file_1080 = pjoin(proj_dir, 'analysis/s2/subject_id') meas_file = '/nfs/m1/hcp/retest/{0}/MNINonLinear/Results/tfMRI_WM/'\ 'tfMRI_WM_hp200_s2_level2_MSMAll.feat/GrayordinatesStats/'\ 'cope20.feat/zstat1.dtseries.nii' roi_type2file = { 'ROI-test': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'rois_v3_{hemi}.nii.gz'), 'ROI-retest': pjoin( proj_dir, 'analysis/s2/1080_fROI/refined_with_Kevin/' 'retest/rois_{hemi}_v2.nii.gz') } roi_file = roi_type2file[roi_type] # outputs out_file = pjoin(work_dir, f'activ-retest_{roi_type}.csv') # prepare subj_ids_45 = open(subj_file_45).read().splitlines() subj_ids_1080 = open(subj_file_1080).read().splitlines() retest_idx_in_1080 = [subj_ids_1080.index(i) for i in subj_ids_45] n_subj = len(subj_ids_45) out_df = pd.DataFrame(index=range(n_subj)) # prepare atlas hemi2atlas = {} for hemi in hemis: atlas = nib.load(roi_file.format(hemi=hemi)).get_fdata().squeeze().T if roi_type == 'ROI-test': hemi2atlas[hemi] = atlas[retest_idx_in_1080] else: hemi2atlas[hemi] = atlas # calculate for idx, subj_id in enumerate(subj_ids_45): time1 = time.time() meas_reader = CiftiReader(meas_file.format(subj_id)) for hemi in hemis: meas_map = meas_reader.get_data(hemi2stru[hemi], True)[0] roi_map = hemi2atlas[hemi][idx] for roi in rois: col = f"{hemi}_{roi.split('-')[0]}" roi_idx_map = roi_map == roi2label[roi] if np.any(roi_idx_map): out_df.loc[idx, col] = np.mean(meas_map[roi_idx_map]) print(f'Finished {idx+1}/{n_subj}: cost {time.time()-time1} seconds') # save out_df.to_csv(out_file, index=False)
def prepare_series(sess=1, run='AP'): import numpy as np import nibabel as nib import pickle as pkl from cxy_hcp_ffa.lib.predefine import hemi2stru, roi2label from magicbox.io.io import CiftiReader # prepare seeds seeds = ('IOG-face', 'pFus-face', 'mFus-face') n_seed = len(seeds) seed_mask_lh_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/' 'refined_with_Kevin/MPM_v3_lh_0.25.nii.gz') seed_mask_rh_file = pjoin( proj_dir, 'analysis/s2/1080_fROI/' 'refined_with_Kevin/MPM_v3_rh_0.25.nii.gz') hemi2seed_mask = { 'lh': nib.load(seed_mask_lh_file).get_fdata().squeeze(), 'rh': nib.load(seed_mask_rh_file).get_fdata().squeeze() } # prepare targets trg_file = '/nfs/p1/atlases/multimodal_glasser/surface/'\ 'MMP_mpmLR32k.dlabel.nii' trg_reader = CiftiReader(trg_file) hemi2trg_mask = { 'lh': trg_reader.get_data(hemi2stru['lh'], True).squeeze(), 'rh': trg_reader.get_data(hemi2stru['rh'], True).squeeze() } trg_labels = np.unique(np.r_[hemi2trg_mask['lh'], hemi2trg_mask['rh']]) trg_labels = trg_labels[trg_labels != 0].astype(int).tolist() n_trg = len(trg_labels) # prepare series dictionary subj_id_file = pjoin(work_dir, 'rfMRI_REST_4run_id') subj_ids = open(subj_id_file).read().splitlines() n_subj = len(subj_ids) n_tp = 478 # the number of time points seed_lh_dict = { 'shape': 'n_subject x n_seed x n_time_point', 'subject': subj_ids, 'seed': seeds, 'rfMRI': np.ones((n_subj, n_seed, n_tp)) * np.nan } seed_rh_dict = { 'shape': 'n_subject x n_seed x n_time_point', 'subject': subj_ids, 'seed': seeds, 'rfMRI': np.ones((n_subj, n_seed, n_tp)) * np.nan } hemi2seed_dict = {'lh': seed_lh_dict, 'rh': seed_rh_dict} trg_dict = { 'shape': 'n_subject x n_target x n_time_point', 'subject': subj_ids, 'trg_label': trg_labels, 'rfMRI': np.ones((n_subj, n_trg, n_tp)) * np.nan } global_dict = { 'shape': 'n_subject x n_global x n_time_point', 'subject': subj_ids, 'global': ['lr', 'lh', 'rh'], 'rfMRI': np.ones((n_subj, 3, n_tp)) * np.nan } # prepare outputs out_seed_lh = pjoin(work_dir, f'rfMRI{sess}_{run}_MPM_lh.pkl') out_seed_rh = pjoin(work_dir, f'rfMRI{sess}_{run}_MPM_rh.pkl') out_trg = pjoin(work_dir, f'rfMRI{sess}_{run}_MMP.pkl') out_global = pjoin(work_dir, f'rfMRI{sess}_{run}_global.pkl') # start maps_files = '/nfs/e1/HCPD/fmriresults01/{0}/MNINonLinear/'\ 'Results/rfMRI_REST{1}_{2}/'\ 'rfMRI_REST{1}_{2}_Atlas_MSMAll_hp0_clean.dtseries.nii' for subj_idx, subj_id in enumerate(subj_ids): print('Progress: {}/{}'.format(subj_idx + 1, n_subj)) # prepare maps maps_file = maps_files.format(f'{subj_id}_V1_MR', sess, run) maps_reader = CiftiReader(maps_file) hemi2maps = { 'lh': maps_reader.get_data(hemi2stru['lh'], True), 'rh': maps_reader.get_data(hemi2stru['rh'], True) } for hemi in ['lh', 'rh']: maps = hemi2maps[hemi] # seed dict seed_mask = hemi2seed_mask[hemi] for seed_idx, seed in enumerate(seeds): lbl = roi2label[seed] hemi2seed_dict[hemi]['rfMRI'][subj_idx, seed_idx] =\ np.mean(maps[:, seed_mask == lbl], 1) # target dict trg_mask = hemi2trg_mask[hemi] tmp_labels = np.unique(trg_mask) tmp_labels = tmp_labels[tmp_labels != 0].astype(int) for lbl in tmp_labels: trg_idx = trg_labels.index(lbl) trg_dict['rfMRI'][subj_idx, trg_idx] =\ np.mean(maps[:, trg_mask == lbl], 1) # global dict global_idx = global_dict['global'].index(hemi) global_dict['rfMRI'][subj_idx, global_idx] = np.mean(maps, 1) maps = np.c_[hemi2maps['lh'], hemi2maps['rh']] global_idx = global_dict['global'].index('lr') global_dict['rfMRI'][subj_idx, global_idx] = np.mean(maps, 1) del maps pkl.dump(hemi2seed_dict['lh'], open(out_seed_lh, 'wb')) pkl.dump(hemi2seed_dict['rh'], open(out_seed_rh, 'wb')) pkl.dump(trg_dict, open(out_trg, 'wb')) pkl.dump(global_dict, open(out_global, 'wb'))