Home > OS >  Using nested for loop in BASH to run 2x3x6 variable loop
Using nested for loop in BASH to run 2x3x6 variable loop

Time:11-26

I would like to run a command on my data that registers 3 regions of interest (ROI) to 2 hemispheres and names each output accordingly. I am having trouble figuring out how to keep one line of command within a nested loop, instead of breaking down the loop into specific ROI loops.

In general, something like this:

for a in Right_hemi Left_hemi; do
    for b in ROI1 ROI2 ROI3; do
        for ROI in ${ROI1_LEFT} ${ROI2_LEFT} ${ROI3_LEFT} ${ROI1_RIGHT} ${ROI2_RIGHT} ${ROI3_RIGHT}; do

            antsApplyTransforms -d 3 -i $ROI -r ${dir_out}/FA_${subject}.nii.gz -o ${dir_out}/warped_atlas/${a}_${b}_${subject}.nii.gz 

            echo "${ROI} warp completed"

        done
    done
done

However, this will not work as I will not be able to separate ROIs without mixing, for example, left_hemi_ROI1 with $ROI2_LEFT variables.

I'm not sure if there is a non-loop approach like R's apply function that I can be using here.

The outputs should be:

Left_hemi_ROI1_${ROI1_LEFT}_*.gz
Right_hemi_ROI1_${ROI1_RIGHT}_*.gz
Left_hemi_ROI2_${ROI2_LEFT}_*.gz
.
.
.

CodePudding user response:

Would you please try the following:

for a in Right_hemi Left_hemi; do
    a2=${a%_*}                          # remove underscore and following characters
    for b in ROI1 ROI2 ROI3; do
        varname="${b}_${a2^^}"          # concatenate $b, "_", and uppercased "$a2"
        ROI=${!varname}                 # indirect variable reference
            antsApplyTransforms -d 3 -i "$ROI" -r "${dir_out}/FA_${subject}".nii.gz -o "${dir_out}/warped_atlas/${a}_${b}_${subject}.nii.gz"
            echo "${ROI} warp completed"
    done
done

It generates varname such as ROI1_LEFT using the loop variables a and b then accesses $ROI1_LEFT via ${varname}.

CodePudding user response:

Another potential solution is to load your "ROI's" into an array and cycle through them, e.g.

c=('${ROI1_LEFT}' '${ROI2_LEFT}' '${ROI3_LEFT}' '${ROI1_RIGHT}' '${ROI2_RIGHT}' '${ROI3_RIGHT}')

i=0
for f in Left_hemi Right_hemi
do
    for g in ROI{1..3}
    do
        echo "${f}_${g}_${c[i]}_subject.gz"
        i=$(( i   1 ))
    done
done
Left_hemi_ROI1_${ROI1_LEFT}_subject.gz
Left_hemi_ROI2_${ROI2_LEFT}_subject.gz
Left_hemi_ROI3_${ROI3_LEFT}_subject.gz
Right_hemi_ROI1_${ROI1_RIGHT}_subject.gz
Right_hemi_ROI2_${ROI2_RIGHT}_subject.gz
Right_hemi_ROI3_${ROI3_RIGHT}_subject.gz

So, my guess as to how you could apply this to your actual data is:

c=(${ROI1_LEFT} ${ROI2_LEFT} ${ROI3_LEFT} ${ROI1_RIGHT} ${ROI2_RIGHT} ${ROI3_RIGHT})

for subject in subjects
do
    i=0
    for f in Left_hemi Right_hemi
    do
        for g in ROI{1..3}
        do
            antsApplyTransforms -d 3 -i ${c[i]} -r ${dir_out}/FA_${subject}.nii.gz -o ${dir_out}/warped_atlas/"${f}_${g}_${c[i]}_${subject}.nii.gz" 
        i=$(( i   1 ))
        done
    done
done

CodePudding user response:

Just iterate over left right. The following code:

for a in Right_hemi Left_hemi; do
    for b in ROI1 ROI2 ROI3; do
        for direction in LEFT RIGHT; do
             echo "${a}_${b}_\${${b}_${direction}}_*.gz"
        done
    done
done | head -n 3

outputs:

Right_hemi_ROI1_${ROI1_LEFT}_*.gz
Right_hemi_ROI1_${ROI1_RIGHT}_*.gz
Right_hemi_ROI2_${ROI2_LEFT}_*.gz
  • Related