diff --git a/long_fastsurfer.sh b/long_fastsurfer.sh index ef27a4f2..a4d4133f 100755 --- a/long_fastsurfer.sh +++ b/long_fastsurfer.sh @@ -165,6 +165,7 @@ case $key in --parallel_long) parallel=1 ;; --py) python="$1" ; shift ;; -h|--help) usage ; exit ;; + --remove_suffix) echo "ERROR: The --remove_suffix option is not supported by long_prepare_template.sh" ; exit 1 ;; --sid|--t1|--t2) echo "ERROR: --sid, --t1 and --t2 are not valid for long_fastsurfer.sh, these values are" echo " populated via --tpids, --tid and --t1s, respectively." diff --git a/recon_surf/functions.sh b/recon_surf/functions.sh index 20c0f895..9040d1b4 100644 --- a/recon_surf/functions.sh +++ b/recon_surf/functions.sh @@ -190,4 +190,17 @@ function echo_quoted() sep=" " done echo "" -} \ No newline at end of file +} + +function check_is_template() +{ + # params: + # 1: subjects_dir + # 2: subject_if + if [ ! -f "$1/$2/base-tps.fastsurfer" ] ; then + echo "ERROR: $2 is either not found in \$SUBJECTS_DIR or it is not a longitudinal template" + echo " directory (base), which needs to contain base-tps.fastsurfer file. Please ensure that" + echo " the base (template) has been created with long_prepare_template.sh." + exit 1 + fi +} diff --git a/recon_surf/long_prepare_template.sh b/recon_surf/long_prepare_template.sh index 632ce598..22a4a421 100755 --- a/recon_surf/long_prepare_template.sh +++ b/recon_surf/long_prepare_template.sh @@ -68,11 +68,7 @@ interpol="cubic" # for the final interpolation of all time points in median i robust_template_avg_arg=1 # median for template creation (if more than 1 time point) # default arguments -batch_size=1 -device="auto" -viewagg="auto" python="python3.10 -s" # avoid user-directory package inclusion -vox_size="min" sd="$SUBJECTS_DIR" # init variables that need to be passed @@ -154,6 +150,7 @@ fi # PARSE Command line inputargs=("$@") POSITIONAL_FASTSURFER=() +run_pred_flags=() i=0 while [[ $# -gt 0 ]] do @@ -179,23 +176,18 @@ case $key in done ;; --sd) sd="$1" ; export SUBJECTS_DIR="$1" ; shift ;; - --vox_size) vox_size="$1" ; shift ;; + # these flags are passed through to run_prediction.py + --vox_size|--device|--viewagg_device|--conform_to_1mm_threshold|--threads) + run_pred_flags+=("$key" "$1") ; shift ;; + --batch) run_pred_flags+=("--batch_size" "$1") ; shift ;; + # these known arguments get ignored + --aseg_name|--conformed_name|--asegdkt_segfile|--brainmask_name|--seg_log|--qc_log) shift ;; + --async_io) ;; + --fs_license) export FS_LICENSE="$1" ; shift ;; + --remove_suffix) echo "ERROR: The --remove_suffix option is not supported by long_prepare_template.sh" ; exit 1 ;; -h|--help) usage ; exit ;; --py) python="$1" ; shift ;; - --device) device="$1" ; shift ;; - --batch) batch_size="$1" ; shift ;; - --viewagg_device) - case "$1" in - check) - echo "WARNING: the option \"check\" is deprecated for --viewagg_device , use \"auto\"." - viewagg="auto" - ;; - gpu) viewagg="cuda" ;; - *) viewagg="$1" ;; - esac - shift # past value - ;; - *) # unknown options get forwarded to run_fastsurfer (or ignored) + *) # unknown options also get ignored, but also print warnings POSITIONAL_FASTSURFER[i]="$arg" i=$((i + 1)) ;; @@ -209,28 +201,34 @@ done ################################## CHECKS ############################## +if [[ "${#POSITIONAL_FASTSURFER[@]}" -gt 0 ]] +then + echo "WARNING: The arguments ${POSITIONAL_FASTSURFER[*]}" + echo " are not recognized and therefore ignored!" +fi + if [ "${#t1s[@]}" -lt 1 ] then - echo "ERROR: must supply T1 inputs (full head) via --t1s" + echo "ERROR: You must supply T1 inputs (full head) via --t1s!" exit 1 fi if [ "${#tpids[@]}" -lt 1 ] then - echo "ERROR: must supply time points ids via --tpids" + echo "ERROR: You must supply time points ids via --tpids!" exit 1 fi if [ -z "$tid" ] then - echo "ERROR: must supply subject template name via --tid" + echo "ERROR: You must supply subject template name via --tid!" exit 1 fi # check that t1s list is same length as tpids if [ "${#tpids[@]}" -ne "${#t1s[@]}" ] then - echo "ERROR: length of tpids must equal t1s" + echo "ERROR: The length of tpids must equal t1s!" exit 1 fi @@ -247,8 +245,9 @@ then fi if [[ "$(stat -c "%u:%g" "$SUBJECTS_DIR")" == "0:0" ]] && [[ "$(id -u)" != "0" ]] && [[ "$(stat -c "%a" "$SUBJECTS_DIR" | tail -c 2)" -lt 6 ]] then - echo "ERROR: The subject directory ($SUBJECTS_DIR) is owned by root and is not writable. FastSurfer cannot write results! " - echo "This can happen if the directory is created by docker. Make sure to create the directory before invoking docker!" + echo "ERROR: The subject directory ($SUBJECTS_DIR) is owned by root and is not writable." + echo " FastSurfer cannot write results! This can happen if the directory is created by" + echo " docker. Make sure to create the directory before invoking docker!" exit 1; fi @@ -288,6 +287,7 @@ echo "Log file for long_prepare_template" >> "$LF" ### IF THE SCRIPT GETS TERMINATED, ADD A MESSAGE +# shellcheck disable=SC2064 trap "{ echo \"long_prepare_template.sh terminated via signal at \$(date -R)!\" >> \"$LF\" ; }" SIGINT SIGTERM @@ -354,7 +354,7 @@ for ((i=0;i<${#tpids[@]};++i)); do RunIt "$cmd" "$LF" # conform !!!!!!! should we conform to some common value, determined from all time points?? !!!!!! - # this is relevant if input resolutions differe (which they should not), currently conform min may not work as expected + # this is relevant if input resolutions different (which they should not), currently conform min may not work as expected #conform="$mdir/T1_conform${extension}" #cmd="mri_convert -c ${t1s[i]} $conform" #cmd="$python $fastsurfercnndir/data_loader/conform.py -i ${t1s[i]} -o $conform --vox_size $vox_size --dtype any --verbose" @@ -368,21 +368,19 @@ for ((i=0;i<${#tpids[@]};++i)); do mask_name="$mdir/cross_mask${extension}" aseg_segfile="$mdir/cross_aseg.auto_noCCseg${extension}" seg_log="/dev/null" - cmd=($python "$fastsurfercnndir/run_prediction.py" - "${POSITIONAL_FASTSURFER[@]}" --t1 "$t1input" + cmda=($python "$fastsurfercnndir/run_prediction.py" --t1 "$t1input" --async_io --asegdkt_segfile "$asegdkt_segfile" --conformed_name "$conformed_name" --brainmask_name "$mask_name" --aseg_name "$aseg_segfile" --sid "${tpids[i]}" - --seg_log "$seg_log" --vox_size "$vox_size" --batch_size "$batch_size" - --viewagg_device "$viewagg" --device "$device") - run_it "$LF" "${cmd[@]}" + --seg_log "$seg_log" "${run_pred_flags[@]}") + run_it "$LF" "${cmda[@]}" # remove mri subdirectory (run_prediction creates 001 there) - cmd=(rm -rf "$mdir/mri") - run_it "$LF" "${cmd[@]}" + cmda=(rm -rf "$mdir/mri") + run_it "$LF" "${cmda[@]}" # mask is binary, we need to use on conformed image: - cmd=(mri_mask "$conformed_name" "$mask_name" "$mdir/cross_brainmask${extension}") - run_it "$LF" "${cmd[@]}" + cmda=(mri_mask "$conformed_name" "$mask_name" "$mdir/cross_brainmask${extension}") + run_it "$LF" "${cmda[@]}" done # skip intensity normalization or bias field removal for now @@ -401,30 +399,29 @@ done # create a file with all time points names # this cannot be "base-tps" else recon-surf (and inside recon-all) will fail BaseSubjsListFname="$SUBJECTS_DIR/$tid/base-tps.fastsurfer" -rm -f ${BaseSubjsListFname} -mkdir -p $SUBJECTS_DIR/$tid/mri/transforms +rm -f "${BaseSubjsListFname}" +mkdir -p "$SUBJECTS_DIR/$tid/mri/transforms" subjInVols=() normInVols=() ltaXforms=() for s in "${tpids[@]}" do - echo $s - echo "${s}" >> ${BaseSubjsListFname} + echo "$s" | tee -a "${BaseSubjsListFname}" mdir="$SUBJECTS_DIR/$tid/long-inputs/${s}" invol="$mdir/cross_conform${extension}" - subjInVols+=($invol) + subjInVols+=("$invol") normvol="$mdir/cross_brainmask${extension}" - normInVols+=($normvol) - ltaname=${s}_to_${tid}.lta - ltaXforms+=(${SUBJECTS_DIR}/$tid/mri/transforms/${ltaname}) + normInVols+=("$normvol") + ltaname="${s}_to_${tid}.lta" + ltaXforms+=("${SUBJECTS_DIR}/$tid/mri/transforms/${ltaname}") done if [ ${#tpids[@]} == 1 ] then # if only a single time point, create fake 'base' by making the image upright - # this assures that also subjects with a single time point get processes as the other + # this assures that also subjects with a single time point get processed as the other # subjects in the longitudinal stream # 1. make the norm upright (base space) @@ -441,17 +438,17 @@ else #more than 1 time point: # create the 'mean/median' norm volume: - cmd="mri_robust_template --mov ${normInVols[@]}" - cmd="$cmd --lta ${ltaXforms[@]}" + cmd="mri_robust_template --mov ${normInVols[*]}" + cmd="$cmd --lta ${ltaXforms[*]}" cmd="$cmd --template ${SUBJECTS_DIR}/$tid/mri/base_brainmask${extension}" cmd="$cmd --average ${robust_template_avg_arg}" cmd="$cmd --sat 4.685" RunIt "$cmd" "$LF" # create the 'mean/median' input (orig) volume: - cmd="mri_robust_template --mov ${subjInVols[@]}" + cmd="mri_robust_template --mov ${subjInVols[*]}" cmd="$cmd --average ${robust_template_avg_arg}" - cmd="$cmd --ixforms ${ltaXforms[@]}" + cmd="$cmd --ixforms ${ltaXforms[*]}" cmd="$cmd --noit" t1=${SUBJECTS_DIR}/$tid/mri/orig.mgz cmd="$cmd --template $t1" diff --git a/run_fastsurfer.sh b/run_fastsurfer.sh index 0cafbb35..702c863a 100755 --- a/run_fastsurfer.sh +++ b/run_fastsurfer.sh @@ -697,12 +697,7 @@ fi if [[ "$base" == "1" ]] then - if [ ! -f "$sd/$subject/base-tps.fastsurfer" ] ; then - echo "ERROR: $subject is either not found in \$SUBJECTS_DIR or it is not a longitudinal template" - echo " directory (base), which needs to contain base-tps.fastsurfer file. Please ensure that" - echo " the base (template) has been created with long_prepare_template.sh." - exit 1 - fi + check_is_template "$sd" "$subject" if [[ -n "$t1" ]] && [[ "$t1" != "from-base" ]]; then echo "WARNING: --t1 was passed but will be overwritten with T1 from base template." fi @@ -713,12 +708,7 @@ fi if [[ "$long" == "1" ]] then - if [ ! -f "$sd/$baseid/base-tps.fastsurfer" ] ; then - echo "ERROR: $baseid is either not found in \$SUBJECTS_DIR or it is not a longitudinal template" - echo " directory (base), which needs to contain base-tps.fastsurfer file. Please ensure that" - echo " the base (template) has been created with long_prepare_template.sh." - exit 1 - fi + check_is_template "$sd" "$baseid" if ! grep -Fxq "$subject" "$sd/$baseid/base-tps.fastsurfer" ; then echo "ERROR: $subject id not found in base-tps.fastsurfer. Please ensure that this time point" echo " was included during creation of the base (template)."