Imaging resources

fMRI: Create a single montage (png) from a nifti (.nii) in fsl

For reporting clinical fMRI scans it's often useful to provide a single montage of the final map. The below script uses fsl, most notably its 'slicer' and 'pngappend' commands, to create a montage.

Currently:

  • It is hard coded to provide a 4x6 image.  
  • It takes as input an image, and optionally the lowest and top-most slices you'd like to include.

 

#####################################################################

#Required : $1 -  .nii from which creates a 4x6 montage.
#Optional:
#   $2 - Bottom slice to include. Default 100.
#   $3 - Top slice to include.  Default 230.
#Christopher Benjamin May 13 2018


#####################################################################

## Specify inputs.

#####################################################################

image_to_slice=$1

#Count the number of slices in your image
number_of_slices=`fslval $image_to_slice dim3`

#Specify the upper and lower-most slices you want to cut.
if [ -z $2 ] ; then
  slice_bottom=100;   #Slice you will start slicing from
else
  slice_bottom=$2;
fi
if [-z $3 ] ; then
  slice_top=230;      #Slice you will stop slicing at
else
  slice_top=$3;
fi

#Calculate the number of actual slices of brain you want to slice from.
dead_space_above_brain=`echo "$number_of_slices-$slice_top" | bc -l`
n_slices_of_actual_brain=`echo "$number_of_slices-$slice_bottom-$dead_space_above_brain" | bc -l`

#Calculate the max spacing necessary to allow 24 slices to be cut
let slice_increment=($n_slices_of_actual_brain+24-1)/24


#####################################################################

## Run loop to slice and stitch montage

#####################################################################

count=1
col_count=7
row=0

#Slice the image.
for (( N = $slice_bottom; N <= $slice_top; N += $slice_increment )); do
  FRAC=$(echo "scale=2; $N / $number_of_slices" | bc -l);
  slicer "$image_to_slice" -L -z $FRAC "${image_to_slice}_$count.png";

  #Add current image to a row.
  #If you have the first image of a new row (i.e., column 7), create new row
  if [[ $col_count == 7 ]] ; then
    row=$(echo "${row}+1" | bc -l);
    mv "${image_to_slice}_$count.png" montage_row$row.png
    col_count=2;
    just_started_a_new_row=1;
  #Otherwise, append your image to the existing row.
  else
    pngappend montage_row$row.png + "${image_to_slice}_$count.png" montage_row$row.png
    col_count=$(echo "${col_count}+1" | bc -l);
    just_started_a_new_row=0;
    rm "${image_to_slice}_$count.png"
  fi
  count=$(echo "${count}+1" | bc -l);
done

#####################################################################

## Stitch your rows into a single montage

#####################################################################

label=`basename $image_to_slice .nii.gz`

mv montage_row1.png montage-$label.png
pngappend montage-$label.png - montage_row2.png montage-$label.png
pngappend montage-$label.png - montage_row3.png montage-$label.png
pngappend montage-$label.png - montage_row4.png montage-$label.png
rm montage_row*