|
| 1 | + |
| 2 | +######################################################################################################## |
| 3 | +######################################################################################################## |
| 4 | + |
| 5 | +#' @title CIFTItoFC_concat_ses |
| 6 | +#' |
| 7 | +#' @description Extracting FC matrices from CIFTI files, concatenating runs within each session |
| 8 | +#' |
| 9 | +#' @details This function extracts FC matrices from CIFTI volumes postprocessed with XCP_d |
| 10 | +#' |
| 11 | +#' @param wb_path The filepath to the workbench folder that you have previously downloaded and unzipped. Set to `/home/junhong.yu/workbench/bin_rh_linux64` by default |
| 12 | +#' @param path The filepath to directory containing the subject folders. Set to `./.` by default. |
| 13 | +#' @param atlas The version (number of parcels) of the Schaefer atlas; it has to be in multiples of 100, from 100 to 1000. set to `200` by default. The specified atlas template will be automatically downloaded from here if it does not exist in the current directory. |
| 14 | +#' @param dtseries The filename extension of the fMRI volumes. Set to `_space-fsLR_den-91k_desc-denoised_bold.dtseries.nii` by default |
| 15 | +#' @param timeseries If set to `TRUE`, FC matrices will not be computed, instead the parcellated timeseries will be return in a list format, where each subject's parcellated timeseries data is contained within a list element. Set to `FALSE` by default. |
| 16 | +#' @param filename Filename of the concatenated FC vector file. Set to `FC.rds` by default |
| 17 | +#' @returns outputs N (number of subjects) x E (number of unique) matrices as a .rds file |
| 18 | +#' |
| 19 | +#' @examples |
| 20 | +#' \dontrun{ |
| 21 | +#' CIFTItoFC_concatses(dtseries="_task-rest_run-00._space-fsLR_den-91k_desc-denoised_bold.dtseries.nii", atlas=200, filename="PREVENTAD_stage1_rsFC.rds") |
| 22 | +#' } |
| 23 | +#' @importFrom stringr str_detect |
| 24 | +#' @importFrom ciftiTools ciftiTools.setOption read_cifti read_xifti newdata_xifti move_from_mwall |
| 25 | +#' @importFrom psych fisherz |
| 26 | +#' @export |
| 27 | + |
| 28 | +######################################################################################################## |
| 29 | +######################################################################################################## |
| 30 | +CIFTItoFC_concat_ses=function(path="./",wb_path="/home/junhong.yu/workbench/bin_rh_linux64", dtseries="_space-fsLR_den-91k_desc-denoised_bold.dtseries.nii", timeseries=F, atlas=200,filename="FC.rds") |
| 31 | +{ |
| 32 | + filelist=list.files(path=path,pattern=dtseries,recursive = T) |
| 33 | + sublist=unique(gsub(pattern ="/ses-.*/func",replacement = "",dirname(filelist))) |
| 34 | + |
| 35 | + ##load and configure ciftitools |
| 36 | + ciftiTools::ciftiTools.setOption('wb_path', wb_path) |
| 37 | + |
| 38 | + ##atlas checks |
| 39 | + if(is.na(match(atlas,(1:10)*100))) {stop("\nAtlas should be a multiple of 100 from 100 to 1000")} |
| 40 | + #download atlas template if it is missing |
| 41 | + if(!file.exists(paste(system.file(package='FCtools'),"/data/Schaefer2018_",atlas,"Parcels_7Networks_order.dlabel.nii",sep=""))) |
| 42 | + { |
| 43 | + cat(paste("\nThe",paste("Schaefer2018_",atlas,"Parcels_7Networks_order.dlabel.nii",sep=""),"template file does not exist and will be downloaded\n"),sep=" ") |
| 44 | + download.file(url=paste0("https://raw.githubusercontent.com/ThomasYeoLab/CBIG/master/stable_projects/brain_parcellation/Schaefer2018_LocalGlobal/Parcellations/HCP/fslr32k/cifti/Schaefer2018_",atlas,"Parcels_7Networks_order.dlabel.nii"), |
| 45 | + destfile =paste(system.file(package='FCtools'),"/data/Schaefer2018_",atlas,"Parcels_7Networks_order.dlabel.nii",sep=""),mode = "wb") |
| 46 | + |
| 47 | + } |
| 48 | + parc=c(as.matrix(ciftiTools::read_cifti(paste(system.file(package='FCtools'),"/data/Schaefer2018_",atlas,"Parcels_7Networks_order.dlabel.nii",sep=""),brainstructures=c("left","right")))) |
| 49 | + |
| 50 | + ## defining subcortical parcel indices for reordering ROIs subsequently |
| 51 | + reorder.subcortical.idx=c(9,18,8,17,6,3,13,1,11,10,19,7,16,5,15,4,14,2,12)+atlas |
| 52 | + |
| 53 | + if(timeseries==F) |
| 54 | + { |
| 55 | + all_FC=matrix(NA,nrow=length(sublist),ncol=(((atlas+19)^2)-(atlas+19))/2) |
| 56 | + } else if(timeseries==T) |
| 57 | + { |
| 58 | + all_TS=list() |
| 59 | + } |
| 60 | + |
| 61 | + count=1 |
| 62 | + |
| 63 | + for (sub in 1:length(sublist)) |
| 64 | + { |
| 65 | + |
| 66 | + filelist.sub=filelist[stringr::str_detect(pattern=sublist[sub],string=filelist)] |
| 67 | + sessions=list.files(path=paste0(sublist[sub],"/"),pattern="ses") |
| 68 | + |
| 69 | + for (session in 1: length(sessions)) |
| 70 | + { |
| 71 | + |
| 72 | + filelist.sub.session=filelist.sub[stringr::str_detect(pattern=sessions[session],string=filelist.sub)] |
| 73 | + if(length(filelist.sub.session)>0) |
| 74 | + { |
| 75 | + start=Sys.time() |
| 76 | + cat(paste0("processing ",sublist[sub],"_",sessions[session]," (",sub," / ",length(sublist),")...")) |
| 77 | + for (scan in 1:length(filelist.sub.session)) |
| 78 | + { |
| 79 | + if(scan==1) |
| 80 | + { |
| 81 | + xii0=ciftiTools::read_xifti(paste0(path,"/",filelist.sub.session[scan]), brainstructures="all") |
| 82 | + xii=scale(as.matrix(xii0)) |
| 83 | + if(sum(colSums(xii)==0)!=0) |
| 84 | + { |
| 85 | + cat(paste0("WARNING: ",filelist.sub.session[scan]," contains column(s) with entirely 0 values\n")) |
| 86 | + } |
| 87 | + } |
| 88 | + else |
| 89 | + { |
| 90 | + xii=cbind(scale(as.matrix(ciftiTools::read_xifti(paste0(path,"/",filelist.sub.session[scan]), brainstructures="all"))),xii) |
| 91 | + if(sum(colSums(xii)==0)!=0) |
| 92 | + { |
| 93 | + cat(paste0("WARNING: ",filelist.sub.session[scan]," contains column(s) with entirely 0 values\n")) |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + if(length(filelist.sub.session)==1) |
| 98 | + { |
| 99 | + xii.final=xii0 |
| 100 | + timeseries.dat=as.matrix(ciftiTools::move_from_mwall(xii0, NA)) |
| 101 | + } else |
| 102 | + { |
| 103 | + xii.final=ciftiTools::newdata_xifti(xii0, xii) |
| 104 | + timeseries.dat=as.matrix(ciftiTools::move_from_mwall(xii.final, NA)) |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + ##generate parcellated timeseries |
| 109 | + sub_keys=as.numeric(xii.final$meta$subcort$labels) - 2 +atlas |
| 110 | + brain_vec=c(parc, sub_keys) |
| 111 | + |
| 112 | + xii_pmean=matrix(ncol=atlas+19,nrow=ncol(xii)) |
| 113 | + |
| 114 | + for (p in 1:(atlas+19)) |
| 115 | + { |
| 116 | + xii_pmean[,p]=colMeans(timeseries.dat[which(brain_vec==p),],na.rm = T) |
| 117 | + } |
| 118 | + #reorder parcel indices for visualization purpose |
| 119 | + xii_pmean=xii_pmean[,c(1:atlas,reorder.subcortical.idx)] |
| 120 | + |
| 121 | + if(count==1) |
| 122 | + { |
| 123 | + sub.sess=paste0(sublist[sub],"_",sessions[session]) |
| 124 | + if(timeseries==F) |
| 125 | + { |
| 126 | + FCmat=cor(xii_pmean) |
| 127 | + all_FC=FCmat[upper.tri(FCmat,diag=F)] |
| 128 | + remove(FCmat) |
| 129 | + } else if(timeseries==T) |
| 130 | + { |
| 131 | + all_TS[[sub]]=xii_pmean |
| 132 | + } |
| 133 | + } else |
| 134 | + { |
| 135 | + sub.sess=c(sub.sess,paste0(sublist[sub],"_",sessions[session])) |
| 136 | + if(timeseries==F) |
| 137 | + { |
| 138 | + FCmat=cor(xii_pmean) |
| 139 | + all_FC=rbind(all_FC,FCmat[upper.tri(FCmat,diag=F)]) |
| 140 | + remove(FCmat) |
| 141 | + } else if(timeseries==T) |
| 142 | + { |
| 143 | + all_TS[[sub]]=xii_pmean |
| 144 | + } |
| 145 | + } |
| 146 | + ##clean temp dir |
| 147 | + files_to_remove=list.files(tempdir(), full.names = TRUE) |
| 148 | + removedfiles=file.remove(files_to_remove) |
| 149 | + count=count+1 |
| 150 | + end=Sys.time() |
| 151 | + cat(paste0(" Completed in ", round(difftime(end,start, units="secs"),1),"s\n")) |
| 152 | + remove(xii, xii0, xii.final, xii_pmean, timeseries.dat,filelist.sub.session, start,end,removedfiles) |
| 153 | + } |
| 154 | + } |
| 155 | + remove(filelist.sub) |
| 156 | + } |
| 157 | + cat(paste0("Saving ", filename," ...")) |
| 158 | + |
| 159 | + if(timeseries==F) |
| 160 | + { |
| 161 | + saveRDS(list(sublist,psych::fisherz(all_FC)),file=filename) |
| 162 | + } else if(timeseries==T) |
| 163 | + { |
| 164 | + saveRDS(list(sub.sess,all_TS),file=filename) |
| 165 | + } |
| 166 | + |
| 167 | +} |
| 168 | + |
0 commit comments