Skip to content

Commit

Permalink
Structural longitudinal pipelines (#295)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmilch01 authored Oct 23, 2024
1 parent e1eafb1 commit 3f8a8a3
Show file tree
Hide file tree
Showing 27 changed files with 2,534 additions and 626 deletions.
Empty file modified .gitignore
100755 → 100644
Empty file.
139 changes: 139 additions & 0 deletions Examples/Scripts/FreeSurferPipelineBatch-long.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/bin/bash

command_line_specified_run_local=FALSE
while [ -n "$1" ]; do
case "$1" in
--runlocal) shift; command_line_specified_run_local=TRUE ;;
*) shift ;;
esac
done

#################################################################################################
# General input variables
##################################################################################################
#Location of Subject folders (named by subjectID)
StudyFolder="/my/study/path"
#The list of subject labels, space separated
Subjects=(HCA6002236 HCA6002237 HCA6002238)
#The list of possible visits (aka timepoints, sessions) that each subject may have. Timepoint directories should be named <Subject>_<Visit>.
PossibleVisits=(V1_MR V2_MR V3_MR)
#The list of possible visits that each subject may have. Timepoint (visit) is expected to be named <Subject>_<Visit>.
#Actual visits (timepoints) are determined based on existing directories that match the visit name pattern.
#ExcludeVisits=(HCA6002237_V1_MR HCA6002238_V1_MR)
ExcludeVisits=()
#Longitudinal template labels, one per each subject.
Templates=(HCA6002236_V1_V2 HCA6002237_V1_V2 HCA6002238_V1_V2)

EnvironmentScript="<HCPInstallDir>/scripts/SetUpHCPPipeline.sh" #Pipeline environment script

# Requirements for this script
# installed versions of: FSL, FreeSurfer, Connectome Workbench (wb_command), gradunwarp (HCP version)
# environment: HCPPIPEDIR, FSLDIR, FREESURFER_HOME, CARET7DIR, PATH for gradient_unwarp.py

# If you want to use FreeSurfer 5.3, change the ${queuing_command} line below to use
# ${HCPPIPEDIR}/FreeSurfer/FreeSurferPipeline-v5.3.0-HCP.sh

#Set up pipeline environment variables and software
source "$EnvironmentScript"

# Log the originating call
echo "$@"

#NOTE: syntax for QUEUE has changed compared to earlier pipeline releases,
#DO NOT include "-q " at the beginning
#default to no queue, implying run local
QUEUE="long.q"
#QUEUE="hcp_priority.q"

#parallel options
parallel_mode=BUILTIN

# This setting is for BUILTIN mode. Set to -1 to auto-detect the # of CPU cores on the node where each per-subject job is run.
# Note that in case when multiple subject jobs are run on the same node and are submitted
# in parallel by e.g. fsl_sub, max_jobs should be set manually to not significantly exceed
# (number of available cores)/(number of subjects) in the batch.
max_jobs=-1
#max_jobs=4

#TEMPLATE stage must be run before TIMEPOINTS stage
start_stage=TEMPLATE
end_stage=TIMEPOINTS

#Processing goes here.
function identify_timepoints
{
local subject=$1
local tplist=""
local tp visit n

#build the list of timepoints (sessions)
n=0
for session in ${PossibleVisits[*]}; do
tp="${subject}_${session}"
if [ -d "$StudyFolder/$tp" ] && ! [[ " ${ExcludeVisits[*]+${ExcludeVisits[*]}} " =~ [[:space:]]"$tp"[[:space:]] ]]; then
if (( n==0 )); then
tplist="$tp"
else
tplist="$tplist@$tp"
fi
fi
((n++))
done
echo $tplist
}

########################################## INPUTS ##########################################
#Scripts called by this script do assume they run on the outputs of the PreFreeSurfer Pipeline
######################################### DO WORK ##########################################

for i in ${!Subjects[@]}; do
Subject=${Subjects[i]}
#Subject's time point list, @ separated.
TPlist=(`identify_timepoints $Subject`)
#Array with timepoints
IFS=@ read -ra Timepoints <<< "$TPlist"
#Freesurfer longitudinal average template label
LongitudinalTemplate=${Templates[i]}

#Longitudinal FreeSurfer Input Variables
SubjectID="$Subject" #FreeSurfer Subject ID Name
SubjectDIR="${StudyFolder}/${Subject}/T1w" #Location to Put FreeSurfer Subject's Folder
T1wImage="${StudyFolder}/${Subject}/T1w/T1w_acpc_dc_restore.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T1wImageBrain="${StudyFolder}/${Subject}/T1w/T1w_acpc_dc_restore_brain.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T2wImage="${StudyFolder}/${Subject}/T1w/T2w_acpc_dc_restore.nii.gz" #T2w FreeSurfer Input (Full Resolution)

if [ "$parallel_mode" != FSLSUB ]; then #fsl_sub does not allow nested submissions
if [[ "${command_line_specified_run_local}" == "TRUE" || "$QUEUE" == "" ]] ; then
echo "About to locally run ${HCPPIPEDIR}/FreeSurfer/LongitudinalFreeSurferPipeline.sh"
#NOTE: fsl_sub without -q runs locally and captures output in files
queuing_command=("$FSLDIR/bin/fsl_sub")
else
echo "About to use fsl_sub to queue ${HCPPIPEDIR}/FreeSurfer/LongitudinalFreeSurferPipeline.sh"
queuing_command=("$FSLDIR/bin/fsl_sub" -q "$QUEUE")
fi
else
queuing_command=()
fi

#DO NOT PUT timepoint-specific options here!!!
cmd=(${queuing_command[@]+"${queuing_command[@]}"} "$HCPPIPEDIR"/FreeSurfer/LongitudinalFreeSurferPipeline.sh \
--subject="$Subject" \
--path="$StudyFolder" \
--sessions="$TPlist" \
--fslsub-queue="$QUEUE" \
--longitudinal-template="$LongitudinalTemplate" \
--parallel-mode="$parallel_mode" \
--max-jobs="$max_jobs" \
--start-stage="$start_stage" \
--end-stage="$end_stage" \
)

#--extra-reconall-arg-base=-conf2hires Freesurfer reports this is unneeded.
echo "Running command: ${cmd[*]}"
"${cmd[@]}"

# The following lines are used for interactive debugging to set the positional parameters: $1 $2 $3 ...
# echo set --subject=$Subject --subjectDIR=$SubjectDIR --t1=$T1wImage --t1brain=$T1wImageBrain --t2=$T2wImage --extra-reconall-arg-long="-i \"$SubjectDIR\"/T1w/T1w_acpc_dc_restore.nii.gz -emregmask \"$SubjectDIR\"/T1w/T1w_acpc_dc_restore_brain.nii.gz -T2 $SubjectDIR\"/T1w/T2w_acpc_dc_restore.nii.gz -T2pial"
#echo ". ${EnvironmentScript}"

done
40 changes: 22 additions & 18 deletions Examples/Scripts/FreeSurferPipelineBatch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ get_batch_options() {
local arguments=("$@")

command_line_specified_study_folder=""
command_line_specified_subj=""
command_line_specified_session=""
command_line_specified_run_local="FALSE"

local index=0
Expand All @@ -19,8 +19,12 @@ get_batch_options() {
command_line_specified_study_folder=${argument#*=}
index=$(( index + 1 ))
;;
--Subject=*)
command_line_specified_subj=${argument#*=}
--Subject=*) #legacy option, please use '--Session' instead
command_line_specified_session=${argument#*=}
index=$(( index + 1 ))
;;
--Session=*)
command_line_specified_session=${argument#*=}
index=$(( index + 1 ))
;;
--runlocal)
Expand All @@ -39,16 +43,16 @@ get_batch_options() {

get_batch_options "$@"

StudyFolder="${HOME}/projects/Pipelines_ExampleData" #Location of Subject folders (named by subjectID)
Subjlist="100307 100610" #Space delimited list of subject IDs
StudyFolder="${HOME}/projects/Pipelines_ExampleData" #Location of Session folders (named by sessionID)
Sessionlist="100307 100610" #Space delimited list of session IDs
EnvironmentScript="${HOME}/projects/Pipelines/Examples/Scripts/SetUpHCPPipeline.sh" #Pipeline environment script

if [ -n "${command_line_specified_study_folder}" ]; then
StudyFolder="${command_line_specified_study_folder}"
fi

if [ -n "${command_line_specified_subj}" ]; then
Subjlist="${command_line_specified_subj}"
if [ -n "${command_line_specified_session}" ]; then
Sessionlist="${command_line_specified_session}"
fi

# Requirements for this script
Expand Down Expand Up @@ -76,15 +80,15 @@ QUEUE=""

######################################### DO WORK ##########################################

for Subject in $Subjlist ; do
echo $Subject
for Session in $Sessionlist ; do
echo $Session

#Input Variables
SubjectID="$Subject" #FreeSurfer Subject ID Name
SubjectDIR="${StudyFolder}/${Subject}/T1w" #Location to Put FreeSurfer Subject's Folder
T1wImage="${StudyFolder}/${Subject}/T1w/T1w_acpc_dc_restore.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T1wImageBrain="${StudyFolder}/${Subject}/T1w/T1w_acpc_dc_restore_brain.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T2wImage="${StudyFolder}/${Subject}/T1w/T2w_acpc_dc_restore.nii.gz" #T2w FreeSurfer Input (Full Resolution)
SessionID="$Session" #FreeSurfer Subject ID Name
SessionDIR="${StudyFolder}/${Session}/T1w" #Location to Put FreeSurfer Subject's Folder
T1wImage="${StudyFolder}/${Session}/T1w/T1w_acpc_dc_restore.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T1wImageBrain="${StudyFolder}/${Session}/T1w/T1w_acpc_dc_restore_brain.nii.gz" #T1w FreeSurfer Input (Full Resolution)
T2wImage="${StudyFolder}/${Session}/T1w/T2w_acpc_dc_restore.nii.gz" #T2w FreeSurfer Input (Full Resolution)

if [[ "${command_line_specified_run_local}" == "TRUE" || "$QUEUE" == "" ]] ; then
echo "About to locally run ${HCPPIPEDIR}/FreeSurfer/FreeSurferPipeline.sh"
Expand All @@ -95,16 +99,16 @@ for Subject in $Subjlist ; do
fi

"${queuing_command[@]}" "$HCPPIPEDIR"/FreeSurfer/FreeSurferPipeline.sh \
--subject="$Subject" \
--subject-dir="$SubjectDIR" \
--session="$Session" \
--session-dir="$SessionDIR" \
--t1w-image="$T1wImage" \
--t1w-brain="$T1wImageBrain" \
--t2w-image="$T2wImage"

# The following lines are used for interactive debugging to set the positional parameters: $1 $2 $3 ...

echo "set -- --subject=$Subject \
--subject-dir=$SubjectDIR \
echo "set -- --session=$Session \
--session-dir=$SessionDIR \
--t1w-image=$T1wImage \
--t1w-brain=$T1wImageBrain \
--t2w-image=$T2wImage"
Expand Down
169 changes: 169 additions & 0 deletions Examples/Scripts/PostFreeSurferPipelineBatch-long.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/bin/bash

command_line_specified_run_local=FALSE
while [ -n "$1" ]; do
case "$1" in
--runlocal) shift; command_line_specified_run_local=TRUE ;;
*) shift ;;
esac
done

#################################################################################################
# General input variables
##################################################################################################
#Location of Subject folders (named by subjectID)
StudyFolder="<MyStudyPath>"
#The list of subject labels, space separated
Subjects=(HCA6002236 HCA6002237 HCA6002238)
#The list of possible visits that each subject may have. Timepoint (visit) is expected to be named <Subject>_<Visit>.
PossibleVisits=(V1_MR V2_MR V3_MR)
#Actual visits (timepoints) are determined based on existing directories that match the visit name pattern <Subject>_<visit>.
#Excluded timepoint directories
#ExcludeVisits=(HCA6002237_V1_MR HCA6002238_V1_MR)
ExcludeVisits=()
#Longitudinal template labels, one per each subject.
Templates=(HCA6002236_V1_V2 HCA6002237_V1_V2 HCA6002238_V1_V2)
#EnvironmentScript="${HOME}/projects/HCPPipelines/Examples/Scripts/SetUpHCPPipeline.sh" #Pipeline environment script
EnvironmentScript="${HOME}/projects/HCPPipelines/Examples/Scripts/SetUpHCPPipeline.sh"
source "$EnvironmentScript"

##################################################################################################
# Input variables used by PostFreeSurferPipelineLongPrep
##################################################################################################
# Hires T1w MNI template
T1wTemplate="${HCPPIPEDIR_Templates}/MNI152_T1_0.8mm.nii.gz"
# Hires brain extracted MNI template1
T1wTemplateBrain="${HCPPIPEDIR_Templates}/MNI152_T1_0.8mm_brain.nii.gz"
# Lowres T1w MNI template
T1wTemplate2mm="${HCPPIPEDIR_Templates}/MNI152_T1_2mm.nii.gz"
# Hires T2w MNI Template
T2wTemplate="${HCPPIPEDIR_Templates}/MNI152_T2_0.8mm.nii.gz"
# Hires T2w brain extracted MNI Template
T2wTemplateBrain="${HCPPIPEDIR_Templates}/MNI152_T2_0.8mm_brain.nii.gz"
# Lowres T2w MNI Template
T2wTemplate2mm="${HCPPIPEDIR_Templates}/MNI152_T2_2mm.nii.gz"
# Hires MNI brain mask template
TemplateMask="${HCPPIPEDIR_Templates}/MNI152_T1_0.8mm_brain_mask.nii.gz"
# Lowres MNI brain mask template
Template2mmMask="${HCPPIPEDIR_Templates}/MNI152_T1_2mm_brain_mask_dil.nii.gz"
# FNIRT 2mm T1w Config
FNIRTConfig="${HCPPIPEDIR_Config}/T1_2_MNI152_2mm.cnf"

##################################################################################################
# Input variables used by PostFreesurferPipeline (longitudinal mode)
##################################################################################################
SurfaceAtlasDIR="${HCPPIPEDIR_Templates}/standard_mesh_atlases"
GrayordinatesSpaceDIR="${HCPPIPEDIR_Templates}/91282_Greyordinates"
GrayordinatesResolutions="2" #Usually 2mm, if multiple delimit with @, must already exist in templates dir
HighResMesh="164" #Usually 164k vertices
LowResMeshes="32" #Usually 32k vertices, if multiple delimit with @, must already exist in templates dir
SubcorticalGrayLabels="${HCPPIPEDIR_Config}/FreeSurferSubcorticalLabelTableLut.txt"
FreeSurferLabels="${HCPPIPEDIR_Config}/FreeSurferAllLut.txt"
ReferenceMyelinMaps="${HCPPIPEDIR_Templates}/standard_mesh_atlases/Conte69.MyelinMap_BC.164k_fs_LR.dscalar.nii"
RegName="MSMSulc" #MSMSulc is recommended, if binary is not available use FS (FreeSurfer)

# Requirements for this script
# installed versions of: FSL, Connectome Workbench (wb_command)
# environment: HCPPIPEDIR, FSLDIR, CARET7DIR

#fslsub queue
#QUEUE=short.q
#top level parallelization

QUEUE="long.q"

#pipeline level parallelization
#parallel mode: FSLSUB, BUILTIN, NONE
parallel_mode=BUILTIN

if [ "$parallel_mode" != FSLSUB ]; then #fsl_sub does not allow nested submissions
if [[ "${command_line_specified_run_local}" == "TRUE" || "$QUEUE" == "" ]] ; then
echo "About to locally run ${HCPPIPEDIR}/PostFreeSurfer/PostFreeSurferPipelineLongLauncher.sh"
# #NOTE: fsl_sub without -q runs locally and captures output in files
queuing_command=("$FSLDIR/bin/fsl_sub")
QUEUE=long.q
else
echo "About to use fsl_sub to queue ${HCPPIPEDIR}/FreeSurfer/PostFreeSurferPipelineLongLauncher.sh"
queuing_command=("$FSLDIR/bin/fsl_sub" -q "$QUEUE")
QUEUE=""
fi
else
queuing_command=""
fi
# This setting is for BUILTIN mode. Set to -1 to auto-detect the # of CPU cores on the node where each per-subject job is run.
# Note that in case when multiple subject jobs are run on the same node and are submitted
# in parallel by e.g. fsl_sub, it may be inefficient to have the
# (number of fsl_sub jobs running per node) * (BUILTIN parallelism) substantially exceed
# the number of cores per node
max_jobs=-1
#max_jobs=4

# Stages to run. Must be run in the following order:
# 1. PREP-TP, 2.PREP-T, 3. POSTFS-TP1, 4. POSTFS-T, 5. POSTFS-TP2
start_stage=PREP-TP
end_stage=POSTFS-TP2


function identify_timepoints
{
local subject=$1
local tplist=""
local tp visit n

#build the list of timepoints
n=0
for visit in ${PossibleVisits[*]}; do
tp="${subject}_${visit}"
if [ -d "$StudyFolder/$tp" ] && ! [[ " ${ExcludeVisits[*]+${ExcludeVisits[*]}} " =~ [[:space:]]"$tp"[[:space:]] ]]; then
if (( n==0 )); then
tplist="$tp"
else
tplist="$tplist@$tp"
fi
fi
((n++))
done
echo $tplist
}

#iterate over all subjects.
for i in ${!Subjects[@]}; do
Subject=${Subjects[i]}
LongitudinalTemplate=${Templates[i]}
Timepoint_list=(`identify_timepoints $Subject`)

echo Subject: $Subject
echo Template: $LongitudinalTemplate
echo Timepoints: $Timepoint_list

cmd=(${queuing_command[@]+"${queuing_command[@]}"} ${HCPPIPEDIR}/PostFreeSurfer/PostFreeSurferPipelineLongLauncher.sh \
--study-folder="$StudyFolder" \
--subject="$Subject" \
--longitudinal-template="$LongitudinalTemplate" \
--sessions="$Timepoint_list" \
--parallel-mode=$parallel_mode \
--fslsub-queue=$QUEUE \
--start-stage=$start_stage \
--end-stage=$end_stage \
--t1template="$T1wTemplate" \
--t1templatebrain="$T1wTemplateBrain" \
--t1template2mm="$T1wTemplate2mm" \
--t2template="$T2wTemplate" \
--t2templatebrain="$T2wTemplateBrain" \
--t2template2mm="$T2wTemplate2mm" \
--templatemask="$TemplateMask" \
--template2mmmask="$Template2mmMask" \
--fnirtconfig="$FNIRTConfig" \
--freesurferlabels="$FreeSurferLabels" \
--surfatlasdir="$SurfaceAtlasDIR" \
--grayordinatesres="$GrayordinatesResolutions" \
--grayordinatesdir="$GrayordinatesSpaceDIR" \
--hiresmesh="$HighResMesh" \
--lowresmesh="$LowResMeshes" \
--subcortgraylabels="$SubcorticalGrayLabels" \
--refmyelinmaps="$ReferenceMyelinMaps" \
--regname="$RegName" \
)
echo "Running $cmd"
"${cmd[@]}"
done
Loading

0 comments on commit 3f8a8a3

Please sign in to comment.