#!/bin/csh -f # epidewarp4.ucsd # # This script uses FSL prelude and fugue tools to unwarp EPI images. # Original version is called epidewarp.fsl authored by Doug Greve at MGH for use # by the fBIRN consortium. # # This version is called epidewarp3.ucsd and is adapted from version 1.1 (2004/7/27) of # epidewarp.fsl. The intent is to faciliate unwarping from GE DICOM images at UCSD. # As much as possible, this script will be updated to reflect improvements # in epidewarp.fsl as these are made available. # # For processing at UCSD, this script is intended to be called by the script: ppge3 # # Version History # 1.0 TTL 040728 Added gemode input to support different processing for GE DICOM files at UCSD # TTL 040926 Checked into CVS repository # TTL 040927 Modifying to support multiple EPI frames # 3.0 TTL 040929 Adding motion correction features # 3.1 TTL 041001 Redefine refnum to go from 0 to nframes-1, in accordance with standard AVW indexing # 3.2 TTL 041014 Added unwarpdir option # 3.3 GTB 050413 Added write fieldmap option # 3.4 GTB 050505 Added -plots flag on mcflirt # 3.5 GTB 061505 Modified for NIFTI format # 3.6 KL 081506 Corrected mismatch of nifti header information by using # avwcpgeom in multiple places. Ohterwise dewarping won't be correct. # 3.7 KL 040507 added number of phase splits to use in prelude. # 3.8 KL 042707 removed option dph2 (dph1 is now the phase difference between echo1 and 2, # Therefore dph2 is no longer needed) # 3.9 KL 090707 updated all avw... commands to fsl... to work with FSL4.0. # 4.0 KL 06172010: added a step to align brain mask to epi space. # Send Comments/Questions to kunlu@ucsd.edu set VERSION = '$Id$' set inputargs = ($argv); set do_outmask = 0; set gemode = 0; set domoco = 1; set dph = (); set mag = (); set epi = (); set refnum = (); set unwarpdir = (); set fmap = (); set np=(); set betf=(); # Difference between first and second echoes of the B0 Map set tediff = (); # Suggest 2.44 ms for 3T # EPI Echo Spacing (MGH .58 ms) set esp = (); # FUGUE parameters set sigma = (); set npart = (); # Outputs set epidw = (); set vsm = (); set exfdw = (); set tmpdir = (); set cleanup = 1; set cleanup_forced = 0; set PrintHelp = 0; ## If there are no arguments, just print useage and exit ## if($#argv == 0) goto usage_exit; set n = `echo $argv | grep -e --help | wc -l` if($n != 0) then set PrintHelp = 1; goto usage_exit; endif set n = `echo $argv | grep -e --version | wc -l` if($n != 0) then echo $VERSION exit 0; endif goto parse_args; parse_args_return: goto check_params; check_params_return: # Create a log file set LF = $vsm.log if(-e $LF) mv $LF $LF.bak echo Logfile is $LF date >> $LF echo $VERSION >> $LF pwd >> $LF echo $0 >> $LF echo $inputargs >> $LF df -h $tmpdir >> $LF df -h $outdir >> $LF which prelude >> $LF which fugue >> $LF # Some temp files set exf = $tmpdir/exf$postfix set brain = $tmpdir/brain$postfix set head = $tmpdir/head$postfix # Extract the middle time point for the example func (exf) set nframes = `fslinfo $epi | awk '{if($1 == "dim4") print $2}'` if($nframes == 1) then set nmidframe = 0; else set nmidframe = `echo "$nframes/2-1" | bc `; endif echo "nframes = $nframes, nmidframe = $nmidframe" |& tee -a $LF set cmd = (fslroi $epi $exf $nmidframe 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # See if there's a .mat file to propogate set epibase = `basename $epi $postfix`; set epimat = $epibase.mat if(! -e $epimat) set epimat = (); #REDEFINE exf if refnum exists if($#refnum > 0 ) then if ($refnum >= 0 && $refnum < $nframes) then set cmd = (fslroi $epi $exf $refnum 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set nmidframe = $refnum else echo "refnum should be >= 0 and < $nframes" exit 1 endif endif # Keep only the first frame from mag set cmd = (fslroi $mag $tmpdir/mag 0 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set mag = $tmpdir/mag$postfix # Create brain mask from the mag set cmd = (bet $mag $brain -f $betf) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set cmd = (fslmaths $brain -bin $brain) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Create head mask by dilating the brain mask 3 times @ nthdil = 1; while($nthdil <= 3) if($nthdil == 1) then set cmd = (fslmaths $brain -dilM $head) else set cmd = (fslmaths $head -dilM $head) endif echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; @ nthdil = $nthdil + 1; end #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # now DIFFERENT for multi-channel KL #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Do the phase unwrapping of phase difference (-f for 3D, -v for verbose) set cmd = (prelude -c $dph -o $tmpdir/dph$postfix -n $np -f -v -m $head); echo $cmd |& tee -a $LF $cmd |& tee -a $LF set dph = $tmpdir/dph$postfix # FUGUE wants a phase image for each echo, but we only have # phase difference between echoes. So create an image of 0s # and merging with the phase diff. set ph1 = $tmpdir/ph1$postfix set cmd = (fslmaths $dph -mul 0 $ph1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; #currrent version (FSL3.3) prelude does not preserve header information #thus we need to add header to ph1 and dph, copy from brain mask. KL fslcpgeom $brain $ph1 fslcpgeom $brain $dph # Merge, baby, merge set ph2 = $tmpdir/ph2$postfix set cmd = (fslmerge -t $ph2 $ph1 $dph) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Create the voxel shift map (VSM) in the mag/phase space. Use mag as # input to assure that VSM is same dimension as mag. The input only affects # the output dimension. The content of the input has no effect # on the VSM. The dewarped mag volume is meaningless and will be thrown away. set vsmmag = $tmpdir/vsmmag$postfix set magdw = $tmpdir/magdw$postfix # To be thrown away set cmd = (fugue -i $mag -u $magdw -p $ph2 \ --dwell=$esp --asym=$tediff --mask=$brain --saveshift=$vsmmag); if($#unwarpdir > 0 ) then set cmd = "$cmd --unwarpdir=$unwarpdir"; endif if($#fmap > 0 ) then set cmd = "$cmd --savefmap=$fmap"; endif echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Forward warp the mag in order to reg with func # What does mask do here? set magfw = $tmpdir/magfw$postfix set cmd = (fugue -i $mag -w $magfw --loadshift=$vsmmag --mask=$brain ) if($#unwarpdir > 0 ) then set cmd = "$cmd --unwarpdir=$unwarpdir"; endif echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Register magfw to example func. There are some parameters here # that may need to be tweeked. set cmd = (flirt -in $magfw -ref $exf \ -out $tmpdir/magfw-in-exf$postfix \ -omat $tmpdir/magfw-in-exf.fsl.mat \ -bins 256 -cost corratio \ -nosearch \ -searchrx -10 10 \ -searchry -10 10 \ -searchrz -10 10 \ -dof 6 \ -interp trilinear) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Now resample VSM into epi space. This will take care of any # differences in in-plane voxel size. set cmd = (flirt -in $vsmmag -ref $exf -out $vsm \ -init $tmpdir/magfw-in-exf.fsl.mat -applyxfm -paddingsize 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # KL added: Now align brain mask to epi space as well. set cmd = (flirt -in $brain -ref $exf -out $tmpdir/brain1$postfix\ -init $tmpdir/magfw-in-exf.fsl.mat -applyxfm -paddingsize 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set brain = $tmpdir/brain1$postfix if($#epimat) then # Propogate mat file set vsmbase = `basename $vsm $postfix`; cp $epimat $vsmbase.mat endif # Check whether we can stop at this point if($#exfdw == 0 && $#epidw == 0) goto done; # UNWARP ONLY THE EXAMPLE FRAME HERE if($#exfdw != 0) then # Now apply the VSM to the exf (um=unmasked) set exfdwum = $tmpdir/exfdwum$postfix set cmd = (fugue -i $exf -u $exfdwum --loadshift=$vsm --mask=$brain ); if($#unwarpdir > 0 ) then set cmd = "$cmd --unwarpdir=$unwarpdir"; endif echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; # Now mask the dewarped exf using the mag brain mask. # This is necessary to prevent voxels in the original EPI # that are out of the brain from simply being copied into # the dewarped image. set cmd = (fslmaths $exfdwum -mul $brain $exfdw) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; if($#epimat) then # Propogate mat file set exfbase = `basename $exfdw $postfix`; cp $epimat $exfbase.mat endif endif # UNWARP ALL EPI FRAMES HERE if($#epidw != 0) then if($domoco == 1 && $epimerged == 1) then set mepi = $tmpdir/mepi$postfix set cmd = (mcflirt -in $epi -out $mepi -refvol $nmidframe -plots ) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set epi = $mepi endif @ frame = 1; while($frame <= $nframes) set inimg = $tmpdir/inframe$postfix @ roiframe = $frame - 1 set cmd = (fslroi $epi $inimg $roiframe 1) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; set outimg = `printf $tmpdir/uavwepi%04d$postfix $frame`; echo $inimg $outimg set cmd = (fugue -i $inimg -u $outimg --loadshift=$vsm --mask=$brain ); if($#unwarpdir > 0 ) then set cmd = "$cmd --unwarpdir=$unwarpdir"; endif echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; #OPTIONAL MASKING OF THE DATA if($do_outmask) then set moutimg = `printf $tmpdir/muavwepi%04d$postfix $frame`; set cmd = (fslmaths $outimg -mul $brain $moutimg) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) exit 1; endif # Need to add propagation of mat file! @ frame = $frame + 1; end endif goto done; exit 0; ############################################################## ############################################################## done: if($cleanup) then echo "Deleting tmp dir $tmpdir" |& tee -a $LF rm -r $tmpdir endif date |& tee -a $LF echo "epidewarp.ucsd done" |& tee -a $LF exit 0; ############################################################## parse_args: set cmdline = ($argv); while( $#argv != 0 ) set flag = $argv[1]; shift; switch($flag) case "--mag": if ( $#argv == 0) goto arg1err; set mag = $argv[1]; shift; if(! -e $mag) then echo "ERROR: cannot find $mag" exit 1; endif breaksw case "--dph": if ( $#argv == 0) goto arg1err; set dph = $argv[1]; shift; if(! -e $dph) then echo "ERROR: cannot find $dph" exit 1; endif breaksw case "--epi": if ( $#argv == 0) goto arg1err; set epi = $argv[1]; shift; set epimerged = 1 if(! -e $epi) then echo "ERROR: cannot find $epi" exit 1; endif breaksw case "--sepi": if ( $#argv == 0) goto arg1err; set epi = $argv[1]; shift; set epimerged = 0 if(! -e {$epi}0001.$postfix) then echo "ERROR: cannot find {$epi}0001$postfix (first image in series)" exit 1; endif breaksw case "--tediff": if ( $#argv == 0) goto arg1err; set tediff = $argv[1]; shift; breaksw case "--esp": if ( $#argv == 0) goto arg1err; set esp = $argv[1]; shift; breaksw case "--epidw": if ( $#argv == 0) goto arg1err; set epidw = $argv[1]; shift; breaksw case "--exfdw": if ( $#argv == 0) goto arg1err; set exfdw = $argv[1]; shift; breaksw case "--vsm": if ( $#argv == 0) goto arg1err; set vsm = $argv[1]; shift; breaksw case "--fmap": if ( $#argv == 0) goto arg1err; set fmap = $argv[1]; shift; breaksw case "--unwarpdir": if ( $#argv == 0) goto arg1err; set unwarpdir = $argv[1]; shift; breaksw case "--tmpdir": if ( $#argv == 0) goto arg1err; set tmpdir = $argv[1]; shift; set cleanup = 0; breaksw case "--postfix": if ( $#argv == 0) goto arg1err; set postfix = $argv[1]; shift; breaksw case "--nphase": if ( $#argv == 0) goto arg1err; set np = $argv[1]; shift; breaksw case "--betf": if ( $#argv == 0) goto arg1err; set betf = $argv[1]; shift; breaksw case "--refnum": set refnum = $argv[1]; shift; breaksw case "--nomoco": set domoco = 0; breaksw case "--nocleanup": set cleanup = 0; breaksw case "--outmask": set do_outmask = 1; breaksw case "--cleanup": set cleanup_forced = 1; breaksw case "--debug": set verbose = 1; set echo = 1; # turns on terminal echoing breaksw default: echo ERROR: Flag $flag unrecognized. echo $cmdline exit 1 breaksw endsw end goto parse_args_return; ############--------------################## ############--------------################## check_params: if($#mag == 0) then echo "ERROR: no magnitude volume specified" exit 1; endif if($#dph == 0) then echo "ERROR: no phase diff volume specified" exit 1; endif if($#tediff == 0) then echo "ERROR: no TE diff specified" exit 1; endif if($#esp == 0) then echo "ERROR: no Echo Spacing specified" exit 1; endif if($#vsm == 0) then echo "ERROR: no output VSM specified" exit 1; endif if($#postfix == 0) then echo "ERROR: no postfix (nii vs nii.gz) specified" exit 1; endif if($cleanup_forced) set cleanup = 1; set outdir = `dirname $vsm`; mkdir -p $outdir if($status) then echo "ERROR: cannot create $outdir" exit 1; endif if($#tmpdir == 0) set tmpdir = $outdir mkdir -p $tmpdir if($status) then echo "ERROR: cannot create $tmpdir" exit 1; endif if($#epidw != 0) then set epidwdir = `dirname $epidw`; mkdir -p $epidwdir if($status) then echo "ERROR: cannot create $epidwdir" exit 1; endif endif if($#exfdw != 0) then set exfdwdir = `dirname $exfdw`; mkdir -p $exfdwdir if($status) then echo "ERROR: cannot create $exfdwdir" exit 1; endif endif goto check_params_return; ############--------------################## ############--------------################## arg1err: echo "ERROR: flag $flag requires one argument" exit 1 ############--------------################## ############--------------################## usage_exit: echo "" echo "USAGE: epidewarp4.ucsd" echo "" echo "Inputs" echo " --mag volid : B0 magnitude volume" echo " --dph volid : B0 phase difference volume " echo " --epi volid : epi volume (note: specify this for merged AVW data)" echo " --tediff tediff : difference in B0 field map TEs" echo " --esp esp : EPI echo spacing" echo " " echo "Outputs" echo " --vsm volid : voxel shift map (required)" echo " --exfdw volid : dewarped example func volume" echo " --epidw volid : dewarped epi volume" echo " --fmap volid : fieldmap volume" echo " " echo "Options " echo " --unwarpdir