#!/bin/tcsh -f # dcmunpack # set VERSION = 'dcmunpack @FS_VERSION@'; set SeriesInfo = (); set DoUnpack = 0; set TargetDir = (); set SrcInfo = (); set SrcDirList = (); set SrcPre = (); set SrcPat = (); set SrcExt = (); set FSFAST = 1; set DoInfoDump = 1; set DoConvert = 1; set DoCopy = 0; set OnePerDir = 0; set MGHDCM = 0; set Key = (); set DoBase = 0; set infofile = (); set itdicom = (); set DoAutoRunSeq = 0; set AutoRunSeqFmt = "" set ExitOnError = 1; @ ErrorsFound = 0; set RunNoSkip = () set iid = () set ijd = () set ikd = () set UseDCM2NIIX = 1; # changed this to 1 on 4/06/2023 set CreateBIDS = 0 set DoPhase = 0; set DoSiemensAscii = 1; set KeepScouts = 0; set ForceUpdate = 0; set RunNos = (); set SubDirs = (); set Formats = (); set FNames = (); set NSkips = (); set NDrops = (); set DoFIPS = 0; set Project = (); set Site = (); set BIRNID = (); set VisitNo = (); set RunPars = (); set GetMax = 0; set DoExtraInfo = 0; set siemensBVecsCross = 0; if($?FS_dcmGetDWIParamsSiemens_VoxelSpace) then set siemensBVecsCross = $FS_dcmGetDWIParamsSiemens_VoxelSpace; endif set inputargs = ("$argv"); set PrintHelp = 0; set LF = (); set DoFirstDicom = 0; 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 source $FREESURFER_HOME/sources.csh goto parse_args; parse_args_return: goto check_params; check_params_return: # Create target dir, if necessary if($#TargetDir) mkdir -p $TargetDir/log # Create the log file if($#LF == 0) then if($#TargetDir) then set LF = $TargetDir/log/dcmunpack.log if(-e $LF) mv $LF $TargetDir/log/dcmunpack.$$.log else set LF = /dev/null endif endif # Start populating the log file echo ""| tee -a $LF echo "cd `pwd`" | tee -a $LF echo "$0 $inputargs"| tee -a $LF echo ""| tee -a $LF echo $VERSION >> $LF ls -l $0 | tee -a $LF uname -a >> $LF date >> $LF set StartTime = `date`; set tSecStart = `date '+%s'`; # Print out a summary echo "---------------------------------------" | tee -a $LF @ nth = 0; foreach run ($RunNos) @ nth = $nth + 1; if(! $DoFIPS) then echo " $nth $run $SubDirs[$nth] $FNames[$nth] $NSkips[$nth] $NDrops[$nth]" | tee -a $LF else echo " $nth $run $RunPars[$nth] $RunParNos[$nth] $NSkips[$nth] $NDrops[$nth]" | tee -a $LF endif end echo "---------------------------------------" | tee -a $LF if($OnePerDir) then # This creates a list of all the subdirs in the tree set SrcDirList2 = (`find -L $d -type d`); else set SrcDirList2 = ($SrcDirList) endif echo "Searching for matching files" | tee -a $LF date | tee -a $LF set flist = (); foreach d ($SrcDirList2) #echo "Searching $d" >> $LF if($#SrcPre || $#SrcPat || $#SrcExt) then set flist0 = (`find -L $d -name "$SrcPre*$SrcPat*$SrcExt"`) else set flist0 = (`find -L $d`) endif if($OnePerDir && $#flist0 > 0) then set flist0 = ($flist0[1]); endif set flist = ($flist $flist0); end date | tee -a $LF echo "Found $#flist total files." | tee -a $LF if($#flist == 0) then echo "ERROR: did not find any files"| tee -a $LF exit 1; endif if($#flist > 100 && $#SrcInfo == 0) then echo " Interrogating each and every one of them." echo " Be patient." endif # Go through each file, create an info dump, extract params. # This can be slow, esp for GE. In that case, try using the # -one-per-dir functionality with -ext, -pat, and/or -pre. if($#infofile == 0) then if($#TargetDir) then set infofile = $TargetDir/log/imagelist.dat if($SrcInfo != $infofile) then if(-e $infofile) mv $infofile $TargetDir/log/imagelist.$$.dat endif else set infofile = `fs_temp_file` endif endif if($#SrcInfo) then if($SrcInfo != $infofile) then # This may still fail if they are truly the same file but diff # path spec, but that will not be important (it just might # confuse people) cp $SrcInfo $infofile endif else rm -f $infofile endif set dumpfile = `fs_temp_file` rm -f $dumpfile @ nth = 0; @ mth = 0; foreach f ($flist) @ nth = $nth + 1; set filetype = `mri_probedicom --i $f --d filetype` if($filetype == notdicom) continue; @ mth = $mth + 1; #echo "#@# $nth/$#flist `date`" >>& $LF set cmd = (mri_probedicom --i $f) if($DoSiemensAscii == 0) set cmd = ($cmd --no-siemens-ascii) $cmd >& $dumpfile if($status) then cat $dumpfile | tee -a $LF exit 1; endif set SeriesNo = `cat $dumpfile | awk '{if($1 == "SeriesNo") print $2}'` if($status) then echo "ERROR: cannot find series number in $dumpfile" | tee -a $LF exit 1; endif set Patient = (`cat $dumpfile | awk '{if($1 == "PatientName") print $2}'`) if($#Patient == 0) set Patient = 'unknown' set Date = (`cat $dumpfile | awk '{if($1 == "StudyDate") print $2}'`) if($#Date == 0) set Date = 'unknown'; set Time = (`cat $dumpfile | awk '{if($1 == "StudyTime") print $2}'`) if($#Time == 0) set Time = 'unknown'; set Institution = (`cat $dumpfile | awk '{if($1 == "Institution") print $0}'`) if($#Institution == 0) set Institution = 'Institution unknown'; set EchoTime = (`cat $dumpfile | awk '{if($1 == "EchoTime") print $2}'`) if($#EchoTime == 0) set EchoTime = 'unknown'; set TR = (`cat $dumpfile | awk '{if($1 == "RepetitionTime") print $2}'`) if($#TR == 0) set TR = 'unknown'; set FlipAngle = (`cat $dumpfile | awk '{if($1 == "FlipAngle") print $2}'`) if($#FlipAngle == 0) set FlipAngle = 'unknown'; #------------------------------------------------------------------------# # Special case for PixSpace. Found a file where pixel spacing had some funny # binary character in it, and it messed everything up set PixSpace = (`cat $dumpfile | awk '{if($1 == "PixelSpacing") print $2}' | strings`) set tmpdat = `fs_temp_file --suffix .dat` echo $PixSpace > $tmpdat set PixSpace = (`cat $tmpdat`) rm $tmpdat if($#PixSpace == 0) set PixSpace = 'unknown'; #------------------------------------------------------------------------# set PhaseEncDir = (`cat $dumpfile | awk '{if($1 == "PhaseEncDir") print $2}'`) if($#PhaseEncDir == 0) set PhaseEncDir = 'unknown'; set PixFreq = (`cat $dumpfile | awk '{if($1 == "PixelFrequency") print $2}'`) if($#PixFreq == 0) set PixFreq = 'unknown'; set PhaseStr = () if($DoPhase) then set ImageType = (`cat $dumpfile | awk '{if($1 == "ImageType") print $2}'`) if($#ImageType == 1) then if($ImageType == "ORIGINAL\PRIMARY\P\ND") set PhaseStr = "_phase" endif if($#PhaseStr == 0) set PhaseStr = NotPhase endif if($#SrcInfo) break; echo "$Patient $SeriesNo $Date $Time $EchoTime $TR $FlipAngle $PixSpace $PhaseEncDir $PixFreq $f $PhaseStr" >> $infofile end if($mth == 0) then echo "ERROR: could not find any dicom files in" echo " $SrcDirList2" exit 1; endif set extra = () if($DoExtraInfo) then set fieldstrength = `grep FieldStrength $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#fieldstrength == 0) set fieldstrength = unknown set manufacturer = `grep Manufacturer $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#manufacturer == 0) set manufacturer = unknown set scannermodel = `grep ScannerModel $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#scannermodel == 0) set scannermodel = unknown set scannerserialno = `grep ScannerSerialNo $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#scannerserialno == 0) set scannerserialno = unknown set studydate = `grep StudyDate $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#studydate == 0) set studydate = unknown set patient = `grep PatientName $dumpfile | awk '{print $2}' | sed 's/ /-/g'` if($#patient == 0) set patient = unknown set extra = ($patient $studydate $manufacturer $scannermodel $fieldstrength $scannerserialno ) echo "ExtraInfo: $extra" endif rm -f $dumpfile set SeriesNos = (`cat $infofile | awk '{print $2}' | sort -n | uniq`) echo "Found $#SeriesNos unique series: $SeriesNos" | tee -a $LF echo "Subject $Patient" | tee -a $LF echo "Date $Date" | tee -a $LF echo "Time $Time" | tee -a $LF echo "$Institution" | tee -a $LF # Print out one line for each series: set AutoRunNos = () set AutoSubDirs = () set AutoFormats = () set AutoFNames = () set AutoNSkips = () set AutoNSkips = () set AutoNDrops = () if($#SeriesInfo == 0) then if($#TargetDir) then set SeriesInfo = $TargetDir/log/series-info.dat if(-e $SeriesInfo) mv $SeriesInfo $TargetDir/log/series-info.$$.dat else set SeriesInfo = `fs_temp_file --suffix .dat` endif endif rm -f $SeriesInfo foreach series ($SeriesNos) set r = `cat $infofile | awk -v s=$series '{if($2 == s) print $0;if($2 == s) exit;}'`; if($DoPhase == 0) set rexpected = 11 if($DoPhase == 1) set rexpected = 12 if($#r != $rexpected) then echo $r continue; endif if($DoPhase == 0) set f = $r[$#r]; if($DoPhase == 1) then @ aa = $#r - 1; set f = $r[$aa]; endif set max = (); if($GetMax) set max = (`mri_probedicom --i $f --max`) # Create a trap in case tag 8 103e is not present (eg, in philips) mri_probedicom --i $f --t 8 103e >& /dev/null if($status) then set descr = "unknown" else set descr = `mri_probedicom --i $f --t 8 103e | sed 's/ //g' | sed 's/\///g' | sed 's/(//g' | sed 's/)//g'| sed 's/\]//g'|sed 's/\[//g'` endif set fname = $r[11]; if($DoBase) set fname = `basename $f` echo $Key $r[2] "$descr" $r[5-10] $fname $max $extra | tee -a $SeriesInfo if($DoAutoRunSeq) then if("$descr" == Localizer || "$descr" == localizer || "$descr" == AAHScout || \ "$descr" == AAHScout_sag || "$descr" == AAHScout_cor || \ "$descr" == AAHScout_tra || "$descr" == AAScout || \ "$descr" == T1w_setter || "$descr" == T2w_setter) then if(! $KeepScouts) continue endif set AutoRunNos = ($AutoRunNos $series) set AutoSubDirs = ($AutoSubDirs ".") set AutoFormats = ($AutoFormats $AutoRunSeqFmt) set FName = `printf %04d.$descr $series` set AutoFNames = ($AutoFNames $FName) set AutoNSkips = ($AutoNSkips 0) set AutoNDrops = ($AutoNDrops 0) endif end cat $SeriesInfo >> $LF if($DoAutoRunSeq) then set RunNos = ($AutoRunNos) set SubDirs = ($AutoSubDirs) set Formats = ($AutoFormats) set FNames = ($AutoFNames) set NSkips = ($AutoNSkips) set NDrops = ($AutoNDrops) endif # If no runs have been specified, then just exit if($#RunNos == 0) then echo "" | tee -a $LF echo "" | tee -a $LF date | tee -a $LF echo "dcmunpack done" | tee -a $LF exit 0; endif # Unpack --------------------------------------------------------- # Make sure all runs are represented foreach run ($RunNos) set ok = 0; foreach series ($SeriesNos) if($run == $series) then set ok = 1; break; endif end if(! $ok) then echo "ERROR: could not find run $run in data" | tee -a $LF exit 1; endif end # ------------------ Unpack -------------------------- @ nth = 0; foreach run ($RunNos) @ nth = $nth + 1; set skipit = 0 foreach jj ($RunNoSkip) if($run == $jj) set skipit = 1 end if($skipit) then echo "Skipping run $run" |& tee -a $LF continue endif if($DoFIPS == 0) then set SubDir = $SubDirs[$nth]; set Format = $Formats[$nth]; set FName = $FNames[$nth]; else set fipsPar = $RunPars[$nth]; set fipsRun = $RunParNos[$nth]; set SubDir = $fipsPar; set Format = "nii.gz" set FName = f; endif set NSkip = $NSkips[$nth]; set NDrop = $NDrops[$nth]; if($FSFAST) then set rundir = `printf %03d $run` else set rundir = (); endif set outdir = $TargetDir/$SubDir/$rundir mkdir -p $outdir/log if($DoConvert) then set f = `cat $infofile | awk -v r=$run '{if($2 == r) print $11}' | head -n 1` set PhaseStr = () if($DoPhase) then set PhaseStr = `cat $infofile | awk -v r=$run '{if($2 == r) print $12}' | head -n 1` if($PhaseStr == NotPhase) set PhaseStr = "" endif set outfname = $outdir/$FName$PhaseStr.$Format echo "" |& tee -a $LF echo "#@# Run $run `date` ==================================" |& tee -a $LF set ud = (`UpdateNeeded $outfname $f`) if($ud || $ForceUpdate) then set cmd = (mri_convert $f $outfname --nskip $NSkip --ndrop $NDrop $itdicom) if($#iid) set cmd = ($cmd -iid $iid); if($#ijd) set cmd = ($cmd -ijd $ijd); if($#ikd) set cmd = ($cmd -ikd $ikd); if($DoFirstDicom) set cmd = ($cmd --first-dicom $outdir/log/$FName.first.dicom.path) if($UseDCM2NIIX) then # environment variable FS_DCM2NIIX_OUTDIR # this will be picked up in DICOMRead3(), and passed to dcm2niix_fswrapper() setenv FS_DCM2NIIX_OUTDIR $outdir set cmd = ($cmd -dcm2niix) if($CreateBIDS) then set cmd = ($cmd -createBIDS) endif endif if(! $UseDCM2NIIX) set cmd = ($cmd -no-dcm2niix) if($siemensBVecsCross) set cmd = ($cmd -siemensBVecsCross) if(! $siemensBVecsCross) set cmd = ($cmd -no-siemensBVecsCross) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) then if($ExitOnError) then echo "ERROR: a conversion error was detected in Run $run" |& tee -a $LF echo "Either find out why, exclude this run, or run with -no-exit-on-error to continue with other runs" |& tee -a $LF exit 1; endif echo "ERROR: a conversion error was detected in Run $run, but ExitOnError=1 so continuing to next run" |& tee -a $LF @ ErrorsFound = $ErrorsFound + 1; endif else echo "$outfname does not need updating" | tee -a $LF endif if($DoFirstDicom) then set cmd = (cp `cat $outdir/log/$FName.first.dicom.path` $outdir/$FName.first.dcm) echo $cmd |& tee -a $LF $cmd |& tee -a $LF if($status) then if($ExitOnError) then echo "ERROR: an error was detected in Run $run copying firt dicom file" |& tee -a $LF echo "Either find out why, exclude this run, or run with -no-exit-on-error to continue with other runs" |& tee -a $LF exit 1; endif echo "ERROR: an error was detected in Run $run copying firt dicom file, but ExitOnError=1 so continuing to next run" |& tee -a $LF @ ErrorsFound = $ErrorsFound + 1; endif endif endif if($DoCopy) then set flist = (`cat $infofile | awk -v r=$run '{if($2 == r) print $11}'`); foreach f ($flist) cp $f $outdir |& tee -a $LF if($status) exit 1; end endif if($DoInfoDump) then set f = `cat $infofile | awk -v r=$run '{if($2 == r) print $11}' | head -n 1` set dumpfile = $outdir/log/$FName-infodump.dat set ud = (`UpdateNeeded $dumpfile $f`) if($ud || $ForceUpdate) then set cmd = (mri_probedicom --i $f) if($DoSiemensAscii == 0) set cmd = ($cmd --no-siemens-ascii) $cmd >& $dumpfile if($status) cat $dumpfile | tee -a $LF else echo "$dumpfile does not need updating" | tee -a $LF endif endif if($DoFIPS) then set f = `cat $infofile | awk -v r=$run '{if($2 == r) print $11}' | head -n 1` # Get full path set fd = `dirname $f`; pushd $fd > /dev/null set fd = `pwd` popd > /dev/null set f = $fd/`basename $f`; # Create XML File set cmd = (fips-set --def-template --project $Project --site $Site \ --birnid $BIRNID --visit $VisitNo --studyname MRI --studyid 001 \ --datafile $f --run $fipsRun --paradigm $fipsPar \ --dicom-date --o $outdir/fips-process.xml --disacqs $NSkip) # Note: spec --disacqs here. There is a skip above, but that is for # when the dicom data are converted, and this applies to the dicom # data itself. A skip should always be specified, even if it is 0. # This can cause some confusion because the fips-process.xml file # will be with the converted file but will not necessarily apply to it. $cmd | tee -a $LF if($status) exit 1; endif end set tSecEnd = `date '+%s'`; @ tSecRun = $tSecEnd - $tSecStart; set tRunMins = `echo $tSecRun/60|bc -l` set tRunMins = `printf %5.2f $tRunMins` echo "Started at $StartTime " |& tee -a $LF echo "Ended at `date`" |& tee -a $LF echo "dcmunpack-Run-Time-Min $tRunMins" |& tee -a $LF if($ErrorsFound > 0) then echo "WARNING: $ErrorsFound errors during conversion, check logs" |& tee -a $LF endif echo "" | tee -a $LF echo "" | tee -a $LF date | tee -a $LF echo "dcmunpack done" | tee -a $LF exit 0 ############################################### ############--------------################## parse_args: set cmdline = ($argv); while( $#argv != 0 ) set flag = $argv[1]; shift; switch($flag) case "-targ": case "-trg": if($#argv < 1) goto arg1err; set TargetDir = "$argv[1]"; shift; set DoUnpack = 1; breaksw case "-index-in": if($#argv < 1) goto arg1err; set SrcInfo = "$argv[1]"; shift; if(! -e $SrcInfo) then echo "ERROR: cannot find $SrcInfo" exit 1; endif breaksw case "-index-out": if($#argv < 1) goto arg1err; set infofile = "$argv[1]"; shift; breaksw case "-pre": if($#argv < 1) goto arg1err; set SrcPre = "$argv[1]"; shift; breaksw case "-pat": if($#argv < 1) goto arg1err; set SrcPat = "$argv[1]"; shift; breaksw case "-ext": if($#argv < 1) goto arg1err; set SrcExt = "$argv[1]"; shift; breaksw case "-key": if($#argv < 1) goto arg1err; set Key = "$argv[1]"; shift; breaksw case "-iid": if($#argv < 3) goto arg3err; set iid = ($argv[1] $argv[2] $argv[3]); shift; shift; shift; breaksw case "-ijd": if($#argv < 3) goto arg3err; set ijd = ($argv[1] $argv[2] $argv[3]); shift; shift; shift; breaksw case "-ikd": if($#argv < 3) goto arg3err; set ikd = ($argv[1] $argv[2] $argv[3]); shift; shift; shift; breaksw case "-base": set DoBase = 1; breaksw case "-itdicom": # This adds -it dicom to the mri_convert cmd line # This will force Seimens dicoms to be treated as generic # which may be helpful for some applications (eg, PET) set itdicom = ("-it dicom") breaksw case "-first-dicom": # Copy first dicom in the series set DoFirstDicom = 1 breaksw case "-src": case "-d": if($#argv < 1) goto arg1err; set d = "$argv[1]"; shift; if(! -e $d) then echo "ERROR: cannot find $d" exit 1; endif if(! -r $d) then echo "ERROR: $d exists but is not readable" exit 1; endif set d = `getfullpath $d` set SrcDirList = ($SrcDirList $d); breaksw case "-run": if($#argv < 4) goto arg4err; set RunNo = "$argv[1]"; shift; set RunNos = ($RunNos $RunNo); set SubDir = "$argv[1]"; shift; set SubDirs = ($SubDirs $SubDir); set Format = "$argv[1]"; shift; if($Format != nii && $Format != nii.gz &&\ $Format != img &&\ $Format != mgh && $Format != mgz) then echo "ERROR: format $Format not recoginzed" echo "Valid values are nii, nii.gz, mgh, and mgz" exit 1; endif set Formats = ($Formats $Format); set FName = "$argv[1]"; shift; # Strip extension from FName, if there fname2stem $FName >& /dev/null if($status == 0) set FName = `fname2stem $FName`; set FNames = ($FNames $FName); # Optional next argument is nskip set NSkip = 0; if($#argv != 0) then set tmp = $argv[1]; set c = `echo $tmp | cut -c 1` if("$c" != "-") then set NSkip = $argv[1]; shift; endif endif set NSkips = ($NSkips $NSkip) # Optional next argument is ndrop set NDrop = 0; if($#argv != 0) then set tmp = $argv[1]; set c = `echo $tmp | cut -c 1` if("$c" != "-") then set NDrop = $argv[1]; shift; endif endif set NDrops = ($NDrops $NDrop) set DoUnpack = 1; breaksw case "-auto-runseq": if($#argv < 1) goto arg1err; set AutoRunSeqFmt = $argv[1]; shift; set DoAutoRunSeq = 1 set DoUnpack = 1; set FSFAST = 0; breaksw case "-keep-scouts" set KeepScouts = 1; breaksw case "-no-rescale-dicom" setenv FS_RESCALE_DICOM 0 breaksw case "-rescale-dicom" # This is currently the default for mri_convert setenv FS_RESCALE_DICOM 1 breaksw case "-fips": if($#argv < 4) goto arg4err; set Project = "$argv[1]"; shift; set Site = "$argv[1]"; shift; set BIRNID = "$argv[1]"; shift; set VisitNo = "$argv[1]"; shift; set DoUnpack = 1; set DoFIPS = 1; breaksw case "-fips-run": if($#argv < 2) goto arg2err; set RunNo = "$argv[1]"; shift; set RunNos = ($RunNos $RunNo); set RunPar = "$argv[1]"; shift; set RunPars = ($RunPars $RunPar); # Optional next argument is nskip set NSkip = 0; if($#argv != 0) then set tmp = $argv[1]; set c = `echo $tmp | cut -c 1` if("$c" != "-") then set NSkip = $argv[1]; shift; endif endif set NSkips = ($NSkips $NSkip) # Optional next argument is ndrop set NDrop = 0; if($#argv != 0) then set tmp = $argv[1]; set c = `echo $tmp | cut -c 1` if("$c" != "-") then set NDrop = $argv[1]; shift; endif endif set NDrops = ($NDrops $NDrop) set DoUnpack = 1; set DoFIPS = 1; breaksw case "-no-convert": case "-xml-only": set DoConvert = 0; breaksw case "-copy-only": set DoConvert = 0; set DoCopy = 1; breaksw case "--dcm2niix": case "-dcm2niix": case "-dcr3": set UseDCM2NIIX = 1; set DoSiemensAscii = 0; # Newer dicoms do not have ascii breaksw case "--no-dcm2niix": case "-no-dcm2niix": case "-no-dcr3": set UseDCM2NIIX = 1; breaksw case "--createBIDS": case "-createBIDS": set CreateBIDS = 1; breaksw case "-siemensBVecsCross" set siemensBVecsCross = 1; breaksw case "-no-siemensBVecsCross" set siemensBVecsCross = 0; breaksw case "-phase": set DoPhase = 1; breaksw case "-no-phase": set DoPhase = 0; breaksw case "-siemens-ascii": set DoSiemensAscii = 1; breaksw case "-no-siemens-ascii": # Newer dicoms do not have ascii and cause mri_probedicom to fail set DoSiemensAscii = 0; breaksw case "-max": set GetMax = 1; breaksw case "-extra-info": set DoExtraInfo = 1; breaksw case "-no-extra-info": set DoExtraInfo = 0; breaksw case "-generic": set FSFAST = 0; breaksw case "-fsfast": set FSFAST = 1; breaksw case "-noinfodump": case "-no-infodump": set DoInfoDump = 0; breaksw case "-log": if($#argv < 1) goto arg1err; set LF = "$argv[1]"; shift; breaksw case "-scanonly": case "-series": if($#argv < 1) goto arg1err; set SeriesInfo = "$argv[1]"; shift; breaksw case "-oneperdir": case "-one-per-dir": set OnePerDir = 1; breaksw case "-old-bourget": set SrcExt = "1.dcm" breaksw case "-mgh": case "-martinos": case "-bourget": set SrcExt = "0001.dcm" breaksw case "-gedcm": case "-one": set SrcExt = ".dcm"; set OnePerDir = 1; breaksw case "-no-exit-on-error": # continue to unpack data even if there is an error in coversion set ExitOnError = 0; breaksw case "-force-update": set ForceUpdate = 1 breaksw case "-no-force-update": set ForceUpdate = 0 breaksw case "-run-skip": if($#argv < 1) goto arg1err; set RunNoSkip = ($RunNoSkip $argv[1]); shift breaksw case "-no-dwi": setenv FS_LOAD_DWI 0 # turn off trying to read DWI parameters breaksw case "-debug": set verbose = 1; set echo = 1; breaksw default: echo ERROR: Flag $flag unrecognized. echo $cmdline exit 1 breaksw endsw end goto parse_args_return; ############--------------################## ############--------------################## check_params: if($#SrcDirList == 0) then echo "ERROR: must specify an list of input directories" exit 1; endif if($OnePerDir && $#SrcPre == 0 && $#SrcPat == 0 && $#SrcExt == 0) then echo "ERROR: must spec -pre, -pat, and/or -ext with -one-per-dir" exit 1; endif if($DoUnpack) then if($#TargetDir == 0) then echo "ERROR: need target directory" exit 1; endif if($#RunNos != 0 && $DoAutoRunSeq) then echo "ERROR: cannot use -run and -auto-runseq at the same time" exit 1; endif if($#RunNos == 0 && ! $DoAutoRunSeq) then echo "ERROR: need input runs" exit 1; endif if($DoFIPS) then if($#Project == 0) then echo "ERROR: need project, etc, with FIPS" exit 1; endif if($#SubDirs != 0) then echo "ERROR: cannot spec -fips-run and -run" exit 1; endif # Sort the list of run numbers in ascending order and get # the run-within-paraidgm number set tmp = `fs_temp_file` #set tmp = dcmdir.tmp rm -f $tmp @ nth = 0; foreach run ($RunNos) @ nth = $nth + 1; echo " $run $RunPars[$nth] $NSkips[$nth] $NDrops[$nth]" >> $tmp end # Sort by paradigm set tmp2 = $tmp.2 cat $tmp | sort -k 2 > $tmp2 # Sort each paradigm by run set tmp3 = $tmp.3 rm -f $tmp3 set ParList = (`cat $tmp | awk '{print $2}' | sort | uniq`) foreach par ($ParList) cat $tmp2 | sort -n -k 1 | \ awk -v p=$par 'BEGIN{n=1}{if($2 == p) print $0" "n; if($2 == p)n++}' >> $tmp3 end set RunNos = `cat $tmp3 | awk '{print $1}'` set RunPars = `cat $tmp3 | awk '{print $2}'` set NSkips = `cat $tmp3 | awk '{print $3}'` set NDrops = `cat $tmp3 | awk '{print $4}'` set RunParNos = `cat $tmp3 | awk '{print $5}'` rm -f $tmp $tmp2 $tmp3 endif # Make sure no runs specified twice foreach run1 ($RunNos) @ n = 0; foreach run2 ($RunNos) if($run1 == $run2) @ n = $n + 1; end if($n > 1) then echo "ERROR: run $run1 is specified multiple times" exit 1; endif end endif # This controls how the bvecs are computed. Previously, the function # called dcmGetDWIParamsSiemens() would attempt to convert the bvecs # to voxel space on a slice-by-slice basis; this was problematic # because the slice normal was not known so it was computed using a # cross product; but the cross product has a sign ambiguity that # turned out to be wrong when det<0. Now, by default, this function # will leave the bvecs in scanner space, then convert them to voxel # space once the final vox2ras is known. If one wants to override this # behavior and revert back to using the cross, then use # -siemensBVecsCross. Note that if # FS_dcmGetDWIParamsSiemens_VoxelSpace is already set, # siemensBVecsCross will be set to that value (which can then be # overridden with -siemensBVecsCross or -no-siemensBVecsCross) if($siemensBVecsCross) then setenv FS_dcmGetDWIParamsSiemens_VoxelSpace 1; else unsetenv FS_dcmGetDWIParamsSiemens_VoxelSpace endif goto check_params_return; ############--------------################## ############--------------################## arg1err: echo "ERROR: flag $flag requires one argument" exit 1 ############--------------################## ############--------------################## arg3err: echo "ERROR: flag $flag requires three arguments" exit 1 ############--------------################## ############--------------################## arg4err: echo "ERROR: flag $flag requires four arguments" exit 1 ############--------------################## ############--------------################## usage_exit: echo "" echo "dcmunpack : run with -help for more info" echo "" echo "Required Arguments:"; echo " -src dcmdir <-src dcmdir>" echo "" echo "Other Arguments" echo " -targ targetdir" echo " -run run subdir format stemname < ndrop>" echo " -auto-runseq format : save all scans in the targetdir as runo.seqname.format" echo " -keep-scouts : unpack series with 'scout' or 'setter' in the name" echo " -scanonly file : only scan the directory and put result in file" echo " -one-per-dir : assume that there is only one dicom series in each subdir" echo " -gedcm : same as -one-per-dir -ext dcm" echo " -ext extension : input extension (eg, dcm)" echo " -pre prefix : input prefix (ie, input file name init string)" echo " -pat pattern : input pattern (ie, string that occurs in the middle of file name)" echo " -no-infodump : do not create infodump.dat" echo " -generic : do not use fs-fast hierarchy" echo " -copy-only" echo " -no-convert : do not convert to output format" echo " -force-update : convert even if output is newer than the input dicom" echo " -max : print out max in given dicom file" echo " -base : report filename without path" echo " -key keystring : put keystring before each run line (good for searching)" echo " -index-out index.out.dat : save index of files to index.out.dat (for re-use)" echo " this file will also be stored in targetdir/log/imagelist.dat" echo " -index-in index.dat : read index of files (can make things much faster on 2nd run) " echo " -itdicom : add -it dicom to mri_convert cmd line" echo " -no-exit-on-error : continue to unpack data even if there is an error in coversion" echo " -run-skip runno : skip a given run (good when using -auto-runseq)" echo " -no-rescale-dicom : turn off DICOM rescaling based on tags (0028,1052) (0028,1053)" echo " -rescale-dicom : turn it on (default)" echo " -no-dwi : turn off trying to read DWI parameters" echo " -iid dcx dcy dcz : set -iid to mri_convert" echo " -ijd dcx dcy dcz : set -ijd to mri_convert" echo " -ikd dcx dcy dcz : set -ikd to mri_convert" echo " -extra-info : add session info to each line of the info file (pat, date, man, scan, field, serno)" echo " -first-dicom : copy first dicom file into output folder. This was implemented to " echo " be able to have the pixel data from a dicom file with little or no tissue in it" if($UseDCM2NIIX) then echo " -no-dcm2niix : Turn it off" else echo " -dcm2niix : use internal version of dcm2niix to convert (output still user spec)" echo " -createBIDS : generate a Brain Imaging Data Structure file in the JSON text format." endif echo " -phase : add the string _phase to volumes that are phase images based on ImageType" echo "" echo " -fips project site birnid visit" echo " -fips-run run paradigm < ndrop>" echo " -xml-only : for fips, only create xml file, do not convert to output" echo "" echo " -log logfile" echo " -debug" echo " -help" echo "" if(! $PrintHelp) exit 1; echo $VERSION cat $0 | awk 'BEGIN{prt=0}{if(prt) print $0; if($1 == "BEGINHELP") prt = 1 }' exit 1; #---- Everything below here is printed out as part of help -----# BEGINHELP Sorts and converts a directory of DICOM files (Siemens, GE, Philips) into an output hierarchy with nifti (nii), mgh, mgz, or analyze output formats (will not create a series of 3D SPM files). This will recursively search through all the subdirectories of the source directory. To a large extent, this replaces unpacksdcmdir (the Siemens-only unpacker) and will take most of its command-line arguments. This program can often take a long time to run and usually has to be run twice, once to get the list of runs and second to specify which runs to unpack. There are two ways to make it run faster. First, use -auto-runseq (see below) which will unpack all runs. Alternatively, when you run it the first time to get a list of runs, add -index-out index.dat. Then when you run it a second time, use -index-in index.dat to make it run much faster. -src dcmdir <-src dcmdir> Dicom source directory. You can specify more than one. If you just specify a source directory, it will give a summary of what it finds (like -scanonly did for unpacksdcmdir). You should still give it -one-per-dir or -martinos if applicable. -targ targetdir Output directory. Do not need to include when just getting information about what is in the directory. -run run subdir format stemname < ndrop> Specify unpacking rules for a given run (series), subdir is the subdirectory under the target dir, format is the format extension (nii, mgh, mgz, img), stemname is the base file name, nskip is the number of time points to skip (optional, good for some fMRI), and ndrop is the number of time points to drop from the end. The output file will be targetdir/subdir/RRR/fname.format if using the FSFAST output hierarchy (the default) or targetdir/subdir/fname.format with -generic, where RRR is the 3-digit, zero-padded run number. Eg, "-run 3 bold nii f" would become targetdir/bold/003/f.nii in fsfast or targetdir/bold/f.nii in generic. If the stemname has an extension, that extension is ignored. -auto-runseq format Save all scans in the targetdir as runo.seqname.format. Eg, -auto-runseq nii.gz would save files with names like 0002.mprage.nii.gz, 0003.ge_functionals.nii.gz, etc. This can be easier than using the -run because you do not have to specify all the runs on the command line and you only need to run this dcmunpack once. It will exclude any sequneces named Localizer, localizer, AAHScout, AHScout_sag, AAHScout_cor, AAHScout_tra, AAScout. If you want to skip a run, then add -run-skip runno. If there are errors in the conversion, then, by default, dcmunpack will exit with error. If you want to convert all you can and deal with the errors later, then add -no-exit-on-error. -one-per-dir Assume that the source directory (or subdirectory) contains only one series. This is usually the case for GE, and this can speed things up tremendously. -martinos -mgh -bourget Assume that the DICOM file names have the form produced at the MGH Martinos Center when you "push something to bourget" from the scanner, namely that each series will have one file that ends in "1.dcm", eg 397000-000007-000001.dcm. This can speed things up considerably. Note: as of August, 2012, the naming convention that allows for fast unpacking does not exist. If you have to run this twice, it will be faster if you run it with --index-out index.dat when you are getting a list of runs, then run it again with --index-in index.dat when you go to unpack it. -no-infodump Do not create the fname-infodump.dat file -generic Do not use FSFAST hierarchy. -no-convert Do not actually run mri_convert -copy-only Only copy dicom files to output directory (implies -no-convert) EXAMPLE # CD into the dicom directory cd Avanto-25096-20100325-162822-229000 # See what's there dcmunpack -src . -martinos --------------------------------------- Searching for matching files Mon Jul 12 10:21:10 EDT 2010 Mon Jul 12 10:21:10 EDT 2010 Found 6 total files. Found 6 unique series: 1 2 3 4 5 6 Subject Subj5 Date 20100325 Time 162822.229000 Institution Martinos Center Bay 2 1 Localizer 2.95 7 20 0.546875 ROW 285 ./229000-000001-000001.dcm 2 AAScout 1.23 2.6 0 2.5\2.5 ROW 1085 ./229000-000002-000001.dcm 3 ge_functionals 40 2000 90 3.125\3.125 COL 2300 ./229000-000003-000001.dcm 4 ge_functionals 40 2000 90 3.125\3.125 COL 2300 ./229000-000004-000001.dcm 5 ge_functionals 40 2000 90 3.125\3.125 COL 2300 ./229000-000005-000001.dcm 6 ge_functionals 40 2000 90 3.125\3.125 COL --------------------------------------- # Now unpack it dcmunpack -src . -martinos -targ /space/ProjectDir/subj5 \ -run 3 bold nii f.nii \ -run 4 bold nii f.nii \ -run 5 bold nii f.nii \ -run 6 bold nii f.nii RELATIONSHIP TO UNPACKSDCMDIR unpacksdcmdir is the Siemens-only unpacker. dcmunpack will take the same command-line arguments except: -cfg, -seqcfg, -nspmzeropad, -no-unpackerr (it unpacks everything), and -scanonly (you can still get a scanonly-like summary of the data). dcmunpack does not accept SPM as an output format. The seq.info file is not created (it is not needed for newer versions of FSFAST). These features can be programmed, I just have not gotten around to it. Unlike unpacksdcmdir, dcmunpack searches subdirectories and can unpack GE data.