Search code examples
bashfor-loopnested-loops

Using nested for loop in BASH to run 2x3x6 variable loop


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

In general, something like this:

for a in Right_hemi Left_hemi; do
    for b in ROI1 ROI2 ROI3; do
        for file in ${file1_LEFT} ${file2_LEFT} ${file3_LEFT} ${file1_RIGHT} ${file2_RIGHT} ${file3_RIGHT}; do

            antsApplyTransforms -d 3 -i $file  ${dir_out}/warped_atlas/${a}_${b}_${subject}.nii.gz 

            echo "${a}_${b}_${subject}.nii.gz"

        done
    done
done

$file is a variable of the actual image used in the code

  • example of $file1_LEFT variable: /path/to/variable/file1_LEFT.nii.gz

$a is a naming variable (right/left)

$b is a naming variable for $file, since I cannot use a file path/name

For clarity, in $b:

  • ROI1 represents file1_LEFT and file1_RIGHT

  • ROI2 represents file2_LEFT and file2_RIGHT

  • ROI3 represents file3_LEFT and file3_RIGHT

So the command within the loop will call on $file variables but because I cannot use a file for a name, I created $b variable strictly for naming purposes. However, this will not work as I will not be able to separate ROIs without mixing them with all files, for example, I cannot have an output combining ROI1_file2 or ROI1_file3. Each $b name must match the appropriate $file variable so the outputs should be:

Left_hemi_ROI1*.gz  # where ROI1 represents file1_LEFT
Right_hemi_ROI1*.gz # where ROI1 represents file1_RIGHT
Left_hemi_ROI2*.gz  # where ROI2 represents file2_LEFT
Right_hemi_ROI2*.gz # where ROI2 represents file2_RIGHT
.
.

Solution

  • 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