1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
#!/bin/bash
# Copyright 2015. The Regents of the University of California.
# All rights reserved. Use of this source code is governed by
# a BSD-style license which can be found in the LICENSE file.
#
# Authors:
# 2015 Martin Uecker <uecker@eecs.berkeley.edu>
#
# Compressed sensing parallel imaging reconstruction with temporal
# total-variation regularization for Siemens radial VIBE sequence
# with golden-angle sampling (GRASP).
#
set -e
# default settings
export SPOKES=21
export SKIP=0
export CALIB=400
export ITER=30
export REG=0.05
SCALE=0.6
LOGFILE=/dev/stdout
MAXPROC=4
MAXTHREADS=4
title=$(cat <<- EOF
(BART-)GRASP v0.3 (Berkeley Advanced Reconstruction Toolbox)
--- EXPERIMENTAL --- FOR RESEARCH USE ONLY ---
EOF
)
helpstr=$(cat <<- EOF
Compressed sensing parallel imaging reconstruction with temporal
total-variation regularization for Siemens radial VIBE sequence
with golden-angle sampling (GRASP).
This script requires the Berkeley Advanced Reconstruction Toolbox
version 0.2.09. (later versions may also work).
-s spokes number of spokes per frame
-r lambda regularization parameter
-p maxproc max. number of slices processed in parallel
-t maxthreads max. number of threads per slice
-l logfile
-h help
EOF
)
usage="Usage: $0 [-h] [-s spokes] [-r lambda] <meas.dat> <output>"
echo "$title"
echo
while getopts "hl:s:p:t:r:" opt; do
case $opt in
s)
SPOKES=$OPTARG
;;
r)
REG=$OPTARG
;;
h)
echo "$usage"
echo
echo "$helpstr"
exit 0
;;
l)
LOGFILE=$(readlink -f "$OPTARG")
;;
p)
MAXPROC=$OPTARG
;;
t)
MAXTHREADS=$OPTARG
;;
\?)
echo "$usage" >&2
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 2 ] ; then
echo "$usage" >&2
exit 1
fi
if [ ! -e "$BART_TOOLBOX_PATH"/bart ] ; then
if [ -e "$TOOLBOX_PATH"/bart ] ; then
BART_TOOLBOX_PATH="$TOOLBOX_PATH"
else
echo "\$BART_TOOLBOX_PATH is not set correctly!" >&2
exit 1
fi
fi
export PATH="$BART_TOOLBOX_PATH:$PATH"
input=$(readlink -f "$1")
output=$(readlink -f "$2")
if [ ! -e $input ] ; then
echo "Input file does not exist." >&2
echo "$usage" >&2
exit 1
fi
if [ ! -e $TOOLBOX_PATH/bart ] ; then
echo "\$TOOLBOX_PATH is not set correctly!" >&2
exit 1
fi
#WORKDIR=$(mktemp -d)
# Mac: http://unix.stackexchange.com/questions/30091/fix-or-alternative-for-mktemp-in-os-x
WORKDIR=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`
trap 'rm -rf "$WORKDIR"' EXIT
cd $WORKDIR
# start group for redirection of output to the logfile
{
# read TWIX file
bart twixread -A $input grasp
export READ=$(bart show -d0 grasp)
export COILS=$(bart show -d3 grasp)
export PHASES=$(($(bart show -d1 grasp) / $SPOKES))
export OMP_NUM_THREADS=$((MAXPROC * $MAXTHREADS))
# zero-pad
#flip $(bitmask 2) grasp grasp2
#resize 2 64 grasp2 grasp
#circshift 2 10 grasp grasp2
#fft -u $(bitmask 2) grasp2 grasp_hybrid
#rm grasp.* grasp2.*
# inverse FFT along 3rd dimension
bart fft -i -u $(bart bitmask 2) grasp grasp_hybrid
rm grasp.cfl grasp.hdr
SLICES=$(bart show -d2 grasp_hybrid)
# create trajectory with 400 spokes and 2x oversampling
bart traj -G -x$READ -y$CALIB r
bart scale $SCALE r rcalib
# create trajectory with 2064 spokes and 2x oversampling
bart traj -G -x$READ -y$(($SPOKES * $PHASES)) r
bart scale $SCALE r r2
# split off time dimension into index 10
bart reshape $(bart bitmask 2 10) $SPOKES $PHASES r2 rfull
# number of threads per slice
export OMP_NUM_THREADS=$MAXTHREADS
calib_slice()
{
# extract slice
bart slice 2 $1 grasp_hybrid grasp1-$1
# extract first $CALIB spokes
bart extract 1 $(($SKIP + 0)) $(($SKIP + $CALIB)) grasp1-$1 grasp2-$1
# reshape dimensions
bart reshape $(bart bitmask 0 1 2 3) 1 $READ $CALIB $COILS grasp2-$1 grasp3-$1
# apply inverse nufft to first $CALIB spokes
bart nufft -i -t rcalib grasp3-$1 img-$1.coo
}
recon_slice()
{
# extract sensitivities for slice
bart slice 2 $1 sens sens-$1
# extract spokes and split-off time dim
bart extract 1 $(($SKIP + 0)) $(($SKIP + $SPOKES * $PHASES)) grasp1-$1 grasp2-$1
bart reshape $(bart bitmask 1 2) $SPOKES $PHASES grasp2-$1 grasp1-$1
# move time dimensions to dim 10 and reshape
bart transpose 2 10 grasp1-$1 grasp2-$1
bart reshape $(bart bitmask 0 1 2) 1 $READ $SPOKES grasp2-$1 grasp1-$1
rm grasp2-$1.cfl grasp2-$1.hdr
# reconstruction with tv penality along dimension 10
# old (v0.2.08):
# pics -S -d5 -lv -u10. -r$REG -R$(bitmask 10) -i$ITER -t rfull grasp1-$1 sens-$1 i-$1.coo
# new (v0.2.09):
bart pics -S -d5 -u10. -RT:$(bart bitmask 10):0:$REG -i$ITER -t rfull grasp1-$1 sens-$1 i-$1.coo
# clean up temp files
rm *-$1.cfl *-$1.hdr
}
export -f calib_slice
export -f recon_slice
# loop over slices
seq -w 0 $(($SLICES - 1)) | xargs -I {} -P $MAXPROC bash -c "calib_slice {}"
# transform back to k-space and compute sensitivities
bart join 2 img-*.coo img
bart fft -u $(bart bitmask 0 1 2) img ksp
#ecalib -S -c0.8 -m1 -r20 ksp sens
# transpose because we already support off-center calibration region
# in dim 0 but here we might have it in 2
bart transpose 0 2 ksp ksp2
bart ecalib -S -c0.8 -m1 -r20 ksp2 sens2
bart transpose 0 2 sens2 sens
# loop over slices
seq -w 0 $(($SLICES - 1)) | xargs -I {} -P $MAXPROC bash -c "recon_slice {}"
#echo 20 | xargs -i --max-procs=$MAXPROC bash -c "recon_slice {}"
# join slices back together
bart join 2 i-*.coo $output
# generate dicoms
#for s in $(seq -w 0 $(($SLICES - 1))) ; do
# for p in $(seq -w 0 $(($PHASES - 1))) ; do
# bart slice 10 $p i-$s.coo i-$p-$s.coo
# bart toimg i-$p-$s.coo $output.series$p.slice$s.dcm
# done
#done
} > $LOGFILE
exit 0
|