From d96196419842a62077e387c302e6bb1c11b8b205 Mon Sep 17 00:00:00 2001 From: Andrew Hoopes Date: Tue, 25 May 2021 16:23:51 -0400 Subject: [PATCH] tracula update (#859) --- distribution/FreeSurferColorLUT.txt | 99 +- distribution/trctrain/trctraindata.tar.gz | 2 +- include/cma.h | 90 +- infant/infant_recon_all | 2 +- infant/infant_recon_py | 2 +- mri_binarize/mri_binarize.cpp | 154 +- mri_vol2vol/mri_vol2vol.cpp | 11 +- scripts/CMakeLists.txt | 3 + scripts/apas2aseg | 2 +- scripts/bedpostx_mgh | 370 ++--- scripts/dmri_bset | 24 +- scripts/dmrirc.example | 67 +- scripts/dmrirc.long.example | 67 +- scripts/dmrirc.long.multiscan.example | 67 +- scripts/dmrirc.multiscan.example | 67 +- scripts/fslregister | 2 + scripts/spmseg | 4 +- scripts/trac-all | 722 ++++++--- scripts/trac-paths | 1337 +++++++++------- scripts/trac-preproc | 1712 +++++++++++---------- scripts/xcerebralseg | 4 +- trc/bite.cxx | 2 +- trc/bite.h | 3 +- trc/blood.cxx | 1505 +++++++++++++----- trc/blood.h | 83 +- trc/coffin.cxx | 357 ++--- trc/coffin.h | 84 +- trc/dmri_forrest.cxx | 18 +- trc/dmri_group.cxx | 54 +- trc/dmri_mergepaths.cxx | 47 +- trc/dmri_motion.cxx | 20 +- trc/dmri_paths.cxx | 145 +- trc/dmri_pathstats.cxx | 245 ++- trc/dmri_spline.cxx | 44 +- trc/dmri_train.cxx | 316 ++-- trc/dmri_trk2trk.cxx | 475 ++++-- trc/dmri_vox2vox.cxx | 86 +- trc/forrest.cxx | 26 +- trc/forrest.h | 15 +- trc/spline.cxx | 68 +- trc/spline.h | 20 +- trc/vial.cxx | 128 +- trc/vial.h | 11 +- utils/gca.cpp | 133 +- 44 files changed, 5305 insertions(+), 3388 deletions(-) diff --git a/distribution/FreeSurferColorLUT.txt b/distribution/FreeSurferColorLUT.txt index 5bf4591f235..1511f76e88e 100644 --- a/distribution/FreeSurferColorLUT.txt +++ b/distribution/FreeSurferColorLUT.txt @@ -1046,44 +1046,71 @@ # 5100 fmajor 204 102 102 0 5101 fminor 204 102 102 0 +5102 cc.body 204 102 102 0 +5103 cc.bodyc 255 153 153 0 +5104 cc.bodypf 255 153 153 0 +5105 cc.bodypm 255 204 204 0 +5106 cc.bodyp 255 102 102 0 +5107 cc.bodyt 255 204 204 0 +5108 cc.genu 255 102 102 0 +5109 cc.rostrum 204 51 51 0 +5110 cc.splenium 204 51 51 0 +5111 acomm 204 102 102 0 +5112 mcp 102 51 153 0 # -5102 lh.atr 255 255 102 0 -5103 lh.cab 153 204 0 0 -5104 lh.ccg 0 153 153 0 -5105 lh.cst 204 153 255 0 -5106 lh.ilf 255 153 51 0 -5107 lh.slfp 204 204 204 0 -5108 lh.slft 153 255 255 0 -5109 lh.unc 102 153 255 0 +5200 lh.atr 255 255 102 0 +5201 lh.cab 153 204 0 0 +5202 lh.ccg 0 153 153 0 +5203 lh.cst 204 153 255 0 +5204 lh.ilf 255 153 51 0 +5205 lh.slfp 204 204 204 0 +5206 lh.slft 153 255 255 0 +5207 lh.unc 102 153 255 0 +5208 lh.cb 0 153 153 0 +5209 lh.slf 204 204 204 0 +5210 lh.af 153 255 255 0 +5211 lh.ifof 51 153 51 0 +5212 lh.fx 255 153 204 0 +5213 lh.fat 204 51 102 0 +5214 lh.or 153 102 255 0 +5215 lh.mlf 255 255 204 0 +5216 lh.slf1 51 204 255 0 +5217 lh.slf2 51 255 204 0 +5218 lh.slf3 204 204 204 0 +5219 lh.afd 153 255 255 0 +5220 lh.afv 153 255 255 0 +5221 lh.ar 153 0 204 0 +5222 lh.cbd 0 153 153 0 +5223 lh.cbv 153 204 0 0 +5224 lh.emc 51 153 51 0 +5225 lh.uf 102 153 255 0 # -5110 rh.atr 255 255 102 0 -5111 rh.cab 153 204 0 0 -5112 rh.ccg 0 153 153 0 -5113 rh.cst 204 153 255 0 -5114 rh.ilf 255 153 51 0 -5115 rh.slfp 204 204 204 0 -5116 rh.slft 153 255 255 0 -5117 rh.unc 102 153 255 0 - -# These are the same tracula labels as above in human-readable form -5200 CC-ForcepsMajor 204 102 102 0 -5201 CC-ForcepsMinor 204 102 102 0 -5202 LAntThalRadiation 255 255 102 0 -5203 LCingulumAngBundle 153 204 0 0 -5204 LCingulumCingGyrus 0 153 153 0 -5205 LCorticospinalTract 204 153 255 0 -5206 LInfLongFas 255 153 51 0 -5207 LSupLongFasParietal 204 204 204 0 -5208 LSupLongFasTemporal 153 255 255 0 -5209 LUncinateFas 102 153 255 0 -5210 RAntThalRadiation 255 255 102 0 -5211 RCingulumAngBundle 153 204 0 0 -5212 RCingulumCingGyrus 0 153 153 0 -5213 RCorticospinalTract 204 153 255 0 -5214 RInfLongFas 255 153 51 0 -5215 RSupLongFasParietal 204 204 204 0 -5216 RSupLongFasTemporal 153 255 255 0 -5217 RUncinateFas 102 153 255 0 +5300 rh.atr 255 255 102 0 +5301 rh.cab 153 204 0 0 +5302 rh.ccg 0 153 153 0 +5303 rh.cst 204 153 255 0 +5304 rh.ilf 255 153 51 0 +5305 rh.slfp 204 204 204 0 +5306 rh.slft 153 255 255 0 +5307 rh.unc 102 153 255 0 +5308 rh.cb 0 153 153 0 +5309 rh.slf 204 204 204 0 +5310 rh.af 153 255 255 0 +5311 rh.ifof 51 153 51 0 +5312 rh.fx 255 153 204 0 +5313 rh.fat 204 51 102 0 +5314 rh.or 153 102 255 0 +5315 rh.mlf 255 255 204 0 +5316 rh.slf1 51 204 255 0 +5317 rh.slf2 51 255 204 0 +5318 rh.slf3 204 204 204 0 +5319 rh.afd 153 255 255 0 +5320 rh.afv 153 255 255 0 +5321 rh.ar 153 0 204 0 +5322 rh.cbd 0 153 153 0 +5323 rh.cbv 153 204 0 0 +5324 rh.emc 51 153 51 0 +5325 rh.uf 102 153 255 0 ######################################## diff --git a/distribution/trctrain/trctraindata.tar.gz b/distribution/trctrain/trctraindata.tar.gz index 42f69665bd8..c54fc897798 120000 --- a/distribution/trctrain/trctraindata.tar.gz +++ b/distribution/trctrain/trctraindata.tar.gz @@ -1 +1 @@ -../../.git/annex/objects/38/74/SHA256-s527649569--8461dba9dc4edccfb1f4f13647809023cd302619690c95b6c448ebe6a07a15a3/SHA256-s527649569--8461dba9dc4edccfb1f4f13647809023cd302619690c95b6c448ebe6a07a15a3 \ No newline at end of file +../../.git/annex/objects/PV/v9/SHA256E-s136824944--191035af650736242f2200feb662ab466d842ca45958a5d0667399f285c00420.tar.gz/SHA256E-s136824944--191035af650736242f2200feb662ab466d842ca45958a5d0667399f285c00420.tar.gz \ No newline at end of file diff --git a/include/cma.h b/include/cma.h index d99a6d708db..df988224d55 100644 --- a/include/cma.h +++ b/include/cma.h @@ -313,29 +313,77 @@ #define SUSPICIOUS 999 // 255 100 100 0 -// Tracula labeling +// TRACULA labeling +// Interhemispheric tracts #define fmajor 5100 // 204 102 102 0 #define fminor 5101 // 204 102 102 0 -#define lh_atr 5102 // 255 255 102 0 -#define lh_cab 5103 // 153 204 0 0 -#define lh_ccg 5104 // 0 153 153 0 -#define lh_cst 5105 // 204 153 255 0 -#define lh_ilf 5106 // 255 153 51 0 -#define lh_slfp 5107 // 204 204 204 0 -#define lh_slft 5108 // 153 255 255 0 -#define lh_unc 5109 // 102 153 255 0 -#define rh_atr 5110 // 255 255 102 0 -#define rh_cab 5111 // 153 204 0 0 -#define rh_ccg 5112 // 0 153 153 0 -#define rh_cst 5113 // 204 153 255 0 -#define rh_ilf 5114 // 255 153 51 0 -#define rh_slfp 5115 // 204 204 204 0 -#define rh_slft 5116 // 153 255 255 0 -#define rh_unc 5117 // 102 153 255 0 -#define lh_ifof 5118 // 153 255 255 0 -#define rh_ifof 5119 // 153 255 255 0 -#define lh_fornix 5120 // 204 102 153 0 -#define rh_fornix 5121 // 204 102 153 0 +#define cc_body 5102 // 255 153 153 0 +#define cc_bodyc 5103 // 255 102 102 0 +#define cc_bodypf 5104 // 255 102 102 0 +#define cc_bodypm 5105 // 255 153 153 0 +#define cc_bodyp 5106 // 255 102 102 0 +#define cc_bodyt 5107 // 255 153 153 0 +#define cc_genu 5108 // 255 102 102 0 +#define cc_rostrum 5109 // 204 51 51 0 +#define cc_splenium 5110 // 204 51 51 0 +#define acomm 5111 // 204 102 102 0 +#define mcp 5112 // 102 51 153 0 + +// Left hemi tracts +#define lh_atr 5200 // 255 255 102 0 +#define lh_cab 5201 // 153 204 0 0 +#define lh_ccg 5202 // 0 153 153 0 +#define lh_cst 5203 // 204 153 255 0 +#define lh_ilf 5204 // 255 153 51 0 +#define lh_slfp 5205 // 204 204 204 0 +#define lh_slft 5206 // 153 255 255 0 +#define lh_unc 5207 // 102 153 255 0 +#define lh_cb 5208 // 0 153 153 0 +#define lh_slf 5209 // 204 204 204 0 +#define lh_af 5210 // 153 255 255 0 +#define lh_ifof 5211 // 51 153 51 0 +#define lh_fx 5212 // 255 153 204 0 +#define lh_fat 5213 // 204 51 102 0 +#define lh_or 5214 // 153 102 255 0 +#define lh_mlf 5215 // 255 255 204 0 +#define lh_slf1 5216 // 51 204 255 0 +#define lh_slf2 5217 // 51 255 204 0 +#define lh_slf3 5218 // 204 204 204 0 +#define lh_afd 5219 // 153 255 255 0 +#define lh_afv 5220 // 153 255 255 0 +#define lh_ar 5221 // 153 0 204 0 +#define lh_cbd 5222 // 0 153 153 0 +#define lh_cbv 5223 // 153 204 0 0 +#define lh_emc 5224 // 51 153 51 0 +#define lh_uf 5225 // 102 153 255 0 + +// Right hemi tracts +#define rh_atr 5300 // 255 255 102 0 +#define rh_cab 5301 // 153 204 0 0 +#define rh_ccg 5302 // 0 153 153 0 +#define rh_cst 5303 // 204 153 255 0 +#define rh_ilf 5304 // 255 153 51 0 +#define rh_slfp 5305 // 204 204 204 0 +#define rh_slft 5306 // 153 255 255 0 +#define rh_unc 5307 // 102 153 255 0 +#define rh_cb 5308 // 0 153 153 0 +#define rh_slf 5309 // 204 204 204 0 +#define rh_af 5310 // 153 255 255 0 +#define rh_ifof 5311 // 51 153 51 0 +#define rh_fx 5312 // 255 153 204 0 +#define rh_fat 5313 // 204 51 102 0 +#define rh_or 5314 // 153 102 255 0 +#define rh_mlf 5315 // 255 255 204 0 +#define rh_slf1 5316 // 51 204 255 0 +#define rh_slf2 5317 // 51 255 204 0 +#define rh_slf3 5318 // 204 204 204 0 +#define rh_afd 5319 // 153 255 255 0 +#define rh_afv 5320 // 153 255 255 0 +#define rh_ar 5321 // 153 0 204 0 +#define rh_cbd 5322 // 0 153 153 0 +#define rh_cbv 5323 // 153 204 0 0 +#define rh_emc 5324 // 51 153 51 0 +#define rh_uf 5325 // 102 153 255 0 /* diff --git a/infant/infant_recon_all b/infant/infant_recon_all index 6035174b37a..11dd81dc776 100755 --- a/infant/infant_recon_all +++ b/infant/infant_recon_all @@ -688,7 +688,7 @@ endif set asegfile = $WORK_DIR/aseg.nii.gz # switching OLD thalamus labels to NEW FS standard ones -set cmd = (mri_binarize --i $asegfile --replace 48 49 --replace 9 10 --o $asegfile) +set cmd = (mri_binarize --i $asegfile --replaceonly 48 49 --replaceonly 9 10 --o $asegfile) echo $cmd >> $LF echo $cmd >> $sLF $cmd |& tee -a $LF diff --git a/infant/infant_recon_py b/infant/infant_recon_py index c1144a71f93..ea104504736 100755 --- a/infant/infant_recon_py +++ b/infant/infant_recon_py @@ -366,7 +366,7 @@ else: # Switching old thalamus labels to new FS ones recoded = 'work/recoded.nii.gz' - commands.append(f'mri_binarize --i {mrf_seg} --replace 48 49 --replace 9 10 --o {recoded}') + commands.append(f'mri_binarize --i {mrf_seg} --replaceonly 48 49 --replaceonly 9 10 --o {recoded}') # Full brain # TODO is this even used? diff --git a/mri_binarize/mri_binarize.cpp b/mri_binarize/mri_binarize.cpp index 970d98cf3e7..d3ba8dbe296 100644 --- a/mri_binarize/mri_binarize.cpp +++ b/mri_binarize/mri_binarize.cpp @@ -93,8 +93,22 @@ Replace every occurrence of (int) value V1 with value V2. Multiple --replaceonly V1 V2 Replace every occurrence of (int) value V1 with value V2. Multiple ---replace args are possible. Other locations in the source volume will be propagated -to the output (unlike --replace which masks those locations) +--replaceonly args are possible. Other locations in the source volume +will be propagated to the output (unlike --replace which masks those +locations). + +--replace-nn V1 W + +Replace every occurrence of (int) value V1 with that of its nearest +neighbor voxel within a window of W voxels. Multiple --replace-nn args +are possible. + +--replaceonly-nn V1 W + +Replace every occurrence of (int) value V1 with that of its nearest +neighbor voxel within a window of W voxels. Multiple --replaceonly-nn +args are possible. Other locations in the source volume will be propagated +to the output (unlike --replace-nn which masks those locations). --frame frameno @@ -252,7 +266,8 @@ int FDRSign = 0; int nErodeNN=0, NNType=0; static int replace_only = 0 ; -int nReplace = 0, SrcReplace[1000], TrgReplace[1000]; +int nReplace = 0, SrcReplace[1000], TrgReplace[1000], + nReplaceNN = 0, SrcReplaceNN[1000], ReplaceWindowNN[1000]; char *SurfFile=NULL; int nsmoothsurf=0; @@ -429,7 +444,7 @@ int main(int argc, char *argv[]) { MRIcopyHeader(InVol, OutVol); nhits = 0; - if(nReplace == 0){ + if(!replace_only){ // Binarize for(frame = fstart; frame <= fend; frame++){ // Do openmp for columns because often nframes = 1 @@ -495,10 +510,9 @@ int main(int argc, char *argv[]) { } // row } // col } // frame - } // if(nReplace == 0) + } // if(!replace_only) if(nReplace != 0) { - if (replace_only) { printf("Replacing %d and propagating source list\n",nReplace); @@ -517,7 +531,78 @@ int main(int argc, char *argv[]) { } } - if (noverbose == 0) + if(nReplaceNN != 0) { + if (replace_only) + { + printf("Replacing %d with nearest neighbors and propagating source list\n", nReplaceNN); + OutVol = MRIcopy(InVol, NULL) ; + } + else + printf("Replacing %d with nearest neighbors\n", nReplaceNN); + + for(frame = fstart; frame <= fend; frame++){ + for (c=0; c < InVol->width; c++) { + int r,s; + for (r=0; r < InVol->height; r++) { + for (s=0; s < InVol->depth; s++) { + if (!MaskVol || MRIgetVoxVal(MaskVol, c, r, s, 0) > MaskThresh) { + int segid = MRIgetVoxVal(InVol, c, r, s, frame); + + for (n = 0; n < nReplaceNN; n++) { + if (segid == SrcReplaceNN[n]) { + int whalf = (ReplaceWindowNN[n] - 1) / 2, + nn_val = segid; + float min_dist = 100000; + + for (int ds = -whalf; ds <= whalf; ds++) { + int s1 = s + ds; + + if (s1 < 0 || s1 >= InVol->depth) continue; + + for (int dr = -whalf; dr <= whalf; dr++) { + int r1 = r + dr; + + if (r1 < 0 || r1 >= InVol->height) continue; + + for (int dc = -whalf; dc <= whalf; dc++) { + int c1 = c + dc, + newsegid, isrep = 0; + float dist; + + if (c1 < 0 || c1 >= InVol->width) continue; + + newsegid = MRIgetVoxVal(InVol, c1, r1, s1, frame); + + for (int n1 = 0; n1 < nReplaceNN; n1++) + if (newsegid == SrcReplaceNN[n1]) { + isrep = 1; + break; + } + + if (isrep) continue; + + dist = sqrt((float) dc * dc + dr * dr + ds * ds); + + if (dist < min_dist) { + min_dist = dist; + nn_val = newsegid; + } + } // ck + } // rk + } // sk + + MRIsetVoxVal(OutVol, c, r, s, frame-fstart, nn_val); + break; + } + } // n + } // mask + } // s + } // r + } // c + } // frame + } + + if (noverbose == 0 && replace_only == 0) printf("Found %d values in range\n",nhits); if(nDilate3d > 0){ @@ -543,7 +628,7 @@ int main(int argc, char *argv[]) { } nhits = -1; - if(DoCount){ + if(DoCount && !replace_only){ if(noverbose == 0) printf("Counting number of voxels in first frame\n"); #ifdef HAVE_OPENMP #pragma omp parallel for if_ROMP(assume_reproducible) reduction(+ : nhits) @@ -581,7 +666,7 @@ int main(int argc, char *argv[]) { } // if we didn't binarize, copy any embedded color table from the input - if ((nReplace != 0) && (InVol->ct)) OutVol->ct = CTABdeepCopy(InVol->ct); + if (replace_only && (InVol->ct)) OutVol->ct = CTABdeepCopy(InVol->ct); // Save output if(OutVolFile) { @@ -606,7 +691,7 @@ int main(int argc, char *argv[]) { nvox = OutVol->width * OutVol->height * OutVol->depth; voxvol = OutVol->xsize * OutVol->ysize * OutVol->zsize; - if (noverbose == 0) + if (noverbose == 0 && replace_only == 0) printf("Count: %d %lf %d %lf\n",nhits,nhits*voxvol,nvox,(double)100*nhits/nvox); if(CountFile){ @@ -850,6 +935,21 @@ static int parse_commandline(int argc, char **argv) { nReplace++; nargsused = 2; } + else if (!strcasecmp(option, "--replace-nn")) { + if(nargc < 2) CMDargNErr(option,2); + sscanf(pargv[0],"%d",&SrcReplaceNN[nReplaceNN]); + sscanf(pargv[1],"%d",&ReplaceWindowNN[nReplaceNN]); + nReplaceNN++; + nargsused = 2; + } + else if (!strcasecmp(option, "--replaceonly-nn")) { + if(nargc < 2) CMDargNErr(option,2); + sscanf(pargv[0],"%d",&SrcReplaceNN[nReplaceNN]); + sscanf(pargv[1],"%d",&ReplaceWindowNN[nReplaceNN]); + replace_only = 1 ; + nReplaceNN++; + nargsused = 2; + } else if (!strcasecmp(option, "--binval")) { if (nargc < 1) CMDargNErr(option,1); sscanf(pargv[0],"%d",&BinVal); @@ -997,8 +1097,10 @@ static void print_usage(void) { printf(" --fdr-pos, --fdr-neg, --fdr-abs (use only pos, neg, or abs; abs is default)\n"); printf(" --match matchval : match instead of threshold\n"); printf(" --match-ctab colortable : match all entries in the given color table\n"); - printf(" --replaceonly V1 V2 : replace voxels=V1 with V2 and propagate other src voxels instead of binarizing\n"); printf(" --replace V1 V2 : replace voxels=V1 with V2\n"); + printf(" --replaceonly V1 V2 : replace voxels=V1 with V2 and propagate other src voxels instead of binarizing\n"); + printf(" --replace-nn V1 W : replace voxels=V1 with their nearest neighbor within a window of W voxels\n"); + printf(" --replaceonly-nn V1 W : replace voxels=V1 with their nearest neighbor within a window of W voxels and propagate other src voxels instead of binarizing\n"); printf(" --ctx-wm : set match vals to 2, 41, 77, 251-255 (aseg for cerebral WM)\n"); printf(" --all-wm : set match vals to 2, 41, 77, 251-255, 7, and 46, (aseg for all WM)\n"); printf(" --ventricles : set match vals those for aseg ventricles+choroid (not 4th)\n"); @@ -1114,6 +1216,26 @@ printf("\n"); printf("Replace every occurrence of (int) value V1 with value V2. Multiple \n"); printf("--replace args are possible.\n"); printf("\n"); +printf("--replaceonly V1 V2\n"); +printf("\n"); +printf("Replace every occurrence of (int) value V1 with value V2. Multiple\n"); +printf("--replaceonly args are possible. Other locations in the source volume\n"); +printf("will be propagated to the output (unlike --replace which masks those\n"); +printf("locations).\n"); +printf("\n"); +printf("--replace-nn V1 W\n"); +printf("\n"); +printf("Replace every occurrence of (int) value V1 with that of its nearest\n"); +printf("neighbor voxel within a window of W voxels. Multiple --replace-nn args\n"); +printf("are possible.\n"); +printf("\n"); +printf("--replaceonly-nn V1 W\n"); +printf("\n"); +printf("Replace every occurrence of (int) value V1 with that of its nearest\n"); +printf("neighbor voxel within a window of W voxels. Multiple --replaceonly-nn\n"); +printf("args are possible. Other locations in the source volume will be propagated\n"); +printf("to the output (unlike --replace-nn which masks those locations).\n"); +printf("\n"); printf("--frame frameno\n"); printf("\n"); printf("Use give frame of the input. 0-based. Default is 0.\n"); @@ -1175,9 +1297,13 @@ static void check_options(void) { } if(MinThreshSet == 0 && MaxThreshSet == 0 && RMinThreshSet == 0 && RMaxThreshSet == 0 && - !DoMatch && !DoFDR && nReplace == 0) { - printf("ERROR: must specify minimum and/or maximum threshold or match values\n"); - exit(1); + !DoMatch && !DoFDR) { + if(nReplace > 0 || nReplaceNN > 0) + replace_only = 1; + else { + printf("ERROR: must specify minimum and/or maximum threshold or match values\n"); + exit(1); + } } if((MinThreshSet || MaxThreshSet || RMinThreshSet || RMaxThreshSet) && DoMatch ) { printf("ERROR: cannot specify threshold and match values\n"); diff --git a/mri_vol2vol/mri_vol2vol.cpp b/mri_vol2vol/mri_vol2vol.cpp index d41550dfa0e..ed2b84a7cf1 100644 --- a/mri_vol2vol/mri_vol2vol.cpp +++ b/mri_vol2vol/mri_vol2vol.cpp @@ -2298,10 +2298,13 @@ MRI *MRIvol2volGCAM(MRI *src, LTA *srclta, GCA_MORPH *gcam, LTA *dstlta, MRI *vs vgdst_src->ysize != 1 || vgdst_src->zsize != 1){ if(vgdst_dst->width != 256 || vgdst_dst->height != 256 || vgdst_dst->depth != 256 || vgdst_dst->xsize != 1 || - vgdst_dst->ysize != 1 || vgdst_dst->zsize != 1){ - printf("ERROR: MRIvol2volGCAM(): neither src nor dst VG of Dest LTA is conformed\n"); - return(NULL); - } + vgdst_dst->ysize != 1 || vgdst_dst->zsize != 1) + if(getenv("MY_MORPHS_DO_NOT_CONFORM_DEAL_WITH_IT") == NULL) { + printf("ERROR: MRIvol2volGCAM(): neither src nor dst VG of Dest LTA is conformed\n"); + return(NULL); + } + else + printf("WARN: MRIvol2volGCAM(): neither src nor dst VG of Dest LTA is conformed\n"); else { printf("MRIvol2volGCAM(): Inverting Destination LTA\n"); LTAinvert(dstlta,dstlta); diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 08e31a15a75..10d21e1fa12 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -35,8 +35,11 @@ install_configured( defect2seg defect-seg dicom-rename + dmri_bset dmrirc.example dmrirc.long.example + dmrirc.long.multiscan.example + dmrirc.multiscan.example dt_recon epidewarp.fsl extract_talairach_avi_QA.awk diff --git a/scripts/apas2aseg b/scripts/apas2aseg index dc229d90220..7b078ecd22a 100755 --- a/scripts/apas2aseg +++ b/scripts/apas2aseg @@ -68,7 +68,7 @@ set cmd = (mri_binarize --i $apas --o $outseg) while ($n <= 35) @ lh = 1000 + $n @ rh = 2000 + $n - set cmd = ($cmd --replace $lh 3 --replace $rh 42) + set cmd = ($cmd --replaceonly $lh 3 --replaceonly $rh 42) @ n = $n + 1; end diff --git a/scripts/bedpostx_mgh b/scripts/bedpostx_mgh index dc20cfe586d..9d4b23c8a8f 100755 --- a/scripts/bedpostx_mgh +++ b/scripts/bedpostx_mgh @@ -1,27 +1,27 @@ -#!/bin/bash +#!/bin/sh # bedpostx_mgh # (This script was modified from FSL's bedpostx by Anastasia Yendiki) -# Copyright (C) 2004 University of Oxford +# Copyright (C) 2004,2013 University of Oxford # # Part of FSL - FMRIB's Software Library # http://www.fmrib.ox.ac.uk/fsl # fsl@fmrib.ox.ac.uk -# +# # Developed at FMRIB (Oxford Centre for Functional Magnetic Resonance # Imaging of the Brain), Department of Clinical Neurology, Oxford # University, Oxford, UK -# -# +# +# # LICENCE -# -# FMRIB Software Library, Release 4.0 (c) 2007, The University of +# +# FMRIB Software Library, Release 6.0 (c) 2018, The University of # Oxford (the "Software") -# -# The Software remains the property of the University of Oxford ("the -# University"). -# +# +# The Software remains the property of the Oxford University Innovation +# ("the University"). +# # The Software is distributed "AS IS" under this Licence solely for # non-commercial use in the hope that it will be useful, but in order # that the University as a charitable foundation protects its assets for @@ -33,13 +33,13 @@ # all responsibility for the use which is made of the Software. It # further disclaims any liability for the outcomes arising from using # the Software. -# +# # The Licensee agrees to indemnify the University and hold the # University harmless from and against any and all claims, damages and # liabilities asserted by third parties (including claims for # negligence) which arise directly or indirectly from the use of the # Software or the sale of any products based on the Software. -# +# # No part of the Software may be reproduced, modified, transmitted or # transferred in any form or by any means, electronic or mechanical, # without the express permission of the University. The permission of @@ -50,7 +50,7 @@ # transmitted product. You may be held legally responsible for any # copyright infringement that is caused or encouraged by your failure to # abide by these terms and conditions. -# +# # You are not permitted under this Licence to use this Software # commercially. Use for which any financial return is received shall be # defined as commercial use, and includes (1) integration of all or part @@ -62,20 +62,10 @@ # final aim of developing non-software products for sale or license to a # third party, or (4) use of the Software to provide any service to an # external organisation for which payment is received. If you are -# interested in using the Software commercially, please contact Isis -# Innovation Limited ("Isis"), the technology transfer company of the +# interested in using the Software commercially, please contact Oxford +# University Innovation ("OUI"), the technology transfer company of the # University, to negotiate a licence. Contact details are: -# innovation@isis.ox.ac.uk quoting reference DE/1112. - -BPDIR=`dirname $0` - -if [ "x$SGE_ROOT" = "x" ] ; then - if [ -f /usr/local/share/sge/default/common/settings.sh ] ; then - . /usr/local/share/sge/default/common/settings.sh - elif [ -f /usr/local/sge/default/common/settings.sh ] ; then - . /usr/local/sge/default/common/settings.sh - fi -fi +# fsl@innovation.ox.ac.uk quoting Reference Project 9564, FSL. # Check if this is being run on PBS but isn't a job itself (AY) if [ -d /pbs ] && [ -z $PBS_JOBID ] ; then @@ -84,19 +74,26 @@ else dopbsjobs=0; fi +BPDIR=`dirname $0` + +export LC_ALL=C Usage() { echo "" - echo "Usage: bedpostx_mgh [options] ..." + echo "Usage: bedpostx [options]" echo "" echo "expects to find bvals and bvecs in subject directory" echo "expects to find data and nodif_brain_mask in subject directory" + echo "expects to find grad_dev in subject directory, if -g is set" echo "options (old syntax)" - echo "-n (number of fibres per voxel, default 2)" + echo "-n (number of fibres per voxel, default 3)" echo "-w (ARD weight, more weight means less secondary fibres per voxel, default 1)" echo "-b (burnin period, default 1000)" echo "-j (number of jumps, default 1250)" echo "-s (sample every, default 25)" + echo "-model (Deconvolution model. 1: with sticks, 2: with sticks with a range of diffusivities (default), 3: with zeppelins)" + echo "-g (consider gradient nonlinearities, default off)" + #echo "-c do not use CUDA capable hardware/queue (if found)" echo "" echo "" echo "ALTERNATIVELY: you can pass on xfibres options onto directly bedpostx" @@ -107,23 +104,23 @@ Usage() { echo "Note: Use EITHER old OR new syntax." echo "" echo "This is a modified version of FSL's bedpostx that is compatible with" - echo "the PBS queueing system running on launchpad/seychelles and can be" - echo "used by Martinos Center users to parallelize computation." + echo "the PBS queueing system running on launchpad and can be used by MGH" + echo "Martinos Center users to parallelize computation." echo "" echo "This script runs the exact same algorithm as bedpostx, but it submits" - echo "the processing for each slice as a separate PBS job. Thus, bedpostx" - echo "and bedpostx_mgh will give you the same result, but the former will" - echo "do it in days and the latter in hours." + echo "the processing for each slice as a separate PBS job. Thus," + echo "bedpostx_mgh will give you the same result as bedpostx, but do it" + echo "an order of magnitude faster." echo "" echo "Command line options and the structure of the input directory are the" echo "same as for the original bedpostx." echo "" - echo "Do not submit bedpostx_mgh as a job on launchpad/seychelles. Run it" - echo "directly at the launchpad/seychelles prompt and it will submit the" - echo "jobs for you. Note that this will generate a large number of jobs, so" - echo "don't launch it on more than one data set at the same time. You may" - echo "get some PBS emails about jobs being held that you have to release -" - echo "you can ignore these emails as the script will take care of that." + echo "Do not submit bedpostx_mgh as a job on launchpad. Run it directly at" + echo "the launchpad prompt and it will submit the jobs for you. Note that" + echo "this will generate a large number of jobs, so don't launch it on more" + echo "than one data set at the same time. You may get some PBS emails about" + echo "jobs being held that you have to release - you can ignore these" + echo "emails as this script will take care of that." exit 1 } @@ -131,32 +128,61 @@ Usage() { fslver=(`cat $FSLDIR/etc/fslversion | sed 's/\./ /g'`) if [ -z ${fslver[1]} ]; then fslver[1]=0; fi if [ -z ${fslver[2]} ]; then fslver[2]=0; fi - -# The order of bedpostx_single_slice arguments has been shifting around -# in different versions of FSL -if [ ${fslver[0]} -lt 4 ]; then - echo "Unsupported FSL version (${fslver[0]}.${fslver[1]}.${fslver[2]})" +if [ ${fslver[0]} -lt 6 ]; then + echo "Outdated FSL version (${fslver[0]}.${fslver[1]}.${fslver[2]})" + echo "Use 6.0.0 or newer" exit 1 -else - if [ ${fslver[0]} -eq 4 ] && [ ${fslver[1]} -eq 0 ]; then - if [ ${fslver[2]} -lt 2 ]; then - argorder=400; # Order as in FSL 4.0.0 - else - argorder=402; # Order as in FSL 4.0.2 - fi - elif [ ${fslver[0]} -eq 4 ] && [ ${fslver[1]} -eq 1 ]; then - if [ ${fslver[2]} -lt 5 ]; then - argorder=402; # Order as in FSL 4.0.2 - elif [ ${fslver[2]} -lt 9 ]; then - argorder=415; # Order as in FSL 4.1.5 - else - argorder=419; # Order as in FSL 4.1.9 - fi - else - argorder=419; # Order as in FSL 4.1.9 - fi fi +monitor(){ + cat < ${subjdir}.bedpostX/monitor +#!/bin/sh +echo +echo "----- Bedpostx Monitor -----" +finished=0 +lastprinted=0 +havedad=2 +while [ \$finished -eq 0 ] ; do + nfin=0 + slice=0 + errorFiles=\`ls ${subjdir}.bedpostX/logs/*.e* 2> /dev/null \` + for errorFile in \$errorFiles + do + if [ -s \$errorFile ]; then + echo An error ocurred. Please check file \$errorFile + kill -9 $$ + exit 1 + fi + done + while [ \$slice -le $nslices ];do + if [ -e ${subjdir}.bedpostX/logs/monitor/\$slice ]; then + nfin=\$((\$nfin + 1)) + fi + slice=\$((\$slice + 1)) + done + newmessages=\$((\$nfin - \$lastprinted)) + while [ "\$newmessages" -gt 0 ];do + lastprinted=\$((\$lastprinted + 1)) + echo \$lastprinted slices processed out of $nslices + newmessages=\$((\$newmessages - 1)) + done + if [ -f ${subjdir}.bedpostX/xfms/eye.mat ] ; then + finished=1 + echo "All slices processed" + exit + fi + if [ ! \$havedad -gt 0 ]; then + exit 0 + fi + if [ "x$SGE_ROOT" = "x" ] && [ $dopbsjobs -eq 0 ]; then + havedad=\`ps -e -o pid 2>&1 | grep "$$\\b" | wc -l\` + fi + sleep 180; +done +EOM + chmod +x ${subjdir}.bedpostX/monitor +} + make_absolute(){ dir=$1; if [ -d ${dir} ]; then @@ -172,13 +198,18 @@ make_absolute(){ [ "$1" = "" ] && Usage +myopts="$@" + #parse option arguments -nfibres=2 +nfibres=3 fudge=1 burnin=1000 njumps=1250 sampleevery=25 -model=1 +model=2 +gflag=0 +nocuda=0 +other="" while [ ! -z "$1" ] do @@ -192,14 +223,29 @@ do -j) njumps=$2;shift;; -s) sampleevery=$2;shift;; -model) model=$2;shift;; - *) break;; + -g) gflag=1;; + -c) nocuda=1;; + *) other=$other" "$1;; esac fi shift done opts="--nf=$nfibres --fudge=$fudge --bi=$burnin --nj=$njumps --se=$sampleevery --model=$model" defopts="--cnonlinear" -opts="$opts $defopts $*" +opts="$opts $defopts $other" +if [ -n "$SGE_ROOT" ]; then + # Look for an SGE queue + if [ -n "$FSLGECUDAQ" -a "$nocuda" -eq 0 ]; then + # Test that the queue exists + qconf -sq $FSLGECUDAQ 2>&1 >/dev/null + if [ $? -eq 0 ]; then + # CUDA queue exists + if [ -x $0_gpu ]; then + exec $0_gpu $myopts + fi + fi + fi +fi # Process multiple input directories, queue them up serially (AY) for subjdir in $dirlist; do @@ -217,13 +263,21 @@ if [ ! -d $subjdir ]; then fi if [ ! -e ${subjdir}/bvecs ]; then + if [ -e ${subjdir}/bvecs.txt ]; then + mv ${subjdir}/bvecs.txt ${subjdir}/bvecs + else echo "${subjdir}/bvecs not found" exit 1 + fi fi if [ ! -e ${subjdir}/bvals ]; then + if [ -e ${subjdir}/bvals.txt ]; then + mv ${subjdir}/bvals.txt ${subjdir}/bvals + else echo "${subjdir}/bvals not found" exit 1 + fi fi if [ `${FSLDIR}/bin/imtest ${subjdir}/data` -eq 0 ]; then @@ -231,149 +285,77 @@ if [ `${FSLDIR}/bin/imtest ${subjdir}/data` -eq 0 ]; then exit 1 fi +if [ ${gflag} -eq 1 ]; then + if [ `${FSLDIR}/bin/imtest ${subjdir}/grad_dev` -eq 0 ]; then + echo "${subjdir}/grad_dev not found" + exit 1 + fi +fi + if [ `${FSLDIR}/bin/imtest ${subjdir}/nodif_brain_mask` -eq 0 ]; then echo "${subjdir}/nodif_brain_mask not found" exit 1 fi +if [ -e ${subjdir}.bedpostX/xfms/eye.mat ]; then + echo "${subjdir} has already been processed: ${subjdir}.bedpostX." + echo "Delete or rename ${subjdir}.bedpostX before repeating the process." + exit 1 +fi + echo Making bedpostx directory structure mkdir -p ${subjdir}.bedpostX/ mkdir -p ${subjdir}.bedpostX/diff_slices mkdir -p ${subjdir}.bedpostX/logs -mkdir -p ${subjdir}.bedpostX/logs/pid_${$} +mkdir -p ${subjdir}.bedpostX/logs/monitor mkdir -p ${subjdir}.bedpostX/xfms mailto=`whoami` echo Queuing preprocessing stages if [ "x$mergeid" = "x" ] ; then - preprocid=`${BPDIR}/fsl_sub_mgh -T 60 -m a -N bedpostx_pre -l ${subjdir}.bedpostX/logs ${FSLDIR}/bin/bedpostx_preproc.sh ${subjdir}` + preprocid=`${BPDIR}/fsl_sub_mgh -T 60 -m a -N bedpostx_pre -l ${subjdir}.bedpostX/logs ${FSLDIR}/bin/bedpostx_preproc.sh ${subjdir} ${gflag}` else - preprocid=`${BPDIR}/fsl_sub_mgh -j $mergeid -T 60 -m a -N bedpostx_pre -l ${subjdir}.bedpostX/logs ${FSLDIR}/bin/bedpostx_preproc.sh ${subjdir}` + preprocid=`${BPDIR}/fsl_sub_mgh -j $mergeid -T 60 -m a -N bedpostx_pre -l ${subjdir}.bedpostX/logs ${FSLDIR}/bin/bedpostx_preproc.sh ${subjdir} ${gflag}` fi echo Queuing parallel processing stage nslices=`${FSLDIR}/bin/fslval ${subjdir}/data dim3` [ -f ${subjdir}.bedpostX/commands.txt ] && rm ${subjdir}.bedpostX/commands.txt -if [ "x$SGE_ROOT" = "x" ] && [ $dopbsjobs -eq 0 ]; then - -# -# Need to set off a backgrounded monitoring task -# - cat < ${subjdir}.bedpostX/monitor -#!/bin/sh -finished=0 -logdir=${subjdir}.bedpostX/logs - -check() { - if [ \$finished -eq 1 ];then - echo "\$nfin slices processed" - else - nfin=0 - slice=0 - while [ "\$slice" -le $nslices ];do - slicezp=\`\$FSLDIR/bin/zeropad \$slice 4\` - isimg=\`\$FSLDIR/bin/imtest ${subjdir}.bedpostX/diff_slices/data_slice_\$slicezp/dyads1\` - if [ \$isimg -eq 1 ];then - nfin=\$((\$nfin + 1)) - fi - slice=\$((\$slice + 1)) - done - if [ \$nfin -eq $nslices ] ; then - finished=1 - fi - echo "\$nfin slices processed" - fi -} -exit_test() { - isimg=\`\$FSLDIR/bin/imtest ${subjdir}.bedpostX/dyads1\` - if [ \$isimg -eq 0 ] ; then - echo For some reason the bedpostX process DOES NOT appear - echo to have successfully completed. Please examine your - echo results carefully. - else - echo All slices processed - fi -} -check -n=0 -while [ \$finished -eq 0 ] ; do - sleep 10 - if [ \$n -eq 60 ] ; then - check - n=0 - else - n=\$((\$n + 1)) - fi -done -exit_test -EOM - chmod +x ${subjdir}.bedpostX/monitor +monitor +if [ "x$SGE_ROOT" = "x" ] && [ $dopbsjobs -eq 0 ]; then ${subjdir}.bedpostX/monitor& - monitorpid=$! fi + slice=0 while [ $slice -lt $nslices ] do slicezp=`$FSLDIR/bin/zeropad $slice 4` - if [ `$FSLDIR/bin/imtest ${subjdir}.bedpostX/diff_slices/data_slice_$slicezp/dyads1` -eq 1 ];then + if [ `$FSLDIR/bin/imtest ${subjdir}.bedpostX/diff_slices/data_slice_$slicezp/dyads1` -eq 1 ] && [ -f ${subjdir}.bedpostX/logs/monitor/$slice ];then echo "slice $slice has already been processed" else - if [ $argorder -eq 400 ]; then - echo "${FSLDIR}/bin/bedpostx_single_slice.sh $subjdir $nfibres $fudge $burnin $slice" \ - >> ${subjdir}.bedpostX/commands.txt - elif [ $argorder -eq 402 ]; then - echo "${FSLDIR}/bin/bedpostx_single_slice.sh $subjdir $nfibres $fudge $burnin $njumps $sampleevery $slice" \ - >> ${subjdir}.bedpostX/commands.txt - elif [ $argorder -eq 415 ]; then - echo "${FSLDIR}/bin/bedpostx_single_slice.sh $subjdir $nfibres $fudge $burnin $njumps $sampleevery $model $slice" \ - >> ${subjdir}.bedpostX/commands.txt - elif [ $argorder -eq 419 ]; then - echo "${FSLDIR}/bin/bedpostx_single_slice.sh $subjdir $slice $opts" \ - >> ${subjdir}.bedpostX/commands.txt - fi + [ -f ${subjdir}.bedpostX/logs/monitor/$slice ] && rm ${subjdir}.bedpostX/logs/monitor/$slice + if [ ${gflag} -eq 1 ]; then + gopts="$opts --gradnonlin=${subjdir}/grad_dev_slice_${slicezp}" + else + gopts=$opts + fi + echo "${FSLDIR}/bin/bedpostx_single_slice.sh ${subjdir} ${slice} $gopts" \ + >> ${subjdir}.bedpostX/commands.txt fi slice=$(($slice + 1)) done - bedpostid=`${BPDIR}/fsl_sub_mgh -j $preprocid -l ${subjdir}.bedpostX/logs -m a -N bedpostx -t ${subjdir}.bedpostX/commands.txt` echo Queuing post processing stage mergeid=`${BPDIR}/fsl_sub_mgh -j $bedpostid -T 60 -m ae -N bedpostx_post -l ${subjdir}.bedpostX/logs ${FSLDIR}/bin/bedpostx_postproc.sh $subjdir` -[ "x$SGE_ROOT" = "x" ] && [ $dopbsjobs -eq 0 ] && kill $monitorpid +echo $mergeid > ${subjdir}.bedpostX/logs/postproc_ID -if [ "x$SGE_ROOT" != "x" ]; then +if [ "x$SGE_ROOT" != "x" ] || [ $dopbsjobs -eq 1 ]; then echo echo Type ${subjdir}.bedpostX/monitor to show progress. - cat < ${subjdir}.bedpostX/monitor -#!/bin/sh -finished=0 -logdir=${subjdir}.bedpostX/logs -while [ \$finished -eq 0 ] ; do - nfin=0 - slice=0 - while [ "\$slice" -le $nslices ];do - slicezp=\`\$FSLDIR/bin/zeropad \$slice 4\` - isimg=\`\$FSLDIR/bin/imtest ${subjdir}.bedpostX/diff_slices/data_slice_\$slicezp/dyads1\` - if [ \$isimg -eq 1 ];then - nfin=\$((\$nfin + 1)) - fi - slice=\$((\$slice + 1)) - done - echo "\$nfin slices processed" - - if [ -f ${subjdir}.bedpostX/xfms/eye.mat ] ; then - finished=1 - echo "All slices processed" - fi - - sleep 600; -done -EOM - chmod +x ${subjdir}.bedpostX/monitor - echo Type ${subjdir}.bedpostX/cancel to terminate all the queued tasks. cat < ${subjdir}.bedpostX/cancel #!/bin/sh @@ -384,54 +366,8 @@ EOC echo echo You will get an email at the end of the post-processing stage. echo -elif [ $dopbsjobs -eq 1 ] ; then - echo - echo Type ${subjdir}.bedpostX/monitor on `hostname` to show progress. - cat < ${subjdir}.bedpostX/monitor -#!/bin/sh -finished=0 -logdir=${subjdir}.bedpostX/logs -while [ \$finished -eq 0 ] ; do - nfin=0 - for job in \`cat \$logdir/joblist | awk '{print \$2}'\` ; do - status=\`jobinfo \$job | grep Exit | awk '{print \$3}'\` - if [ "\$status" -eq 0 ] ; then let nfin=nfin+1; fi - done - if [ \$nfin -eq $nslices ] ; then - finished=1 - fi - - echo "\$nfin of $nslices slices processed" - sleep 600; -done -EOM - chmod +x ${subjdir}.bedpostX/monitor - - echo Type ${subjdir}.bedpostX/cputime on `hostname` to show CPU time of completed jobs. - cat < ${subjdir}.bedpostX/cputime -#!/bin/sh -logdir=${subjdir}.bedpostX/logs -for jobname in \`cat \$logdir/joblist | awk '{print \$1}' | sort\` ; do - jobid=\`grep \$jobname \$logdir/joblist | awk '{print \$2}'\` - jobtime=\`jobinfo \$jobid | grep Cputime | awk '{print \$2}'\` - if [ "\${jobtime}x" != "x" ]; then - echo "\$jobname \$jobtime" - fi -done -EOT - chmod +x ${subjdir}.bedpostX/cputime - - echo Type ${subjdir}.bedpostX/cancel on `hostname` to terminate all the queued tasks. - cat < ${subjdir}.bedpostX/cancel -#!/bin/sh -logdir=${subjdir}.bedpostX/logs -qdel $mergeid \`sort -r \$logdir/joblist | awk '{printf \$2 " "}'\` $preprocid -EOC - chmod +x ${subjdir}.bedpostX/cancel - - echo - echo You will get an email at the end of the post-processing stage. - echo +else + sleep 190 fi # Process multiple input directories, queue them up serially (AY) diff --git a/scripts/dmri_bset b/scripts/dmri_bset index 471e8bf105b..b50f57df0e8 100755 --- a/scripts/dmri_bset +++ b/scripts/dmri_bset @@ -79,7 +79,7 @@ else exit 1; endif - set keepframes = ($frames) + set keepframes = ($keepframes $frames) end if (! $bsort) then # Maintain original order (do not order by shell) @@ -211,39 +211,37 @@ check_params: exit 1; endif - if(! $#outdwi == 0) then - echo "ERROR: must specify input DWI" + if(! $#outdwi) then + echo "ERROR: must specify output DWI" exit 1; endif if(! $#inbvals) then set ext = `fname2ext $indwi` - set inbvals = `echo $fname | sed "s/\(.*\)$ext/\1bvals/"` + set inbvals = `echo $indwi | sed "s/\(.*\)$ext/\1bvals/"` if (! -e $inbvals) then - echo "ERROR: $inbvals does not exist" + echo "ERROR: $inbvals does not exist" + exit 1; endif - exit 1; endif if(! $#inbvecs) then set ext = `fname2ext $indwi` - set inbvecs = `echo $fname | sed "s/\(.*\)$ext/\1bvecs/"` + set inbvecs = `echo $indwi | sed "s/\(.*\)$ext/\1bvecs/"` if (! -e $inbvecs) then - echo "ERROR: $inbvecs does not exist" + echo "ERROR: $inbvecs does not exist" + exit 1; endif - exit 1; endif if(! $#outbvals) then set ext = `fname2ext $outdwi` - set outbvals = `echo $fname | sed "s/\(.*\)$ext/\1bvals/"` - exit 1; + set outbvals = `echo $outdwi | sed "s/\(.*\)$ext/\1bvals/"` endif if(! $#outbvecs) then set ext = `fname2ext $outdwi` - set outbvecs = `echo $fname | sed "s/\(.*\)$ext/\1bvecs/"` - exit 1; + set outbvecs = `echo $outdwi | sed "s/\(.*\)$ext/\1bvecs/"` endif if(! $#bshell && ! $#bmax) then diff --git a/scripts/dmrirc.example b/scripts/dmrirc.example index e38d9a11f70..064c9a03956 100755 --- a/scripts/dmrirc.example +++ b/scripts/dmrirc.example @@ -115,49 +115,42 @@ set doeddy = 2 # set dorotbvecs = 1 -# Fractional intensity threshold for BET mask extraction from low-b images -# This mask is used only if usemaskanat = 0 -# Default: 0.3 -# -set thrbet = 0.5 - -# Perform diffusion-to-T1 registration by flirt? -# Default: 0 (no) -# -set doregflt = 0 - -# Perform diffusion-to-T1 registration by bbregister? -# Default: 1 (yes) +# Intra-subject (diffusion-to-T1) registration method +# 1: Affine with a correlation ratio cost +# 2: Affine with a mutual information cost +# 3: Affine with a boundary-based cost (default) # -set doregbbr = 1 +set intrareg = 3 -# Perform registration of T1 to MNI template? -# Default: 1 (yes) -# -set doregmni = 1 - -# MNI template -# Only used if doregmni = 1 -# Default: $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Degrees of freedom for intra-subject registration +# Can be 6 (rigid), 9 (rigid+scaling), or 12 (full affine) +# Default: 6 for infants, 9 otherwise # -set mnitemp = /path/to/mni_template.nii.gz +set intradof = 6 -# Perform registration of T1 to CVS template? -# Default: 0 (no) +# Maximum rotation angle (degrees) for intra-subject registration +# Default: 3 for infants, 90 otherwise # -set doregcvs = 0 +set intrarot = 90 -# CVS template subject ID -# Only used if doregcvs = 1 -# Default: cvs_avg35 +# Inter-subject registration method +# 1: Affine T1-to-T1 with a correlation ratio cost +# 2: Affine T1-to-T1 with a mutual information cost (default) +# 3: Affine T1-to-T1 with a robust cost (default for infants) +# 4: Nonlinear T1-to-T1 with CVS +# 5: Nonlinear FA-to-FA with SyN # -set cvstemp = donald +set interreg = 2 -# Parent directory of the CVS template subject -# Only used if doregcvs = 1 -# Default: $FREESURFER_HOME/subjects +# Target brain for inter-subject registration +# Default for affine T1-to-T1: +# $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Default for nonlinear T1-to-T1: +# $FREESURFER_HOME/subjects/cvs_avg35/ +# Default for nonlinear FA-to-FA: +# $FREESURFER_HOME/trctrain/hcp/MGH35_HCP_FA_template.nii.gz # -set cvstempdir = /path/to/cvs/atlases/of/ducks +set intertrg = /path/to/a/duck/template.nii.gz # Use brain mask extracted from T1 image instead of low-b diffusion image? # Has no effect if there is no T1 data @@ -165,6 +158,12 @@ set cvstempdir = /path/to/cvs/atlases/of/ducks # set usemaskanat = 1 +# Fractional intensity threshold for BET mask extraction from low-b images +# This mask is used only if usemaskanat = 0 +# Default: 0.3 +# +set thrbet = 0.5 + # Paths to reconstruct # Default: All paths in the atlas # diff --git a/scripts/dmrirc.long.example b/scripts/dmrirc.long.example index 609f557274a..e2fe283003e 100755 --- a/scripts/dmrirc.long.example +++ b/scripts/dmrirc.long.example @@ -150,49 +150,42 @@ set doeddy = 2 # set dorotbvecs = 1 -# Fractional intensity threshold for BET mask extraction from low-b images -# This mask is used only if usemaskanat = 0 -# Default: 0.3 -# -set thrbet = 0.5 - -# Perform diffusion-to-T1 registration by flirt? -# Default: 0 (no) -# -set doregflt = 0 - -# Perform diffusion-to-T1 registration by bbregister? -# Default: 1 (yes) +# Intra-subject (diffusion-to-T1) registration method +# 1: Affine with a correlation ratio cost +# 2: Affine with a mutual information cost +# 3: Affine with a boundary-based cost (default) # -set doregbbr = 1 +set intrareg = 3 -# Perform registration of T1 to MNI template? -# Default: 1 (yes) -# -set doregmni = 1 - -# MNI template -# Only used if doregmni = 1 -# Default: $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Degrees of freedom for intra-subject registration +# Can be 6 (rigid), 9 (rigid+scaling), or 12 (full affine) +# Default: 6 for infants, 9 otherwise # -set mnitemp = /path/to/mni_template.nii.gz +set intradof = 6 -# Perform registration of T1 to CVS template? -# Default: 0 (no) +# Maximum rotation angle (degrees) for intra-subject registration +# Default: 3 for infants, 90 otherwise # -set doregcvs = 0 +set intrarot = 90 -# CVS template subject ID -# Only used if doregcvs = 1 -# Default: cvs_avg35 +# Inter-subject registration method +# 1: Affine T1-to-T1 with a correlation ratio cost +# 2: Affine T1-to-T1 with a mutual information cost (default) +# 3: Affine T1-to-T1 with a robust cost (default for infants) +# 4: Nonlinear T1-to-T1 with CVS +# 5: Nonlinear FA-to-FA with SyN # -set cvstemp = donald +set interreg = 2 -# Parent directory of the CVS template subject -# Only used if doregcvs = 1 -# Default: $FREESURFER_HOME/subjects +# Target brain for inter-subject registration +# Default for affine T1-to-T1: +# $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Default for nonlinear T1-to-T1: +# $FREESURFER_HOME/subjects/cvs_avg35/ +# Default for nonlinear FA-to-FA: +# $FREESURFER_HOME/trctrain/hcp/MGH35_HCP_FA_template.nii.gz # -set cvstempdir = /path/to/cvs/atlases/of/ducks +set intertrg = /path/to/a/duck/template.nii.gz # Use brain mask extracted from T1 image instead of low-b diffusion image? # Has no effect if there is no T1 data @@ -200,6 +193,12 @@ set cvstempdir = /path/to/cvs/atlases/of/ducks # set usemaskanat = 1 +# Fractional intensity threshold for BET mask extraction from low-b images +# This mask is used only if usemaskanat = 0 +# Default: 0.3 +# +set thrbet = 0.5 + # Paths to reconstruct # Default: All paths in the atlas # diff --git a/scripts/dmrirc.long.multiscan.example b/scripts/dmrirc.long.multiscan.example index e71a03c0cb8..7c3c81a1bbb 100755 --- a/scripts/dmrirc.long.multiscan.example +++ b/scripts/dmrirc.long.multiscan.example @@ -179,49 +179,42 @@ set doeddy = 2 # set dorotbvecs = 1 -# Fractional intensity threshold for BET mask extraction from low-b images -# This mask is used only if usemaskanat = 0 -# Default: 0.3 -# -set thrbet = 0.5 - -# Perform diffusion-to-T1 registration by flirt? -# Default: 0 (no) -# -set doregflt = 0 - -# Perform diffusion-to-T1 registration by bbregister? -# Default: 1 (yes) +# Intra-subject (diffusion-to-T1) registration method +# 1: Affine with a correlation ratio cost +# 2: Affine with a mutual information cost +# 3: Affine with a boundary-based cost (default) # -set doregbbr = 1 +set intrareg = 3 -# Perform registration of T1 to MNI template? -# Default: 1 (yes) -# -set doregmni = 1 - -# MNI template -# Only used if doregmni = 1 -# Default: $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Degrees of freedom for intra-subject registration +# Can be 6 (rigid), 9 (rigid+scaling), or 12 (full affine) +# Default: 6 for infants, 9 otherwise # -set mnitemp = /path/to/mni_template.nii.gz +set intradof = 6 -# Perform registration of T1 to CVS template? -# Default: 0 (no) +# Maximum rotation angle (degrees) for intra-subject registration +# Default: 3 for infants, 90 otherwise # -set doregcvs = 0 +set intrarot = 90 -# CVS template subject ID -# Only used if doregcvs = 1 -# Default: cvs_avg35 +# Inter-subject registration method +# 1: Affine T1-to-T1 with a correlation ratio cost +# 2: Affine T1-to-T1 with a mutual information cost (default) +# 3: Affine T1-to-T1 with a robust cost (default for infants) +# 4: Nonlinear T1-to-T1 with CVS +# 5: Nonlinear FA-to-FA with SyN # -set cvstemp = donald +set interreg = 2 -# Parent directory of the CVS template subject -# Only used if doregcvs = 1 -# Default: $FREESURFER_HOME/subjects +# Target brain for inter-subject registration +# Default for affine T1-to-T1: +# $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Default for nonlinear T1-to-T1: +# $FREESURFER_HOME/subjects/cvs_avg35/ +# Default for nonlinear FA-to-FA: +# $FREESURFER_HOME/trctrain/hcp/MGH35_HCP_FA_template.nii.gz # -set cvstempdir = /path/to/cvs/atlases/of/ducks +set intertrg = /path/to/a/duck/template.nii.gz # Use brain mask extracted from T1 image instead of low-b diffusion image? # Has no effect if there is no T1 data @@ -229,6 +222,12 @@ set cvstempdir = /path/to/cvs/atlases/of/ducks # set usemaskanat = 1 +# Fractional intensity threshold for BET mask extraction from low-b images +# This mask is used only if usemaskanat = 0 +# Default: 0.3 +# +set thrbet = 0.5 + # Paths to reconstruct # Default: All paths in the atlas # diff --git a/scripts/dmrirc.multiscan.example b/scripts/dmrirc.multiscan.example index 986e04179aa..d53e4d02e68 100755 --- a/scripts/dmrirc.multiscan.example +++ b/scripts/dmrirc.multiscan.example @@ -134,49 +134,42 @@ set doeddy = 2 # set dorotbvecs = 1 -# Fractional intensity threshold for BET mask extraction from low-b images -# This mask is used only if usemaskanat = 0 -# Default: 0.3 -# -set thrbet = 0.5 - -# Perform diffusion-to-T1 registration by flirt? -# Default: 0 (no) -# -set doregflt = 0 - -# Perform diffusion-to-T1 registration by bbregister? -# Default: 1 (yes) +# Intra-subject (diffusion-to-T1) registration method +# 1: Affine with a correlation ratio cost +# 2: Affine with a mutual information cost +# 3: Affine with a boundary-based cost (default) # -set doregbbr = 1 +set intrareg = 3 -# Perform registration of T1 to MNI template? -# Default: 1 (yes) -# -set doregmni = 1 - -# MNI template -# Only used if doregmni = 1 -# Default: $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Degrees of freedom for intra-subject registration +# Can be 6 (rigid), 9 (rigid+scaling), or 12 (full affine) +# Default: 6 for infants, 9 otherwise # -set mnitemp = /path/to/mni_template.nii.gz +set intradof = 6 -# Perform registration of T1 to CVS template? -# Default: 0 (no) +# Maximum rotation angle (degrees) for intra-subject registration +# Default: 3 for infants, 90 otherwise # -set doregcvs = 0 +set intrarot = 90 -# CVS template subject ID -# Only used if doregcvs = 1 -# Default: cvs_avg35 +# Inter-subject registration method +# 1: Affine T1-to-T1 with a correlation ratio cost +# 2: Affine T1-to-T1 with a mutual information cost (default) +# 3: Affine T1-to-T1 with a robust cost (default for infants) +# 4: Nonlinear T1-to-T1 with CVS +# 5: Nonlinear FA-to-FA with SyN # -set cvstemp = donald +set interreg = 2 -# Parent directory of the CVS template subject -# Only used if doregcvs = 1 -# Default: $FREESURFER_HOME/subjects +# Target brain for inter-subject registration +# Default for affine T1-to-T1: +# $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz +# Default for nonlinear T1-to-T1: +# $FREESURFER_HOME/subjects/cvs_avg35/ +# Default for nonlinear FA-to-FA: +# $FREESURFER_HOME/trctrain/hcp/MGH35_HCP_FA_template.nii.gz # -set cvstempdir = /path/to/cvs/atlases/of/ducks +set intertrg = /path/to/a/duck/template.nii.gz # Use brain mask extracted from T1 image instead of low-b diffusion image? # Has no effect if there is no T1 data @@ -184,6 +177,12 @@ set cvstempdir = /path/to/cvs/atlases/of/ducks # set usemaskanat = 1 +# Fractional intensity threshold for BET mask extraction from low-b images +# This mask is used only if usemaskanat = 0 +# Default: 0.3 +# +set thrbet = 0.5 + # Paths to reconstruct # Default: All paths in the atlas # diff --git a/scripts/fslregister b/scripts/fslregister index 3c8f249fbc6..fa46bcaccd8 100755 --- a/scripts/fslregister +++ b/scripts/fslregister @@ -227,6 +227,7 @@ if($initxfm) then set fslmat0 = $fslmat"0"; set reg0 = $tmpdir/reg0.$$.dat set cmd = (tkregister2_cmdl --mov $movvolimg --reg $reg0 \ + --targ $fsvol --fstarg \ --regheader --fslregout $fslmat0 --s $subjid --noedit); pwd | tee -a $LF echo $cmd | tee -a $LF @@ -318,6 +319,7 @@ set cmd = (tkregister2_cmdl --s $subjid) # The lines below are for backwards compatibiltiy if(! $DoSwap) set cmd = ($cmd --mov $movvol) if($DoSwap) set cmd = ($cmd --mov $movvolimg) +set cmd = ($cmd --targ $fsvol --fstarg) set cmd = ($cmd --reg $regfile) set cmd = ($cmd --fslreg $fslmat) set tkregcheckcmd = ($cmd --surf orig); # for visual inspection diff --git a/scripts/spmseg b/scripts/spmseg index 43139203f81..419f12575a2 100755 --- a/scripts/spmseg +++ b/scripts/spmseg @@ -208,8 +208,8 @@ if(! $monly) then # Change segnos to match FS set cmd = (mri_binarize --i $spmseg0 --o $spmseg0 \ - --replace 1 3 --replace 2 2 --replace 3 257 \ - --replace 4 165 --replace 5 258 --replace 6 130 ) + --replaceonly 1 3 --replaceonly 2 2 --replaceonly 3 257 \ + --replaceonly 4 165 --replaceonly 5 258 --replaceonly 6 130 ) echo $cmd | tee -a $LF $cmd | tee -a $LF if($status) exit 1; diff --git a/scripts/trac-all b/scripts/trac-all index 7da06f6c93a..5c226d329c6 100755 --- a/scripts/trac-all +++ b/scripts/trac-all @@ -72,9 +72,8 @@ set dostats = 0 set docorr = 0 set doqa = 0 set dointra = 0 -set dointer = 0 -set domasks = 0 set dotensor = 0 +set dointer = 0 set dopriors = 0 set rcfile = () # Run command file @@ -96,6 +95,7 @@ if ($n != 0) then endif # Set defaults +set doinfant = 0 set dtroot = () set subjlist = () set runlist = () @@ -117,27 +117,24 @@ set pedir = () set dTE = () set doeddy = 2 set dorotbvecs = 1 -set thrbet = 0.3 -set doregflt = 0 -set doregbbr = 1 -set doregmni = 1 -set doregcvs = 0 -set mnitemp = $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz -set cvstempdir = $FREESURFER_HOME/subjects -set cvstemp = cvs_avg35 +set intrareg = () +set intracost = () +set intradof = () +set intrarot = () +set interreg = () +set intercost = () +set intertrg = () +set segname = aparc+aseg +set gmgrow = () +set usethalnuc = 0 set usemaskanat = 1 +set thrbet = 0.3 set baselist = () -set pathlist = ( lh.cst_AS rh.cst_AS \ - lh.ilf_AS rh.ilf_AS \ - lh.unc_AS rh.unc_AS \ - fmajor_PP fminor_PP \ - lh.atr_PP rh.atr_PP \ - lh.ccg_PP rh.ccg_PP \ - lh.cab_PP rh.cab_PP \ - lh.slfp_PP rh.slfp_PP \ - lh.slft_PP rh.slft_PP ) -set ncpts = (6 6 5 5 5 5 7 5 5 5 5 5 4 4 5 5 5 5) -set trainfile = $FREESURFER_HOME/trctrain/trainlist.txt +set pathfile = () +set pathlist = () +set gmids = () +set ncpts = () +set trainfile = () set trainsubjlist = () set ntrainlist = () set avgname = () @@ -155,6 +152,10 @@ set nsample = () # Default is set below set nupdate = 0 set nkeep = 5 set doinitprop = 1 +set pmin = () +set projmin = -3 +set projmax = 3 +set dproj = .1 set overwrite = 1 set trcdir = $FREESURFER_HOME/bin @@ -164,17 +165,23 @@ goto parse_args; parse_args_return: # Source run command file -if ($#rcfile) source $rcfile +if ($#rcfile) then + source $rcfile -# Set default number of samples for cross-sectional or longitudinal case -if ($#nsample == 0) then - if ($#baselist == 0) then - set nsample = 7500 - else - set nsample = 12000 + if ($status) then + echo "ERROR: Syntax error in configuration file $rcfile" + exit 1 endif endif +# Set defaults for registration (depending on adult or infant stream) +goto set_reg_defaults; +set_reg_defaults_return: + +# Set defaults for pathway reconstruction (depending on adult or infant stream) +goto set_path_defaults; +set_path_defaults_return: + goto check_params; check_params_return: @@ -279,8 +286,8 @@ if ($#baselist == 0) then #--->>> A single time point for each subject if ($dostats) continue - # Check freesurfer directory - if (($dointra || $dointer || $domasks) && ! $do1out) then + # Check FreeSurfer directory + if (($dointra || $dointer) && ! $do1out) then set fsdir = $SUBJECTS_DIR/$subj if (! -e $fsdir) then @@ -450,9 +457,8 @@ if ($#baselist == 0) then #--->>> A single time point for each subject echo "set docorr = ($docorr)" >> $RCF echo "set doqa = ($doqa)" >> $RCF echo "set dointra = ($dointra)" >> $RCF - echo "set dointer = ($dointer)" >> $RCF - echo "set domasks = ($domasks)" >> $RCF echo "set dotensor = ($dotensor)" >> $RCF + echo "set dointer = ($dointer)" >> $RCF echo "set dopriors = ($dopriors)" >> $RCF echo "#" >> $RCF echo "# Options for image corrections and tensor fit" >> $RCF @@ -505,13 +511,20 @@ if ($#baselist == 0) then #--->>> A single time point for each subject echo "#" >> $RCF echo "# Options for registrations" >> $RCF echo "#" >> $RCF - echo "set doregflt = ($doregflt)" >> $RCF - echo "set doregbbr = ($doregbbr)" >> $RCF - echo "set doregmni = ($doregmni)" >> $RCF - echo "set doregcvs = ($doregcvs)" >> $RCF - echo "set mnitemp = ($mnitemp)" >> $RCF - echo "set cvstempdir = ($cvstempdir)" >> $RCF - echo "set cvstemp = ($cvstemp)" >> $RCF + echo "set intrareg = ($intrareg)" >> $RCF + echo "set intracost = ($intracost)" >> $RCF + echo "set intradof = ($intradof)" >> $RCF + echo "set intrarot = ($intrarot)" >> $RCF + echo "set interreg = ($interreg)" >> $RCF + echo "set intercost = ($intercost)" >> $RCF + echo "set intertrg = ($intertrg)" >> $RCF + echo "#" >> $RCF + echo "# Options for anatomical segmentation" >> $RCF + echo "#" >> $RCF + echo "set segname = ($segname)" >> $RCF + echo "set gmgrow = ($gmgrow)" >> $RCF + echo "set usethalnuc = ($usethalnuc)" >> $RCF + echo "set usemaskanat = ($usemaskanat)" >> $RCF echo "#" >> $RCF echo "# Options for ball-and-stick model fit" >> $RCF echo "#" >> $RCF @@ -519,8 +532,8 @@ if ($#baselist == 0) then #--->>> A single time point for each subject echo "#" >> $RCF echo "# Options for path reconstructions" >> $RCF echo "#" >> $RCF - echo "set usemaskanat = ($usemaskanat)" >> $RCF echo "set pathlist = ($pathlist)" >> $RCF + echo "set gmids = ($gmids)" >> $RCF echo "set ncpts = ($ncpts)" >> $RCF echo "set trainsubjlist = ($trainsubjlist)" >> $RCF echo "set ntrainlist = ($ntrainlist)" >> $RCF @@ -537,6 +550,10 @@ if ($#baselist == 0) then #--->>> A single time point for each subject echo "set nupdate = ($nupdate)" >> $RCF echo "set nkeep = ($nkeep)" >> $RCF echo "set doinitprop = ($doinitprop)" >> $RCF + echo "set pmin = ($pmin)" >> $RCF + echo "set projmin = ($projmin)" >> $RCF + echo "set projmax = ($projmax)" >> $RCF + echo "set dproj = ($dproj)" >> $RCF echo "set overwrite = ($overwrite)" >> $RCF echo "#" >> $RCF echo "# Location of TRACULA executables" >> $RCF @@ -557,6 +574,20 @@ if ($#baselist == 0) then #--->>> A single time point for each subject if ($status) exit 1 endif else if ($dobedpost) then # Bedpost #################### + # Create symbolic link to brain mask with the name that bedpostx expects + if ($usemaskanat) then + set bedmask = ../dlabel/diff/${segname}_mask.$reg.nii.gz + else + set bedmask = ../dlabel/diff/lowb_brain_mask.nii.gz + endif + + set cmd = (ln -sf $bedmask $dtdir/dmri/nodif_brain_mask.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) exit 1 + endif + if (! $onpbs) then if ($#submitfile) then set cmd = (bedpostx_preproc.sh $dtdir/dmri) @@ -577,7 +608,7 @@ if ($#baselist == 0) then #--->>> A single time point for each subject |& tee -a $LF echo "WARN: It is recommended to run this step on a cluster" \ |& tee -a $LF - set cmd = (bedpostx_mgh -n $nstick $dtdir/dmri) + set cmd = (bedpostx_mgh -n $nstick -model 1 $dtdir/dmri) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF @@ -683,8 +714,8 @@ else #--->>> Multiple time points for each subject continue endif - if (($dointra || $dointer || $domasks) && ! $do1out) then - # Check freesurfer directory + if (($dointra || $dointer) && ! $do1out) then + # Check FreeSurfer directory set fsdir = $SUBJECTS_DIR/$subj if (! -e $fsdir) then @@ -860,14 +891,12 @@ else #--->>> Multiple time points for each subject if ($subj == $bsubj) then echo "set docorr = (0)" >> $RCF echo "set doqa = (0)" >> $RCF - echo "set dointra = (0)" >> $RCF else echo "set docorr = ($docorr)" >> $RCF echo "set doqa = ($doqa)" >> $RCF - echo "set dointra = ($dointra)" >> $RCF endif + echo "set dointra = ($dointra)" >> $RCF echo "set dointer = ($dointer)" >> $RCF - echo "set domasks = ($domasks)" >> $RCF if ($subj == $bsubj) then echo "set dotensor = (0)" >> $RCF echo "set dopriors = ($dopriors)" >> $RCF @@ -908,36 +937,48 @@ else #--->>> Multiple time points for each subject else echo "set b0pfile = ()" >> $RCF endif - if ($#echospacing > 1) then - echo "set echospacing = ($my_echospacing)" >> $RCF - else - echo "set echospacing = ($echospacing)" >> $RCF - endif - if ($#epifactor > 1) then - echo "set epifactor = ($my_epifactor)" >> $RCF - else - echo "set epifactor = ($epifactor)" >> $RCF - endif - if ($#pedir > 1) then - echo "set pedir = ($my_pedir)" >> $RCF + if ($subj != $bsubj) then + if ($#echospacing > 1) then + echo "set echospacing = ($my_echospacing)" >> $RCF + else + echo "set echospacing = ($echospacing)" >> $RCF + endif + if ($#epifactor > 1) then + echo "set epifactor = ($my_epifactor)" >> $RCF + else + echo "set epifactor = ($epifactor)" >> $RCF + endif + if ($#pedir > 1) then + echo "set pedir = ($my_pedir)" >> $RCF + else + echo "set pedir = ($pedir)" >> $RCF + endif else - echo "set pedir = ($pedir)" >> $RCF + echo "set echospacing = ()" >> $RCF + echo "set epifactor = ()" >> $RCF + echo "set pedir = ()" >> $RCF endif echo "set dTE = ($dTE)" >> $RCF echo "set doeddy = ($doeddy)" >> $RCF echo "set dorotbvecs = ($dorotbvecs)" >> $RCF echo "set thrbet = ($thrbet)" >> $RCF - echo "set usemaskanat = ($usemaskanat)" >> $RCF echo "#" >> $RCF echo "# Options for registrations" >> $RCF echo "#" >> $RCF - echo "set doregflt = ($doregflt)" >> $RCF - echo "set doregbbr = ($doregbbr)" >> $RCF - echo "set doregmni = ($doregmni)" >> $RCF - echo "set doregcvs = ($doregcvs)" >> $RCF - echo "set mnitemp = ($mnitemp)" >> $RCF - echo "set cvstempdir = ($cvstempdir)" >> $RCF - echo "set cvstemp = ($cvstemp)" >> $RCF + echo "set intrareg = ($intrareg)" >> $RCF + echo "set intracost = ($intracost)" >> $RCF + echo "set intradof = ($intradof)" >> $RCF + echo "set intrarot = ($intrarot)" >> $RCF + echo "set interreg = ($interreg)" >> $RCF + echo "set intercost = ($intercost)" >> $RCF + echo "set intertrg = ($intertrg)" >> $RCF + echo "#" >> $RCF + echo "# Options for anatomical segmentation" >> $RCF + echo "#" >> $RCF + echo "set segname = ($segname)" >> $RCF + echo "set gmgrow = ($gmgrow)" >> $RCF + echo "set usethalnuc = ($usethalnuc)" >> $RCF + echo "set usemaskanat = ($usemaskanat)" >> $RCF echo "#" >> $RCF echo "# Options for ball-and-stick model fit" >> $RCF echo "#" >> $RCF @@ -946,6 +987,7 @@ else #--->>> Multiple time points for each subject echo "# Options for path reconstructions" >> $RCF echo "#" >> $RCF echo "set pathlist = ($pathlist)" >> $RCF + echo "set gmids = ($gmids)" >> $RCF echo "set ncpts = ($ncpts)" >> $RCF echo "set trainsubjlist = ($trainsubjlist)" >> $RCF echo "set ntrainlist = ($ntrainlist)" >> $RCF @@ -962,6 +1004,10 @@ else #--->>> Multiple time points for each subject echo "set nupdate = ($nupdate)" >> $RCF echo "set nkeep = ($nkeep)" >> $RCF echo "set doinitprop = ($doinitprop)" >> $RCF + echo "set pmin = ($pmin)" >> $RCF + echo "set projmin = ($projmin)" >> $RCF + echo "set projmax = ($projmax)" >> $RCF + echo "set dproj = ($dproj)" >> $RCF echo "set overwrite = ($overwrite)" >> $RCF echo "#" >> $RCF echo "# Location of TRACULA executables" >> $RCF @@ -996,6 +1042,21 @@ else #--->>> Multiple time points for each subject else if ($dobedpost) then # Bedpost #################### @ iproc = 1 while ($iproc <= $#proclist) + # Create symbolic link to brain mask with the name that bedpostx expects + if ($usemaskanat) then + set bedmask = ../dlabel/diff/${segname}_mask.$reg.nii.gz + else + set bedmask = ../dlabel/diff/lowb_brain_mask.nii.gz + endif + + set cmd = (ln -sf $bedmask) + set cmd = ($cmd $dtroot/$proclist[$iproc]/dmri/nodif_brain_mask.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) exit 1 + endif + if (! $onpbs) then if ($#submitfile) then set cmd = (bedpostx_preproc.sh $dtroot/$proclist[$iproc]/dmri) @@ -1017,7 +1078,7 @@ else #--->>> Multiple time points for each subject |& tee -a $LFlist[$iproc] echo "WARN: It is recommended to run this step on a cluster" \ |& tee -a $LFlist[$iproc] - set cmd = (bedpostx_mgh -n $nstick $dtroot/$proclist[$iproc]/dmri) + set cmd = (bedpostx_mgh -n $nstick -model 1 $dtroot/$proclist[$iproc]/dmri) echo $cmd |& tee -a $LFlist[$iproc] |& tee -a $CFlist[$iproc] if ($RunIt) then $cmd |& tee -a $LFlist[$iproc] @@ -1051,7 +1112,7 @@ if ($dostats) then exit 1 endif - if ($#baselist == 0) then + if (! $#baselist) then set statdir = $dtroot/stats else set statdir = $dtroot/stats.long @@ -1061,126 +1122,130 @@ if ($dostats) then mkdir -p $statdir endif - set cvswarp = final_CVSmorph_to$cvstemp + if ($xspace == cvs) then + set cvstemp = `dirname $intertrg` # Assuming ../mri/norm.mgz + set cvstemp = `dirname $cvstemp` + set cvstemp = `basename $cvstemp` + set cvswarp = final_CVSmorph_to$cvstemp + endif + + foreach ntrain ($ntrainlist) + set outdir = dpath - set xspacelist = () - if ($doregmni) set xspacelist = ($xspacelist mni) - if ($doregcvs) set xspacelist = ($xspacelist cvs) + if ($dopathsubdirs) then + set outdir = $outdir/${nsample}samp - set reglist = () - if ($doregflt) set reglist = ($reglist flt) - if ($doregbbr) set reglist = ($reglist bbr) + set ptype = () - foreach ntrain ($ntrainlist) - foreach xspace ($xspacelist) - foreach reg ($reglist) - set outdir = dpath + if ($dosegprior) then + set ptype = seg14 + endif + if ($dotangprior) then + if ($#ptype) then + set ptype = $ptype.tang + else + set ptype = tang + endif + endif + if ($doxyzprior) then + if ($#ptype) then + set ptype = $ptype.xyz + else + set ptype = xyz + endif + endif + if (! $#ptype) then + set ptype = none + endif - if ($dopathsubdirs) then - set outdir = $outdir/${nsample}samp + set outdir = $outdir/$ptype + endif - set ptype = () + set avgmode = $avgname${ntrain}_${xspace}_$reg - if ($dosegprior) then - set ptype = seg14 - endif - if ($dotangprior) then - if ($#ptype) then - set ptype = $ptype.tang - else - set ptype = tang - endif - endif - if ($doxyzprior) then - if ($#ptype) then - set ptype = $ptype.xyz - else - set ptype = xyz + foreach pathname ($pathlist) + if ($RunIt) then + rm -f $statdir/$pathname.$avgmode.inputs.txt + + @ k = 1 + while ($k <= $#subjdirs) + set pathdir = $subjdirs[$k]/$outdir/${pathname}_$avgmode + + if (-e $pathdir/path.pd.nii.gz) then + if (! $#baselist) then # Cross-sectional + set xfmdir = $subjdirs[$k]/dmri/xfms + set labdir = $subjdirs[$k]/dlabel + set refvol = $labdir/diff/${segname}_mask.$reg.nii.gz + else # Longitudinal + set xfmdir = $basedirs[$k]/dmri/xfms + set labdir = $basedirs[$k]/dlabel + set refvol = $labdir/anatorig/${segname}_mask.nii.gz endif - endif - if (! $#ptype) then - set ptype = none - endif - set outdir = $outdir/$ptype - endif - - set avgmode = $avgname${ntrain}_${xspace}_$reg + set inputs = ($pathdir $refvol) - foreach pathname ($pathlist) - if ($RunIt) then - rm -f $statdir/$pathname.$avgmode.inputs.txt - - @ k = 1 - while ($k <= $#subjdirs) - set pathdir = $subjdirs[$k]/$outdir/${pathname}_$avgmode - - if (-e $pathdir/path.pd.nii.gz) then - if ($#baselist == 0) then # Cross-sectional - set xfmdir = $subjdirs[$k]/dmri/xfms - set labdir = $subjdirs[$k]/dlabel - set refvol = $labdir/diff/aparc+aseg_mask.$reg.nii.gz - else # Longitudinal - set xfmdir = $basedirs[$k]/dmri/xfms - set labdir = $basedirs[$k]/dlabel - set refvol = $labdir/anatorig/aparc+aseg_mask.nii.gz + if ($xspace == mni || $xspace == rob) then + if (! $#baselist) then # Cross-sectional + set inputs = ($inputs $xfmdir/diff2$xspace.$reg.lta) + else # Longitudinal + set inputs = ($inputs $xfmdir/anatorig2$xspace.lta) + endif + else if ($xspace == cvs) then + if (! $#baselist) then # Cross-sectional + set inputs = ($inputs $xfmdir/diff2anatorig.$reg.lta) + if (-e $xfmdir/cvs/$cvswarp.m3z) then + set inputs = ($inputs $xfmdir/cvs/$cvswarp.m3z) endif - - set inputs = ($pathdir $refvol) - - if ($xspace == mni) then - if ($#baselist == 0) then # Cross-sectional - set inputs = ($inputs $xfmdir/diff2mni.$reg.mat) - else # Longitudinal - set inputs = ($inputs $xfmdir/anatorig2mni.mat) - endif - else if ($xspace == cvs) then - if ($#baselist == 0) then # Cross-sectional - set inputs = ($inputs $xfmdir/diff2anatorig.$reg.mat) - if (-e $xfmdir/cvs/$cvswarp.m3z) then - set inputs = ($inputs $xfmdir/cvs/$cvswarp.m3z) - endif - else # Longitudinal - if (-e $xfmdir/cvs/$cvswarp.m3z) then - set inputs = ($inputs $xfmdir/cvs/$cvswarp.m3z) - endif - endif + else # Longitudinal + if (-e $xfmdir/cvs/$cvswarp.m3z) then + set inputs = ($inputs $xfmdir/cvs/$cvswarp.m3z) endif - - echo $inputs >> $statdir/$pathname.$avgmode.inputs.txt endif - - @ k = $k + 1 - end - - if (! -e $statdir/$pathname.$avgmode.inputs.txt) then - echo "ERROR: no pathway reconstructions found" - exit 1 + else if ($xspace == syn) then + if (! $#baselist) then # Cross-sectional + set inputs = ($inputs $xfmdir/diff2syn.lta) + set inputs = ($inputs $xfmdir/syn_warp.m3z) + else # Longitudinal + set inputs = ($inputs $xfmdir/anatorig2syn.$reg.lta) + set inputs = ($inputs $xfmdir/syn_warp.m3z) + endif + else if ($xspace == fnt) then + if (! $#baselist) then # Cross-sectional + set inputs = ($inputs $xfmdir/diff2fsl_warp.m3z) + else # Longitudinal + set inputs = ($inputs $xfmdir/anatorig2diff.$reg.lta) + set inputs = ($inputs $xfmdir/diff2fsl_warp.m3z) + endif endif - endif - set cmd = $trcdir/dmri_group - set cmd = ($cmd --list $statdir/$pathname.$avgmode.inputs.txt) - if ($xspace == mni) then - set cmd = ($cmd --ref $mnitemp) - else if ($xspace == cvs) then - set cmd = ($cmd --ref $cvstempdir/$cvstemp/mri/norm.mgz) + echo $inputs >> $statdir/$pathname.$avgmode.inputs.txt endif - set cmd = ($cmd --out $statdir/$pathname.$avgmode) - set LF = $statdir/$pathname.$avgmode.log - - if ($RunIt) then - if ($#submitfile) then - echo "$cmd |& tee -a $LF" >> $submitfile - else - echo $cmd - $cmd |& tee -a $LF - if ($status) exit 1 - endif - endif + @ k = $k + 1 end - end + + if (! -e $statdir/$pathname.$avgmode.inputs.txt) then + echo "ERROR: no pathway reconstructions found" + exit 1 + endif + endif + + set cmd = $trcdir/dmri_group + set cmd = ($cmd --list $statdir/$pathname.$avgmode.inputs.txt) + set cmd = ($cmd --ref $intertrg) + set cmd = ($cmd --out $statdir/$pathname.$avgmode) + + set LF = $statdir/$pathname.$avgmode.log + + if ($RunIt) then + if ($#submitfile) then + echo "$cmd |& tee -a $LF" >> $submitfile + else + echo $cmd + $cmd |& tee -a $LF + if ($status) exit 1 + endif + endif end end endif @@ -1190,20 +1255,20 @@ if ($onpbs && $RunIt) then if ($dopreproc) then if (! $?MYPBSWAIT) setenv MYPBSWAIT 30 - if ($doregcvs) setenv MYPBSARCH "ppn=4,vmem=28gb" + if ($xspace == cvs) setenv MYPBSARCH "ppn=4,vmem=28gb" echo Queueing pre-processing set preid = `fsl_sub_mgh -l $pbslogdir/log -m a -N trcpre -t $submitfile` else if ($dobedpost) then if (! $?MYPBSWAIT) setenv MYPBSWAIT 0 - bedpostx_mgh -n $nstick `printf '%s/dmri ' $subjdirs` + bedpostx_mgh -n $nstick -model 1 `printf '%s/dmri ' $subjdirs` else if ($dopaths) then if (! $?MYPBSWAIT) setenv MYPBSWAIT 30 - if ($doregcvs) setenv MYPBSARCH "ppn=4,vmem=28gb" + if ($xspace == cvs) setenv MYPBSARCH "ppn=4,vmem=28gb" echo Queueing path reconstruction set trcid = `fsl_sub_mgh -l $pbslogdir/log -m a -N trc -t $submitfile` else if ($dostats) then if (! $?MYPBSWAIT) setenv MYPBSWAIT 30 - if ($doregcvs) setenv MYPBSARCH "ppn=4,vmem=28gb" + if ($xspace == cvs) setenv MYPBSARCH "ppn=4,vmem=28gb" echo Queueing group tables set grpid = `fsl_sub_mgh -l $pbslogdir/log -m a -N trcgrp -t $submitfile` endif @@ -1279,9 +1344,8 @@ while( $#argv != 0 ) set docorr = 1 set doqa = 1 set dointra = 1 - set dointer = 1 - set domasks = 1 set dotensor = 1 + set dointer = 1 set dopriors = 1 set dobedpost = 0 set dopaths = 0 @@ -1345,40 +1409,28 @@ while( $#argv != 0 ) set dointra = 0 breaksw - case "-inter": - set dopreproc = 1 - set dointer = 1 - set dobedpost = 0 - set dopaths = 0 - set dostats = 0 - breaksw - - case "-nointer": - set dointer = 0 - breaksw - - case "-masks": + case "-tensor": set dopreproc = 1 - set domasks = 1 + set dotensor = 1 set dobedpost = 0 set dopaths = 0 set dostats = 0 breaksw - case "-nomasks": - set domasks = 0 + case "-notensor": + set dotensor = 0 breaksw - case "-tensor": + case "-inter": set dopreproc = 1 - set dotensor = 1 + set dointer = 1 set dobedpost = 0 set dopaths = 0 set dostats = 0 breaksw - case "-notensor": - set dotensor = 0 + case "-nointer": + set dointer = 0 breaksw case "-prior": @@ -1393,6 +1445,10 @@ while( $#argv != 0 ) set dopriors = 0 breaksw + case "-infant": + set doinfant = 1 + breaksw + case "-cleancsdf": set DoCleanCSDF = 1 breaksw @@ -1487,6 +1543,189 @@ end goto parse_args_return; +############--------------################## +set_reg_defaults: + +# These variables are deprecated, but check for backwards compatibility +if ($?doregflt) then + if ($doregflt) set intrareg = 1 +endif +if ($?doregbbr) then + if ($doregbbr) set intrareg = 3 +endif +if ($?doregcvs) then + if ($doregcvs) set interreg = 4 +endif +if ($?doregmni) then + if ($doregmni) set interreg = 2 +endif +if ($?mnitemp && ($interreg == 1 || $interreg == 2)) then + set intertrg = $mnitemp +endif +if ($?cvstemp && $interreg == 4) then + set intertrg = $cvstempdir/$cvstemp/mri/norm.mgz +endif + +# Default settings for intra-subject registration +if (! $#intrareg) then + if ($doinfant) set intrareg = 2 + if (! $doinfant) set intrareg = 3 +endif + +switch ($intrareg) + case 1: # Affine with a correlation ratio cost + set reg = flt + set intracost = corratio + breaksw + case 2: # Affine with a mutual information cost + set reg = flt + set intracost = mutualinfo + breaksw + case 3: # Affine with a boundary-based cost + set reg = bbr + breaksw + default: + echo "ERROR: $intrareg not a valid option for intra-subject registration" + exit 1 + breaksw +endsw + +if ($reg == flt) then # Parameters for affine registration + if ($doinfant) then + if (! $#intradof) set intradof = 6 + if (! $#intrarot) set intrarot = 3 + else + if (! $#intradof) set intradof = 12 + if (! $#intrarot) set intrarot = 90 + endif +else if ($reg == bbr) then + if (! $#intradof) set intradof = 6 +endif + +# Default settings for intra-subject registration +if (! $#interreg) then + if ($doinfant) set interreg = 3 + if (! $doinfant) set interreg = 2 +endif + +switch ($interreg) + case 1: # Affine T1-to-T1 with a correlation ratio cost + set xspace = mni + set intercost = corratio + breaksw + case 2: # Affine T1-to-T1 with a mutual information cost + set xspace = mni + set intercost = mutualinfo + breaksw + case 3: # Affine T1-to-T1 with a robust cost + set xspace = rob + breaksw + case 4: # Nonlinear T1-to-T1 with CVS + set xspace = cvs + breaksw + case 5: # Nonlinear FA-to-FA with SyN + set xspace = syn + setenv MY_MORPHS_DO_NOT_CONFORM_DEAL_WITH_IT + breaksw + case 6: # Nonlinear FA-to-FA with FNIRT + set xspace = fnt + breaksw + default: + echo "ERROR: $interreg not a valid option for inter-subject registration" + exit 1 + breaksw +endsw + +if (! $#intertrg) then # Target for inter-subject registration + if ($xspace == mni || $xspace == rob) then + if ($doinfant) then + set intertrg = $FREESURFER_HOME/trctrain/inf/wustl_robtemplate_affine_mean.nii.gz + else + set intertrg = $FSLDIR/data/standard/MNI152_T1_1mm_brain.nii.gz + endif + else if ($xspace == cvs) then + if ($doinfant) then + echo "ERROR: CVS registration not available for infants" + exit 1 + else + set intertrg = $FREESURFER_HOME/subjects/cvs_avg35/mri/norm.mgz + endif + else if ($xspace == syn) then + if ($doinfant) then + echo "ERROR: SyN registration not available for infants" + exit 1 + else + set intertrg = $FREESURFER_HOME/trctrain/hcp/MGH35_HCP_FA_template.nii.gz + endif + else if ($xspace == fnt) then + if ($doinfant) then + echo "ERROR: FNIRT registration not available for infants" + exit 1 + else + set intertrg = $FSLDIR/data/standard/FMRIB58_FA_1mm.nii.gz + endif + endif +endif + +goto set_reg_defaults_return; + +############--------------################## +set_path_defaults: + +# Default settings for pathway reconstruction +if ($doinfant) then + if (! $#trainfile) set trainfile = $FREESURFER_HOME/trctrain/inf/trainlist.txt + if (! $#gmgrow) set gmgrow = 1 + if (! $#pmin) set pmin = .1 +else + if (! $#trainfile) set trainfile = $FREESURFER_HOME/trctrain/trainlist.txt + if (! $#gmgrow) set gmgrow = 2 + if (! $#pmin && ! $#baselist) set pmin = .2 + if (! $#pmin && $#baselist) set pmin = .02 +endif + +if (! $#pathfile) set pathfile = `dirname $trainfile`/pathlist.txt + +if (! $#pathlist) then # Pathway names + if (! -e $pathfile) then + echo "ERROR: Cannot find list of pathways $pathfile" + exit 1 + endif + + set pathlist = `awk '{print $1}' $pathfile` +endif + +if (! $#gmids) then # Non-cortex label IDs to allow as pathway ends + if (! -e $pathfile) then + echo "ERROR: Cannot find list of pathways $pathfile" + exit 1 + endif + + set gmids = () + foreach pname ($pathlist) + set gmids = ($gmids `awk -v p=$pname '{if ($1 == p) print $2}' $pathfile`) + end +endif + +if (! $#ncpts) then # Number of spline control points + if (! -e $pathfile) then + echo "ERROR: Cannot find list of pathways $pathfile" + exit 1 + endif + + set ncpts = () + foreach pname ($pathlist) + set ncpts = ($ncpts `awk -v p=$pname '{if ($1 == p) print $3}' $pathfile`) + end +endif + +if (! $#nsample) then # Number of MCMC samples + if (! $#baselist) set nsample = 7500 # Cross-sectional case + if ($#baselist) set nsample = 12000 # Longitudinal case +endif + +goto set_path_defaults_return; + ############--------------################## arg1err: echo "ERROR: flag $flag requires one argument" @@ -1579,9 +1818,15 @@ check_params: set dtroot = $SUBJECTS_DIR endif - if ($#ncpts > 1 && $#ncpts != $#pathlist) then - echo "ERROR: must specify either one number of control points" - echo "ERROR: or as many numbers as pathways" + if ($#gmids != $#pathlist) then + echo "ERROR: length of pathway list ($pathlist) and endpoint label ID list" + echo "ERROR: ($gmids) do not match" + exit 1 + endif + + if ($#ncpts != $#pathlist) then + echo "ERROR: length of pathway list ($pathlist) and control point list + echo "ERROR: ($ncpts) do not match" exit 1 endif @@ -1592,6 +1837,11 @@ check_params: endif end + if ($#bmax && $#bshell) then + echo "ERROR: cannot specify both bshell and bmax" + exit 1 + endif + if ($#runlist > $#subjlist) then echo "ERROR: run list is longer than subject ID list" exit 1 @@ -1680,8 +1930,8 @@ check_params: exit 1 endif - if ((! $dopreproc || (! $docorr && ! $doqa && ! $dointra && ! $dointer && \ - ! $domasks && ! $dotensor && ! $dopriors)) && \ + if ((! $dopreproc || (! $docorr && ! $doqa && ! $dointra && \ + ! $dotensor && ! $dointer && ! $dopriors)) && \ ! $dobedpost && ! $dopaths && ! $dostats) then echo "ERROR: no analysis step (-{prep,bedp,path,stat}) has been selected" exit 1 @@ -1714,29 +1964,27 @@ usage_exit: echo " -noqa : don't do step 1.2" echo " -intra : do intra-subject registration (step 1.3)" echo " -nointra : don't do step 1.3" - echo " -inter : do inter-subject registration (step 1.4)" - echo " -nointer : don't do step 1.4" - echo " -masks : do masks (step 1.5)" - echo " -nomasks : don't do step 1.5" - echo " -tensor : do tensor fit (step 1.6)" - echo " -notensor : don't do step 1.6" - echo " -prior : do pathway priors (step 1.7)" - echo " -noprior : don't do step 1.7" + echo " -tensor : do tensor fit (step 1.4)" + echo " -notensor : don't do step 1.4" + echo " -inter : do inter-subject registration (step 1.5)" + echo " -nointer : don't do step 1.5" + echo " -prior : do pathway priors (step 1.6)" + echo " -noprior : don't do step 1.6" echo "" echo "Analysis steps:" echo " 1. Pre-processing" echo " 1.1 Image corrections (eddy-current and/or B0)" echo " 1.2 Image quality assessment (head motion measures)" - echo " 1.3 Intra-subject registration (diffusion to T1)" - echo " 1.4 Inter-subject registration (T1 to template)" - echo " 1.5 White-matter, cortical, and whole-brain masks" - echo " 1.6 Tensor fit" - echo " 1.7 Pathway priors from atlas and T1" + echo " 1.3 Intra-subject registration (individual DWI to individual T1)" + echo " 1.4 Tensor fit" + echo " 1.5 Inter-subject registration (individual DWI/T1 to template)" + echo " 1.6 Pathway priors from atlas and T1" echo " 2. Stick-and-ball model fitting with bedpost" echo " 3. Pathway reconstruction" echo " 4. Assemble pathway measures from all subjects" echo "" echo "Other options:" + echo " -infant : use infant brain processing options" echo " -jobs : write a text file with command lines that can be" echo " run in parallel but do not run them - the user can" echo " then submit each line as a job on a compute cluster" @@ -1797,18 +2045,22 @@ If there are conflicting step-wise arguments, the ones that come later in the command line override the ones that come earlier. Various aspects of each processing step can be configured in the dmrirc -file. See dmrirc.example for more details. +file. See example configuration files ($FREESURFER_HOME/bin/dmrirc.*) for +more details: + dmrirc.example : Single session, single DWI scan per session + dmrirc.multiscan.example : Single session, multiple DWI scans per session + dmrirc.long.example : Multiple sessions, single DWI scan per session + dmrirc.long.multiscan.example : Multiple sessions, multiple DWI scans per session > Step 1: Pre-processing -prep to do this step - Pre-processing includes steps 1.1 through 1.5 below. + Pre-processing includes steps 1.1 through 1.6 below. > Step 1.1: Image corrections -corr to do this step, -nocorr to skip this step - Eddy current correction with eddy_correct, B0 field map correction with - epidewarp.fsl. + Eddy current and susceptibility distortion correction. > Step 1.2: Image quality assessment -qa to do this step, -noqa to skip this step @@ -1818,25 +2070,19 @@ file. See dmrirc.example for more details. > Step 1.3: Intra-subject registration -intra to do this step, -nointra to skip this step - Diffusion-to-T1 registration with flirt and/or bbregister. - -> Step 1.4: Inter-subject registration - -inter to do this step, -nointer to skip this step - - T1-to-template registration using MNI and/or CVS templates. - -> Step 1.5: White-matter, cortical, and whole-brain masks - -masks to do this step, -nomasks to skip this step - - Generate masks of the white matter and cortex from FreeSurfer outputs, - whole-brain masks from T1 and DWIs. + Individual DWI-to-T1 registration. -> Step 1.6: Tensor fit +> Step 1.4: Tensor fit -tensor to do this step, -notensor to skip this step Tensor model fitting on DWIs. -> Step 1.7: Pathway priors +> Step 1.5: Inter-subject registration + -inter to do this step, -nointer to skip this step + + Individual-to-template registration, affine or nonlinear, T1- or DWI-based. + +> Step 1.6: Pathway priors -prior to do this step, -noprior to skip this step Combine training data and subject's own data to generate pathway priors. @@ -1854,10 +2100,11 @@ file. See dmrirc.example for more details. > Step 4: Assemble pathway measures from multiple subjects -stat to do this step - Combine whole-path or along-the-path measures (anisotropy and - diffusivity) from multiple subjects to feed into group analyses. + Combine whole-path or along-the-path measures (anisotropy and + diffusivity) from multiple subjects to feed into group analyses. OTHER OPTIONS +-infant : use infant brain processing options -jobs : write a text file with command lines that can be run in parallel but do not run them - the user can then submit each line as a job on a compute cluster @@ -1881,5 +2128,6 @@ command line. If run on a local machine, trac-all will run all analyses locally. If run on the cluster, trac-all will submit the analysis of each subject listed in your dmrirc file as a job. -SEE ALSO: dmrirc.example +SEE ALSO: dmrirc.example, dmrirc.multiscan.example, dmrirc.long.example, + dmrirc.long.multiscan.example diff --git a/scripts/trac-paths b/scripts/trac-paths index 0ac1157a2d8..f76246cc794 100755 --- a/scripts/trac-paths +++ b/scripts/trac-paths @@ -69,6 +69,29 @@ check_params_return: source $rcfile +if ($intrareg == 1 || $intrareg == 2) then + set reg = flt +else if ($intrareg == 3) then + set reg = bbr +endif + +if ($interreg == 1 || $interreg == 2) then + set xspace = mni +else if ($interreg == 3) then + set xspace = rob +else if ($interreg == 4) then + set xspace = cvs + set cvstempdir = `dirname $intertrg` # Assuming ../mri/norm.mgz + set cvstempdir = `dirname $cvstempdir` + set cvstemp = `basename $cvstempdir` + set cvstempdir = `dirname $cvstempdir` + set cvswarp = final_CVSmorph_to$cvstemp +else if ($interreg == 5) then + set xspace = syn +else if ($interreg == 6) then + set xspace = fnt +endif + if ($DoTime) then fs_time ls >& /dev/null if (! $status) set fs_time = fs_time @@ -169,642 +192,862 @@ endif echo "#-------------------------------------" |& tee -a $LF echo "$0 $argv" |& tee -a $LF |& tee -a $CF -if (! $dolong) then - echo "#-------------------------------------" |& tee -a $LF - echo "#@# Path reconstruction `date`" |& tee -a $LF +#------------ Select DWI set to use for path reconstruction ---------------# - set cvswarp = final_CVSmorph_to$cvstemp +echo "#-------------------------------------" |& tee -a $LF +echo "#@# DWI set selection `date`" |& tee -a $LF - set xspacelist = () - if ($doregmni) set xspacelist = ($xspacelist mni) - if ($doregcvs) set xspacelist = ($xspacelist cvs) +if ($dolong) then + set dirlist = `printf "$dtroot/%s/dmri " $tplist` +else + set dirlist = $dwidir +endif - set reglist = () - if ($doregflt) set reglist = ($reglist flt) - if ($doregbbr) set reglist = ($reglist bbr) +foreach dwidir ($dirlist) + if ($#bmax) then # Use all DWIs up to a maximum b-value + set dwiset = dwi.bmax$bmax + + if (! -e $dwidir/$dwiset.nii.gz) then + set cmd = dmri_bset + set cmd = ($cmd --in $dwidir/dwi.nii.gz) + set cmd = ($cmd --bmax $bmax) + set cmd = ($cmd --out $dwidir/$dwiset.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif + else if ($#bshell) then # Use DWIs from one or more shells + set dwiset = dwi`printf '.b%s' $bshell` + + if (! -e $dwidir/$dwiset.nii.gz) then + set cmd = dmri_bset + set cmd = ($cmd --in $dwidir/dwi.nii.gz) + set cmd = ($cmd `printf '--b %s ' $bshell`) + set cmd = ($cmd --out $dwidir/$dwiset.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif + else # Use all DWIs + set dwiset = dwi + endif - foreach ntrain ($ntrainlist) - foreach xspace ($xspacelist) - foreach reg ($reglist) - set avgmode = $avgname${ntrain}_${xspace}_$reg + set cmd = (ln -sf $dwiset.nii.gz $dwidir/data.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - set outdir = $dtdir/dpath + set cmd = (ln -sf $dwiset.bvecs $dwidir/bvecs) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - if ($dopathsubdirs) then - set outdir = $outdir/${nsample}samp + set cmd = (ln -sf $dwiset.bvals $dwidir/bvals) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif +end - set ptype = () +if (! $dolong) then + echo "#-------------------------------------" |& tee -a $LF + echo "#@# Path reconstruction `date`" |& tee -a $LF - if ($dosegprior) then - set ptype = seg14 - endif - if ($dotangprior) then - if ($#ptype) then - set ptype = $ptype.tang - else - set ptype = tang - endif - endif - if ($doxyzprior) then - if ($#ptype) then - set ptype = $ptype.xyz - else - set ptype = xyz - endif - endif - if (! $#ptype) then - set ptype = none - endif + foreach ntrain ($ntrainlist) + set avgmode = $avgname${ntrain}_${xspace}_$reg - set outdir = $outdir/$ptype - endif + set outdir = $dtdir/dpath - mkdir -p $outdir + if ($dopathsubdirs) then + set outdir = $outdir/${nsample}samp - set outlist = `printf "$outdir/%s_$avgmode " $pathlist` + set ptype = () - set roi1list = `printf \ - "$labdir/$xspace/%s_${avgmode}_end1_dil.nii.gz " $pathlist` - set roi2list = `printf \ - "$labdir/$xspace/%s_${avgmode}_end2_dil.nii.gz " $pathlist` + if ($dosegprior) then + set ptype = seg14 + endif + if ($dotangprior) then + if ($#ptype) then + set ptype = $ptype.tang + else + set ptype = tang + endif + endif + if ($doxyzprior) then + if ($#ptype) then + set ptype = $ptype.xyz + else + set ptype = xyz + endif + endif + if (! $#ptype) then + set ptype = none + endif - if ($#ncpts == 1) then # Same number of controls for all paths - set initlist = `printf \ - "$labdir/diff/%s_${avgmode}_cpts_$ncpts.txt " $pathlist` - set sdplist = `printf \ - "$labdir/diff/%s_${avgmode}_cpts_${ncpts}_std.txt " $pathlist` - else # Variable number of controls - set initlist = () - set sdplist = () - @ ipath = 1 + set outdir = $outdir/$ptype + endif - while ($ipath <= $#pathlist) - set pname = $pathlist[$ipath] - set nc = $ncpts[$ipath] + mkdir -p $outdir - set initlist = ($initlist \ - $labdir/diff/${pname}_${avgmode}_cpts_$nc.txt) - set sdplist = ($sdplist \ - $labdir/diff/${pname}_${avgmode}_cpts_${nc}_std.txt) + set outlist = `printf "$outdir/%s_$avgmode " $pathlist` - @ ipath = $ipath + 1 - end - endif + set roi1list = `printf \ + "$labdir/$xspace/%s_${avgmode}_end1_dil.nii.gz " $pathlist` + set roi2list = `printf \ + "$labdir/$xspace/%s_${avgmode}_end2_dil.nii.gz " $pathlist` - set priorlist = () - foreach pathname ($pathlist) - set priorlist = ($priorlist \ - $labdir/$xspace/${pathname}_${avgmode}_logprior_str_0.nii.gz \ - $labdir/$xspace/${pathname}_${avgmode}_logprior_str_1.nii.gz) - end + set initlist = () + set sdplist = () + @ ipath = 1 + while ($ipath <= $#pathlist) + set pname = $pathlist[$ipath] + set nc = $ncpts[$ipath] - set npriorlist = () - foreach pathname ($pathlist) - set npriorlist = ($npriorlist \ - $labdir/$xspace/${pathname}_${avgmode}_fsnnprior \ - $labdir/$xspace/${pathname}_${avgmode}_fsnnids) - end + set initlist = ($initlist \ + $labdir/diff/${pname}_${avgmode}_cpts_$nc.txt) + set sdplist = ($sdplist \ + $labdir/diff/${pname}_${avgmode}_cpts_${nc}_std.txt) - if ($usetrunc) then - set npriorlist = `printf "%s_all " $npriorlist` - endif + @ ipath = $ipath + 1 + end - set lpriorlist = () - foreach pathname ($pathlist) - set lpriorlist = ($lpriorlist \ - $labdir/$xspace/${pathname}_${avgmode}_fsprior \ - $labdir/$xspace/${pathname}_${avgmode}_fsids) - end + set priorlist = () + foreach pathname ($pathlist) + set priorlist = ($priorlist \ + $labdir/$xspace/${pathname}_${avgmode}_logprior_str_0.nii.gz \ + $labdir/$xspace/${pathname}_${avgmode}_logprior_str_1.nii.gz) + end - if ($usetrunc) then - set lpriorlist = `printf "%s_all " $lpriorlist` - endif + set npriorlist = () + foreach pathname ($pathlist) + set npriorlist = ($npriorlist \ + $labdir/$xspace/${pathname}_${avgmode}_fsnnprior \ + $labdir/$xspace/${pathname}_${avgmode}_fsnnids) + end - set tpriorlist = `printf \ - "$labdir/$xspace/%s_${avgmode}_tangprior.txt " $pathlist` - set cpriorlist = `printf \ - "$labdir/$xspace/%s_${avgmode}_curvprior.txt " $pathlist` + if ($usetrunc) then + set npriorlist = `printf "%s_all " $npriorlist` + endif - if ($usetrunc) then - set tpriorlist = `echo $tpriorlist | sed 's/\.txt/_all\.txt/'` - set cpriorlist = `echo $cpriorlist | sed 's/\.txt/_all\.txt/'` - endif + set lpriorlist = () + foreach pathname ($pathlist) + set lpriorlist = ($lpriorlist \ + $labdir/$xspace/${pathname}_${avgmode}_fsprior \ + $labdir/$xspace/${pathname}_${avgmode}_fsids) + end - if ($overwrite) then # Clean up pre-existing directories - foreach dname ($outlist) - set cmd = (rm -rf $dname) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - end - else # Rename pre-existing directories - foreach dname ($outlist) - if (-e $dname) then - @ vno = 0 - while (-e $dname.v$vno) - @ vno = $vno + 1 - end - set cmd = (mv $dname $dname.v$vno) - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif + if ($usetrunc) then + set lpriorlist = `printf "%s_all " $lpriorlist` + endif + + set tpriorlist = `printf \ + "$labdir/$xspace/%s_${avgmode}_tangprior.txt " $pathlist` + set cpriorlist = `printf \ + "$labdir/$xspace/%s_${avgmode}_curvprior.txt " $pathlist` + + if ($usetrunc) then + set tpriorlist = `echo $tpriorlist | sed 's/\.txt/_all\.txt/'` + set cpriorlist = `echo $cpriorlist | sed 's/\.txt/_all\.txt/'` + endif + + if ($overwrite) then # Clean up pre-existing directories + foreach dname ($outlist) + set cmd = (rm -rf $dname) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + end + else # Rename pre-existing directories + foreach dname ($outlist) + if (-e $dname) then + @ vno = 0 + while (-e $dname.v$vno) + @ vno = $vno + 1 end + set cmd = (mv $dname $dname.v$vno) + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif + end + endif + + if ($usemaskanat) then + set brainmask = $labdir/diff/${segname}_mask.$reg.nii.gz + else + set brainmask = $labdir/diff/lowb_brain_mask.nii.gz + endif + + @ irep = 0 + + while ($irep <= 5) + if ($irep) then + cp $rcfile $rcfile.reinit + echo "set dopriors = 1" >> $rcfile.reinit + echo "set reinit = 1" >> $rcfile.reinit + echo "set pathlist = ($rep_pathlist)" >> $rcfile.reinit + echo "set gmids = ($rep_gmids)" >> $rcfile.reinit + echo "set ncpts = ($rep_ncpts)" >> $rcfile.reinit + + set cmd = trac-preproc + set cmd = ($cmd -c $rcfile.reinit) + set cmd = ($cmd -log $LF) + set cmd = ($cmd -cmd $CF) + set cmd = ($cmd -no-isrunning) + echo $cmd + $cmd + if ($status) exit 1 + endif - set brainmask = $labdir/diff/lowb_brain_mask.nii.gz - - if ($usemaskanat) then - if ($doregbbr && -e $labdir/diff/aparc+aseg_mask.bbr.nii.gz) then - set brainmask = $labdir/diff/aparc+aseg_mask.bbr.nii.gz - else if (-e $labdir/diff/aparc+aseg_mask.flt.nii.gz) then - set brainmask = $labdir/diff/aparc+aseg_mask.flt.nii.gz - endif + set cmd = $trcdir/dmri_paths + set cmd = ($cmd --outdir $outlist) + set cmd = ($cmd --dwi $dwidir/data.nii.gz) + set cmd = ($cmd --grad $dwidir/bvecs) + set cmd = ($cmd --bval $dwidir/bvals) + set cmd = ($cmd --mask $brainmask) + set cmd = ($cmd --bpdir $dtdir/dmri.bedpostX) + set cmd = ($cmd --ntr $nstick) + set cmd = ($cmd --fmin $fmin) + set cmd = ($cmd --roi1 $roi1list) + set cmd = ($cmd --roi2 $roi2list) + if ($xspace == mni || $xspace == rob) then + set cmd = ($cmd --reg $xfmdir/diff2$xspace.$reg.lta) + else if ($xspace == cvs) then + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.lta) + if ($subj != $cvstemp) then + set cmd = ($cmd --regnl $xfmdir/cvs/$cvswarp.m3z) + endif + else if ($xspace == syn) then + set cmd = ($cmd --reg $xfmdir/diff2syn.lta) + set cmd = ($cmd --regnl $xfmdir/syn_warp.m3z) + else if ($xspace == fnt) then + set cmd = ($cmd --regnl $xfmdir/diff2fsl_warp.m3z) + endif + set cmd = ($cmd --init $initlist) + if ($dosegprior) then + set cmd = ($cmd --nprior $npriorlist) + set cmd = ($cmd --lprior $lpriorlist) + if ($usethalnuc) then + set cmd = ($cmd --seg $labdir/$xspace/${segname}+thalnuc.nii.gz) + else + set cmd = ($cmd --seg $labdir/$xspace/$segname.nii.gz) endif + endif + if ($dotangprior) then + set cmd = ($cmd --tprior $tpriorlist) + set cmd = ($cmd --cprior $cpriorlist) + endif + if ($doxyzprior) then + set cmd = ($cmd --prior $priorlist) + endif + set cmd = ($cmd --nb $nburnin --ns $nsample --nu $nupdate --nk $nkeep) + if ($doinitprop) then + set cmd = ($cmd --sdp $sdplist) + endif + if ($debug) then + set cmd = ($cmd --debug) + endif + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif - @ irep = 0 - - while ($irep <= 5) - if ($irep) then - cp $rcfile $rcfile.reinit - echo "set dopriors = 1" >> $rcfile.reinit - echo "set reinit = 1" >> $rcfile.reinit - echo "set pathlist = ($rep_pathlist)" >> $rcfile.reinit - echo "set ncpts = ($rep_ncpts)" >> $rcfile.reinit - - set cmd = trac-preproc - set cmd = ($cmd -c $rcfile.reinit) - set cmd = ($cmd -log $LF) - set cmd = ($cmd -cmd $CF) - set cmd = ($cmd -no-isrunning) - echo $cmd - $cmd - if ($status) exit 1 - endif + # Check if any paths need to be reinitialized + set rep_pathlist = () + set rep_gmids = () + set rep_ncpts = () - set cmd = $trcdir/dmri_paths - set cmd = ($cmd --outdir $outlist) - set cmd = ($cmd --dwi $dwidir/dwi.nii.gz) - set cmd = ($cmd --grad $dwidir/bvecs) - set cmd = ($cmd --bval $dwidir/bvals) - set cmd = ($cmd --mask $brainmask) - set cmd = ($cmd --bpdir $dtdir/dmri.bedpostX) - set cmd = ($cmd --ntr $nstick) - set cmd = ($cmd --fmin $fmin) - set cmd = ($cmd --roi1 $roi1list) - set cmd = ($cmd --roi2 $roi2list) - if ($xspace == mni) then - set cmd = ($cmd --reg $xfmdir/diff2mni.$reg.mat) - else if ($xspace == cvs) then - set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.mat) - if ($subj != $cvstemp) then - set cmd = ($cmd --regnl $xfmdir/cvs/$cvswarp.m3z) - endif - endif - set cmd = ($cmd --init $initlist) - if ($dosegprior) then - set cmd = ($cmd --nprior $npriorlist) - set cmd = ($cmd --lprior $lpriorlist) - set cmd = ($cmd --seg $labdir/$xspace/aparc+aseg.nii.gz) - endif - if ($dotangprior) then - set cmd = ($cmd --tprior $tpriorlist) - set cmd = ($cmd --cprior $cpriorlist) - endif - if ($doxyzprior) then - set cmd = ($cmd --prior $priorlist) - endif - set cmd = ($cmd --nb $nburnin --ns $nsample --nu $nupdate --nk $nkeep) - if ($doinitprop) then - set cmd = ($cmd --sdp $sdplist) + @ ipath = 1 + while ($ipath <= $#pathlist) + set pathname = $pathlist[$ipath] + set pathdir = $outdir/${pathname}_$avgmode + + if (-e $pathdir/path.pd.nii.gz) then + set pmax = `fslstats $pathdir/path.pd.nii.gz -R | awk '{print $2}'` + set pthr = `echo "$pmax * .2" | bc -l` + + set cmd = fslmaths + set cmd = ($cmd $pathdir/path.pd.nii.gz -thr $pthr) + set cmd = ($cmd $pathdir/tmp.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit endif - if ($debug) then - set cmd = ($cmd --debug) + + if (`fslstats $pathdir/tmp.nii.gz -V | awk '{print $2}'` \ + == `fslstats $pathdir/path.map.nii.gz -V | awk '{print $2}'`) then + set rep_pathlist = ($rep_pathlist $pathname) + set rep_gmids = ($rep_gmids $gmids[$ipath]) + set rep_ncpts = ($rep_ncpts $ncpts[$ipath]) + else + set pathpre = ${pathname}_$avgmode + + set outlist = `printf '%s\n' $outlist | grep -v $pathpre` + set roi1list = `printf '%s\n' $roi1list | grep -v $pathpre` + set roi2list = `printf '%s\n' $roi2list | grep -v $pathpre` + set initlist = `printf '%s\n' $initlist | grep -v $pathpre` + set sdplist = `printf '%s\n' $sdplist | grep -v $pathpre` + set priorlist = `printf '%s\n' $priorlist | grep -v $pathpre` + set npriorlist = `printf '%s\n' $npriorlist | grep -v $pathpre` + set lpriorlist = `printf '%s\n' $lpriorlist | grep -v $pathpre` + set tpriorlist = `printf '%s\n' $tpriorlist | grep -v $pathpre` + set cpriorlist = `printf '%s\n' $cpriorlist | grep -v $pathpre` endif + + set cmd = (rm -rf $pathdir/tmp.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then - $fs_time $cmd |& tee -a $LF + $cmd |& tee -a $LF if ($status) goto error_exit endif + endif - # Check if any paths need to be reinitialized - set rep_pathlist = () - set rep_ncpts = () - - @ ipath = 1 - while ($ipath <= $#pathlist) - set pathname = $pathlist[$ipath] - set pathdir = $outdir/${pathname}_$avgmode - - if (-e $pathdir/path.pd.nii.gz) then - set pmax = `fslstats $pathdir/path.pd.nii.gz -R | awk '{print $2}'` - set pthr = `echo "$pmax * .2" | bc -l` - - set cmd = fslmaths - set cmd = ($cmd $pathdir/path.pd.nii.gz -thr $pthr) - set cmd = ($cmd $pathdir/tmp.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - if (`fslstats $pathdir/tmp.nii.gz -V | awk '{print $2}'` \ - == `fslstats $pathdir/path.map.nii.gz -V | awk '{print $2}'`) then - set rep_pathlist = ($rep_pathlist $pathname) - set rep_ncpts = ($rep_ncpts $ncpts[$ipath]) - else - set outlist = `printf '%s\n' $outlist | grep -v $pathname` - set roi1list = `printf '%s\n' $roi1list | grep -v $pathname` - set roi2list = `printf '%s\n' $roi2list | grep -v $pathname` - set initlist = `printf '%s\n' $initlist | grep -v $pathname` - set sdplist = `printf '%s\n' $sdplist | grep -v $pathname` - set priorlist = `printf '%s\n' $priorlist | grep -v $pathname` - set npriorlist = `printf '%s\n' $npriorlist | grep -v $pathname` - set lpriorlist = `printf '%s\n' $lpriorlist | grep -v $pathname` - set tpriorlist = `printf '%s\n' $tpriorlist | grep -v $pathname` - set cpriorlist = `printf '%s\n' $cpriorlist | grep -v $pathname` - endif - - set cmd = (rm -rf $pathdir/tmp.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif + @ ipath = $ipath + 1 + end - @ ipath = $ipath + 1 - end + if ($#rep_pathlist == 0) break; - if ($#rep_pathlist == 0) break; + @ irep = $irep + 1 + end - @ irep = $irep + 1 - end + foreach pathname ($pathlist) + set pathpre = ${pathname}_$avgmode + + if (! -e $outdir/$pathpre/path.map.txt) continue + + set pname = `echo $pathname | awk -v FS=_ '{print $1}'` + + # Get whole-path and along-path statistics + set cmd = $trcdir/dmri_pathstats + set cmd = ($cmd --intrc $outdir/$pathpre) + set cmd = ($cmd --dtbase $dwidir/dtifit) + set cmd = ($cmd --path $pname) + set cmd = ($cmd --subj $subj) + set cmd = ($cmd --out $outdir/$pathpre/pathstats.overall.txt) + set cmd = ($cmd --outvox $outdir/$pathpre/pathstats.byvoxel.txt) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif - foreach pathname ($pathlist) - set pathpre = ${pathname}_$avgmode + # Project path endpoints onto cortical surface + # Skip cerebellum pathways + if ($pname == mcp) continue - if (-e $outdir/$pathpre/path.map.txt) then - set pname = `echo $pathname | awk -v FS=_ '{print $1}'` + # Is it an inter-hemispheric pathway? + if ($pname =~ cc.* || $pname == acomm || $pname == mcp) then + set isinter = 1 + else + set isinter = 0 + endif - set cmd = $trcdir/dmri_pathstats - set cmd = ($cmd --intrc $outdir/$pathpre) - set cmd = ($cmd --dtbase $dwidir/dtifit) - set cmd = ($cmd --path $pname) - set cmd = ($cmd --subj $subj) - set cmd = ($cmd --out $outdir/$pathpre/pathstats.overall.txt) - set cmd = ($cmd --outvox $outdir/$pathpre/pathstats.byvoxel.txt) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - end + foreach pt (1 2) + if ( $pname =~ lh.* || ($isinter == 1 && $pt == 2) ) then + set hemi = lh + else + set hemi = rh + endif - set mergelist = () - foreach dname ($outdir/*_$avgmode) - if (-e $dname/path.pd.nii.gz) then - set mergelist = ($mergelist `basename $dname`/path.pd.nii.gz) - endif - end + if ($isinter) then + set labelname = $hemi.$pname + else + set labelname = $pname + endif - if ($#mergelist) then - set cmd = $trcdir/dmri_mergepaths - set cmd = ($cmd --indir $outdir) - set cmd = ($cmd --in $mergelist) - set cmd = ($cmd --out $outdir/merged_$avgmode.mgz) - set cmd = ($cmd --ctab $FREESURFER_HOME/FreeSurferColorLUT.txt) - set cmd = ($cmd --thresh .2) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif + # Project from volume in DWI space to surface in structural space + set cmd = mri_vol2surf + set cmd = ($cmd --mov $outdir/$pathpre/endpt$pt.pd.nii.gz) + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd --srcsubject $subj) + set cmd = ($cmd --hemi $hemi) + set cmd = ($cmd --projdist-avg $projmin $projmax $dproj) + set cmd = ($cmd --trgsubject $subj) + set cmd = ($cmd --o $outdir/$pathpre/end$pt.surf.mgz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set nproj = `echo "($projmax - ($projmin))/$dproj + 1" | bc -l` + + set cmd = fscalc + set cmd = ($cmd $outdir/$pathpre/end$pt.surf.mgz) + set cmd = ($cmd mul $nproj) + set cmd = ($cmd --o $outdir/$pathpre/end$pt.surf.mgz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set cmd = mri_binarize + set cmd = ($cmd --min 1) + set cmd = ($cmd --i $outdir/$pathpre/end$pt.surf.mgz) + set cmd = ($cmd --o $outdir/$pathpre/end$pt.surf.bin.mgz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set cmd = mri_cor2label + set cmd = ($cmd --i $outdir/$pathpre/end$pt.surf.bin.mgz) + set cmd = ($cmd --id 1) + set cmd = ($cmd --l $outdir/$pathpre/end$pt.surf.label) + set cmd = ($cmd --surf $subj $hemi white) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set cmd = mri_label2label + set cmd = ($cmd --srclabel $outdir/$pathpre/end$pt.surf.label) + set cmd = ($cmd --s $subj --hemi $hemi --regmethod surface) + set cmd = ($cmd --dilate 5 --erode 5) + set cmd = ($cmd --trglabel $outdir/$pathpre/end$pt.surf.label) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif end end + + # Merge all existing pathways into a 4D volume + set mergelist = () + foreach dname ($outdir/*_$avgmode) + if (-e $dname/path.pd.nii.gz) then + set mergelist = ($mergelist `basename $dname`/path.pd.nii.gz) + endif + end + + if ($#mergelist) then + set cmd = $trcdir/dmri_mergepaths + set cmd = ($cmd --indir $outdir) + set cmd = ($cmd --in $mergelist) + set cmd = ($cmd --out $outdir/merged_$avgmode.mgz) + set cmd = ($cmd --ctab $FREESURFER_HOME/FreeSurferColorLUT.txt) + set cmd = ($cmd --thresh $pmin) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif end else echo "#-------------------------------------" |& tee -a $LF echo "#@# Path reconstruction (longitudinal) `date`" |& tee -a $LF - set cvswarp = final_CVSmorph_to$cvstemp + foreach ntrain ($ntrainlist) + set avgmode = $avgname${ntrain}_${xspace}_$reg + + set outdir = dpath + + if ($dopathsubdirs) then + set outdir = $outdir/${nsample}samp + + if ($dosegprior && $dotangprior) then + set outdir = $outdir/all + else if ($dosegprior) then + set outdir = $outdir/seg14 + else if ($doxyzprior) then + set outdir = $outdir/xyz + else if ($dotangprior) then + set outdir = $outdir/tang + else + set outdir = $outdir/none + endif + endif - set xspacelist = () - if ($doregmni) set xspacelist = ($xspacelist mni) - if ($doregcvs) set xspacelist = ($xspacelist cvs) + set outlist = `printf "$outdir/%s_$avgmode " $pathlist` - set reglist = () - if ($doregflt) set reglist = ($reglist flt) - if ($doregbbr) set reglist = ($reglist bbr) + set roi1list = `printf \ + "$labdir/$xspace/%s_${avgmode}_end1_dil.nii.gz " $pathlist` + set roi2list = `printf \ + "$labdir/$xspace/%s_${avgmode}_end2_dil.nii.gz " $pathlist` - foreach ntrain ($ntrainlist) - foreach xspace ($xspacelist) - foreach reg ($reglist) - set avgmode = $avgname${ntrain}_${xspace}_$reg - - set outdir = dpath - - if ($dopathsubdirs) then - set outdir = $outdir/${nsample}samp - - if ($dosegprior && $dotangprior) then - set outdir = $outdir/all - else if ($dosegprior) then - set outdir = $outdir/seg14 - else if ($doxyzprior) then - set outdir = $outdir/xyz - else if ($dotangprior) then - set outdir = $outdir/tang - else - set outdir = $outdir/none - endif - endif + set initlist = () + set sdplist = () + @ ipath = 1 + while ($ipath <= $#pathlist) + set pname = $pathlist[$ipath] + set nc = $ncpts[$ipath] - set outlist = `printf "$outdir/%s_$avgmode " $pathlist` - - set roi1list = `printf \ - "$labdir/$xspace/%s_${avgmode}_end1_dil.nii.gz " $pathlist` - set roi2list = `printf \ - "$labdir/$xspace/%s_${avgmode}_end2_dil.nii.gz " $pathlist` - - if ($#ncpts == 1) then # Same number of controls for all paths - set initlist = `printf \ - "$labdir/anatorig/%s_${avgmode}_cpts_$ncpts.txt " $pathlist` - set sdplist = `printf \ - "$labdir/anatorig/%s_${avgmode}_cpts_${ncpts}_std.txt " $pathlist` - else # Variable number of controls - set initlist = () - set sdplist = () - @ ipath = 1 - - while ($ipath <= $#pathlist) - set pname = $pathlist[$ipath] - set nc = $ncpts[$ipath] - - set initlist = ($initlist \ - $labdir/anatorig/${pname}_${avgmode}_cpts_$nc.txt) - set sdplist = ($sdplist \ - $labdir/anatorig/${pname}_${avgmode}_cpts_${nc}_std.txt) - - @ ipath = $ipath + 1 - end - endif + set initlist = ($initlist \ + $labdir/anatorig/${pname}_${avgmode}_cpts_$nc.txt) + set sdplist = ($sdplist \ + $labdir/anatorig/${pname}_${avgmode}_cpts_${nc}_std.txt) - set priorlist = () - foreach pathname ($pathlist) - set priorlist = ($priorlist \ - $labdir/$xspace/${pathname}_${avgmode}_logprior_str_0.nii.gz \ - $labdir/$xspace/${pathname}_${avgmode}_logprior_str_1.nii.gz) - end + @ ipath = $ipath + 1 + end - set npriorlist = () - foreach pathname ($pathlist) - set npriorlist = ($npriorlist \ - $labdir/$xspace/${pathname}_${avgmode}_fsnnprior \ - $labdir/$xspace/${pathname}_${avgmode}_fsnnids) - end + set priorlist = () + foreach pathname ($pathlist) + set priorlist = ($priorlist \ + $labdir/$xspace/${pathname}_${avgmode}_logprior_str_0.nii.gz \ + $labdir/$xspace/${pathname}_${avgmode}_logprior_str_1.nii.gz) + end - if ($usetrunc) then - set npriorlist = `printf "%s_all " $npriorlist` - endif + set npriorlist = () + foreach pathname ($pathlist) + set npriorlist = ($npriorlist \ + $labdir/$xspace/${pathname}_${avgmode}_fsnnprior \ + $labdir/$xspace/${pathname}_${avgmode}_fsnnids) + end - set lpriorlist = () - foreach pathname ($pathlist) - set lpriorlist = ($lpriorlist \ - $labdir/$xspace/${pathname}_${avgmode}_fsprior \ - $labdir/$xspace/${pathname}_${avgmode}_fsids) - end + if ($usetrunc) then + set npriorlist = `printf "%s_all " $npriorlist` + endif - if ($usetrunc) then - set lpriorlist = `printf "%s_all " $lpriorlist` - endif + set lpriorlist = () + foreach pathname ($pathlist) + set lpriorlist = ($lpriorlist \ + $labdir/$xspace/${pathname}_${avgmode}_fsprior \ + $labdir/$xspace/${pathname}_${avgmode}_fsids) + end - set tpriorlist = `printf \ - "$labdir/$xspace/%s_${avgmode}_tangprior.txt " $pathlist` - set cpriorlist = `printf \ - "$labdir/$xspace/%s_${avgmode}_curvprior.txt " $pathlist` + if ($usetrunc) then + set lpriorlist = `printf "%s_all " $lpriorlist` + endif - if ($usetrunc) then - set tpriorlist = `echo $tpriorlist | sed 's/\.txt/_all\.txt/'` - set cpriorlist = `echo $cpriorlist | sed 's/\.txt/_all\.txt/'` - endif + set tpriorlist = `printf \ + "$labdir/$xspace/%s_${avgmode}_tangprior.txt " $pathlist` + set cpriorlist = `printf \ + "$labdir/$xspace/%s_${avgmode}_curvprior.txt " $pathlist` - foreach subj_t ($tplist) - if ($overwrite) then # Clean up pre-existing directories - foreach dname (`printf "$dtroot/$subj_t/%s " $outlist`) - set cmd = (rm -rf $dname) - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - end - else # Rename pre-existing directories - foreach dname (`printf "$dtroot/$subj_t/%s " $outlist`) - if (-e $dname) then - @ vno = 0 - while (-e $dname.v$vno) - @ vno = $vno + 1 - end - set cmd = (mv $dname $dname.v$vno) - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif + if ($usetrunc) then + set tpriorlist = `echo $tpriorlist | sed 's/\.txt/_all\.txt/'` + set cpriorlist = `echo $cpriorlist | sed 's/\.txt/_all\.txt/'` + endif + + foreach subj_t ($tplist) + if ($overwrite) then # Clean up pre-existing directories + foreach dname (`printf "$dtroot/$subj_t/%s " $outlist`) + set cmd = (rm -rf $dname) + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + end + else # Rename pre-existing directories + foreach dname (`printf "$dtroot/$subj_t/%s " $outlist`) + if (-e $dname) then + @ vno = 0 + while (-e $dname.v$vno) + @ vno = $vno + 1 end + set cmd = (mv $dname $dname.v$vno) + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif end + endif + end - if ($usemaskanat) then - set brainmask = aparc+aseg_mask.$reg - set basemask = aparc+aseg_mask - else - set brainmask = lowb_brain_mask - set basemask = lowb_brain_mask.$reg + if ($usemaskanat) then + set brainmask = ${segname}_mask.$reg + set basemask = ${segname}_mask + else + set brainmask = lowb_brain_mask + set basemask = lowb_brain_mask.$reg + endif + + set inlist = `printf "$dtroot/%s " $tplist` + + if ($usethalnuc) then + set seglist = `printf \ + "$dtroot/%s/dlabel/$xspace/${segname}+thalnuc.nii.gz " $tplist` + else + set seglist = `printf \ + "$dtroot/%s/dlabel/$xspace/$segname.nii.gz " $tplist` + endif + + @ irep = 0 + + while ($irep <= 5) + if ($irep) then + cp $rcfile $rcfile.reinit + echo "set dopriors = 1" >> $rcfile.reinit + echo "set reinit = 1" >> $rcfile.reinit + echo "set pathlist = ($rep_pathlist)" >> $rcfile.reinit + echo "set gmids = ($rep_gmids)" >> $rcfile.reinit + echo "set ncpts = ($rep_ncpts)" >> $rcfile.reinit + + set cmd = trac-preproc + set cmd = ($cmd -c $rcfile.reinit) + set cmd = ($cmd -log $LF) + set cmd = ($cmd -cmd $CF) + set cmd = ($cmd -no-isrunning) + echo $cmd + $cmd + if ($status) exit 1 + endif + + set cmd = $trcdir/dmri_paths + set cmd = ($cmd --indir $inlist) + set cmd = ($cmd --outdir $outlist) + set cmd = ($cmd --dwi dmri/data.nii.gz) + set cmd = ($cmd --grad dmri/bvecs) + set cmd = ($cmd --bval dmri/bvals) + set cmd = ($cmd --mask dlabel/diff/$brainmask.nii.gz) + set cmd = ($cmd --bpdir dmri.bedpostX) + set cmd = ($cmd --ntr $nstick) + set cmd = ($cmd --fmin $fmin) + set cmd = ($cmd --basereg dmri/xfms/anatorig2diff.$reg.lta) + set cmd = ($cmd --basemask $labdir/anatorig/$basemask.nii.gz) + set cmd = ($cmd --roi1 $roi1list) + set cmd = ($cmd --roi2 $roi2list) + if ($xspace == mni || $xspace == rob) then + set cmd = ($cmd --reg $xfmdir/anatorig2$xspace.lta) + else if ($xspace == cvs) then + # Hack: Using one time point for now! + if ($tplist[1] != $cvstemp) then + set xfmdir_t = $dtroot/$tplist[1]/dmri/xfms + set cmd = ($cmd --regnl $xfmdir_t/cvs/$cvswarp.m3z) endif + else if ($xspace == syn) then + set cmd = ($cmd --reg $xfmdir/anatorig2syn.$reg.lta) + set cmd = ($cmd --regnl $xfmdir/syn_warp.m3z) + else if ($xspace == fnt) then + set cmd = ($cmd --reg $xfmdir/anatorig2diff.$reg.lta) + set cmd = ($cmd --regnl $xfmdir/diff2fsl_warp.m3z) + endif + set cmd = ($cmd --init $initlist) + if ($dosegprior) then + set cmd = ($cmd --nprior $npriorlist) + set cmd = ($cmd --lprior $lpriorlist) + set cmd = ($cmd --seg $seglist) + else if ($doxyzprior) then + set cmd = ($cmd --prior $priorlist) + else if ($dotangprior) then + set cmd = ($cmd --tprior $tpriorlist) + set cmd = ($cmd --cprior $cpriorlist) + endif + set cmd = ($cmd --nb $nburnin --ns $nsample --nu $nupdate --nk $nkeep) + if ($doinitprop) then + set cmd = ($cmd --sdp $sdplist) + endif + if ($debug) then + set cmd = ($cmd --debug) + endif + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + # Check if any paths need to be reinitialized + set rep_pathlist = () + set rep_gmids = () + set rep_ncpts = () - set inlist = `printf "$dtroot/%s " $tplist` - set seglist = `printf \ - "$dtroot/%s/dlabel/$xspace/aparc+aseg.nii.gz " $tplist` - - @ irep = 0 - - while ($irep <= 5) - if ($irep) then - cp $rcfile $rcfile.reinit - echo "set dopriors = 1" >> $rcfile.reinit - echo "set reinit = 1" >> $rcfile.reinit - echo "set pathlist = ($rep_pathlist)" >> $rcfile.reinit - echo "set ncpts = ($rep_ncpts)" >> $rcfile.reinit - - set cmd = trac-preproc - set cmd = ($cmd -c $rcfile.reinit) - set cmd = ($cmd -log $LF) - set cmd = ($cmd -cmd $CF) - set cmd = ($cmd -no-isrunning) - echo $cmd - $cmd - if ($status) exit 1 + set outdir_t = $dtroot/$tplist[1]/$outdir + + @ ipath = 1 + while ($ipath <= $#pathlist) + set pathname = $pathlist[$ipath] + set pathdir = $outdir_t/${pathname}_$avgmode + + if (-e $pathdir/path.pd.nii.gz) then + set pmax = `fslstats $pathdir/path.pd.nii.gz -R | awk '{print $2}'` + set pthr = `echo "$pmax * .2" | bc -l` + + set cmd = fslmaths + set cmd = ($cmd $pathdir/path.pd.nii.gz -thr $pthr) + set cmd = ($cmd $pathdir/tmp.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit endif - set cmd = $trcdir/dmri_paths - set cmd = ($cmd --indir $inlist) - set cmd = ($cmd --outdir $outlist) - set cmd = ($cmd --dwi dmri/dwi.nii.gz) - set cmd = ($cmd --grad dmri/bvecs) - set cmd = ($cmd --bval dmri/bvals) - set cmd = ($cmd --mask dlabel/diff/$brainmask.nii.gz) - set cmd = ($cmd --bpdir dmri.bedpostX) - set cmd = ($cmd --ntr $nstick) - set cmd = ($cmd --fmin $fmin) - set cmd = ($cmd --basereg dmri/xfms/anatorig2diff.$reg.mat) - set cmd = ($cmd --basemask $labdir/anatorig/$basemask.nii.gz) - set cmd = ($cmd --roi1 $roi1list) - set cmd = ($cmd --roi2 $roi2list) - if ($xspace == mni) then - set cmd = ($cmd --reg $xfmdir/anatorig2mni.mat) - else if ($xspace == cvs) then - # Hack: Using one time point for now! - if ($tplist[1] != $cvstemp) then - set xfmdir_t = $dtroot/$tplist[1]/dmri/xfms - - set cmd = ($cmd --regnl $xfmdir_t/cvs/$cvswarp.m3z) - endif + if (`fslstats $pathdir/tmp.nii.gz -V | awk '{print $2}'` \ + == `fslstats $pathdir/path.map.nii.gz -V | awk '{print $2}'`) then + set rep_pathlist = ($rep_pathlist $pathname) + set rep_gmids = ($rep_gmids $gmids[$ipath]) + set rep_ncpts = ($rep_ncpts $ncpts[$ipath]) + else + set pathpre = ${pathname}_$avgmode + + set outlist = `printf '%s\n' $outlist | grep -v $pathpre` + set roi1list = `printf '%s\n' $roi1list | grep -v $pathpre` + set roi2list = `printf '%s\n' $roi2list | grep -v $pathpre` + set initlist = `printf '%s\n' $initlist | grep -v $pathpre` + set sdplist = `printf '%s\n' $sdplist | grep -v $pathpre` + set priorlist = `printf '%s\n' $priorlist | grep -v $pathpre` + set npriorlist = `printf '%s\n' $npriorlist | grep -v $pathpre` + set lpriorlist = `printf '%s\n' $lpriorlist | grep -v $pathpre` + set tpriorlist = `printf '%s\n' $tpriorlist | grep -v $pathpre` + set cpriorlist = `printf '%s\n' $cpriorlist | grep -v $pathpre` endif - set cmd = ($cmd --init $initlist) - if ($dosegprior) then - set cmd = ($cmd --nprior $npriorlist) - set cmd = ($cmd --lprior $lpriorlist) - set cmd = ($cmd --seg $seglist) - else if ($doxyzprior) then - set cmd = ($cmd --prior $priorlist) - else if ($dotangprior) then - set cmd = ($cmd --tprior $tpriorlist) - set cmd = ($cmd --cprior $cpriorlist) + + set cmd = (rm -rf $pathdir/tmp.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif - set cmd = ($cmd --nb $nburnin --ns $nsample --nu $nupdate --nk $nkeep) - if ($doinitprop) then - set cmd = ($cmd --sdp $sdplist) + endif + + @ ipath = $ipath + 1 + end + + if ($#rep_pathlist == 0) break; + + @ irep = $irep + 1 + end + + foreach subj_t ($tplist) + set dwidir_t = $dtroot/$subj_t/dmri + set outdir_t = $dtroot/$subj_t/$outdir + + foreach pathname ($pathlist) + set pathdir = $outdir_t/${pathname}_$avgmode + + if (! -e $pathdir/path.map.txt) continue + + set pname = `echo $pathname | awk -v FS=_ '{print $1}'` + + # Get whole-path and along-path statistics + set cmd = $trcdir/dmri_pathstats + set cmd = ($cmd --intrc $pathdir) + set cmd = ($cmd --dtbase $dwidir_t/dtifit) + set cmd = ($cmd --path $pname) + set cmd = ($cmd --subj $subj_t) + set cmd = ($cmd --out $pathdir/pathstats.overall.txt) + set cmd = ($cmd --outvox $pathdir/pathstats.byvoxel.txt) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + # Project path endpoints onto cortical surface + # Skip cerebellum pathways + if ($pname == mcp) continue + + # Is it an inter-hemispheric pathway? + if ($pname =~ cc.* || $pname == acomm || $pname == mcp) then + set isinter = 1 + else + set isinter = 0 + endif + + foreach pt (1 2) + if ( $pname =~ lh.* || ($isinter == 1 && $pt == 2) ) then + set hemi = lh + else + set hemi = rh endif - if ($debug) then - set cmd = ($cmd --debug) + + if ($isinter) then + set labelname = $hemi.$pname + else + set labelname = $pname endif + + # Project from volume in DWI space to surface in structural space + set cmd = mri_vol2surf + set cmd = ($cmd --mov $pathdir/endpt$pt.pd.nii.gz) + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd --srcsubject $subj_t) + set cmd = ($cmd --hemi $hemi) + set cmd = ($cmd --projdist-avg $projmin $projmax $dproj) + set cmd = ($cmd --trgsubject $subj_t) + set cmd = ($cmd --o $pathdir/end$pt.surf.mgz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then - $fs_time $cmd |& tee -a $LF + $cmd |& tee -a $LF if ($status) goto error_exit endif - # Check if any paths need to be reinitialized - set rep_pathlist = () - set rep_ncpts = () - - set outdir_t = $dtroot/$tplist[1]/$outdir - - @ ipath = 1 - while ($ipath <= $#pathlist) - set pathname = $pathlist[$ipath] - set pathdir = $outdir_t/${pathname}_$avgmode - - if (-e $pathdir/path.pd.nii.gz) then - set pmax = `fslstats $pathdir/path.pd.nii.gz -R | awk '{print $2}'` - set pthr = `echo "$pmax * .2" | bc -l` - - set cmd = fslmaths - set cmd = ($cmd $pathdir/path.pd.nii.gz -thr $pthr) - set cmd = ($cmd $pathdir/tmp.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - if (`fslstats $pathdir/tmp.nii.gz -V | awk '{print $2}'` \ - == `fslstats $pathdir/path.map.nii.gz -V | awk '{print $2}'`) then - set rep_pathlist = ($rep_pathlist $pathname) - set rep_ncpts = ($rep_ncpts $ncpts[$ipath]) - else - set outlist = `printf '%s\n' $outlist | grep -v $pathname` - set roi1list = `printf '%s\n' $roi1list | grep -v $pathname` - set roi2list = `printf '%s\n' $roi2list | grep -v $pathname` - set initlist = `printf '%s\n' $initlist | grep -v $pathname` - set sdplist = `printf '%s\n' $sdplist | grep -v $pathname` - set priorlist = `printf '%s\n' $priorlist | grep -v $pathname` - set npriorlist = `printf '%s\n' $npriorlist | grep -v $pathname` - set lpriorlist = `printf '%s\n' $lpriorlist | grep -v $pathname` - set tpriorlist = `printf '%s\n' $tpriorlist | grep -v $pathname` - set cpriorlist = `printf '%s\n' $cpriorlist | grep -v $pathname` - endif - - set cmd = (rm -rf $pathdir/tmp.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif + set nproj = `echo "($projmax - ($projmin))/$dproj + 1" | bc -l` - @ ipath = $ipath + 1 - end - - if ($#rep_pathlist == 0) break; - - @ irep = $irep + 1 - end + set cmd = fscalc + set cmd = ($cmd $pathdir/end$pt.surf.mgz) + set cmd = ($cmd mul $nproj) + set cmd = ($cmd --o $pathdir/end$pt.surf.mgz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - foreach subj_t ($tplist) - set dwidir_t = $dtroot/$subj_t/dmri - set outdir_t = $dtroot/$subj_t/$outdir - - foreach pathname ($pathlist) - set pathdir = $outdir_t/${pathname}_$avgmode - - if (-e $pathdir/path.map.txt) then - set pname = `echo $pathname | awk -v FS=_ '{print $1}'` - - set cmd = $trcdir/dmri_pathstats - set cmd = ($cmd --intrc $pathdir) - set cmd = ($cmd --dtbase $dwidir_t/dtifit) - set cmd = ($cmd --path $pname) - set cmd = ($cmd --subj $subj_t) - set cmd = ($cmd --out $pathdir/pathstats.overall.txt) - set cmd = ($cmd --outvox $pathdir/pathstats.byvoxel.txt) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - end + set cmd = mri_binarize + set cmd = ($cmd --min 1) + set cmd = ($cmd --i $pathdir/end$pt.surf.mgz) + set cmd = ($cmd --o $pathdir/end$pt.surf.bin.mgz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - set mergelist = () - foreach dname ($outdir_t/*_$avgmode) - if (-e $dname/path.pd.nii.gz) then - set mergelist = ($mergelist `basename $dname`/path.pd.nii.gz) - endif - end + set cmd = mri_cor2label + set cmd = ($cmd --i $pathdir/end$pt.surf.bin.mgz) + set cmd = ($cmd --id 1) + set cmd = ($cmd --l $pathdir/end$pt.surf.label) + set cmd = ($cmd --surf $subj_t $hemi white) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - if ($#mergelist) then - set cmd = $trcdir/dmri_mergepaths - set cmd = ($cmd --indir $outdir_t) - set cmd = ($cmd --in $mergelist) - set cmd = ($cmd --out $outdir_t/merged_$avgmode.mgz) - set cmd = ($cmd --ctab $FREESURFER_HOME/FreeSurferColorLUT.txt) - set cmd = ($cmd --thresh .2) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif + set cmd = mri_label2label + set cmd = ($cmd --srclabel $pathdir/end$pt.surf.label) + set cmd = ($cmd --s $subj_t --hemi $hemi --regmethod surface) + set cmd = ($cmd --dilate 5 --erode 5) + set cmd = ($cmd --trglabel $pathdir/end$pt.surf.label) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif end end + + # Merge all existing pathways into a 4D volume + set mergelist = () + foreach dname ($outdir_t/*_$avgmode) + if (-e $dname/path.pd.nii.gz) then + set mergelist = ($mergelist `basename $dname`/path.pd.nii.gz) + endif + end + + if ($#mergelist) then + set cmd = $trcdir/dmri_mergepaths + set cmd = ($cmd --indir $outdir_t) + set cmd = ($cmd --in $mergelist) + set cmd = ($cmd --out $outdir_t/merged_$avgmode.mgz) + set cmd = ($cmd --ctab $FREESURFER_HOME/FreeSurferColorLUT.txt) + set cmd = ($cmd --thresh $pmin) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif end end endif diff --git a/scripts/trac-preproc b/scripts/trac-preproc index c4466f35a86..dceb4c77aa5 100755 --- a/scripts/trac-preproc +++ b/scripts/trac-preproc @@ -7,7 +7,7 @@ # # Original Author: Anastasia Yendiki # -# Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" +# Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" # # Terms and conditions for use, reproduction, distribution and contribution # are found in the 'FreeSurfer Software License Agreement' contained @@ -69,6 +69,29 @@ check_params_return: source $rcfile +if ($intrareg == 1 || $intrareg == 2) then + set reg = flt +else if ($intrareg == 3) then + set reg = bbr +endif + +if ($interreg == 1 || $interreg == 2) then + set xspace = mni +else if ($interreg == 3) then + set xspace = rob +else if ($interreg == 4) then + set xspace = cvs + set cvstempdir = `dirname $intertrg` # Assuming ../mri/norm.mgz + set cvstempdir = `dirname $cvstempdir` + set cvstemp = `basename $cvstempdir` + set cvstempdir = `dirname $cvstempdir` + set cvswarp = final_CVSmorph_to$cvstemp +else if ($interreg == 5) then + set xspace = syn +else if ($interreg == 6) then + set xspace = fnt +endif + if ($DoTime) then fs_time ls >& /dev/null if (! $status) set fs_time = fs_time @@ -190,6 +213,7 @@ if ($docorr && ! $dobase) then if ($#dcmroot > 0) set infile = $dcmroot/$infile set cmd = (rm -f $dwibase.bvals $dwibase.bvecs) + echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit @@ -343,6 +367,7 @@ if ($docorr && ! $dobase) then set blist = `cat $dwibase.bvals` set cmd = (rm -f $dwibase.bvals.tmp $dwibase.bvecs.tmp) + echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit @@ -472,11 +497,36 @@ if ($docorr && ! $dobase) then if ($status) goto error_exit endif + # If image has an odd dimension, must turn off topup subsampling :/ + set dims = `mri_info --dim $dwidir/lowb_orig_las.nii.gz` + foreach k (1 2 3) + set isodd = `echo $dims[$k] | awk '{print $1 % 2 == 1}'` + if ($isodd) break + end + + set cnf = $FSLDIR/src/topup/flirtsch/b02b0.cnf + + if ($isodd) then + echo "sed '/--subsamp/ s/2/1/g' $cnf > $dwidir/b02b0.cnf" \ + |& tee -a $LF |& tee -a $CF + if ($RunIt) then + (sed '/--subsamp/ s/2/1/g' $cnf > $dwidir/b02b0.cnf) >>& $LF + if ($status) goto error_exit + endif + else + set cmd = (cp -p $FSLDIR/src/topup/flirtsch/b02b0.cnf $dwidir) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif + # Estimate off-resonance field set cmd = topup set cmd = ($cmd --imain=$dwidir/lowb_orig_las.nii.gz) set cmd = ($cmd --datain=$dwidir/acqp.txt) - set cmd = ($cmd --config=b02b0.cnf) + set cmd = ($cmd --config=$dwidir/b02b0.cnf) set cmd = ($cmd --out=$dwidir/topup) set cmd = ($cmd --iout=$dwidir/lowb_topup.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF @@ -656,6 +706,7 @@ if ($docorr && ! $dobase) then set cmd = ($cmd --bvals=$dwidir/dwi_orig_las.bvals) set cmd = ($cmd --acqp=$dwidir/acqp.txt) set cmd = ($cmd --index=$dwidir/index.txt) + set cmd = ($cmd --data_is_shelled) # Assuming that it is! if ($dob0 > 1) then # Use previously run topup output set cmd = ($cmd --topup=$dwidir/topup) endif @@ -954,50 +1005,30 @@ if ($docorr && ! $dobase) then ### TODO: TOPUP OUTPUT ONLY, NOT EDDY # # In case FSL tools have wiped out the xform from the NIfTI header - set cmd = mri_convert - if (-e $dwidir/dwi_orig_las.nii.gz) then - set cmd = ($cmd --in_like $dwidir/dwi_orig_las.nii.gz) - else - set cmd = ($cmd --in_like $dwidir/dwi_orig_las.1.nii.gz) - endif - set cmd = ($cmd $dwidir/dwi.nii.gz $dwidir/dwi.nii.gz) - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit + if ($doeddy || $dob0) then # Some correction has been applied + set cmd = mri_convert + if (-e $dwidir/dwi_orig_las.nii.gz) then + set cmd = ($cmd --in_like $dwidir/dwi_orig_las.nii.gz) + else + set cmd = ($cmd --in_like $dwidir/dwi_orig_las.1.nii.gz) + endif + set cmd = ($cmd $dwidir/dwi.nii.gz $dwidir/dwi.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif ####################################### # In case I have discarded frames before, clean up set cmd = (rm -f $dwidir/dwi.full.nii.gz) set cmd = ($cmd $dwidir/dwi.bvecs.full $dwidir/dwi.bvals.full) - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - # Create symbolic links to files with the names that bedpostx expects - set cmd = (ln -sf $dwidir/dwi.nii.gz $dwidir/data.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - -### TODO: RENAMED THESE ############### - set cmd = (ln -sf $dwidir/dwi.bvecs $dwidir/bvecs) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - set cmd = (ln -sf $dwidir/dwi.bvals $dwidir/bvals) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif -###################################### # Make diffusion brain mask if ($#nb0 > 0) then @@ -1055,36 +1086,72 @@ if ($docorr && ! $dobase) then $cmd |& tee -a $LF if ($status) goto error_exit endif +endif + +if ($docorr && $dobase) then + echo "ERROR: Image correction step not available for base template" + goto error_exit +endif + +#------------ Select DWI set to use any subsequent steps ------------------# + +if (($docorr || $dotensor) && ! $dobase) then + echo "#-------------------------------------" |& tee -a $LF + echo "#@# DWI set selection `date`" |& tee -a $LF # If using a subset of b-values - if ($#bmax) then - set cmd = dmri_bset - set cmd = ($cmd --in $dwidir/dwi.nii.gz) - set cmd = ($cmd --bmax $bmax) - set cmd = ($cmd --out $dwidir/dwi.bmax$bmax.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit + if ($#bmax) then # Use all DWIs up to a maximum b-value + set dwiset = dwi.bmax$bmax + + if ($docorr || ! -e $dwidir/$dwiset.nii.gz) then + set cmd = dmri_bset + set cmd = ($cmd --in $dwidir/dwi.nii.gz) + set cmd = ($cmd --bmax $bmax) + set cmd = ($cmd --out $dwidir/$dwiset.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif - endif + else if ($#bshell) then # Use DWIs from one or more shells + set dwiset = dwi`printf '.b%s' $bshell` - if ($#bshell) then - set cmd = dmri_bset - set cmd = ($cmd --in $dwidir/dwi.nii.gz) - set cmd = ($cmd `printf '--b %s ' $bshell`) - set cmd = ($cmd --out $dwidir/dwi.`printf 'b%s.' $bshell`nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit + if ($docorr || ! -e $dwidir/$dwiset.nii.gz) then + set cmd = dmri_bset + set cmd = ($cmd --in $dwidir/dwi.nii.gz) + set cmd = ($cmd `printf '--b %s ' $bshell`) + set cmd = ($cmd --out $dwidir/$dwiset.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif + else # Use all DWIs + set dwiset = dwi endif -endif -if ($docorr && $dobase) then - echo "ERROR: Image correction step not available for base template" - goto error_exit + set cmd = (ln -sf $dwiset.nii.gz $dwidir/data.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set cmd = (ln -sf $dwiset.bvecs $dwidir/bvecs) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + set cmd = (ln -sf $dwiset.bvals $dwidir/bvals) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif #------------ Image quality assessment ------------------------------------# @@ -1187,952 +1254,919 @@ if ($doqa && $dobase) then goto error_exit endif - #------------ Intra-subject registration ----------------------------------# if ($dointra && ! $dobase && -e $fsdir/mri/brain.mgz) then echo "#-------------------------------------" |& tee -a $LF echo "#@# Intra-subject registration `date`" |& tee -a $LF - # Copy anatomical brain + mkdir -p $labdir/anatorig $labdir/diff + + set fslut = $FREESURFER_HOME/FreeSurferColorLUT.txt + + if ($reg == flt) then + # Register low-b to anatomical using flirt + set cmd = fslregister + set cmd = ($cmd --s $subj) + set cmd = ($cmd --mov $dwidir/lowb_brain.nii.gz) + set cmd = ($cmd --fsvol brain) + set cmd = ($cmd --out $dwidir/lowb_brain_anat_orig.$reg.nii.gz) + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.dat) + set cmd = ($cmd --lta $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd --cost $intracost --niters 2) + set cmd = ($cmd --dof $intradof --maxangle $intrarot) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($reg == bbr) then + # Register low-b to anatomical using bbregister + set cmd = bbregister + set cmd = ($cmd --s $subj) + set cmd = ($cmd --init-fsl --dti --$intradof) + set cmd = ($cmd --mov $dwidir/lowb.nii.gz) + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif + + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/anatorig2diff.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + + # Copy individual FreeSurfer segmentation (cross-sectional or longitudinal) set cmd = mri_convert - set cmd = ($cmd $fsdir/mri/brain.mgz) - set cmd = ($cmd $dwidir/brain_anat_orig.nii.gz) + set cmd = ($cmd $fsdir/mri/$segname.mgz) + set cmd = ($cmd $labdir/anatorig/$segname.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Change orientation to make FSL happy - set cmd = orientLAS - set cmd = ($cmd $dwidir/brain_anat_orig.nii.gz) - set cmd = ($cmd $dwidir/brain_anat.nii.gz) + # Dilate segmentation to make brain mask + set cmd = mri_binarize + set cmd = ($cmd --i $labdir/anatorig/$segname.nii.gz) + set cmd = ($cmd --min .5 --dilate 4 --erode 2) + set cmd = ($cmd --o $labdir/anatorig/${segname}_mask.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Calculate original anatomical to LAS anatomical - set cmd = tkregister2 - set cmd = ($cmd --mov $dwidir/brain_anat_orig.nii.gz) - set cmd = ($cmd --targ $dwidir/brain_anat.nii.gz) - set cmd = ($cmd --regheader --noedit) - set cmd = ($cmd --fslregout $xfmdir/anatorig2anat.mat) - set cmd = ($cmd --reg $xfmdir/anat2anatorig.dat) + if ($usethalnuc) then + set thalseg = ThalamicNuclei.v12.T1.FSvoxelSpace + + if (! -e $fsdir/mri/$thalseg.mgz) then + echo "ERROR: Could not find $fsdir/mri/$thalseg.mgz" + echo "ERROR: Thalamic nuclei segmentation is strongly recommended to use" + echo "ERROR: for tracts that terminate in or travel near the thalamus" + echo "ERROR: If there is good reason not to use it, set usethalnuc = 0" + goto error_exit + endif + + # Replace thalamus in main segmentation with nearest neighbor labels + set ids = () + foreach label (Left-Thalamus Right-Thalamus) + set ids = ($ids `grep -i " ${label}[ \t]" $fslut | awk '{print $1}'`) + end + + set cmd = mri_binarize + set cmd = ($cmd --i $fsdir/mri/$segname.mgz) + set cmd = ($cmd `printf "--replaceonly-nn %s 11 " $ids`) + set cmd = ($cmd --o $labdir/anatorig/${segname}+thalnuc.nii.gz) + echo $cmd + $cmd + + # Merge main segmentation with thalamic nuclei segmentation + set cmd = mri_concat + set cmd = ($cmd --i $labdir/anatorig/${segname}+thalnuc.nii.gz) + set cmd = ($cmd --i $fsdir/mri/$thalseg.mgz) + set cmd = ($cmd --max) + set cmd = ($cmd --o $labdir/anatorig/${segname}+thalnuc.nii.gz) + echo $cmd + $cmd + endif + + # Extract white-matter labels from segmentation + set wmlist = ( Left-Cerebral-White-Matter \ + Right-Cerebral-White-Matter \ + Left-Cerebellum-White-Matter \ + Right-Cerebellum-White-Matter \ + Vermis \ + Vermis-White-Matter \ + WM-hypointensities \ + Left-VentralDC \ + Right-VentralDC \ + Brain-Stem \ + Midbrain \ + Pons \ + Medulla ) + + # Make mask including cerebral WM, cerebellar WM, and WM hypointensities + set ids = () + foreach label ($wmlist[1-7]) + set ids = ($ids `grep -i " ${label}[ \t]" $fslut | awk '{print $1}'`) + end + + set cmd = mri_binarize + set cmd = ($cmd --i $fsdir/mri/$segname.mgz) + set cmd = ($cmd --match $ids) + set cmd = ($cmd --o $labdir/anatorig/White-Matter.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anat2anatorig.mat) - set cmd = ($cmd -inverse $xfmdir/anatorig2anat.mat) + # As above, plus ventral DC and brainstem + set ids = () + foreach label ($wmlist) + set ids = ($ids `grep -i " ${label}[ \t]" $fslut | awk '{print $1}'`) + end + + set cmd = mri_binarize + set cmd = ($cmd --i $fsdir/mri/$segname.mgz) + set cmd = ($cmd --match $ids) + set cmd = ($cmd --o $labdir/anatorig/White-Matter++.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - if ($doregflt) then - # Register low-b to anatomical using flirt - set cmd = flirt - set cmd = ($cmd -in $dwidir/lowb_brain.nii.gz) - set cmd = ($cmd -ref $dwidir/brain_anat.nii.gz) - set cmd = ($cmd -out $dwidir/lowb_brain_anat.flt.nii.gz) - set cmd = ($cmd -omat $xfmdir/diff2anat.flt.mat) - set cmd = ($cmd -cost corratio) + # Map anatomical segmentation and mask to diffusion space + set labelist = ( $segname ${segname}_mask White-Matter White-Matter++ ) + if ($usethalnuc) set labelist = ( $labelist ${segname}+thalnuc ) + + foreach label ($labelist) + set cmd = mri_convert + set cmd = ($cmd -at $xfmdir/anatorig2diff.$reg.lta) + set cmd = ($cmd -rt nearest) # Binary masks! + set cmd = ($cmd $labdir/anatorig/$label.nii.gz) + set cmd = ($cmd $labdir/diff/$label.$reg.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then - $fs_time $cmd |& tee -a $LF + $cmd |& tee -a $LF if ($status) goto error_exit endif + end + + # Calculate SNR of DWIs in WM mask + set cmd = fslstats + set cmd = ($cmd -t $dwidir/dwi.nii.gz) + set cmd = ($cmd -k $labdir/diff/White-Matter++.$reg.nii.gz) + set cmd = ($cmd -m -s) + echo "$cmd | awk '{print "'$1/$2'"}' > $dwidir/dwi_snr.txt" \ + |& tee -a $LF |& tee -a $CF + if ($RunIt) then + ($cmd | awk '{print $1/$2}' > $dwidir/dwi_snr.txt) >>& $LF + endif + + # Map diffusion brain mask to individual anatomical space + set cmd = mri_convert + set cmd = ($cmd -at $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd -rt nearest) # Binary masks! + set cmd = ($cmd $labdir/diff/lowb_brain_mask.nii.gz) + set cmd = ($cmd $labdir/anatorig/lowb_brain_mask.$reg.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif +endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anat2diff.flt.mat) - set cmd = ($cmd -inverse $xfmdir/diff2anat.flt.mat) +if ($dointra && $dobase) then + echo "#-------------------------------------" |& tee -a $LF + echo "#@# Intra-subject registration (base template) `date`" |& tee -a $LF + + mkdir -p $labdir/anatorig + + # Compute intersection of masks from all time points in base template space + foreach fname (${segname}_mask lowb_brain_mask.$reg) + set inlist = `printf "$dtroot/%s/dlabel/anatorig/$fname.nii.gz " $tplist` + + set cmd = mri_concat + set cmd = ($cmd --i $inlist) + set cmd = ($cmd --min) + set cmd = ($cmd --o $labdir/anatorig/$fname.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif + end +endif + +#------------ Tensor fit --------------------------------------------------# + +if ($dotensor && ! $dobase) then + echo "#-------------------------------------" |& tee -a $LF + echo "#@# Tensor fit `date`" |& tee -a $LF + + if ($usemaskanat) then + set brainmask = $labdir/diff/${segname}_mask.$reg.nii.gz + else + set brainmask = $labdir/diff/lowb_brain_mask.nii.gz + endif + + # LS tensor estimation + set cmd = dtifit + set cmd = ($cmd -k $dwidir/data.nii.gz) + set cmd = ($cmd -m $brainmask) + set cmd = ($cmd -r $dwidir/bvecs) + set cmd = ($cmd -b $dwidir/bvals) + set cmd = ($cmd -o $dwidir/dtifit) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif +endif + +if ($dotensor && $dobase) then + echo "ERROR: Tensor-fit step not available for base template" + goto error_exit +endif + +#------------ Inter-subject registration ----------------------------------# + +if ($dointer && ! $dobase) then + echo "#-------------------------------------" |& tee -a $LF + echo "#@# Inter-subject registration `date`" |& tee -a $LF + + if ($xspace != syn && $xspace != fnt) then # Check if individual T1 exists + if (! -e $fsdir/mri/brain.mgz) then + echo "ERROR: Could not find $fsdir/mri/brain.mgz" + goto error_exit + endif + endif + + if ($xspace == cvs) then + if ($subj == $cvstemp) then + if (-e $labdir/cvs && ! -l $labdir/cvs) rm -rf $labdir/cvs + ln -sfn ../anatorig $labdir/cvs + else + if (-l $labdir/cvs) rm -f $labdir/cvs + mkdir -p $labdir/cvs + endif + else + mkdir -p $labdir/$xspace + endif - # Calculate original (freesurfer) anatomical to low-b - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anatorig2diff.flt.mat) - set cmd = ($cmd -concat $xfmdir/anat2diff.flt.mat) - set cmd = ($cmd $xfmdir/anatorig2anat.mat) + if ($xspace == mni) then + # Copy anatomical brain + set cmd = mri_convert + set cmd = ($cmd $fsdir/mri/brain.mgz) + set cmd = ($cmd $dwidir/brain_anat_orig.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/diff2anatorig.flt.mat) - set cmd = ($cmd -inverse $xfmdir/anatorig2diff.flt.mat) + # Change orientation to LAS before running flirt to avoid flipping + set cmd = orientLAS + set cmd = ($cmd $dwidir/brain_anat_orig.nii.gz) + set cmd = ($cmd $dwidir/brain_anat.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif - if ($doregbbr) then - # Register low-b to anatomical using bbregister - set cmd = bbregister - set cmd = ($cmd --s $subj) - set cmd = ($cmd --init-fsl --dti) - set cmd = ($cmd --mov $dwidir/dwi.nii.gz) - set cmd = ($cmd --reg $xfmdir/anatorig2diff.bbr.dat) - set cmd = ($cmd --fslmat $xfmdir/diff2anatorig.bbr.mat) + # Register anatomical to MNI template + set cmd = flirt + set cmd = ($cmd -in $dwidir/brain_anat.nii.gz) + set cmd = ($cmd -ref $intertrg) + set cmd = ($cmd -out $dwidir/brain_anat_mni.nii.gz) + set cmd = ($cmd -omat $xfmdir/anat2mni.mat) + set cmd = ($cmd -cost $intercost) + echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $fs_time $cmd |& tee -a $LF if ($status) goto error_exit endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anatorig2diff.bbr.mat) - set cmd = ($cmd -inverse $xfmdir/diff2anatorig.bbr.mat) + set cmd = lta_convert + set cmd = ($cmd --infsl $xfmdir/anat2mni.mat) + set cmd = ($cmd --src $dwidir/brain_anat.nii.gz) + set cmd = ($cmd --trg $intertrg) + set cmd = ($cmd --outlta $xfmdir/anat2mni.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Calculate LAS anatomical to low-b - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anat2diff.bbr.mat) - set cmd = ($cmd -concat $xfmdir/anatorig2diff.bbr.mat) - set cmd = ($cmd $xfmdir/anat2anatorig.mat) + # Calculate original anatomical to LAS anatomical + set cmd = tkregister2 + set cmd = ($cmd --mov $dwidir/brain_anat_orig.nii.gz) + set cmd = ($cmd --targ $dwidir/brain_anat.nii.gz) + set cmd = ($cmd --regheader --noedit) + set cmd = ($cmd --reg $xfmdir/anatorig2anat.dat) + set cmd = ($cmd --ltaout $xfmdir/anatorig2anat.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/diff2anat.bbr.mat) - set cmd = ($cmd -inverse $xfmdir/anat2diff.bbr.mat) + # Calculate original anatomical to MNI template + set cmd = mri_concatenate_lta + set cmd = ($cmd $xfmdir/anatorig2anat.lta) + set cmd = ($cmd $xfmdir/anat2mni.lta) + set cmd = ($cmd $xfmdir/anatorig2mni.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif -endif -if ($dointra && $dobase) then - echo "ERROR: Intra-subject registration step not available for base template" - goto error_exit -endif + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/anatorig2mni.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/mni2anatorig.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif -#------------ Inter-subject registration ----------------------------------# + # Calculate low-b to MNI template + set cmd = mri_concatenate_lta + set cmd = ($cmd $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd $xfmdir/anatorig2mni.lta) + set cmd = ($cmd $xfmdir/diff2mni.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif -if ($dointer && ! $dobase) then - echo "#-------------------------------------" |& tee -a $LF - echo "#@# Inter-subject registration `date`" |& tee -a $LF + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/diff2mni.$reg.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/mni2diff.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($xspace == rob) then + # Register anatomical to robust template + set cmd = mri_robust_register + set cmd = ($cmd --mov $fsdir/mri/brain.mgz) + set cmd = ($cmd --dst $intertrg) + set cmd = ($cmd --mapmov $dwidir/brain_anat_orig_rob.nii.gz) + set cmd = ($cmd --lta $xfmdir/anatorig2rob.lta) + set cmd = ($cmd --affine --cost ROB --satit) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - if (-e $fsdir/mri/brain.mgz) then # If individual T1 exists - if ($doregmni) then - # Register anatomical to MNI template - set cmd = flirt - set cmd = ($cmd -in $dwidir/brain_anat.nii.gz) - set cmd = ($cmd -ref $mnitemp) - set cmd = ($cmd -out $dwidir/brain_anat_mni.nii.gz) - set cmd = ($cmd -omat $xfmdir/anat2mni.mat) - set cmd = ($cmd -cost mutualinfo) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/mni2anat.mat) - set cmd = ($cmd -inverse $xfmdir/anat2mni.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - # Calculate low-b to MNI template - foreach reg (flt bbr) - if (-e $xfmdir/diff2anat.$reg.mat) then - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/diff2mni.$reg.mat) - set cmd = ($cmd -concat $xfmdir/anat2mni.mat) - set cmd = ($cmd $xfmdir/diff2anat.$reg.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/mni2diff.$reg.mat) - set cmd = ($cmd -inverse $xfmdir/diff2mni.$reg.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - end + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/anatorig2rob.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/rob2anatorig.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - # Calculate original (freesurfer) anatomical to MNI template - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/anatorig2mni.mat) - set cmd = ($cmd -concat $xfmdir/anat2mni.mat) - set cmd = ($cmd $xfmdir/anatorig2anat.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif + # Calculate low-b to template + set cmd = mri_concatenate_lta + set cmd = ($cmd $xfmdir/diff2anatorig.$reg.lta) + set cmd = ($cmd $xfmdir/anatorig2rob.lta) + set cmd = ($cmd $xfmdir/diff2rob.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/mni2anatorig.mat) - set cmd = ($cmd -inverse $xfmdir/anatorig2mni.mat) + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/diff2rob.$reg.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/rob2diff.$reg.lta) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($xspace == cvs) then + if ($subj == $cvstemp) then + set cmd = (rm -f $xfmdir/cvs) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif - - if ($doregcvs) then - if ($subj == $cvstemp) then - set cmd = (rm -f $xfmdir/cvs) + else + # Create morph of anatomical to CVS template if it doesn't exist + if (-e $fsdir/cvs/el_reg_to$cvstemp.mgz) then + set cmd = (ln -sfn $fsdir/cvs $xfmdir/cvs) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif else - # Create morph of anatomical to CVS template if it doesn't exist - if (-e $fsdir/cvs/el_reg_to$cvstemp.mgz) then - set cmd = (ln -sfn $fsdir/cvs $xfmdir/cvs) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - else - mkdir -p $fsdir/cvs/$cvstemp + mkdir -p $fsdir/cvs/$cvstemp + + set cmd = (ln -sfn $fsdir/cvs/$cvstemp $xfmdir/cvs) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + endif + + if (! -e $xfmdir/cvs/$cvswarp.m3z) then + set oldcvswarp = combined_to${cvstemp}_elreg_afteraseg-norm - set cmd = (ln -sfn $fsdir/cvs/$cvstemp $xfmdir/cvs) + if (-e $xfmdir/cvs/$oldcvswarp.m3z) then + # If 2nd-generation CVS was run, + # make symlink with 3rd-generation naming + set cmd = (ln -s ./$oldcvswarp.m3z $xfmdir/cvs/$cvswarp.m3z) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif - - set cvswarp = final_CVSmorph_to$cvstemp - - if (! -e $xfmdir/cvs/$cvswarp.m3z) then - set oldcvswarp = combined_to${cvstemp}_elreg_afteraseg-norm + else + if (! -e $SUBJECTS_DIR/$cvstemp) then + if (! -e $cvstempdir/$cvstemp) then + echo "ERROR: Could not find CVS template $cvstempdir/$cvstemp" + goto error_exit + endif - if (-e $xfmdir/cvs/$oldcvswarp.m3z) then - # If 2nd-generation CVS was run, - # make symlink with 3rd-generation naming - set cmd = (ln -s ./$oldcvswarp.m3z $xfmdir/cvs/$cvswarp.m3z) + set cmd = (ln -s $cvstempdir/$cvstemp $SUBJECTS_DIR) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - else - if (! -e $SUBJECTS_DIR/$cvstemp) then - if (! -e $cvstempdir/$cvstemp) then - echo "ERROR: Could not find CVS template $cvstempdir/$cvstemp" - goto error_exit - endif + endif - set cmd = (ln -s $cvstempdir/$cvstemp $SUBJECTS_DIR) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif + if (! -e $xfmdir/cvs/nlalign-afteraseg-norm.m3z) then + # Register anatomical to CVS template + set cmd = mri_cvs_register + set cmd = ($cmd --mov $subj) + set cmd = ($cmd --template $cvstemp) + set cmd = ($cmd --outdir $xfmdir/cvs) + set cmd = ($cmd --cleanall) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit endif - - if (! -e $xfmdir/cvs/nlalign-afteraseg-norm.m3z) then - # Register anatomical to CVS template - set cmd = mri_cvs_register - set cmd = ($cmd --mov $subj) - set cmd = ($cmd --template $cvstemp) - set cmd = ($cmd --outdir $xfmdir/cvs) - set cmd = ($cmd --cleanall) + else # 1st-generation mri_cvs_register has been run + if (! -e $xfmdir/cvs/$cvswarp.tm3d) then + # Recreate full morph .tm3d from its components + set cmd = createMorph + set cmd = ($cmd --out $xfmdir/cvs/$cvswarp.tm3d) + set cmd = ($cmd --template $intertrg) + set cmd = ($cmd --subject $fsdir/mri/norm.mgz) + set cmd = ($cmd --in gcam $xfmdir/cvs/nlalign-afteraseg-norm.m3z) + set cmd = ($cmd morph $xfmdir/cvs/el_reg_to$cvstemp.tm3d) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $fs_time $cmd |& tee -a $LF if ($status) goto error_exit endif - else # 1st-generation mri_cvs_register has been run - if (! -e $xfmdir/cvs/$cvswarp.tm3d) then - # Recreate full morph .tm3d from its components - set cmd = createMorph - set cmd = ($cmd --out $xfmdir/cvs/$cvswarp.tm3d) - set cmd = ($cmd --template $SUBJECTS_DIR/$cvstemp/mri/norm.mgz) - set cmd = ($cmd --subject $fsdir/mri/norm.mgz) - set cmd = ($cmd --in gcam $xfmdir/cvs/nlalign-afteraseg-norm.m3z) - set cmd = ($cmd morph $xfmdir/cvs/el_reg_to$cvstemp.tm3d) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif + endif - # Convert .tm3d to .m3z - set cmd = exportGcam - set cmd = ($cmd --morph $xfmdir/cvs/$cvswarp.tm3d) - set cmd = ($cmd --fixed $SUBJECTS_DIR/$cvstemp/mri/norm.mgz) - set cmd = ($cmd --moving $fsdir/mri/norm.mgz) - set cmd = ($cmd --out_gcam $xfmdir/cvs/$cvswarp.m3z) - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif + # Convert .tm3d to .m3z + set cmd = exportGcam + set cmd = ($cmd --morph $xfmdir/cvs/$cvswarp.tm3d) + set cmd = ($cmd --fixed $intertrg) + set cmd = ($cmd --moving $fsdir/mri/norm.mgz) + set cmd = ($cmd --out_gcam $xfmdir/cvs/$cvswarp.m3z) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit endif endif endif endif endif - else # If individual T1 doesn't exist - # Register low-b directly to MNI template - set cmd = flirt - set cmd = ($cmd -in $dwidir/lowb_brain.nii.gz) - set cmd = ($cmd -ref $mnitemp) - set cmd = ($cmd -out $dwidir/lowb_brain_mni.nii.gz) - set cmd = ($cmd -omat $xfmdir/diff2mni.mat) - set cmd = ($cmd -cost corratio) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit + else if ($xspace == syn) then + if (! $?ANTSPATH) then + echo "ERROR: must set ANTSPATH environment variable to use ANTs" + exit 1 endif - set cmd = convert_xfm - set cmd = ($cmd -omat $xfmdir/mni2diff.mat) - set cmd = ($cmd -inverse $xfmdir/diff2mni.mat) + # Register FA nonlinearly to FA template with SyN + set cmd = $ANTSPATH/antsRegistrationSyNQuick.sh + set cmd = ($cmd -d 3) + set cmd = ($cmd -m $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd -f $intertrg) + set cmd = ($cmd -o $xfmdir/diff2syn) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif -endif - -if ($dointer && $dobase) then - echo "#-------------------------------------" |& tee -a $LF - echo "#@# Inter-subject registration (base template) `date`" |& tee -a $LF - - if ($doregmni) then - # Affine registration from MNI template to base template - # Hack: Using one time point for now! - set xfmdir_t = $dtroot/$tplist[1]/dmri/xfms - set cmd = cp - set cmd = ($cmd $xfmdir_t/mni2anatorig.mat) - set cmd = ($cmd $xfmdir_t/anatorig2mni.mat) - set cmd = ($cmd $xfmdir) + # Convert affine transform to .lta + set cmd = ConvertTransformFile + set cmd = ($cmd 3 $xfmdir/diff2syn0GenericAffine.mat) + set cmd = ($cmd $xfmdir/diff2syn0GenericAffine.txt) + set cmd = ($cmd --hm --ras) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif -endif - -#------------ White-matter, cortex, and whole-brain masks -----------------# -if ($domasks && ! $dobase) then - echo "#-------------------------------------" |& tee -a $LF - echo "#@# Masks `date`" |& tee -a $LF - - set cvswarp = final_CVSmorph_to$cvstemp - - mkdir -p $labdir/diff - if (-e $fsdir/mri/aparc+aseg.mgz) mkdir -p $labdir/anatorig $labdir/anat - if ($doregmni && -e $xfmdir/anat2mni.mat) mkdir -p $labdir/mni - if ($doregcvs) then - if ($subj == $cvstemp) then - if (-e $labdir/cvs && ! -l $labdir/cvs) rm -rf $labdir/cvs - ln -sfn $labdir/anatorig $labdir/cvs - else - if (-l $labdir/cvs) rm -f $labdir/cvs - if (-e $xfmdir/cvs/$cvswarp.m3z) mkdir -p $labdir/cvs - endif - endif - - if (! -e $fsdir/mri/aparc+aseg.mgz) then - echo "WARN: Could not find $fsdir/mri/aparc+aseg.mgz" - echo "WARN: You will not be able to complete TRACULA processing without it" - else - # - # Extract all necessary files from FreeSurfer segmentation - # (cross-sectional or longitudinal) - # - - set wmlist = ( Left-Cerebral-White-Matter \ - Left-Cerebellum-White-Matter \ - Right-Cerebral-White-Matter \ - Right-Cerebellum-White-Matter \ - WM-hypointensities \ - Left-VentralDC \ - Right-VentralDC \ - Brain-Stem ) - - set ventlist = ( Left-Lateral-Ventricle \ - Right-Lateral-Ventricle ) - - set fslut = $FREESURFER_HOME/FreeSurferColorLUT.txt - - # Make mask including cerebral WM, cerebellar WM, and WM hypointensities - set cmd = mri_binarize - set cmd = ($cmd --i $fsdir/mri/aparc+aseg.mgz) - foreach label ($wmlist[1-5]) - set id = `grep -i " ${label}[ \t]" $fslut` - set id = $id[1] - set cmd = ($cmd --match $id) - end - set cmd = ($cmd --o $labdir/anatorig/White-Matter.nii.gz) + set cmd = lta_convert + set cmd = ($cmd --inniftyreg $xfmdir/diff2syn0GenericAffine.txt) + set cmd = ($cmd --outlta $xfmdir/diff2syn.lta) + set cmd = ($cmd --src $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd --trg $intertrg) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # As above, plus ventral DC and brainstem - set cmd = mri_binarize - set cmd = ($cmd --i $fsdir/mri/aparc+aseg.mgz) - foreach label ($wmlist) - set id = `grep -i " ${label}[ \t]" $fslut` - set id = $id[1] - set cmd = ($cmd --match $id) - end - set cmd = ($cmd --o $labdir/anatorig/White-Matter++.nii.gz) + # Convert nonlinear warp to .m3z + set cmd = mri_warp_convert + set cmd = ($cmd --initk $xfmdir/diff2syn1Warp.nii.gz) + set cmd = ($cmd --outm3z $xfmdir/syn_warp.m3z) + set cmd = ($cmd --insrcgeom $intertrg) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Make mask excluding lateral ventricles - set cmd = mri_binarize - set cmd = ($cmd --i $fsdir/mri/aparc+aseg.mgz) - foreach label ($ventlist) - set id = `grep -i " ${label}[ \t]" $fslut` - set id = $id[1] - set cmd = ($cmd --match $id) - end - set cmd = ($cmd --binval 0 --binvalnot 1) - set cmd = ($cmd --o $labdir/anatorig/notventricles.nii.gz) + # Calculate affine from template to individual diffusion + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/diff2syn.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/syn2diff.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Map cortical parcellation to volume, growing 2mm into the WM - set gmgrow = 2 - - set cmd = mri_aparc2aseg - set cmd = ($cmd --s $subj) - set cmd = ($cmd --annot aparc) - set cmd = ($cmd --wmparc-dmax $gmgrow) - set cmd = ($cmd --labelwm --hypo-as-wm) - set cmd = ($cmd --o $labdir/anatorig/aparc+aseg+${gmgrow}mm.nii.gz) + # Calculate affine from individual anatomical to template + set cmd = mri_concatenate_lta + set cmd = ($cmd $xfmdir/anatorig2diff.$reg.lta) + set cmd = ($cmd $xfmdir/diff2syn.lta) + set cmd = ($cmd $xfmdir/anatorig2syn.$reg.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Make mask of cortex - set cmd = mri_binarize - set cmd = ($cmd --i $labdir/anatorig/aparc+aseg+${gmgrow}mm.nii.gz) - set cmd = ($cmd --min 1000 --max 2999) - set cmd = ($cmd --o $labdir/anatorig/cortex.nii.gz) + # Calculate affine from template to individual anatomical + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/anatorig2syn.$reg.lta) + set cmd = ($cmd --invert) + set cmd = ($cmd --outlta $xfmdir/syn2anatorig.$reg.lta) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Make mask of grown cortex - set cmd = mri_binarize - set cmd = ($cmd --i $labdir/anatorig/aparc+aseg+${gmgrow}mm.nii.gz) - set cmd = ($cmd --min 1000 --max 4999) - set cmd = ($cmd --o $labdir/anatorig/cortex+${gmgrow}mm.nii.gz) + # Create identity transform in template space + printf '1 0 0 0\n0 1 0 0\n0 0 1 0\n0 0 0 1' > $xfmdir/identity.mat + + set cmd = lta_convert + set cmd = ($cmd --infsl $xfmdir/identity.mat) + set cmd = ($cmd --outlta $xfmdir/syn2syn.lta) + set cmd = ($cmd --src $intertrg) + set cmd = ($cmd --trg $intertrg) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - - # Make mask of grown cortex plus brainstem - set id = `grep -i " Brain-Stem[ \t]" $fslut` - set id = $id[1] - - set cmd = mri_binarize - set cmd = ($cmd --i $fsdir/mri/aparc+aseg.mgz) - set cmd = ($cmd --match $id) - set cmd = ($cmd --o $labdir/anatorig/Brain-Stem.nii.gz) + else if ($xspace == fnt) then + # Register FA nonlinearly to FA template with FNIRT + set cmd = fsl_reg + set cmd = ($cmd $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd $intertrg) + set cmd = ($cmd $xfmdir/diff2fsl) + set cmd = ($cmd -e -FA) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - set cmd = fslmaths - set cmd = ($cmd $labdir/anatorig/cortex+${gmgrow}mm.nii.gz) - set cmd = ($cmd -add $labdir/anatorig/Brain-Stem.nii.gz) - set cmd = ($cmd $labdir/anatorig/cortex+${gmgrow}mm+bs.nii.gz) + # Calculate template to individual diffusion + set cmd = invwarp + set cmd = ($cmd -r $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd -w $xfmdir/diff2fsl_warp) + set cmd = ($cmd -o $xfmdir/fsl2diff_warp) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Copy T1 brain mask - set cmd = mri_convert - set cmd = ($cmd $fsdir/mri/brainmask.mgz) - set cmd = ($cmd $labdir/anatorig/anat_brain_mask.nii.gz) + # Calculate individual anatomical to template + set cmd = lta_convert + set cmd = ($cmd --inlta $xfmdir/anatorig2diff.$reg.lta) + set cmd = ($cmd --outfsl $xfmdir/anatorig2diff.$reg.mat) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Exclude ventricles from brain mask - set cmd = fslmaths - set cmd = ($cmd $labdir/anatorig/anat_brain_mask.nii.gz) - set cmd = ($cmd -mul $labdir/anatorig/notventricles.nii.gz) - set cmd = ($cmd $labdir/anatorig/anat_brain_mask-vent.nii.gz) + set cmd = convertwarp + set cmd = ($cmd -r $intertrg) + set cmd = ($cmd -m $xfmdir/anatorig2diff.$reg.mat) + set cmd = ($cmd -w $xfmdir/diff2fsl_warp) + set cmd = ($cmd -o $xfmdir/anatorig2fsl_warp.$reg) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - # Copy T1 segmentation - set cmd = mri_convert - set cmd = ($cmd $fsdir/mri/aparc+aseg.mgz) - set cmd = ($cmd $labdir/anatorig/aparc+aseg.nii.gz) + # Convert original warp to .m3z + set cmd = mri_warp_convert + set cmd = ($cmd --infsl $xfmdir/diff2fsl_warp.nii.gz) + set cmd = ($cmd --outm3z $xfmdir/diff2fsl_warp.m3z) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif + endif - # Dilate segmentation to make brain mask - set cmd = fslmaths - set cmd = ($cmd $labdir/anatorig/aparc+aseg.nii.gz) - set cmd = ($cmd -dilM -bin) - set cmd = ($cmd $labdir/anatorig/aparc+aseg_mask.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit + # Map anatomical segmentation and mask to template space + set labelist = ( $segname ${segname}_mask White-Matter White-Matter++ ) + if ($usethalnuc) set labelist = ( $labelist ${segname}+thalnuc ) + + foreach label ($labelist) + if (! -e $labdir/anatorig/$label.nii.gz) then + echo "WARN: Could not find $labdir/anatorig/$label.nii.gz" + continue endif - foreach label ( White-Matter White-Matter++ notventricles \ - cortex cortex+${gmgrow}mm cortex+${gmgrow}mm+bs \ - aparc+aseg aparc+aseg+${gmgrow}mm aparc+aseg_mask \ - anat_brain_mask anat_brain_mask-vent ) - # Change orientation to make FSL happy - set cmd = orientLAS - set cmd = ($cmd $labdir/anatorig/$label.nii.gz) - set cmd = ($cmd $labdir/anat/$label.nii.gz) + if ($xspace == mni || $xspace == rob) then + set cmd = mri_convert + set cmd = ($cmd -at $xfmdir/anatorig2$xspace.lta) + set cmd = ($cmd -rt nearest) # Binary masks! + set cmd = ($cmd $labdir/anatorig/$label.nii.gz) + set cmd = ($cmd $labdir/$xspace/$label.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - - # Map label to diffusion space - foreach reg (flt bbr) - if (-e $xfmdir/anat2diff.$reg.mat) then - set cmd = flirt - set cmd = ($cmd -in $labdir/anat/$label.nii.gz) - set cmd = ($cmd -ref $dwidir/lowb.nii.gz) - set cmd = ($cmd -out $labdir/diff/$label.$reg.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/anat2diff.$reg.mat) - set cmd = ($cmd -interp nearestneighbour) # Binary masks! - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - end - - # Map label to MNI space - if ($doregmni && -e $xfmdir/anat2mni.mat) then - set cmd = flirt - set cmd = ($cmd -in $labdir/anat/$label.nii.gz) - set cmd = ($cmd -ref $mnitemp) - set cmd = ($cmd -out $labdir/mni/$label.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/anat2mni.mat) - set cmd = ($cmd -interp nearestneighbour) # Binary masks! - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - - # Map label to CVS space - if ($doregcvs && -e $xfmdir/cvs/$cvswarp.m3z) then - set cmd = mri_vol2vol - set cmd = ($cmd --mov $labdir/anatorig/$label.nii.gz) - set cmd = ($cmd --targ $SUBJECTS_DIR/$cvstemp/mri/norm.mgz) - set cmd = ($cmd --o $labdir/cvs/$label.nii.gz) - set cmd = ($cmd --m3z $xfmdir/cvs/$cvswarp.m3z) - set cmd = ($cmd --noDefM3zPath) - set cmd = ($cmd --interp nearest) # Binary masks! - set cmd = ($cmd --no-save-reg) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif + else if ($xspace == cvs) then + set cmd = mri_vol2vol + set cmd = ($cmd --mov $labdir/anatorig/$label.nii.gz) + set cmd = ($cmd --targ $intertrg) + set cmd = ($cmd --o $labdir/cvs/$label.nii.gz) + set cmd = ($cmd --m3z $xfmdir/cvs/$cvswarp.m3z) + set cmd = ($cmd --noDefM3zPath) + set cmd = ($cmd --interp nearest) # Binary masks! + set cmd = ($cmd --no-save-reg) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit endif - end - - # Calculate SNR of DWIs in WM mask - set cmd = fslstats - set cmd = ($cmd -t $dwidir/dwi.nii.gz) - if ($doregbbr && -e $labdir/diff/White-Matter++.bbr.nii.gz) then - set cmd = ($cmd -k $labdir/diff/White-Matter++.bbr.nii.gz) - else - set cmd = ($cmd -k $labdir/diff/White-Matter++.flt.nii.gz) - endif - set cmd = ($cmd -m -s) - echo "$cmd | awk '{print "'$1/$2'"}' > $dwidir/dwi_snr.txt" \ - |& tee -a $LF |& tee -a $CF - if ($RunIt) then - ($cmd | awk '{print $1/$2}' > $dwidir/dwi_snr.txt) >>& $LF - endif - endif - - foreach reg (flt bbr) - if ($doregmni && -e $xfmdir/diff2mni.$reg.mat) then - # Map diffusion brain mask to MNI space - set cmd = flirt - set cmd = ($cmd -in $labdir/diff/lowb_brain_mask.nii.gz) - set cmd = ($cmd -ref $mnitemp) - set cmd = ($cmd -out $labdir/mni/lowb_brain_mask.$reg.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/diff2mni.$reg.mat) - set cmd = ($cmd -interp nearestneighbour) # Binary masks! + else if ($xspace == syn) then + set cmd = mri_vol2vol + set cmd = ($cmd --gcam $labdir/anatorig/$label.nii.gz) + set cmd = ($cmd $xfmdir/anatorig2syn.$reg.lta) + set cmd = ($cmd $xfmdir/syn_warp.m3z) + set cmd = ($cmd $xfmdir/syn2syn.lta 0 0) # Binary masks! + set cmd = ($cmd $labdir/syn/$label.nii.gz) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - endif - - if (-e $xfmdir/diff2anatorig.$reg.mat) then - # Map diffusion brain mask to individual anatomical space - set cmd = flirt - set cmd = ($cmd -in $labdir/diff/lowb_brain_mask.nii.gz) - set cmd = ($cmd -ref $dwidir/brain_anat_orig.nii.gz) - set cmd = ($cmd -out $labdir/anatorig/lowb_brain_mask.$reg.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/diff2anatorig.$reg.mat) - set cmd = ($cmd -interp nearestneighbour) # Binary masks! + else if ($xspace == fnt) then + set cmd = applywarp + set cmd = ($cmd -w $xfmdir/anatorig2fsl_warp.$reg --rel) + set cmd = ($cmd -i $labdir/anatorig/$label.nii.gz) + set cmd = ($cmd -r $intertrg) + set cmd = ($cmd -o $labdir/fnt/$label.nii.gz) + set cmd = ($cmd --interp=nn) # Binary masks! echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - - if ($doregcvs && -e $xfmdir/cvs/$cvswarp.m3z) then - # Map diffusion brain mask to CVS space - set cmd = mri_vol2vol - set cmd = ($cmd --mov $labdir/anatorig/lowb_brain_mask.$reg.nii.gz) - set cmd = ($cmd --targ $SUBJECTS_DIR/$cvstemp/mri/norm.mgz) - set cmd = ($cmd --o $labdir/cvs/lowb_brain_mask.$reg.nii.gz) - set cmd = ($cmd --m3z $xfmdir/cvs/$cvswarp.m3z) - set cmd = ($cmd --noDefM3zPath) - set cmd = ($cmd --interp nearest) # Binary masks! - set cmd = ($cmd --no-save-reg) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif endif end - # Create symbolic link to brain mask with the name that bedpostx expects - set bedmask = $labdir/diff/lowb_brain_mask.nii.gz - - if ($usemaskanat) then - if ($doregbbr && -e $labdir/diff/aparc+aseg_mask.bbr.nii.gz) then - set bedmask = $labdir/diff/aparc+aseg_mask.bbr.nii.gz - else if (-e $labdir/diff/aparc+aseg_mask.flt.nii.gz) then - set bedmask = $labdir/diff/aparc+aseg_mask.flt.nii.gz + # Map diffusion brain mask to template space + if ($xspace == mni || $xspace == rob) then + set cmd = mri_convert + set cmd = ($cmd -at $xfmdir/diff2$xspace.$reg.lta) + set cmd = ($cmd -rt nearest) # Binary masks! + set cmd = ($cmd $labdir/diff/lowb_brain_mask.nii.gz) + set cmd = ($cmd $labdir/$xspace/lowb_brain_mask.$reg.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($xspace == cvs) then + set cmd = mri_vol2vol + set cmd = ($cmd --mov $labdir/anatorig/lowb_brain_mask.$reg.nii.gz) + set cmd = ($cmd --targ $intertrg) + set cmd = ($cmd --o $labdir/cvs/lowb_brain_mask.$reg.nii.gz) + set cmd = ($cmd --m3z $xfmdir/cvs/$cvswarp.m3z) + set cmd = ($cmd --noDefM3zPath) + set cmd = ($cmd --interp nearest) # Binary masks! + set cmd = ($cmd --no-save-reg) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($xspace == syn) then + set cmd = mri_vol2vol + set cmd = ($cmd --gcam $labdir/diff/lowb_brain_mask.nii.gz) + set cmd = ($cmd $xfmdir/diff2syn.lta) + set cmd = ($cmd $xfmdir/syn_warp.m3z) + set cmd = ($cmd $xfmdir/syn2syn.lta 0 0) # Binary masks! + set cmd = ($cmd $labdir/syn/lowb_brain_mask.nii.gz) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif + else if ($xspace == fnt) then + set cmd = applywarp + set cmd = ($cmd -w $xfmdir/diff2fsl_warp --rel) + set cmd = ($cmd -i $labdir/diff/lowb_brain_mask.nii.gz) + set cmd = ($cmd -r $intertrg) + set cmd = ($cmd -o $labdir/fnt/lowb_brain_mask.nii.gz) + set cmd = ($cmd --interp=nn) # Binary masks! + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif - endif - - set cmd = (ln -sf $bedmask $dwidir/nodif_brain_mask.nii.gz) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit endif endif -if ($domasks && $dobase) then +if ($dointer && $dobase) then echo "#-------------------------------------" |& tee -a $LF - echo "#@# Masks (base template) `date`" |& tee -a $LF - - mkdir -p $labdir/anatorig - - # Compute intersection of masks from all time points - set flist = (aparc+aseg_mask) - if ($doregflt) set flist = ($flist lowb_brain_mask.flt) - if ($doregbbr) set flist = ($flist lowb_brain_mask.bbr) + echo "#@# Inter-subject registration (base template) `date`" |& tee -a $LF - foreach fname ($flist) - set inlist = `printf "$dtroot/%s/dlabel/anatorig/$fname.nii.gz " $tplist` + # Hack: Using one time point for now! + # Replace with within-subject template to between-subject template + set dwidir_t = $dtroot/$tplist[1]/dmri + set xfmdir_t = $dwidir_t/xfms - set cmd = mri_concat - set cmd = ($cmd --i $inlist) - set cmd = ($cmd --min) - set cmd = ($cmd --o $labdir/anatorig/$fname.nii.gz) + if ($xspace == mni || $xspace == rob) then + # Affine registration from MNI template to base template + set cmd = cp + set cmd = ($cmd $xfmdir_t/${xspace}2anatorig.lta) + set cmd = ($cmd $xfmdir_t/anatorig2$xspace.lta) + set cmd = ($cmd $xfmdir) echo $cmd |& tee -a $LF |& tee -a $CF if ($RunIt) then $cmd |& tee -a $LF if ($status) goto error_exit endif - end -endif - -#------------ Tensor fit --------------------------------------------------# - -if ($dotensor && ! $dobase) then - echo "#-------------------------------------" |& tee -a $LF - echo "#@# Tensor fit `date`" |& tee -a $LF - - set brainmask = $labdir/diff/lowb_brain_mask.nii.gz - - if ($usemaskanat) then - if ($doregbbr && -e $labdir/diff/aparc+aseg_mask.bbr.nii.gz) then - set brainmask = $labdir/diff/aparc+aseg_mask.bbr.nii.gz - else if (-e $labdir/diff/aparc+aseg_mask.flt.nii.gz) then - set brainmask = $labdir/diff/aparc+aseg_mask.flt.nii.gz + else if ($xspace == syn) then + # Non-linear registration from SyN FA template to base template + set cmd = cp + set cmd = ($cmd $xfmdir_t/syn2anatorig.$reg.lta) + set cmd = ($cmd $xfmdir_t/anatorig2syn.$reg.lta) + set cmd = ($cmd $xfmdir_t/syn_warp.m3z) + set cmd = ($cmd $xfmdir) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif - endif - - # LS tensor estimation - set cmd = dtifit - set cmd = ($cmd -k $dwidir/dwi.nii.gz) - set cmd = ($cmd -m $brainmask) - set cmd = ($cmd -r $dwidir/bvecs) - set cmd = ($cmd -b $dwidir/bvals) - set cmd = ($cmd -o $dwidir/dtifit) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - # Check for scalar outputs of tensor fit - set maplist = () - foreach fname ( `cd $dwidir; ls dtifit_*` ) - if (`mri_info --nframes $dwidir/$fname` == 1) then - set maplist = ($maplist `echo $fname | sed 's/.nii.gz//'`) + else if ($xspace == fnt) then + # Non-linear registration from fnirt FA template to base template + set cmd = cp + set cmd = ($cmd $xfmdir_t/diff2anatorig.$reg.lta) + set cmd = ($cmd $xfmdir_t/anatorig2diff.$reg.lta) + set cmd = ($cmd $xfmdir_t/diff2fsl_warp.m3z) + set cmd = ($cmd $xfmdir) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit endif - end - - # Map scalar outputs of tensor fit to MNI template - if ($doregmni) then - mkdir -p $dwidir/mni - - foreach reg (flt bbr) - if (-e $xfmdir/diff2mni.$reg.mat) then - foreach fname ($maplist) - set cmd = flirt - set cmd = ($cmd -in $dwidir/$fname.nii.gz) - set cmd = ($cmd -ref $mnitemp) - set cmd = ($cmd -out $dwidir/mni/$fname.$reg.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/diff2mni.$reg.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - end - endif - end - endif - - # Map scalar outputs of tensor fit to CVS template - set cvswarp = final_CVSmorph_to$cvstemp - - if ($doregcvs && -e $xfmdir/cvs/$cvswarp.m3z) then - mkdir -p $dwidir/anatorig - if ($subj == $cvstemp) then - if (-e $dwidir/cvs && ! -l $dwidir/cvs) rm -rf $dwidir/cvs - ln -sfn $dwidir/anatorig $dwidir/cvs - else - if (-l $dwidir/cvs) rm -f $dwidir/cvs - if (-e $xfmdir/cvs/$cvswarp.m3z) mkdir -p $dwidir/cvs - endif - - foreach reg (flt bbr) - foreach fname ($maplist) - if (-e $xfmdir/diff2anatorig.$reg.mat) then - set cmd = flirt - set cmd = ($cmd -in $dwidir/$fname.nii.gz) - set cmd = ($cmd -ref $dwidir/brain_anat_orig.nii.gz) - set cmd = ($cmd -out $dwidir/anatorig/$fname.$reg.nii.gz) - set cmd = ($cmd -applyxfm -init $xfmdir/diff2anatorig.$reg.mat) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - - if (-e $xfmdir/cvs/$cvswarp.m3z) then - set cmd = mri_vol2vol - set cmd = ($cmd --mov $dwidir/anatorig/$fname.$reg.nii.gz) - set cmd = ($cmd --targ $SUBJECTS_DIR/$cvstemp/mri/norm.mgz) - set cmd = ($cmd --o $dwidir/cvs/$fname.$reg.nii.gz) - set cmd = ($cmd --m3z $xfmdir/cvs/$cvswarp.m3z) - set cmd = ($cmd --noDefM3zPath) - set cmd = ($cmd --interp trilin) - set cmd = ($cmd --no-save-reg) - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $cmd |& tee -a $LF - if ($status) goto error_exit - endif - endif - endif - end - end + set cmd = cp + set cmd = ($cmd $dwidir_t/dtifit_FA.nii.gz) + set cmd = ($cmd $dwidir) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $cmd |& tee -a $LF + if ($status) goto error_exit + endif endif endif -if ($dotensor && $dobase) then - echo "ERROR: Tensor-fit step not available for base template" - goto error_exit -endif - #------------ Combine training data ---------------------------------------# if ($dopriors && ! $dobase) then echo "#-------------------------------------" |& tee -a $LF echo "#@# Priors `date`" |& tee -a $LF - set cvswarp = final_CVSmorph_to$cvstemp - - set xspacelist = () - if ($doregmni) set xspacelist = ($xspacelist mni) - if ($doregcvs) set xspacelist = ($xspacelist cvs) - - set reglist = () - if ($doregflt) set reglist = ($reglist flt) - if ($doregbbr) set reglist = ($reglist bbr) - foreach ntrain ($ntrainlist) # Use a subset of the training subjects set slistfile = `fs_temp_file --suffix .$ntrain.$subj.txt` - echo "$trainsubjlist[1-$ntrain]" > $slistfile - - foreach xspace ($xspacelist) - foreach reg ($reglist) - set avgmode = $avgname${ntrain}_${xspace}_$reg - - set outdir = $labdir/$xspace - set outlist = `printf "%s_$avgmode " $pathlist` - - set trklist = `printf "dlabel/$xspace/%s.$reg.trk " $pathlist` - - set roilist = () - set lablist = () - foreach pathname ($pathlist) - set roilist = ($roilist \ - dlabel/$xspace/${pathname}_roi1.$reg.nii.gz \ - dlabel/$xspace/${pathname}_roi2.$reg.nii.gz) - - if ($pathname =~ *cst*) then - set lablist = ($lablist 16) # Add brainstem - else if ($pathname =~ lh.atr*) then - set lablist = ($lablist 10) # Add left thalamus proper - else if ($pathname =~ rh.atr*) then - set lablist = ($lablist 49) # Add right thalamus proper - else - set lablist = ($lablist 0) # Add nothing - endif - end + printf '%s\n' $trainsubjlist[1-$ntrain] > $slistfile - set brainmask = $labdir/$xspace/lowb_brain_mask.$reg.nii.gz + set avgmode = $avgname${ntrain}_${xspace}_$reg - if ($usemaskanat && -e $labdir/$xspace/aparc+aseg_mask.nii.gz) then - set brainmask = $labdir/$xspace/aparc+aseg_mask.nii.gz - endif + set outdir = $labdir/$xspace + set outlist = `printf "%s_$avgmode " $pathlist` - if ($reinit) then # Exclude previous spline initialization - foreach outbase ($outlist) - set oldinit = $outdir/${outbase}_cpts_all.txt + set trklist = `printf "$xspace/%s.$reg.prep.trk " $pathlist` - if (-e $oldinit) then - set excfile = $outdir/${outbase}_cpts_all.bad.txt - echo exclude >> $excfile - cat $oldinit >> $excfile - endif - end - endif + if ($usemaskanat) then + set brainmask = $labdir/$xspace/${segname}_mask.nii.gz + else + set brainmask = $labdir/$xspace/lowb_brain_mask.$reg.nii.gz + endif - # Compute priors, end ROIs, and initial control points from training set - set cmd = $trcdir/dmri_train - set cmd = ($cmd --outdir $outdir) - set cmd = ($cmd --out $outlist) - set cmd = ($cmd --slist $slistfile) - set cmd = ($cmd --trk $trklist) - set cmd = ($cmd --seg dlabel/$xspace/aparc+aseg.nii.gz) - set cmd = ($cmd --cmask dlabel/$xspace/cortex+2mm.nii.gz) - set cmd = ($cmd --lmask $lablist) - set cmd = ($cmd --rois $roilist) - set cmd = ($cmd --bmask $brainmask) - set cmd = ($cmd --fa $dwidir/dtifit_FA.nii.gz) - set cmd = ($cmd --cptdir $labdir/diff) - if ($xspace == mni) then - set cmd = ($cmd --reg $xfmdir/mni2diff.$reg.mat) - else if ($xspace == cvs) then - set cmd = ($cmd --regnl $xfmdir/cvs/$cvswarp.m3z) - set cmd = ($cmd --reg $xfmdir/anatorig2diff.$reg.mat) - set cmd = ($cmd --refnl $dwidir/brain_anat_orig.nii.gz) - endif - set cmd = ($cmd --ncpts $ncpts) - if ($reinit) then - set cmd = ($cmd --xstr) - endif - if ($usetrunc) then - set cmd = ($cmd --trunc) - endif - if ($debug) then - set cmd = ($cmd --debug) - endif - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit + if ($reinit) then # Exclude previous spline initialization + foreach outbase ($outlist) + set oldinit = $outdir/${outbase}_cpts_all.txt + + if (-e $oldinit) then + set excfile = $outdir/${outbase}_cpts_all.bad.txt + echo exclude >> $excfile + cat $oldinit >> $excfile endif end - end + endif + + # Compute priors, end ROIs, and initial control points from training set + set cmd = $trcdir/dmri_train + set cmd = ($cmd --outdir $outdir) + set cmd = ($cmd --out $outlist) + set cmd = ($cmd --slist $slistfile) + set cmd = ($cmd --trk $trklist) + if ($usethalnuc) then + set cmd = ($cmd --seg $xspace/${segname}+thalnuc.nii.gz) + else + set cmd = ($cmd --seg $xspace/$segname.nii.gz) + endif + set cmd = ($cmd --cmask $xspace/cortex+${gmgrow}mm+crblm.nii.gz) + set cmd = ($cmd --lmask $gmids) + set cmd = ($cmd --bmask $brainmask) + set cmd = ($cmd --fa $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd --cptdir $labdir/diff) + if ($xspace == mni || $xspace == rob) then + set cmd = ($cmd --reg $xfmdir/${xspace}2diff.$reg.lta) + else if ($xspace == cvs) then + set cmd = ($cmd --regnl $xfmdir/cvs/$cvswarp.m3z) + set cmd = ($cmd --refnl $dwidir/brain_anat_orig.nii.gz) + set cmd = ($cmd --reg $xfmdir/anatorig2diff.$reg.lta) + else if ($xspace == syn) then + set cmd = ($cmd --regnl $xfmdir/syn_warp.m3z) + set cmd = ($cmd --refnl $intertrg) + set cmd = ($cmd --reg $xfmdir/syn2diff.lta) + else if ($xspace == fnt) then + set cmd = ($cmd --regnl $xfmdir/diff2fsl_warp.m3z) + set cmd = ($cmd --refnl $dwidir/dtifit_FA.nii.gz) + endif + set cmd = ($cmd --ncpts $ncpts) + if ($reinit) set cmd = ($cmd --xstr) + if ($usetrunc) set cmd = ($cmd --trunc) + if ($dosegprior) set cmd = ($cmd --aprior) + if ($dotangprior) set cmd = ($cmd --sprior) + if ($debug) set cmd = ($cmd --debug) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif end endif @@ -2140,119 +2174,91 @@ if ($dopriors && $dobase) then echo "#-------------------------------------" |& tee -a $LF echo "#@# Priors (base template) `date`" |& tee -a $LF - set cvswarp = final_CVSmorph_to$cvstemp - - set xspacelist = () - if ($doregmni) set xspacelist = ($xspacelist mni) - if ($doregcvs) set xspacelist = ($xspacelist cvs) - - set reglist = () - if ($doregflt) set reglist = ($reglist flt) - if ($doregbbr) set reglist = ($reglist bbr) + mkdir -p $labdir/$xspace foreach ntrain ($ntrainlist) # Use a subset of the training subjects - set slistfile = `fs_temp_file --suffix .$ntrain.$subj.txt` - echo "$trainsubjlist[1-$ntrain]" > $slistfile - - foreach xspace ($xspacelist) - mkdir -p $labdir/$xspace - - foreach reg ($reglist) - set avgmode = $avgname${ntrain}_${xspace}_$reg - - set outdir = $labdir/$xspace - set outlist = `printf "%s_$avgmode " $pathlist` - - set trklist = `printf "dlabel/$xspace/%s.$reg.trk " $pathlist` - - set roilist = () - set lablist = () - foreach pathname ($pathlist) - set roilist = ($roilist \ - dlabel/$xspace/${pathname}_roi1.$reg.nii.gz \ - dlabel/$xspace/${pathname}_roi2.$reg.nii.gz) - - if ($pathname =~ *cst*) then - set lablist = ($lablist 16) # Add brainstem - else if ($pathname =~ lh.atr*) then - set lablist = ($lablist 10) # Add left thalamus proper - else if ($pathname =~ rh.atr*) then - set lablist = ($lablist 49) # Add right thalamus proper - else - set lablist = ($lablist 0) # Add nothing - endif - end + set slistfile = /tmp/subj$ntrain.$subj.$$.txt + printf '%s\n' $trainsubjlist[1-$ntrain] > $slistfile - if ($usemaskanat) then - set brainmask = aparc+aseg_mask.nii.gz - else - set brainmask = lowb_brain_mask.$reg.nii.gz - endif + set avgmode = $avgname${ntrain}_${xspace}_$reg - set bmasklist = \ - `printf "$dtroot/%s/dlabel/$xspace/$brainmask " $tplist` + set outdir = $labdir/$xspace + set outlist = `printf "%s_$avgmode " $pathlist` - set falist = \ - `printf "$dtroot/%s/dmri/dtifit_FA.nii.gz " $tplist` + set trklist = `printf "$xspace/%s.$reg.prep.trk " $pathlist` - set basereglist = \ - `printf "$dtroot/%s/dmri/xfms/anatorig2diff.$reg.mat " $tplist` + if ($usemaskanat) then + set brainmask = ${segname}_mask.nii.gz + else + set brainmask = lowb_brain_mask.$reg.nii.gz + endif - if ($reinit) then # Exclude previous spline initialization - foreach outbase ($outlist) - set oldinit = $outdir/${outbase}_cpts_all.txt + set bmasklist = `printf "$dtroot/%s/dlabel/$xspace/$brainmask " $tplist` - if (-e $oldinit) then - set excfile = $outdir/${outbase}_cpts_all.bad.txt - echo exclude >> $excfile - cat $oldinit >> $excfile - endif - end - endif + set falist = `printf "$dtroot/%s/dmri/dtifit_FA.nii.gz " $tplist` - # Compute priors, end ROIs, and initial control points from training set - set cmd = $trcdir/dmri_train - set cmd = ($cmd --outdir $outdir) - set cmd = ($cmd --out $outlist) - set cmd = ($cmd --slist $slistfile) - set cmd = ($cmd --trk $trklist) - set cmd = ($cmd --seg dlabel/$xspace/aparc+aseg.nii.gz) - set cmd = ($cmd --cmask dlabel/$xspace/cortex+2mm.nii.gz) - set cmd = ($cmd --lmask $lablist) - set cmd = ($cmd --rois $roilist) - set cmd = ($cmd --bmask $bmasklist) - set cmd = ($cmd --fa $falist) - set cmd = ($cmd --cptdir $labdir/anatorig) - if ($xspace == mni) then - set cmd = ($cmd --reg $xfmdir/mni2anatorig.mat) - else if ($xspace == cvs) then - # Hack: Using one time point for now! - set dwidir_t = $dtroot/$tplist[1]/dmri - set xfmdir_t = $dwidir_t/xfms - - set cmd = ($cmd --regnl $xfmdir_t/cvs/$cvswarp.m3z) - set cmd = ($cmd --refnl $dwidir_t/brain_anat_orig.nii.gz) - endif - set cmd = ($cmd --basereg $basereglist) - set cmd = ($cmd --baseref $labdir/anatorig/aparc+aseg_mask.nii.gz) - set cmd = ($cmd --ncpts $ncpts) - if ($reinit) then - set cmd = ($cmd --xstr) - endif - if ($usetrunc) then - set cmd = ($cmd --trunc) - endif - if ($debug) then - set cmd = ($cmd --debug) - endif - echo $cmd |& tee -a $LF |& tee -a $CF - if ($RunIt) then - $fs_time $cmd |& tee -a $LF - if ($status) goto error_exit + set basereglist = \ + `printf "$dtroot/%s/dmri/xfms/anatorig2diff.$reg.lta " $tplist` + + if ($reinit) then # Exclude previous spline initialization + foreach outbase ($outlist) + set oldinit = $outdir/${outbase}_cpts_all.txt + + if (-e $oldinit) then + set excfile = $outdir/${outbase}_cpts_all.bad.txt + echo exclude >> $excfile + cat $oldinit >> $excfile endif end - end + endif + + # Compute priors, end ROIs, and initial control points from training set + set cmd = $trcdir/dmri_train + set cmd = ($cmd --outdir $outdir) + set cmd = ($cmd --out $outlist) + set cmd = ($cmd --slist $slistfile) + set cmd = ($cmd --trk $trklist) + if ($usethalnuc) then + set cmd = ($cmd --seg $xspace/${segname}+thalnuc.nii.gz) + else + set cmd = ($cmd --seg $xspace/$segname.nii.gz) + endif + set cmd = ($cmd --cmask $xspace/cortex+${gmgrow}mm+crblm.nii.gz) + set cmd = ($cmd --lmask $gmids) + set cmd = ($cmd --bmask $bmasklist) + set cmd = ($cmd --fa $falist) + set cmd = ($cmd --cptdir $labdir/anatorig) + if ($xspace == mni || $xspace == rob) then + set cmd = ($cmd --reg $xfmdir/${xspace}2anatorig.lta) + else if ($xspace == cvs) then + # Hack: Using one time point for now! + set dwidir_t = $dtroot/$tplist[1]/dmri + set xfmdir_t = $dwidir_t/xfms + set cmd = ($cmd --regnl $xfmdir_t/cvs/$cvswarp.m3z) + set cmd = ($cmd --refnl $dwidir_t/brain_anat_orig.nii.gz) + else if ($xspace == syn) then + set cmd = ($cmd --regnl $xfmdir/syn_warp.m3z) + set cmd = ($cmd --refnl $intertrg) + set cmd = ($cmd --reg $xfmdir/syn2anatorig.$reg.lta) + else if ($xspace == fnt) then + set cmd = ($cmd --regnl $xfmdir/diff2fsl_warp.m3z) + set cmd = ($cmd --refnl $dwidir/dtifit_FA.nii.gz) + set cmd = ($cmd --reg $xfmdir/diff2anatorig.$reg.lta) + endif + set cmd = ($cmd --basereg $basereglist) + set cmd = ($cmd --baseref $labdir/anatorig/${segname}_mask.nii.gz) + set cmd = ($cmd --ncpts $ncpts) + if ($reinit) set cmd = ($cmd --xstr) + if ($usetrunc) set cmd = ($cmd --trunc) + if ($dosegprior) set cmd = ($cmd --aprior) + if ($dotangprior) set cmd = ($cmd --sprior) + if ($debug) set cmd = ($cmd --debug) + echo $cmd |& tee -a $LF |& tee -a $CF + if ($RunIt) then + $fs_time $cmd |& tee -a $LF + if ($status) goto error_exit + endif end endif diff --git a/scripts/xcerebralseg b/scripts/xcerebralseg index a2e5ff3eca3..e9137478ada 100755 --- a/scripts/xcerebralseg +++ b/scripts/xcerebralseg @@ -99,7 +99,7 @@ endif # in the merge anyway set seg2 = $tmpdir/seg2.mgh set cmd = (mri_binarize --i $seg1 --o $seg2 \ - --replace 3 257 --replace 42 257 --replace 2 257 --replace 41 257) + --replaceonly 3 257 --replaceonly 42 257 --replaceonly 2 257 --replaceonly 41 257) echo $cmd | tee -a $LF $cmd | tee -a $LF if($status) goto error_exit; @@ -153,7 +153,7 @@ if($status) exit 1; # Replace unlabeled voxels in the head with head seg set seg4 = $tmpdir/seg4.mgh -set cmd = (mri_binarize --i $seg3 --o $seg4 --replace 0 258 --mask $seghead); +set cmd = (mri_binarize --i $seg3 --o $seg4 --replaceonly 0 258 --mask $seghead); echo $cmd | tee -a $LF $cmd | tee -a $LF if($status) goto error_exit; diff --git a/trc/bite.cxx b/trc/bite.cxx index 07d109916f7..2b17fcb09d7 100644 --- a/trc/bite.cxx +++ b/trc/bite.cxx @@ -89,7 +89,7 @@ Bite::~Bite() { // // Set variables that are common for all voxels // -void Bite::SetStatic(const char *GradientFile, const char *BvalueFile, +void Bite::SetStatic(const string GradientFile, const string BvalueFile, int NumTract, int NumBedpost, float FminPath) { float val; ifstream gfile(GradientFile, ios::in); diff --git a/trc/bite.h b/trc/bite.h index 262dc1f728c..8a4310ccd9d 100644 --- a/trc/bite.h +++ b/trc/bite.h @@ -55,7 +55,8 @@ class Bite { std::vector mF; // [mNumTract] public: - static void SetStatic(const char *GradientFile, const char *BvalueFile, + static void SetStatic(const std::string GradientFile, + const std::string BvalueFile, int NumTract, int NumBedpost, float FminPath); static int GetNumTract(); static int GetNumDir(); diff --git a/trc/blood.cxx b/trc/blood.cxx index ac3fd4146c2..8d07228e378 100644 --- a/trc/blood.cxx +++ b/trc/blood.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -32,21 +32,25 @@ const float Blood::mLengthCutoff = 0.05, Blood::mTangentBinSize = 1/3.0, // 0.1, Blood::mCurvatureBinSize = 0.01; // 0.002; -Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, - const std::string TrainRoi1File, const std::string TrainRoi2File, - const std::string TrainAsegFile, const std::string TrainMaskFile, - float TrainMaskLabel, const std::string ExcludeFile, - const vector &TestMaskList, - const vector &TestFaList, - const std::string TestAffineXfmFile, - const std::string TestNonlinXfmFile, - const std::string TestNonlinRefFile, - const vector &TestBaseXfmList, - const std::string TestBaseMaskFile, - bool UseTruncated, vector &NumControls, - bool Debug) : +Blood::Blood(const string TrainListFile, const string TrainTrkFile, + const string TrainRoi1File, const string TrainRoi2File, + const string TrainAsegFile, const string TrainMaskFile, + float TrainMaskLabel, const string ExcludeFile, + const vector &TestMaskList, + const vector &TestFaList, + const string TestAffineXfmFile, + const string TestNonlinXfmFile, + const string TestNonlinRefFile, + const vector &TestBaseXfmList, + const string TestBaseMaskFile, + bool UseTruncated, bool UseAnatomy, bool UseShape, + vector &NumControls, + int NumStrMax, bool Debug) : mDebug(Debug), mUseTruncated(UseTruncated), + mUseAnatomy(UseAnatomy), + mUseShape(UseShape), + mNumStrMax(NumStrMax), mMaskLabel(TrainMaskLabel) { int dirs[45] = { 0, 0, 0, 1, 0, 0, @@ -72,9 +76,30 @@ Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, mNumNear = 14; mDirNear.insert(mDirNear.begin(), dirs+3, dirs+45); - // Read brain mask - for (auto ifile = TestMaskList.begin(); - ifile < TestMaskList.end(); ifile++) { + // Read training subjects' anatomy + ReadAnatomy(TrainListFile, TrainAsegFile, TrainMaskFile); + + // If no test subject mask is provided, use union of training segmentations + if (TestMaskList.empty()) { + testvol = MRIclone(mAseg[0], NULL); + + for (vector::const_iterator iseg = mAseg.begin(); + iseg != mAseg.end(); iseg++) + for (int iz = (*iseg)->depth - 1; iz >= 0; iz--) + for (int iy = (*iseg)->height - 1; iy >= 0; iy--) + for (int ix = (*iseg)->width - 1; ix >= 0; ix--) + if (MRIgetVoxVal(*iseg, ix, iy, iz, 0) > 0) + MRIsetVoxVal(testvol, ix, iy, iz, 0, + MRIgetVoxVal(testvol, ix, iy, iz, 0) + 1); + + MRIdilate(testvol, testvol); + + mTestMask.push_back(testvol); + } + + // Read test subject's brain mask + for (vector::const_iterator ifile = TestMaskList.begin(); + ifile < TestMaskList.end(); ifile++) { cout << "Loading brain mask of output subject from " << *ifile << endl; testvol = MRIread((*ifile).c_str()); if (!testvol) { @@ -93,8 +118,8 @@ Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, mDx = mTestMask[0]->xsize; // Read FA map - for (auto ifile = TestFaList.begin(); - ifile < TestFaList.end(); ifile++) { + for (vector::const_iterator ifile = TestFaList.begin(); + ifile < TestFaList.end(); ifile++) { cout << "Loading FA map of output subject from " << *ifile << endl; testvol = MRIread((*ifile).c_str()); if (!testvol) { @@ -113,20 +138,20 @@ Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, cout << "ERROR: Could not read " << TestBaseMaskFile << endl; exit(1); } - } else if (!mTestFa.empty()) { + } + else if (!mTestFa.empty()) mTestBaseMask = mTestFa[0]; - } else { + else mTestBaseMask = mTestMask[0]; - } // Read atlas-to-base registration files #ifndef NO_CVS_UP_IN_HERE if (!TestNonlinXfmFile.empty()) { - mTestNonlinReg.ReadXfm(TestNonlinXfmFile.c_str(), mTestMask[0]); + mTestNonlinReg.ReadXfm(TestNonlinXfmFile, mTestMask[0]); if (!TestAffineXfmFile.empty()) { MRI *refvol; - + cout << "Loading non-linear registration source for output subject from " << TestNonlinRefFile << endl; refvol = MRIread(TestNonlinRefFile.c_str()); @@ -135,24 +160,21 @@ Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, exit(1); } - mTestAffineReg.ReadXfm(TestAffineXfmFile.c_str(), refvol, mTestBaseMask); - } - } else { -#endif - if (!TestAffineXfmFile.empty()) { - mTestAffineReg.ReadXfm(TestAffineXfmFile.c_str(), mTestMask[0], mTestBaseMask); + mTestAffineReg.ReadXfm(TestAffineXfmFile, refvol, mTestBaseMask); } -#ifndef NO_CVS_UP_IN_HERE } + else #endif + if (!TestAffineXfmFile.empty()) + mTestAffineReg.ReadXfm(TestAffineXfmFile, mTestMask[0], mTestBaseMask); // Read base-to-DWI registration files - for (auto ifile = TestBaseXfmList.begin(); - ifile < TestBaseXfmList.end(); ifile++) { + for (vector::const_iterator ifile = TestBaseXfmList.begin(); + ifile < TestBaseXfmList.end(); ifile++) { const unsigned int iframe = ifile - TestBaseXfmList.begin(); AffineReg basereg; - basereg.ReadXfm((*ifile).c_str(), mTestBaseMask, mTestFa[iframe]); + basereg.ReadXfm(*ifile, mTestBaseMask, mTestFa[iframe]); mTestBaseReg.push_back(basereg); } @@ -163,31 +185,44 @@ Blood::Blood(const std::string TrainListFile, const std::string TrainTrkFile, ReadStreamlines(TrainListFile, TrainTrkFile, TrainRoi1File, TrainRoi2File, TrainMaskLabel, ExcludeFile); - // Read training subjects' anatomy - ReadAnatomy(TrainListFile, TrainAsegFile, TrainMaskFile); - // Allocate space for histograms - mHistoStr = MRIclone(mTestMask[0], NULL); - mHistoSubj = MRIclone(mTestMask[0], NULL); + AllocateHistogram(mTestMask[0]); } -Blood::Blood(const std::string TrainTrkFile, - const std::string TrainRoi1File, const std::string TrainRoi2File, +Blood::Blood(const string TrainTrkFile, + const string TrainRoi1File, const string TrainRoi2File, bool Debug) : mDebug(Debug), mUseTruncated(false), + mUseAnatomy(false), + mUseShape(false), + mNumStrMax(INT_MAX), mNx(0), mNy(0), mNz(0) { - // Read single input streamline file - ReadStreamlines(0, TrainTrkFile, TrainRoi1File, TrainRoi2File, 0, 0); - - if (!TrainRoi1File.c_str()) { - // Allocate space for histograms - mHistoStr = MRIclone(mRoi1[0], NULL); - mHistoSubj = MRIclone(mRoi1[0], NULL); + // Allocate space for histograms + if (!TrainRoi1File.empty() && TrainRoi2File.empty()) { + MRI *refvol; + + // Not a pair of ROIs, just a reference volume + refvol = MRIread(TrainRoi1File.c_str()); + mNx = refvol->width; + mNy = refvol->height; + mNz = refvol->depth; + AllocateHistogram(refvol); + + // Read single input streamline file + ReadStreamlines(0, TrainTrkFile, 0, 0, 0, 0); } else { - mHistoStr = 0; - mHistoSubj = 0; + // Read single input streamline file + ReadStreamlines(0, TrainTrkFile, TrainRoi1File, TrainRoi2File, 0, 0); + + // Allocate space for histograms + if (!TrainRoi1File.empty()) + AllocateHistogram(mRoi1[0]); + else { + mHistoStr = 0; + mHistoSubj = 0; + } } } @@ -232,18 +267,28 @@ void Blood::SetNumControls(vector &NumControls) { mControlStdTest.clear(); } +// +// Allocate space for histogram volumes +// +void Blood::AllocateHistogram(MRI *RefVol) { + mHistoStr = MRIclone(RefVol, NULL); + mHistoSubj = MRIclone(RefVol, NULL); +} + // // Read streamlines of training subjects // (and the ROIs that were used to label them) // -void Blood::ReadStreamlines(const std::string TrainListFile, - const std::string TrainTrkFile, - const std::string TrainRoi1File, - const std::string TrainRoi2File, +void Blood::ReadStreamlines(const string TrainListFile, + const string TrainTrkFile, + const string TrainRoi1File, + const string TrainRoi2File, float TrainMaskLabel, - const std::string ExcludeFile) { - int nrejmask = 0, nrejrev = 0; + const string ExcludeFile) { + int index = 0, nrejmask = 0, nrejrev = 0; vector dirlist; + vector< pair > strorder; + vector::iterator irank; vector::iterator ivol; if (!TrainListFile.empty()) { // Read multiple inputs from a list @@ -264,6 +309,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, mMaskLabel = TrainMaskLabel; // Clear all variables that depend on pathway + mHavePresorted = true; mStreamlines.clear(); mLengths.clear(); mTruncatedLengths.clear(); @@ -277,6 +323,10 @@ void Blood::ReadStreamlines(const std::string TrainListFile, mVarEnd1.clear(); mVarEnd2.clear(); mVarMid.clear(); + mIsOutHist.clear(); + mIsOutDev.clear(); + mIsOutFa.clear(); + mDistanceRank.clear(); mExcludedStreamlines.clear(); mCenterStreamline.clear(); mControlPoints.clear(); @@ -383,6 +433,19 @@ void Blood::ReadStreamlines(const std::string TrainListFile, cout << "Loading streamlines from " << fname << endl; + if (strcmp(trkheader.reserved, "TRACULAprep") == 0) { + cout << "Pre-sorted training .trk file detected" << endl; + + if (trkheader.n_properties != 3) { + cout << "ERROR: Unexpected number of properties (" + << trkheader.n_properties << ") found in pre-sorted .trk file " + << fname << endl; + exit(1); + } + } + else + mHavePresorted = false; + while (trkreader.GetNextPointCount(&npts)) { bool isinmask = true; int nptsmask = npts, @@ -391,10 +454,11 @@ void Blood::ReadStreamlines(const std::string TrainListFile, forwback2 = 0, forw2 = 0; vector pts; vector dir1(3), dir2(3); - float *rawpts = new float[npts*3], *rawptsmask = rawpts, *iraw; + float *rawpts = new float[npts*3], *rawptsmask = rawpts, *iraw, + *properties = new float [trkheader.n_properties]; // Read a streamline from input file - trkreader.GetNextTrackData(npts, rawpts); + trkreader.GetNextTrackData(npts, rawpts, NULL, properties); // Divide by voxel size, make 0-based, and round to get voxel coords iraw = rawpts; @@ -423,7 +487,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, } iraw = rawptsmask; - for (int ipt = nptsmask; ipt > 1; ipt--) // Remove duplicate points + for (int ipt = nptsmask; ipt > 1; ipt--)// Remove duplicate points if ( (iraw[0] != iraw[3]) || (iraw[1] != iraw[4]) || (iraw[2] != iraw[5]) ) { for (int k = 0; k < 3; k++) { @@ -441,10 +505,10 @@ void Blood::ReadStreamlines(const std::string TrainListFile, // Check directions in which streamline traverses start ROI if (!mRoi1.empty()) { if (IsInRoi(pts.end()-3, *(mRoi1.end()-1))) { - if (xroi1 == 0) { // Entering ROI for the first time + if (xroi1 == 0) { // Entering ROI for the first time xroi1 = 1; - if (xroi2 > 0) // Have already been to the other ROI + if (xroi2 > 0) // Have already been to the other ROI xroi21 = 1; iraw -= 3; @@ -452,7 +516,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, if (iraw == rawptsmask) iraw += 3; else - for (int k = 0; k < 3; k++) { // Direction of entering + for (int k = 0; k < 3; k++) { // Direction of entering const float diff = *iraw - *(iraw-3); dir1[k] = diff; @@ -461,7 +525,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, } } - if (xroi1 == 2) { // Re-entering ROI + if (xroi1 == 2) { // Re-entering ROI if (xroi12 > 0) { // Went back and forth between ROIs xroi1 = 3; nrejrev++; @@ -487,8 +551,8 @@ void Blood::ReadStreamlines(const std::string TrainListFile, } } } - else - if (xroi1 == 1) { // Exiting ROI + else + if (xroi1 == 1) { // Exiting ROI xroi1 = 2; if (forw1 == 0) { // Never entered, started inside ROI @@ -505,7 +569,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, else { iraw -= 3; forwback1 = 0; - for (int k = 0; k < 3; k++) { // Direction of exiting + for (int k = 0; k < 3; k++) { // Direction of exiting const float diff = *iraw - *(iraw-3); forwback1 += dir1[k]*diff; @@ -513,7 +577,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, } // Check if exiting back the way I entered - if (forwback1 < 0) { // |angle| > 90 + if (forwback1 < 0) { // |angle| > 90 xroi1 = 3; nrejrev++; break; @@ -525,10 +589,10 @@ void Blood::ReadStreamlines(const std::string TrainListFile, // Check directions in which streamline traverses end ROI if (!mRoi2.empty()) { if (IsInRoi(pts.end()-3, *(mRoi2.end()-1))) { - if (xroi2 == 0) { // Entering ROI for the first time + if (xroi2 == 0) { // Entering ROI for the first time xroi2 = 1; - if (xroi1 > 0) // Have already been to the other ROI + if (xroi1 > 0) // Have already been to the other ROI xroi12 = 1; iraw -= 3; @@ -536,7 +600,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, if (iraw == rawptsmask) iraw += 3; else - for (int k = 0; k < 3; k++) { // Direction of entering + for (int k = 0; k < 3; k++) { // Direction of entering const float diff = *iraw - *(iraw-3); dir2[k] = diff; @@ -545,7 +609,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, } } - if (xroi2 == 2) { // Re-entering ROI + if (xroi2 == 2) { // Re-entering ROI if (xroi21 > 0) { // Went back and forth between ROIs xroi2 = 3; nrejrev++; @@ -589,7 +653,7 @@ void Blood::ReadStreamlines(const std::string TrainListFile, else { iraw -= 3; forwback2 = 0; - for (int k = 0; k < 3; k++) { // Direction of exiting + for (int k = 0; k < 3; k++) { // Direction of exiting const float diff = *iraw - *(iraw-3); forwback2 += dir2[k]*diff; @@ -632,6 +696,25 @@ void Blood::ReadStreamlines(const std::string TrainListFile, mLengths.push_back(pts.size() / 3); nlines++; + if (mHavePresorted) { + if ((int) properties[0] == 1 || (int) properties[0] == 3) + mIsInEnd1.push_back(true); + else + mIsInEnd1.push_back(false); + + if ((int) properties[0] == 2 || (int) properties[0] == 3) + mIsInEnd2.push_back(true); + else + mIsInEnd2.push_back(false); + + mTruncatedLengths.push_back((int) properties[1]); + + if (*(mIsInEnd1.end()-1) && *(mIsInEnd2.end()-1)) + strorder.push_back(make_pair(properties[2], index)); + + index++; + } + delete[] rawpts; } @@ -653,19 +736,31 @@ void Blood::ReadStreamlines(const std::string TrainListFile, cout << "INFO: Rejected " << nrejrev << " streamlines for reversing direction" << endl; - RemoveLengthOutliers(); + if (mHavePresorted) { + sort(strorder.begin(), strorder.end()); + + mDistanceRank.resize(strorder.size()); + irank = mDistanceRank.begin(); + + for (vector< pair >::const_iterator + iorder = strorder.begin(); iorder < strorder.end(); iorder++) { + *irank = iorder->second; + irank++; + } + } + else + RemoveLengthOutliers(); ComputeStats(); - if (!ExcludeFile.empty()) { + if (!ExcludeFile.empty()) ReadExcludedStreamlines(ExcludeFile); - } } // // Read list of streamlines to be excluded from search for center streamline // -void Blood::ReadExcludedStreamlines(const std::string ExcludeFile) { +void Blood::ReadExcludedStreamlines(const string ExcludeFile) { string excline; ifstream excfile; @@ -810,6 +905,11 @@ void Blood::ComputeEndPointCoM() { vector sum1(3, 0), sum2(3, 0), summ(3, 0), sumsq1(3, 0), sumsq2(3, 0), sumsqm(3, 0); + if (mRoi1.empty() || mRoi2.empty()) { + cout << "ERROR: Need end ROIs to compute streamline midpoints" << endl; + exit(1); + } + mMidPoints.resize(mNumStrEnds); imidpts = mMidPoints.begin(); @@ -909,7 +1009,7 @@ void Blood::ComputeEndPointCoM() { // Check that a point is inside the test subject's brain mask // bool Blood::IsInMask(vector::const_iterator Point) { - if (mTestMask.empty() && mRoi1.empty() && mRoi2.empty()) + if (mNx == 0 && mNy == 0 && mNz == 0) return true; else { bool isinmask = (Point[0] > -1) && (Point[0] < mNx) && @@ -961,14 +1061,19 @@ bool Blood::IsInCortex(vector::const_iterator Point, (Point[2] > -1) && (Point[2] < mNz) && (MRIgetVoxVal(Mask, Point[0], Point[1], Point[2], 0) > 0 || (mMaskLabel > 0 && - MRIgetVoxVal(Aseg, Point[0], Point[1], Point[2], 0) == mMaskLabel)); + MRIgetVoxVal(Aseg, Point[0], Point[1], Point[2], 0) == mMaskLabel) || + (mMaskLabel == 10 && // Left thalamic nuclei + (int)MRIgetVoxVal(Aseg, Point[0], Point[1], Point[2], 0)/100 == 81) || + (mMaskLabel == 49 && // Right thalamic nuclei + (int)MRIgetVoxVal(Aseg, Point[0], Point[1], Point[2], 0)/100 == 82)); } // // Read segmentations and cortical masks of training subjects // -void Blood::ReadAnatomy(const std::string TrainListFile, const std::string TrainAsegFile, - const std::string TrainMaskFile) { +void Blood::ReadAnatomy(const string TrainListFile, + const string TrainAsegFile, + const string TrainMaskFile) { vector dirlist; vector::iterator ivol; @@ -1143,30 +1248,35 @@ void Blood::RemoveLengthOutliers() { void Blood::ComputePriors() { int maxtries; - cout << "Matching streamline ends" << endl; - MatchStreamlineEnds(); + if (mHavePresorted) { + ComputeStatsEnds(); - SetArcSegments(); + cout << "Computing path histograms" << endl; + ComputeHistogram(); - cout << "Computing path histograms" << endl; - ComputeHistogram(); + cout << "Finding outlier streamlines" << endl; + FindOutlierStreamlines(false, false, !mTestFa.empty()); - cout << "Computing prior on underlying anatomy " - << "(non-truncated streamlines only)" << endl; - ComputeAnatomyPrior(false); + cout << "Updating streamline distance ranking" << endl; + UpdateDistanceRank(); + } + else + PrepStreamlines(); - cout << "Computing prior on curvature " - << "(non-truncated streamlines only)" << endl; - ComputeShapePrior(false); + SetArcSegments(); - if (mUseTruncated) { - cout << "Computing prior on underlying anatomy " - << "(all streamlines)" << endl; - ComputeAnatomyPrior(true); + if (mUseAnatomy) { + cout << "Computing prior on underlying anatomy (" + << (mUseTruncated ? "all" : "non-truncated") + << " streamlines)" << endl; + ComputeAnatomyPrior(); + } - cout << "Computing prior on curvature " - << "(all streamlines)" << endl; - ComputeShapePrior(true); + if (mUseShape) { + cout << "Computing prior on curvature (" + << (mUseTruncated ? "all" : "non-truncated") + << " streamlines)" << endl; + ComputeShapePrior(); } maxtries = mNumStrEnds - mExcludedStreamlines.size(); @@ -1180,8 +1290,21 @@ void Blood::ComputePriors() { mControlStd.clear(); mControlStdTest.clear(); - cout << "Finding center streamline" << endl; - FindCenterStreamline(); + //cout << "Finding center streamline" << endl; + //FindCenterStreamline(); + mCenterStreamline = mStreamlines[mDistanceRank[itry-1]]; + + for (vector< vector >::const_iterator + ixstr = mExcludedStreamlines.begin(); + ixstr < mExcludedStreamlines.end(); ixstr++) + if (equal(mCenterStreamline.begin(), mCenterStreamline.end(), + ixstr->begin())) { + retry = true; + break; + } + + if (retry) + continue; for (vector::const_iterator incpt = mNumControls.begin(); incpt < mNumControls.end(); incpt++) { @@ -1205,6 +1328,145 @@ void Blood::ComputePriors() { } } +// +// Prepare training streamlines for prior computation +// +void Blood::PrepStreamlines() { + cout << "Matching streamline ends" << endl; + MatchStreamlineEnds(); + + cout << "Subsampling streamlines" << endl; + SubsampleStreamlines(); + + cout << "Matching truncated to full streamlines" << endl; + MatchTruncatedStreamlines(); + + cout << "Computing path histograms" << endl; + ComputeHistogram(); + + cout << "Finding outlier streamlines" << endl; + FindOutlierStreamlines(true, !mRoi1.empty() && !mRoi2.empty(), + !mTestFa.empty()); + + cout << "Ranking streamlines by distance" << endl; + RankStreamlineDistance(); +} + +// +// Select a subset of training streamlines to speed up computation +// +void Blood::SubsampleStreamlines() { + unsigned int kfull = 0, ktrunc = 0; + vector idxfull, idxtrunc, idxall; + vector::const_iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(); + vector< vector >::const_iterator istr = mStreamlines.begin(); + vector::iterator iall; + vector::const_iterator ifull, itrunc; + + if (mNumStr <= mNumStrMax) + return; + + // Select the streamlines to be removed + idxtrunc.resize(mNumStr-mNumStrEnds); + iota(idxtrunc.begin(), idxtrunc.end(), 0); + + if (mNumStrMax <= mNumStrEnds) { + idxfull.resize(mNumStrEnds); + iota(idxfull.begin(), idxfull.end(), 0); + random_shuffle(idxfull.begin(), idxfull.end()); + idxfull.resize(mNumStrEnds - mNumStrMax); + sort(idxfull.begin(), idxfull.end()); + } + else { + random_shuffle(idxtrunc.begin(), idxtrunc.end()); + idxtrunc.resize(mNumStr - mNumStrMax); + sort(idxtrunc.begin(), idxtrunc.end()); + } + + // Iterate backwards on indices of non-truncated streamlines to be removed + for (ifull = idxfull.end(); ifull > idxfull.begin(); ifull--) { + unsigned int index = *(ifull-1); + + if (!mIsOutHist.empty()) + mIsOutHist.erase(mIsOutHist.begin() + index); + if (!mIsOutFa.empty()) + mIsOutFa.erase(mIsOutFa.begin() + index); + if (!mIsOutDev.empty()) + mIsOutDev.erase(mIsOutDev.begin() + index); + if (!mMidPoints.empty()) + mMidPoints.erase(mMidPoints.begin() + index); + } + + // Find indices of complete set of streamlines to be removed, + // update number of streamlines per training subject + idxall.resize(idxfull.size() + idxtrunc.size()); + iall = idxall.begin(); + ifull = idxfull.begin(); + itrunc = idxtrunc.begin(); + + for (vector::iterator inum = mNumLines.begin(); + inum != mNumLines.end(); inum++) + for (int k = *inum; k > 0; k--) { + if (*ivalid1 && *ivalid2) { // A non-truncated streamline + if (ifull != idxfull.end()) { + if (kfull == *ifull) { + *iall = istr - mStreamlines.begin(); + (*inum)--; + ifull++; + iall++; + } + kfull++; + } + } + else { // A truncated streamline + if (itrunc != idxtrunc.end()) { + if (ktrunc == *itrunc) { + *iall = istr - mStreamlines.begin(); + (*inum)--; + itrunc++; + iall++; + } + ktrunc++; + } + } + + istr++; + ivalid1++; + ivalid2++; + } + + // Iterate backwards on indices of all streamlines to be removed + for (iall = idxall.end(); iall > idxall.begin(); iall--) { + unsigned int index = *(iall-1); + + mStreamlines.erase(mStreamlines.begin() + index); + mLengths.erase(mLengths.begin() + index); + + if (!mIsInEnd1.empty()) + mIsInEnd1.erase(mIsInEnd1.begin() + index); + if (!mIsInEnd2.empty()) + mIsInEnd2.erase(mIsInEnd2.begin() + index); + if (!mTruncatedLengths.empty()) + mTruncatedLengths.erase(mTruncatedLengths.begin() + index); + + if (!mDistanceRank.empty()) { + vector::iterator irank = find(mDistanceRank.begin(), + mDistanceRank.end(), index); + if (irank != mDistanceRank.end()) + mDistanceRank.erase(irank); + + for (irank = mDistanceRank.begin(); irank < mDistanceRank.end(); irank++) + if (*irank > index) + (*irank)--; + } + } + + // Update stats based on remaining streamlines + ComputeStats(); + ComputeStatsEnds(); +} + // // Make sure all streamline start/end points are consistent // and identify those that are within (a small distance of) the cortical mask @@ -1308,10 +1570,9 @@ void Blood::MatchStreamlineEnds() { ivalid2++; } - if (!mMask.empty()) { + if (!mMask.empty()) imask++; - } - iaseg++; + iaseg++; } } else { // Have labeling ROIs @@ -1458,110 +1719,115 @@ void Blood::MatchStreamlineEnds() { } ComputeStatsEnds(); +} - ComputeEndPointCoM(); +// +// Map each truncated streamline to its nearest streamline that has +// both start and end point in mask +// +void Blood::MatchTruncatedStreamlines() { + const int lag = max(1, (int) round(mHausStepRatio * mLengthAvgEnds)) * 3; + vector::iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(); + vector::iterator itrlen; - // Map each truncated streamline to its nearest streamline that has - // both start and end point in mask mTruncatedLengths.resize(mLengths.size()); fill(mTruncatedLengths.begin(), mTruncatedLengths.end(), 0); - if (mUseTruncated) { - const int lag = max(1, (int) round(mHausStepRatio * mLengthAvgEnds)) * 3; + if (!mUseTruncated) + return; + + itrlen = mTruncatedLengths.begin(); + + for (vector< vector >::iterator istr = mStreamlines.begin(); + istr < mStreamlines.end(); istr++) { + if ((*ivalid1 && !*ivalid2) || (!*ivalid1 && *ivalid2)) { + double hdmin = numeric_limits::infinity(); + vector::iterator jvalid1 = mIsInEnd1.begin(), + jvalid2 = mIsInEnd2.begin(); + vector< vector >::const_iterator jstr, jstrnear; + + // Find nearest streamline that has both start and end point in mask + for (jstr = mStreamlines.begin(); jstr < mStreamlines.end(); jstr++) { + if (*jvalid1 && *jvalid2) { + double hd = 0; - ivalid1 = mIsInEnd1.begin(); - ivalid2 = mIsInEnd2.begin(); - itrlen = mTruncatedLengths.begin(); + for (vector::const_iterator ipt = istr->begin(); + ipt < istr->end(); ipt += 3) { + int dmin = 1000000; - for (istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { - if ((*ivalid1 && !*ivalid2) || (!*ivalid1 && *ivalid2)) { - double hdmin = numeric_limits::infinity(); - vector::iterator jvalid1 = mIsInEnd1.begin(), - jvalid2 = mIsInEnd2.begin(); - vector< vector >::const_iterator jstr, jstrnear; + for (vector::const_iterator jpt = jstr->begin(); + jpt < jstr->end(); jpt += lag) { + const int dx = ipt[0] - jpt[0], + dy = ipt[1] - jpt[1], + dz = ipt[2] - jpt[2], + dist = dx*dx + dy*dy + dz*dz; - // Find nearest streamline that has both start and end point in mask - for (jstr = mStreamlines.begin(); jstr < mStreamlines.end(); jstr++) { - if (*jvalid1 && *jvalid2) { - double hd = 0; + if (dist < dmin) + dmin = dist; + } - for (vector::const_iterator ipt = istr->begin(); - ipt < istr->end(); ipt += 3) { - int dmin = 1000000; + hd += sqrt(dmin); + } - for (vector::const_iterator jpt = jstr->begin(); - jpt < jstr->end(); jpt += lag) { - const int dx = ipt[0] - jpt[0], - dy = ipt[1] - jpt[1], - dz = ipt[2] - jpt[2], - dist = dx*dx + dy*dy + dz*dz; + if (hd < hdmin) { + hdmin = hd; + jstrnear = jstr; + } + } - if (dist < dmin) - dmin = dist; - } + jvalid1++; + jvalid2++; + } - hd += sqrt(dmin); - } + if (*ivalid1) { + int dmin = 1000000; + vector::const_iterator jptnear, iend2 = istr->end() - 3; + + // Find point on whole streamline nearest to truncated end point + for (vector::const_iterator jpt = jstrnear->begin(); + jpt < jstrnear->end(); jpt += 3) { + const int dx = iend2[0] - jpt[0], + dy = iend2[1] - jpt[1], + dz = iend2[2] - jpt[2], + dist = dx*dx + dy*dy + dz*dz; - if (hd < hdmin) { - hdmin = hd; - jstrnear = jstr; - } + if (dist < dmin) { + dmin = dist; + jptnear = jpt; } - - jvalid1++; - jvalid2++; } - if (*ivalid1) { - int dmin = 1000000; - vector::const_iterator jptnear, iend2 = istr->end() - 3; - - // Find point on whole streamline nearest to truncated end point - for (vector::const_iterator jpt = jstrnear->begin(); - jpt < jstrnear->end(); jpt += 3) { - const int dx = iend2[0] - jpt[0], - dy = iend2[1] - jpt[1], - dz = iend2[2] - jpt[2], - dist = dx*dx + dy*dy + dz*dz; - - if (dist < dmin) { - dmin = dist; - jptnear = jpt; - } - } + // Make educated guess about how much of streamline has been truncated + *itrlen = (jstrnear->end() - 3 - jptnear) / 3; + } - // Make educated guess about how much of streamline has been truncated - *itrlen = (jstrnear->end() - 3 - jptnear) / 3; - } + if (*ivalid2) { + int dmin = 1000000; + vector::const_iterator jptnear, iend1 = istr->begin(); - if (*ivalid2) { - int dmin = 1000000; - vector::const_iterator jptnear, iend1 = istr->begin(); - - // Find point on whole streamline nearest to truncated start point - for (vector::const_iterator jpt = jstrnear->begin(); - jpt < jstrnear->end(); jpt += 3) { - const int dx = iend1[0] - jpt[0], - dy = iend1[1] - jpt[1], - dz = iend1[2] - jpt[2], - dist = dx*dx + dy*dy + dz*dz; - - if (dist < dmin) { - dmin = dist; - jptnear = jpt; - } - } + // Find point on whole streamline nearest to truncated start point + for (vector::const_iterator jpt = jstrnear->begin(); + jpt < jstrnear->end(); jpt += 3) { + const int dx = iend1[0] - jpt[0], + dy = iend1[1] - jpt[1], + dz = iend1[2] - jpt[2], + dist = dx*dx + dy*dy + dz*dz; - // Make educated guess about how much of streamline has been truncated - *itrlen = (jptnear - jstrnear->begin()) / 3; + if (dist < dmin) { + dmin = dist; + jptnear = jpt; + } } - } - ivalid1++; - ivalid2++; - itrlen++; + // Make educated guess about how much of streamline has been truncated + *itrlen = (jptnear - jstrnear->begin()) / 3; + } } + + ivalid1++; + ivalid2++; + itrlen++; } } @@ -1594,7 +1860,11 @@ bool Blood::IsEnd1InMask(vector< vector >::iterator Streamline, if (MRIgetVoxVal(Mask, itop[0], itop[1], itop[2], 0) > 0 || (mMaskLabel > 0 && - MRIgetVoxVal(Aseg, itop[0], itop[1], itop[2], 0) == mMaskLabel)) + MRIgetVoxVal(Aseg, itop[0], itop[1], itop[2], 0) == mMaskLabel) || + (mMaskLabel == 10 && // Left thalamic nuclei + (int)MRIgetVoxVal(Aseg, itop[0], itop[1], itop[2], 0)/100 == 81) || + (mMaskLabel == 49 && // Right thalamic nuclei + (int)MRIgetVoxVal(Aseg, itop[0], itop[1], itop[2], 0)/100 == 82)) return true; if (itop < Streamline->end() - 3) { // If more than one voxel in streamline @@ -1616,7 +1886,11 @@ bool Blood::IsEnd1InMask(vector< vector >::iterator Streamline, if (MRIgetVoxVal(Mask, newpt[0], newpt[1], newpt[2], 0) > 0 || (mMaskLabel > 0 && - MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0) == mMaskLabel)) { + MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0) == mMaskLabel) || + (mMaskLabel == 10 && // Left thalamic nuclei + (int)MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0)/100 == 81) || + (mMaskLabel == 49 && // Right thalamic nuclei + (int)MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0)/100 == 82)) { Streamline->insert(Streamline->begin(), extend.begin(), extend.end()); mLengths[Streamline - mStreamlines.begin()] = Streamline->size() / 3; return true; @@ -1637,7 +1911,11 @@ bool Blood::IsEnd2InMask(vector< vector >::iterator Streamline, if (MRIgetVoxVal(Mask, ibottom[0], ibottom[1], ibottom[2], 0) > 0 || (mMaskLabel > 0 && - MRIgetVoxVal(Aseg, ibottom[0], ibottom[1], ibottom[2], 0) == mMaskLabel)) + MRIgetVoxVal(Aseg, ibottom[0], ibottom[1], ibottom[2], 0) == mMaskLabel) || + (mMaskLabel == 10 && // Left thalamic nuclei + (int)MRIgetVoxVal(Aseg, ibottom[0], ibottom[1], ibottom[2], 0)/100 == 81) || + (mMaskLabel == 49 && // Right thalamic nuclei + (int)MRIgetVoxVal(Aseg, ibottom[0], ibottom[1], ibottom[2], 0)/100 == 82)) return true; if (ibottom > Streamline->begin()) { // If more than one voxel in streamline @@ -1659,7 +1937,11 @@ bool Blood::IsEnd2InMask(vector< vector >::iterator Streamline, if (MRIgetVoxVal(Mask, newpt[0], newpt[1], newpt[2], 0) > 0 || (mMaskLabel > 0 && - MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0) == mMaskLabel)) { + MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0) == mMaskLabel) || + (mMaskLabel == 10 && // Left thalamic nuclei + (int)MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0)/100 == 81) || + (mMaskLabel == 49 && // Right thalamic nuclei + (int)MRIgetVoxVal(Aseg, newpt[0], newpt[1], newpt[2], 0)/100 == 82)) { Streamline->insert(Streamline->end(), extend.begin(), extend.end()); mLengths[Streamline - mStreamlines.begin()] = Streamline->size() / 3; return true; @@ -1670,6 +1952,374 @@ bool Blood::IsEnd2InMask(vector< vector >::iterator Streamline, return false; } +// +// Find outlier streamlines +// +void Blood::FindOutlierStreamlines(bool CheckOverlap, bool CheckDeviation, + bool CheckFa) { + vector::const_iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(); + vector::iterator iouthist, ioutdev, ioutfa; + vector::const_iterator imidpts; + + if (CheckOverlap || mIsOutHist.size() != mNumStrEnds) { + mIsOutHist.resize(mNumStrEnds); + fill(mIsOutHist.begin(), mIsOutHist.end(), false); + } + + if (CheckDeviation || mIsOutDev.size() != mNumStrEnds) { + mIsOutDev.resize(mNumStrEnds); + fill(mIsOutDev.begin(), mIsOutDev.end(), false); + } + + if (CheckFa || mIsOutFa.size() != mNumStrEnds) { + mIsOutFa.resize(mNumStrEnds); + fill(mIsOutFa.begin(), mIsOutFa.end(), false); + } + + if (mTestFa.empty()) + CheckFa = false; + + if (CheckDeviation) + ComputeEndPointCoM(); + + iouthist = mIsOutHist.begin(); + ioutdev = mIsOutDev.begin(); + ioutfa = mIsOutFa.begin(); + imidpts = mMidPoints.begin(); + + for (vector< vector >::const_iterator istr = mStreamlines.begin(); + istr < mStreamlines.end(); + istr++) { + if (*ivalid1 && *ivalid2) { + if (CheckOverlap) { // Check overlap with histogram + int nzeros = 0; + + for (vector::const_iterator ipt = istr->begin(); + ipt < istr->end(); ipt += 3) { + const float h = MRIgetVoxVal(mHistoStr, ipt[0], ipt[1], ipt[2], 0); + + if (h < 4.0) // Little overlap with other streamlines + nzeros++; + } + + if (nzeros >= (int) (.1 * istr->size()/3)) + *iouthist = true; + } + + if (CheckFa) { // Check overlap with test subject's FA + vector nfzeros(mTestFa.size(), 0), basept(3), dwipt(3); + + for (vector::const_iterator ipt = istr->begin(); + ipt < istr->end(); ipt += 3) { + vector::iterator infzeros; + vector::const_iterator iptbase, iptdwi; + + // Map point to base space if needed + if (!mTestAffineReg.IsEmpty() || !mTestNonlinReg.IsEmpty()) { + if (!MapPointToBase(basept.begin(), ipt)) { + for (infzeros = nfzeros.begin(); infzeros < nfzeros.end(); + infzeros++) { + (*infzeros)++; + + if (*infzeros > 3) { + *ioutfa = true; + break; + } + } + + if (*ioutfa) + break; + + continue; + } + + iptbase = basept.begin(); + } + else + iptbase = ipt; + + infzeros = nfzeros.begin(); + + for (vector::const_iterator ifa = mTestFa.begin(); + ifa < mTestFa.end(); ifa++) { + // Map point to native space if needed + if (!mTestBaseReg.empty()) { + if (!MapPointToNative(dwipt.begin(), iptbase, + ifa - mTestFa.begin())) { + (*infzeros)++; + + if (*infzeros > 3) { + *ioutfa = true; + break; + } + + infzeros++; + continue; + } + + iptdwi = dwipt.begin(); + } + else + iptdwi = iptbase; + + // Check anisotropy at this point + if (MRIgetVoxVal(*ifa, iptdwi[0], iptdwi[1], iptdwi[2], 0) < 0.1) { + (*infzeros)++; + + if (*infzeros > 3) { + *ioutfa = true; + break; + } + } + else + *infzeros = 0; + + infzeros++; + } + + if (*ioutfa) + break; + } + } + + if (CheckDeviation) { // Check endpoint deviation from center of mass + bool okend1 = true, okend2 = true, okmid = true; + vector::const_iterator itop = istr->begin(), + ibottom = istr->end() - 3, + imiddle = itop + *imidpts; + + for (int k = 0; k < 3; k++) { + const float dist = itop[k] - mMeanEnd1[k]; + okend1 = okend1 && (dist*dist < mVarEnd1[k]); + } + + for (int k = 0; k < 3; k++) { + const float dist = ibottom[k] - mMeanEnd2[k]; + okend2 = okend2 && (dist*dist < mVarEnd2[k]); + } + + for (int k = 0; k < 3; k++) { + const float dist = imiddle[k] - mMeanMid[k]; + okmid = okmid && (dist*dist < mVarMid[k]); + } + + if (!okend1 || !okend2 || !okmid) + *ioutdev = true; + } + + iouthist++; + ioutdev++; + ioutfa++; + imidpts++; + } + + ivalid1++; + ivalid2++; + } +} + +// +// Rank streamlines by distance from other streamlines +// +void Blood::RankStreamlineDistance() { + int index = 0; + const int lag = max(1, (int) round(mHausStepRatio * mLengthAvgEnds)) * 3; + vector< pair > distance(mNumStrEnds, make_pair(0,0)); + vector::const_iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(), + iouthist = mIsOutHist.begin(), + ioutdev = mIsOutDev.begin(), + ioutfa = mIsOutFa.begin(); + vector::iterator irank; + vector< pair >::iterator idout = distance.begin(), id0; + + cout << "INFO: Step is " << lag/3 << " voxels" << endl; + + for (vector< vector >::const_iterator istr = mStreamlines.begin(); + istr < mStreamlines.end(); + istr++) { + if (*ivalid1 && *ivalid2) { + double hdtot = 0; + vector::const_iterator jvalid1 = mIsInEnd1.begin(), + jvalid2 = mIsInEnd2.begin(); + vector::const_iterator jlen = mLengths.begin(); + + for (vector< vector >::const_iterator + jstr = mStreamlines.begin(); jstr < mStreamlines.end(); jstr++) { + double hd = 0; + + if (*jvalid1 && *jvalid2 && (jstr != istr)) { + for (vector::const_iterator jpt = jstr->begin(); + jpt < jstr->end(); jpt += lag) { + int dmin = 1000000; + + for (vector::const_iterator ipt = istr->begin(); + ipt < istr->end(); ipt += lag) { + const int dx = ipt[0] - jpt[0], + dy = ipt[1] - jpt[1], + dz = ipt[2] - jpt[2], + dist = dx*dx + dy*dy + dz*dz; + + if (dist < dmin) + dmin = dist; + } + + hd += sqrt(dmin); + } + + hd /= (*jlen); + } + + hdtot += hd; + + jvalid1++; + jvalid2++; + jlen++; + } + + *idout = make_pair(hdtot, index); + idout++; + } + + ivalid1++; + ivalid2++; + index++; + } + + sort(distance.begin(), distance.end()); + + mDistanceRank.resize(mNumStrEnds); + irank = mDistanceRank.begin(); + + for (vector< pair >::const_iterator + idin = distance.begin(); idin < distance.end(); idin++) { + *irank = idin->second; + irank++; + } + + UpdateDistanceRank(); +} + +// +// Update distance ranking of streamlines based on outlier status +// +void Blood::UpdateDistanceRank() { + vector strset(mStreamlines.size(), false); + vector rank(mDistanceRank.size(), 0); + vector::const_iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(), + iouthist = mIsOutHist.begin(), + ioutfa = mIsOutFa.begin(), + ioutdev = mIsOutDev.begin(); + vector::iterator iset = strset.begin(); + vector::iterator irout = rank.begin(); + + for (vector< vector >::const_iterator + istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { + if (*ivalid1 && *ivalid2) { + if (!*iouthist && !*ioutfa && !*ioutdev) + *iset = true; + + iouthist++; ioutfa++; ioutdev++; + } + + ivalid1++; ivalid2++; iset++; + } + + for (vector::const_iterator irin = mDistanceRank.begin(); + irin < mDistanceRank.end(); irin++) + if (strset[*irin]) { + *irout = *irin; + irout++; + } + + ivalid1 = mIsInEnd1.begin(); + ivalid2 = mIsInEnd2.begin(); + iouthist = mIsOutHist.begin(); + ioutfa = mIsOutFa.begin(); + ioutdev = mIsOutDev.begin(); + iset = strset.begin(); + fill(strset.begin(), strset.end(), false); + + for (vector< vector >::const_iterator + istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { + if (*ivalid1 && *ivalid2) { + if (!*iouthist && !*ioutfa && *ioutdev) + *iset = true; + + iouthist++; ioutfa++; ioutdev++; + } + + ivalid1++; ivalid2++; iset++; + } + + for (vector::const_iterator irin = mDistanceRank.begin(); + irin < mDistanceRank.end(); irin++) + if (strset[*irin]) { + *irout = *irin; + irout++; + } + + ivalid1 = mIsInEnd1.begin(); + ivalid2 = mIsInEnd2.begin(); + iouthist = mIsOutHist.begin(); + ioutfa = mIsOutFa.begin(); + ioutdev = mIsOutDev.begin(); + iset = strset.begin(); + fill(strset.begin(), strset.end(), false); + + for (vector< vector >::const_iterator + istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { + if (*ivalid1 && *ivalid2) { + if (!*iouthist && *ioutfa && *ioutdev) + *iset = true; + + iouthist++; ioutfa++; ioutdev++; + } + + ivalid1++; ivalid2++; iset++; + } + + for (vector::const_iterator irin = mDistanceRank.begin(); + irin < mDistanceRank.end(); irin++) + if (strset[*irin]) { + *irout = *irin; + irout++; + } + + ivalid1 = mIsInEnd1.begin(); + ivalid2 = mIsInEnd2.begin(); + iouthist = mIsOutHist.begin(); + ioutfa = mIsOutFa.begin(); + ioutdev = mIsOutDev.begin(); + iset = strset.begin(); + fill(strset.begin(), strset.end(), false); + + for (vector< vector >::const_iterator + istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { + if (*ivalid1 && *ivalid2) { + if ( !(!*iouthist && !*ioutfa && !*ioutdev) && + !(!*iouthist && !*ioutfa && *ioutdev) && + !(!*iouthist && *ioutfa && *ioutdev) ) + *iset = true; + + iouthist++; ioutfa++; ioutdev++; + } + + ivalid1++; ivalid2++; iset++; + } + + for (vector::const_iterator irin = mDistanceRank.begin(); + irin < mDistanceRank.end(); irin++) + if (strset[*irin]) { + *irout = *irin; + irout++; + } + + copy(rank.begin(), rank.end(), mDistanceRank.begin()); +} + // // Determine number of arc length segments for priors // @@ -1762,7 +2412,7 @@ void Blood::ComputeHistogram() { // // Compute prior on underlying anatomy by streamline arc length // -void Blood::ComputeAnatomyPrior(bool UseTruncated) { +void Blood::ComputeAnatomyPrior() { vector::const_iterator ivalid1 = mIsInEnd1.begin(), ivalid2 = mIsInEnd2.begin(); vector::const_iterator ilen = mLengths.begin(), @@ -1780,7 +2430,7 @@ void Blood::ComputeAnatomyPrior(bool UseTruncated) { for (vector::const_iterator inum = mNumLines.begin(); inum != mNumLines.end(); inum++) { for (int k = *inum; k > 0; k--) { - if ( (UseTruncated && (*ivalid1 || *ivalid2)) || + if ( (mUseTruncated && (*ivalid1 || *ivalid2)) || (*ivalid1 && *ivalid2) ) { unsigned int ilocal, inear; const double darc = mNumArc / (double) (*ilen + *itrlen); @@ -1866,7 +2516,7 @@ void Blood::ComputeAnatomyPrior(bool UseTruncated) { iaseg++; } - if (UseTruncated) { + if (mUseTruncated) { mIdsLocalAll.clear(); mHistoLocalAll.clear(); mPriorLocalAll.clear(); @@ -1910,7 +2560,7 @@ void Blood::ComputeAnatomyPrior(bool UseTruncated) { *iprior = -log(1 / denom); - if (UseTruncated) { + if (mUseTruncated) { mIdsLocalAll.push_back(idlist); mHistoLocalAll.push_back(histo); mPriorLocalAll.push_back(prior); @@ -1970,7 +2620,7 @@ void Blood::ComputeAnatomyPrior(bool UseTruncated) { *iprior = -log(1 / denom); - if (UseTruncated) { + if (mUseTruncated) { mIdsNearAll.push_back(idlist); mHistoNearAll.push_back(histo); mPriorNearAll.push_back(prior); @@ -1992,7 +2642,7 @@ void Blood::ComputeAnatomyPrior(bool UseTruncated) { // // Compute prior on tangent vector and curvature by streamline arc length // -void Blood::ComputeShapePrior(bool UseTruncated) { +void Blood::ComputeShapePrior() { const int nbin = (int) ceil(2 / mTangentBinSize); float tangx, tangy, curv; vector::const_iterator ivalid1 = mIsInEnd1.begin(), @@ -2013,7 +2663,7 @@ void Blood::ComputeShapePrior(bool UseTruncated) { // Compute tangent vector and curvature at each point on each streamline for (vector< vector >::const_iterator istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { - if ( ( (UseTruncated && (*ivalid1 || *ivalid2)) || + if ( ( (mUseTruncated && (*ivalid1 || *ivalid2)) || (*ivalid1 && *ivalid2) ) && *ilen >= (int) mDiffStep ) { unsigned int iarc; const double darc = mNumArc / (double) (*ilen + *itrlen); @@ -2093,7 +2743,7 @@ void Blood::ComputeShapePrior(bool UseTruncated) { itrlen++; } - if (UseTruncated) { + if (mUseTruncated) { mHistoTangentAll.clear(); mPriorTangentAll.clear(); mHistoCurvatureAll.clear(); @@ -2165,7 +2815,7 @@ void Blood::ComputeShapePrior(bool UseTruncated) { ihisto++; } - if (UseTruncated) { + if (mUseTruncated) { mHistoTangentAll.push_back(tanghisto); mPriorTangentAll.push_back(tangprior); mHistoCurvatureAll.push_back(curvhisto); @@ -2185,7 +2835,7 @@ void Blood::ComputeShapePrior(bool UseTruncated) { // In debug mode, save all samples of the tangent vector and curvature // by arc length if (mDebug) { - if (UseTruncated) { + if (mUseTruncated) { mTangentXByArcAll.resize(mNumArc); copy(tangxbyarc.begin(), tangxbyarc.end(), mTangentXByArcAll.begin()); mTangentYByArcAll.resize(mNumArc); @@ -2212,8 +2862,8 @@ void Blood::FindCenterStreamline(bool CheckOverlap, bool CheckDeviation, const int lag = max(1, (int) round(mHausStepRatio * mLengthAvgEnds)) * 3; double hdmin = numeric_limits::infinity(); vector::const_iterator ivalid1 = mIsInEnd1.begin(), - ivalid2 = mIsInEnd2.begin(); - vector::const_iterator imidpts = mMidPoints.begin(); + ivalid2 = mIsInEnd2.begin(), + iouthist, ioutdev, ioutfa; vector< vector >::const_iterator icenter; if (mStreamlines.empty() || mNumStrEnds == 0) @@ -2238,6 +2888,21 @@ void Blood::FindCenterStreamline(bool CheckOverlap, bool CheckDeviation, cout << "INFO: Step is " << lag/3 << " voxels" << endl; + if (mNumTrain > 1) + FindOutlierStreamlines(CheckOverlap, CheckDeviation, CheckFa); + else { + mIsOutHist.resize(mNumStrEnds); + fill(mIsOutHist.begin(), mIsOutHist.end(), false); + mIsOutDev.resize(mNumStrEnds); + fill(mIsOutDev.begin(), mIsOutDev.end(), false); + mIsOutFa.resize(mNumStrEnds); + fill(mIsOutFa.begin(), mIsOutFa.end(), false); + } + + iouthist = mIsOutHist.begin(); + ioutdev = mIsOutDev.begin(); + ioutfa = mIsOutFa.begin(); + for (vector< vector >::const_iterator istr = mStreamlines.begin(); istr < mStreamlines.end(); istr++) { @@ -2257,119 +2922,12 @@ void Blood::FindCenterStreamline(bool CheckOverlap, bool CheckDeviation, if (equal(istr->begin(), istr->end(), ixstr->begin())) isexcluded = true; - if (!isexcluded && mNumTrain > 1) { // No checks for single subject - if (CheckOverlap) { // Check overlap with histogram - int nzeros = 0; - - for (vector::const_iterator ipt = istr->begin(); - ipt < istr->end(); ipt += 3) { - const float h = MRIgetVoxVal(mHistoStr, ipt[0], ipt[1], ipt[2], 0); - - if (h < 4.0) // Little overlap with other streamlines - nzeros++; - } - - if (nzeros >= (int) (.1 * istr->size()/3)) - okhist = false; - } - - if (CheckFa) { // Check overlap with test subject's FA - vector nfzeros(mTestFa.size(), 0), basept(3), dwipt(3); - - for (vector::const_iterator ipt = istr->begin(); - ipt < istr->end(); ipt += 3) { - vector::iterator infzeros; - vector::const_iterator iptbase, iptdwi; - - // Map point to base space if needed - if (!mTestAffineReg.IsEmpty() || !mTestNonlinReg.IsEmpty()) { - if (!MapPointToBase(basept.begin(), ipt)) { - for (infzeros = nfzeros.begin(); infzeros < nfzeros.end(); - infzeros++) { - (*infzeros)++; - - if (*infzeros > 3) { - okfa = false; - break; - } - } - - if (!okfa) - break; - - continue; - } - - iptbase = basept.begin(); - } - else - iptbase = ipt; - - infzeros = nfzeros.begin(); - - for (vector::const_iterator ifa = mTestFa.begin(); - ifa < mTestFa.end(); ifa++) { - // Map point to native space if needed - if (!mTestBaseReg.empty()) { - if (!MapPointToNative(dwipt.begin(), iptbase, - ifa - mTestFa.begin())) { - (*infzeros)++; - - if (*infzeros > 3) { - okfa = false; - break; - } - - infzeros++; - continue; - } - - iptdwi = dwipt.begin(); - } - else - iptdwi = iptbase; - - // Check anisotropy at this point - if (MRIgetVoxVal(*ifa, iptdwi[0], iptdwi[1], iptdwi[2], 0) - < 0.1) { - (*infzeros)++; - - if (*infzeros > 3) { - okfa = false; - break; - } - } - else - *infzeros = 0; - - infzeros++; - } - - if (!okfa) - break; - } - } - - if (CheckDeviation) { // Check endpoint deviation from center of mass - vector::const_iterator itop = istr->begin(), - ibottom = istr->end() - 3, - imiddle = itop + *imidpts; - - for (int k = 0; k < 3; k++) { - const float dist = itop[k] - mMeanEnd1[k]; - okend1 = okend1 && (dist*dist < mVarEnd1[k]); - } - - for (int k = 0; k < 3; k++) { - const float dist = ibottom[k] - mMeanEnd2[k]; - okend2 = okend2 && (dist*dist < mVarEnd2[k]); - } - - for (int k = 0; k < 3; k++) { - const float dist = imiddle[k] - mMeanMid[k]; - okmid = okmid && (dist*dist < mVarMid[k]); - } - } + if (mNumTrain > 1) { // No checks for single subject + okhist = !*iouthist; + okfa = !*ioutfa; + okend1 = !*ioutdev; + okend2 = !*ioutdev; + okmid = !*ioutdev; } if (!isexcluded && okhist && okfa && okend1 && okend2 && okmid) { @@ -2412,7 +2970,9 @@ void Blood::FindCenterStreamline(bool CheckOverlap, bool CheckDeviation, } } - imidpts++; + iouthist++; + ioutdev++; + ioutfa++; } ivalid1++; @@ -3354,10 +3914,10 @@ bool Blood::MapPointToNative(vector::iterator OutPoint, // // Write histograms, priors, end ROIs, and initialization control points // -void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { +void Blood::WriteOutputs(const string OutTrainBase, const string OutTestBase) { const int nstr2 = (int) mStreamlines.size() + 2, nsubj2 = mNumTrain + 2; - char fname[PATH_MAX]; + string fname; MRI *out1 = MRIclone(mTestMask[0], NULL); MRI *out2 = MRIclone(mTestMask[0], NULL); ofstream outfile; @@ -3365,8 +3925,8 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { cout << "Writing output files to " << OutTrainBase << "_*" << endl; // Write streamline-wise histogram to volume - sprintf(fname, "%s_histo_str.nii.gz", OutTrainBase); - MRIwrite(mHistoStr, fname); + fname = OutTrainBase + "_histo_str.nii.gz"; + MRIwrite(mHistoStr, fname.c_str()); // Convert streamline-wise histogram to negative log-likelihood for (int iz = 0; iz < mNz; iz++) @@ -3378,14 +3938,14 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { MRIsetVoxVal(out2, ix, iy, iz, 0, -log(1-ratio)); } - sprintf(fname, "%s_logprior_str_1.nii.gz", OutTrainBase); - MRIwrite(out1, fname); + fname = OutTrainBase + "_logprior_str_1.nii.gz"; + MRIwrite(out1, fname.c_str()); - sprintf(fname, "%s_logprior_str_0.nii.gz", OutTrainBase); - MRIwrite(out2, fname); + fname = OutTrainBase + "_logprior_str_0.nii.gz"; + MRIwrite(out2, fname.c_str()); // Write total number of streamlines to text file - sprintf(fname, "%s_histo_nstr.txt", OutTrainBase); + fname = OutTrainBase + "_histo_nstr.txt"; ofstream nstrfile(fname, ios::out); if (!nstrfile) { @@ -3399,8 +3959,8 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { MRIclear(out2); // Write subject-wise histogram to volume - sprintf(fname, "%s_histo.nii.gz", OutTrainBase); - MRIwrite(mHistoSubj, fname); + fname = OutTrainBase + "_histo.nii.gz"; + MRIwrite(mHistoSubj, fname.c_str()); // Convert subject-wise histogram to negative log-likelihood for (int iz = 0; iz < mNz; iz++) @@ -3412,24 +3972,25 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { MRIsetVoxVal(out2, ix, iy, iz, 0, -log(1-ratio)); } - sprintf(fname, "%s_logprior_1.nii.gz", OutTrainBase); - MRIwrite(out1, fname); + fname = OutTrainBase + "_logprior_1.nii.gz"; + MRIwrite(out1, fname.c_str()); - sprintf(fname, "%s_logprior_0.nii.gz", OutTrainBase); - MRIwrite(out2, fname); + fname = OutTrainBase + "_logprior_0.nii.gz"; + MRIwrite(out2, fname.c_str()); - // Save anatomical priors using only non-truncated streamlines - WritePriors(OutTrainBase, false); + // Save anatomical priors + if (mUseAnatomy) + WriteAnatomyPriors(OutTrainBase); - // Save anatomical priors using all streamlines, truncated or not - if (mUseTruncated) - WritePriors(OutTrainBase, true); + // Save shape priors + if (mUseShape) + WriteShapePriors(OutTrainBase); // Write streamline end points to volumes WriteEndPoints(OutTrainBase, mTestMask[0]); // Write central streamline to text file and volume - sprintf(fname, "%s_cpts_all.txt", OutTrainBase); + fname = OutTrainBase + "_cpts_all.txt"; ofstream centfile(fname, ios::out); if (!centfile) { @@ -3445,8 +4006,8 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { MRIsetVoxVal(out1, ipt[0], ipt[1], ipt[2], 0, 1); } - sprintf(fname, "%s_cpts_all.nii.gz", OutTrainBase); - MRIwrite(out1, fname); + fname = OutTrainBase + "_cpts_all.nii.gz"; + MRIwrite(out1, fname.c_str()); MRIfree(&out1); MRIfree(&out2); @@ -3458,7 +4019,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { istr++) { const unsigned int ncpt = istr->size() / 3; - sprintf(fname, "%s_cpts_%d.txt", OutTrainBase, ncpt); + fname = OutTrainBase + "_cpts_" + to_string(ncpt) + ".txt"; ofstream cptfile(fname, ios::out); if (!cptfile) { @@ -3473,7 +4034,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { Spline spline(*istr, mTestMask[0]); spline.InterpolateSpline(); - sprintf(fname, "%s_cpts_%d.nii.gz", OutTrainBase, ncpt); + fname = OutTrainBase + "_cpts_" + to_string(ncpt) + ".nii.gz"; spline.WriteVolume(fname, true); } @@ -3483,7 +4044,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { istd++) { const unsigned int ncpt = istd->size() / 3; - sprintf(fname, "%s_cpts_%d_std.txt", OutTrainBase, ncpt); + fname = OutTrainBase + "_cpts_" + to_string(ncpt) + "_std.txt"; ofstream stdfile(fname, ios::out); if (!stdfile) { @@ -3500,7 +4061,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { // Also write initialization files in the space of the test subject, // if registration was specified // - if (OutTestBase) { + if (!OutTestBase.empty()) { // Write each set of control points chosen from central streamline // to text file and volume for (vector< vector >::const_iterator @@ -3508,7 +4069,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { istr++) { const unsigned int ncpt = istr->size() / 3; - sprintf(fname, "%s_cpts_%d.txt", OutTestBase, ncpt); + fname = OutTestBase + "_cpts_" + to_string(ncpt) + ".txt"; ofstream cptfile(fname, ios::out); if (!cptfile) { @@ -3523,7 +4084,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { Spline spline(*istr, mTestBaseMask); spline.InterpolateSpline(); - sprintf(fname, "%s_cpts_%d.nii.gz", OutTestBase, ncpt); + fname = OutTestBase + "_cpts_" + to_string(ncpt) + ".nii.gz"; spline.WriteVolume(fname, true); } @@ -3532,7 +4093,7 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { istd = mControlStdTest.begin(); istd < mControlStdTest.end(); istd++) { const unsigned int ncpt = istd->size() / 3; - sprintf(fname, "%s_cpts_%d_std.txt", OutTestBase, ncpt); + fname = OutTestBase + "_cpts_" + to_string(ncpt) + "_std.txt"; ofstream stdfile(fname, ios::out); if (!stdfile) { @@ -3550,23 +4111,22 @@ void Blood::WriteOutputs(const char *OutTrainBase, const char *OutTestBase) { // // Save prior information on anatomy and curvature to text files // -void Blood::WritePriors(const char *OutBase, bool UseTruncated) { - char fname[PATH_MAX], pfix[5]; - vector::const_iterator ithisto, itprior, ichisto, icprior; +void Blood::WriteAnatomyPriors(const string OutBase) { + string fname, pfix; vector< vector >::const_iterator ihisto; vector< vector >::const_iterator iprior, idmean, idstd; vector< set >::const_iterator iids; ofstream outfile; // Save anatomical label IDs found in training set, histograms and priors - if (UseTruncated) { - strcpy(pfix, "_all"); + if (mUseTruncated) { + pfix = "_all"; iids = mIdsLocalAll.begin(); ihisto = mHistoLocalAll.begin(); iprior = mPriorLocalAll.begin(); } else { - strcpy(pfix, ""); + pfix = ""; iids = mIdsLocal.begin(); ihisto = mHistoLocal.begin(); iprior = mPriorLocal.begin(); @@ -3579,7 +4139,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { vector< vector >::const_iterator ihistoarc = ihisto; vector< vector >::const_iterator ipriorarc = iprior; - sprintf(fname, "%s_fsids%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsids" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3593,7 +4155,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fshisto%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fshisto" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3607,7 +4171,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fsprior%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsprior" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3626,7 +4192,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { iprior++; } - if (UseTruncated) { + if (mUseTruncated) { iids = mIdsNearAll.begin(); ihisto = mHistoNearAll.begin(); iprior = mPriorNearAll.begin(); @@ -3650,7 +4216,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { vector< vector >::const_iterator idmeanarc = idmean; vector< vector >::const_iterator idstdarc = idstd; - sprintf(fname, "%s_fsnnids%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsnnids" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3664,7 +4232,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fsnnhisto%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsnnhisto" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3678,7 +4248,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fsnnprior%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsnnprior" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3692,7 +4264,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fsnndmean%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsnndmean" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3706,7 +4280,9 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_fsnndstd%s_%d_%d_%d.txt", OutBase, pfix, idx, idy, idz); + fname = OutBase + "_fsnndstd" + pfix + "_" + to_string(idx) + "_" + + to_string(idy) + "_" + + to_string(idz) + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3726,18 +4302,30 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { idmean++; idstd++; } +} + +// +// Save prior information on shape to text files +// +void Blood::WriteShapePriors(const string OutBase) { + string fname, pfix; + vector< vector >::const_iterator ihisto; + vector< vector >::const_iterator iprior; + ofstream outfile; // Save histograms and priors on tangent vector and curvature - if (UseTruncated) { + if (mUseTruncated) { + pfix = "_all"; ihisto = mHistoTangentAll.begin(); iprior = mPriorTangentAll.begin(); } else { + pfix = ""; ihisto = mHistoTangent.begin(); iprior = mPriorTangent.begin(); } - sprintf(fname, "%s_tanghisto%s.txt", OutBase, pfix); + fname = OutBase + "_tanghisto" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3751,7 +4339,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_tangprior%s.txt", OutBase, pfix); + fname = OutBase + "_tangprior" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3765,7 +4353,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - if (UseTruncated) { + if (mUseTruncated) { ihisto = mHistoCurvatureAll.begin(); iprior = mPriorCurvatureAll.begin(); } @@ -3774,7 +4362,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { iprior = mPriorCurvature.begin(); } - sprintf(fname, "%s_curvhisto%s.txt", OutBase, pfix); + fname = OutBase + "_curvhisto" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3788,7 +4376,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_curvprior%s.txt", OutBase, pfix); + fname = OutBase + "_curvprior" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3808,7 +4396,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { vector::const_iterator isamp; vector< vector >::const_iterator itangx, itangy, icurv; - if (UseTruncated) { + if (mUseTruncated) { itangx = mTangentXByArcAll.begin(); itangy = mTangentYByArcAll.begin(); icurv = mCurvatureByArcAll.begin(); @@ -3819,7 +4407,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { icurv = mCurvatureByArc.begin(); } - sprintf(fname, "%s_tangx%s.txt", OutBase, pfix); + fname = OutBase + "_tangx" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3832,7 +4420,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_tangy%s.txt", OutBase, pfix); + fname = OutBase + "_tangy" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3845,7 +4433,7 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { outfile.close(); - sprintf(fname, "%s_curv%s.txt", OutBase, pfix); + fname = OutBase + "_curv" + pfix + ".txt"; outfile.open(fname, ios::out); for (int k = mNumArc; k > 0; k--) { @@ -3863,8 +4451,8 @@ void Blood::WritePriors(const char *OutBase, bool UseTruncated) { // // Save central streamline to .trk file // -void Blood::WriteCenterStreamline(const std::string CenterTrkFile, - const std::string RefTrkFile) { +void Blood::WriteCenterStreamline(const string CenterTrkFile, + const string RefTrkFile) { float *icent, *centpts = new float[mCenterStreamline.size()]; CTrackReader trkreader; CTrackWriter trkwriter; @@ -3906,8 +4494,8 @@ void Blood::WriteCenterStreamline(const std::string CenterTrkFile, // // Save streamline end points to volumes // -void Blood::WriteEndPoints(const std::string OutBase, MRI *RefVol) { - std::string fname; +void Blood::WriteEndPoints(const string OutBase, MRI *RefVol) { + string fname; vector::const_iterator ivalid1 = mIsInEnd1.begin(), ivalid2 = mIsInEnd2.begin(); vector< vector >::const_iterator istr; @@ -4005,6 +4593,173 @@ void Blood::WriteEndPoints(const std::string OutBase, MRI *RefVol) { } } +// +// Write streamlines of training subjects to .trk files +// +void Blood::WriteStreamlines(const string TrainListFile, + const string TrainTrkFile) { + int index = 0; + char outorient[4]; + MATRIX *outv2r; + MRI *outref = mTestMask[0]; + CTrackWriter trkwriter; + TRACK_HEADER trkheader; + vector dirlist; + vector< pair > strorder(mNumStrEnds, make_pair(0,0)); + vector::const_iterator ivalid1 = mIsInEnd1.begin(), + ivalid2 = mIsInEnd2.begin(); + vector::const_iterator inum = mNumLines.begin(), + ilen = mLengths.begin(), + itrlen = mTruncatedLengths.begin(); + vector< vector >::const_iterator istr = mStreamlines.begin(); + vector< pair >::iterator iorder = strorder.begin(); + + for (vector::const_iterator irank = mDistanceRank.begin(); + irank < mDistanceRank.end(); irank++) { + *iorder = make_pair(*irank, index); + iorder++; + index++; + } + + sort(strorder.begin(), strorder.end()); + + if (!TrainListFile.empty()) { // Read multiple inputs from a list + string dirname; + ifstream listfile(TrainListFile, ios::in); + + if (!listfile) { + cout << "ERROR: Could not open " << TrainListFile << endl; + exit(1); + } + + while (listfile >> dirname) + dirlist.push_back(dirname + "/"); + + if (dirlist.size() != mNumTrain) { + cout << "ERROR: Number of output directories (" << dirlist.size() + << ") in " << TrainListFile + << " does not match number of training subjects (" << mNumTrain + << ")" << endl; + exit(1); + } + } + else // Read a single input + dirlist.push_back(""); + + // Output space orientation information + outv2r = MRIgetVoxelToRasXform(outref); + MRIdircosToOrientationString(outref, outorient); + + trkheader.Initialize(); + + trkheader.origin[0] = 0; + trkheader.origin[1] = 0; + trkheader.origin[2] = 0; + + trkheader.voxel_size[0] = outref->xsize; + trkheader.voxel_size[1] = outref->ysize; + trkheader.voxel_size[2] = outref->zsize; + + trkheader.dim[0] = outref->width; + trkheader.dim[1] = outref->height; + trkheader.dim[2] = outref->depth; + + strcpy(trkheader.reserved, "TRACULAprep"); + trkheader.n_properties = 3; + strcpy(trkheader.property_name[0], "ValidEndpts"); + strcpy(trkheader.property_name[1], "TruncatedLength"); + strcpy(trkheader.property_name[2], "DistanceRank"); + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + trkheader.vox_to_ras[i][j] = outv2r->rptr[i+1][j+1]; + + strcpy(trkheader.voxel_order, outorient); + + // Find patient-to-scanner coordinate transform: + // Take x and y vectors from vox2RAS matrix, convert to LPS, + // divide by voxel size + trkheader.image_orientation_patient[0] = + - trkheader.vox_to_ras[0][0] / trkheader.voxel_size[0]; + trkheader.image_orientation_patient[1] = + - trkheader.vox_to_ras[1][0] / trkheader.voxel_size[0]; + trkheader.image_orientation_patient[2] = + trkheader.vox_to_ras[2][0] / trkheader.voxel_size[0]; + trkheader.image_orientation_patient[3] = + - trkheader.vox_to_ras[0][1] / trkheader.voxel_size[1]; + trkheader.image_orientation_patient[4] = + - trkheader.vox_to_ras[1][1] / trkheader.voxel_size[1]; + trkheader.image_orientation_patient[5] = + trkheader.vox_to_ras[2][1] / trkheader.voxel_size[1]; + + iorder = strorder.begin(); + + for (vector::const_iterator idir = dirlist.begin(); + idir != dirlist.end(); idir++) { + string fname; + + if (*inum == 0) { + inum++; + continue; + } + + trkheader.n_count = *inum; + + fname = *idir + TrainTrkFile; + if (!trkwriter.Initialize(fname.c_str(), trkheader)) { + cout << "ERROR: Could not open " << fname << " for reading" << endl; + cout << "ERROR: Error was: " << trkwriter.GetLastErrorMessage() << endl; + exit(1); + } + + cout << "Writing streamlines to " << fname << endl; + + for (int j = *inum; j > 0; j--) { + float *iout, *outpts = new float[istr->size()], + *properties = new float[trkheader.n_properties]; + + if (*ivalid1 && *ivalid2) + properties[0] = 3; + else if (*ivalid2) + properties[0] = 2; + else if (*ivalid1) + properties[0] = 1; + else + properties[0] = 0; + properties[1] = (float) *itrlen; + if (*ivalid1 && *ivalid2) { + properties[2] = (float) iorder->second; + iorder++; + } + else + properties[2] = mNumStrEnds; + + iout = outpts; + // Make .5-based and multiply back by output voxel size + for (vector::const_iterator ipt = istr->begin(); ipt < istr->end(); + ipt += 3) + for (int k = 0; k < 3; k++) { + *iout = (ipt[k] + .5) * trkheader.voxel_size[k]; + iout++; + } + + trkwriter.WriteNextTrack(*ilen, outpts, NULL, properties); + + istr++; + ilen++; + itrlen++; + ivalid1++; + ivalid2++; + } + + trkwriter.Close(); + + inum++; + } + + MatrixFree(&outv2r); +} + // // Print coordinates of all points of a streamline // @@ -4132,7 +4887,7 @@ vector Blood::ComputeAvgCenter(vector &ValueVolumes) { // Write values of input volumes point-wise along streamlines // void Blood::WriteValuesPointwise(vector &ValueVolumes, - const std::string TextFile) { + const string TextFile) { vector valsum(ValueVolumes.size()); vector::iterator ivalsum; ofstream outfile(TextFile, ios::app); diff --git a/trc/blood.h b/trc/blood.h index ae830cf85ad..8cd5172b6b7 100644 --- a/trc/blood.h +++ b/trc/blood.h @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -40,39 +40,52 @@ class Blood { public: - Blood(const std::string TrainListFile, const std::string TrainTrkFile, - const std::string TrainRoi1File, const std::string TrainRoi2File, - const std::string TrainAsegFile, const std::string TrainMaskFile, - float TrainMaskLabel, const std::string ExcludeFile, - const std::vector &TestMaskList, - const std::vector &TestFaList, - const std::string TestAffineXfmFile, - const std::string TestNonlinXfmFile, - const std::string TestNonlinRefFile, - const std::vector &TestBaseXfmList, - const std::string TestBaseMaskFile, - bool UseTruncated, std::vector &NumControls, - bool Debug=false); - Blood(const std::string TrainTrkFile, - const std::string TrainRoi1File, const std::string TrainRoi2File, - bool Debug=false); - ~Blood(); - void SetNumControls(std::vector &NumControls); - void ReadStreamlines(const std::string TrainListFile, const std::string TrainTrkFile, - const std::string TrainRoi1File, const std::string TrainRoi2File, - float TrainMaskLabel, const std::string ExcludeFile); - void ReadAnatomy(const std::string TrainListFile, const std::string TrainAsegFile, - const std::string TrainMaskFile); + Blood(const std::string TrainListFile, const std::string TrainTrkFile, + const std::string TrainRoi1File, const std::string TrainRoi2File, + const std::string TrainAsegFile, const std::string TrainMaskFile, + float TrainMaskLabel, const std::string ExcludeFile, + const std::vector &TestMaskList, + const std::vector &TestFaList, + const std::string TestAffineXfmFile, + const std::string TestNonlinXfmFile, + const std::string TestNonlinRefFile, + const std::vector &TestBaseXfmList, + const std::string TestBaseMaskFile, + bool UseTruncated, bool UseAnatomy, bool UseShape, + std::vector &NumControls, + int NumStrMax=INT_MAX, bool Debug=false); + Blood(const std::string TrainTrkFile, + const std::string TrainRoi1File, const std::string TrainRoi2File, + bool Debug=false); + Blood(const std::string TrainTrkFile, + const std::string RefVolFile, + bool Debug=false); + ~Blood(); + void SetNumControls(std::vector &NumControls); + void ReadStreamlines(const std::string TrainListFile, + const std::string TrainTrkFile, + const std::string TrainRoi1File, + const std::string TrainRoi2File, + float TrainMaskLabel, const std::string ExcludeFile); + void ReadAnatomy(const std::string TrainListFile, + const std::string TrainAsegFile, + const std::string TrainMaskFile); void RemoveLengthOutliers(); + void PrepStreamlines(); void MatchStreamlineEnds(); + void SubsampleStreamlines(); + void MatchTruncatedStreamlines(); void ComputeHistogram(); void ComputePriors(); void FindCenterStreamline(bool CheckOverlap=true, bool CheckDeviation=true, bool CheckFa=true); - void WriteOutputs(const char *OutTrainBase, const char *OutTestBase=NULL); + void WriteOutputs(const std::string OutTrainBase, + const std::string OutTestBase=std::string()); void WriteCenterStreamline(const std::string CenterTrkFile, const std::string RefTrkFile); void WriteEndPoints(const std::string OutBase, MRI *RefVol); + void WriteStreamlines(const std::string TrainListFile, + const std::string TrainTrkFile); void PrintStreamline(int SubjIndex, int LineIndex); std::vector ComputeAvgPath(std::vector &ValueVolumes); std::vector ComputeWeightAvgPath(std::vector &ValueVolumes); @@ -97,14 +110,17 @@ class Blood { mHausStepRatio, mControlStepRatio, mTangentBinSize, mCurvatureBinSize; - const bool mDebug, mUseTruncated; + const bool mDebug, mUseTruncated, mUseAnatomy, mUseShape; + const int mNumStrMax; + bool mHavePresorted; int mNx, mNy, mNz, mNumTrain, mVolume, mNumStr, mLengthMin, mLengthMax, mNumStrEnds, mLengthMinEnds, mLengthMaxEnds, mNumArc, mNumLocal, mNumNear; float mMaskLabel, mDx, mLengthAvg, mLengthAvgEnds; - std::vector mIsInEnd1, mIsInEnd2; + std::vector mIsInEnd1, mIsInEnd2, mIsOutHist, mIsOutDev, mIsOutFa; std::vector mNumLines, mLengths, mMidPoints, mTruncatedLengths, + mDistanceRank, mCenterStreamline, mDirLocal, mDirNear, mNumControls; std::vector mMeanEnd1, mMeanEnd2, mMeanMid, mVarEnd1, mVarEnd2, mVarMid; @@ -136,6 +152,7 @@ class Blood { std::vector mTestBaseReg; MRI *mHistoStr, *mHistoSubj, *mTestBaseMask; + void AllocateHistogram(MRI *RefVol); void ReadExcludedStreamlines(const std::string ExcludeFile); void ComputeStats(); void ComputeStatsEnds(); @@ -145,9 +162,13 @@ class Blood { bool IsInRoi(std::vector::const_iterator Point, MRI *Roi); bool IsInCortex(std::vector::const_iterator Point, MRI *Mask, MRI *Aseg); + void FindOutlierStreamlines(bool CheckOverlap, bool CheckDeviation, + bool CheckFa); + void RankStreamlineDistance(); + void UpdateDistanceRank(); void SetArcSegments(); - void ComputeAnatomyPrior(bool UseTruncated); - void ComputeShapePrior(bool UseTruncated); + void ComputeAnatomyPrior(); + void ComputeShapePrior(); void FindPointsOnStreamline(std::vector &Streamline, int NumPoints); bool FindPointsOnStreamlineLS(std::vector &Streamline, int NumPoints); bool FindPointsOnStreamlineComb(std::vector &Streamline, @@ -171,7 +192,9 @@ class Blood { bool MapPointToNative(std::vector::iterator OutPoint, std::vector::const_iterator InPoint, unsigned int FrameIndex); - void WritePriors(const char *OutBase, bool UseTruncated); + void WriteAnatomyPriors(const std::string OutBase); + void WriteShapePriors(const std::string OutBase); }; #endif + diff --git a/trc/coffin.cxx b/trc/coffin.cxx index 684e69aa979..4359ba83834 100644 --- a/trc/coffin.cxx +++ b/trc/coffin.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011-2016 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -18,12 +18,8 @@ * */ - #include -#include -#include - using namespace std; const unsigned int Aeon::mDiffStep = 3; @@ -80,19 +76,17 @@ void Aeon::SetPathMap(unsigned int PathIndex) { // // Read data specific to a single time point // -void Aeon::ReadData(const std::string RootDir, const std::string DwiFile, - const std::string GradientFile, const std::string BvalueFile, - const std::string MaskFile, const std::string BedpostDir, +void Aeon::ReadData(const string RootDir, const string DwiFile, + const string GradientFile, const string BvalueFile, + const string MaskFile, const string BedpostDir, const int NumTract, const float FminPath, - const std::string BaseXfmFile) { - string dwifile, gradfile, bvalfile, maskfile, bpdir; - std::string fname; + const string BaseXfmFile) { + string dwifile, gradfile, bvalfile, maskfile, bpdir, fname; MRI *dwi, *phi[NumTract], *theta[NumTract], *f[NumTract], *v0[NumTract], *f0[NumTract], *d0; - if (!RootDir.empty()) { + if (!RootDir.empty()) mRootDir = RootDir + "/"; - } dwifile = mRootDir + DwiFile; gradfile = mRootDir + GradientFile; @@ -125,31 +119,31 @@ void Aeon::ReadData(const std::string RootDir, const std::string DwiFile, // Read parameter samples from BEDPOST directory cout << "Loading BEDPOST parameter samples from " << bpdir << endl; for (int itract = 0; itract < NumTract; itract++) { - fname = bpdir + "/merged_ph" + std::to_string(itract+1) + "samples.nii.gz"; + fname = bpdir + "/merged_ph" + to_string(itract+1) + "samples.nii.gz"; phi[itract] = MRIread(fname.c_str()); if (!phi[itract]) { cout << "ERROR: Could not read " << fname << endl; exit(1); } - fname = bpdir + "/merged_th" + std::to_string(itract+1) + "samples.nii.gz"; + fname = bpdir + "/merged_th" + to_string(itract+1) + "samples.nii.gz"; theta[itract] = MRIread(fname.c_str()); if (!theta[itract]) { cout << "ERROR: Could not read " << fname << endl; exit(1); } - fname = bpdir + "/merged_f" + std::to_string(itract+1) + "samples.nii.gz"; + fname = bpdir + "/merged_f" + to_string(itract+1) + "samples.nii.gz"; f[itract] = MRIread(fname.c_str()); if (!f[itract]) { cout << "ERROR: Could not read " << fname << endl; exit(1); } - fname = bpdir + "/dyads" + std::to_string(itract+1) + ".nii.gz"; + fname = bpdir + "/dyads" + to_string(itract+1) + ".nii.gz"; v0[itract] = MRIread(fname.c_str()); if (!v0[itract]) { cout << "ERROR: Could not read " << fname << endl; exit(1); } - fname = bpdir + "/mean_f" + std::to_string(itract+1) + "samples.nii.gz"; + fname = bpdir + "/mean_f" + to_string(itract+1) + "samples.nii.gz"; f0[itract] = MRIread(fname.c_str()); if (!f0[itract]) { cout << "ERROR: Could not read " << fname << endl; @@ -165,8 +159,7 @@ void Aeon::ReadData(const std::string RootDir, const std::string DwiFile, } // Initialize voxel-wise diffusion model - Bite::SetStatic(gradfile.c_str(), bvalfile.c_str(), - NumTract, phi[0]->nframes, FminPath); + Bite::SetStatic(gradfile, bvalfile, NumTract, phi[0]->nframes, FminPath); if (Bite::GetNumDir() != dwi->nframes) { cout << "ERROR: Dimensions of " << bvalfile << " and " << dwifile @@ -224,7 +217,7 @@ void Aeon::ReadData(const std::string RootDir, const std::string DwiFile, << endl; exit(1); } - mBaseReg.ReadXfm(regfile.c_str(), mBaseMask, mMask); + mBaseReg.ReadXfm(regfile, mBaseMask, mMask); } } @@ -261,7 +254,7 @@ void Aeon::FreeMask() { // // Set this time point's output directory for the current pathway // -void Aeon::SetOutputDir(const std::string OutDir) { +void Aeon::SetOutputDir(const string OutDir) { string cmdline("mkdir -p "); mOutDir = mRootDir + OutDir; @@ -1060,33 +1053,33 @@ double Aeon::GetDataFit() const { // // The main container // -Coffin::Coffin(const std::string OutDir, vector InDirList, - const std::string DwiFile, - const std::string GradientFile, const std::string BvalueFile, - const std::string MaskFile, const std::string BedpostDir, +Coffin::Coffin(const string OutDir, vector InDirList, + const string DwiFile, + const string GradientFile, const string BvalueFile, + const string MaskFile, const string BedpostDir, const int NumTract, const float FminPath, - const std::string BaseXfmFile, const std::string BaseMaskFile, - const std::string InitFile, - const std::string RoiFile1, const std::string RoiFile2, - const std::string RoiMeshFile1, const std::string RoiMeshFile2, - const std::string RoiRefFile1, const std::string RoiRefFile2, - const std::string XyzPriorFile0, const std::string XyzPriorFile1, - const std::string TangPriorFile, const std::string CurvPriorFile, - const std::string NeighPriorFile, const std::string NeighIdFile, + const string BaseXfmFile, const string BaseMaskFile, + const string InitFile, + const string RoiFile1, const string RoiFile2, + const string RoiMeshFile1, const string RoiMeshFile2, + const string RoiRefFile1, const string RoiRefFile2, + const string XyzPriorFile0, const string XyzPriorFile1, + const string TangPriorFile, const string CurvPriorFile, + const string NeighPriorFile, const string NeighIdFile, const int NeighPriorSet, - const std::string LocalPriorFile, const std::string LocalIdFile, + const string LocalPriorFile, const string LocalIdFile, const int LocalPriorSet, - const vector AsegList, - const std::string AffineXfmFile, const std::string NonlinXfmFile, + const vectorAsegList, + const string AffineXfmFile, const string NonlinXfmFile, const int NumBurnIn, const int NumSample, const int KeepSampleNth, const int UpdatePropNth, - const std::string PropStdFile, + const string PropStdFile, const bool Debug) : mDebug(Debug), mPriorSetLocal(LocalPriorSet), mPriorSetNear(NeighPriorSet), mMask(0), mRoi1(0), mRoi2(0), mXyzPrior0(0), mXyzPrior1(0) { - vector::const_iterator idir; + vector::const_iterator idir; MRI *atlasref; ostringstream infostr; @@ -1109,16 +1102,16 @@ Coffin::Coffin(const std::string OutDir, vector InDirList, if (!BaseMaskFile.empty()) infostr << "Base mask: " << BaseMaskFile << endl; if (!AffineXfmFile.empty()) - infostr << (!BaseMaskFile.empty()?"Base":"DWI") + infostr << (BaseMaskFile.empty()?"DWI":"Base") << "-to-atlas affine registration: " << AffineXfmFile << endl; if (!NonlinXfmFile.empty()) - infostr << (!BaseMaskFile.empty()?"Base":"DWI") + infostr << (BaseMaskFile.empty()?"DWI":"Base") << "-to-atlas nonlinear registration: " << NonlinXfmFile << endl; if (!AsegList.empty()) { infostr << "Segmentation map: "; - for (auto ifile = AsegList.begin(); ifile < AsegList.end(); ifile++) { + for (vector::const_iterator ifile = AsegList.begin(); + ifile < AsegList.end(); ifile++) infostr << " " << *ifile; - } infostr << endl; } mInfoGeneral = infostr.str(); @@ -1139,7 +1132,7 @@ Coffin::Coffin(const std::string OutDir, vector InDirList, // Read diffusion data, anatomical segmentation, and transform to atlas // for each time point if (InDirList.empty()) - InDirList.push_back(0); + InDirList.push_back(string()); mDwi.resize(InDirList.size()); idir = InDirList.begin(); @@ -1206,17 +1199,14 @@ Coffin::Coffin(const std::string OutDir, vector InDirList, // Read DWI-to-atlas registration #ifndef NO_CVS_UP_IN_HERE if (!NonlinXfmFile.empty()) { - mAffineReg.ReadXfm(AffineXfmFile.c_str(), mMask, 0); - mNonlinReg.ReadXfm(NonlinXfmFile.c_str(), atlasref); - } else { -#endif - if (!AffineXfmFile.empty()) { - mAffineReg.ReadXfm(AffineXfmFile.c_str(), mMask, atlasref); - } -#ifndef NO_CVS_UP_IN_HERE + mAffineReg.ReadXfm(AffineXfmFile, mMask, atlasref); + mNonlinReg.ReadXfm(NonlinXfmFile, atlasref); } + else #endif - + if (!AffineXfmFile.empty()) + mAffineReg.ReadXfm(AffineXfmFile, mMask, atlasref); + /* vector pt(3); pt[0] = 75; pt[1] = 55; pt[2] = 51; @@ -1231,7 +1221,8 @@ exit(1); MRIfree(&atlasref); // Read segmentation map - for (auto ifile = AsegList.begin(); ifile < AsegList.end(); ifile++) { + for (vector::const_iterator ifile = AsegList.begin(); + ifile < AsegList.end(); ifile++) { MRI *aseg = 0; cout << "Loading segmentation map from " << *ifile << endl; @@ -1283,7 +1274,7 @@ Coffin::~Coffin() { // // Set output directory for each time point // -void Coffin::SetOutputDir(const std::string OutDir) { +void Coffin::SetOutputDir(const string OutDir) { for (vector::iterator idwi = mDwi.begin(); idwi < mDwi.end(); idwi++) idwi->SetOutputDir(OutDir); @@ -1293,14 +1284,14 @@ void Coffin::SetOutputDir(const std::string OutDir) { // // Set atlas-derived information specific to a given pathway // -void Coffin::SetPathway(const std::string InitFile, - const std::string RoiFile1, const std::string RoiFile2, - const std::string RoiMeshFile1, const std::string RoiMeshFile2, - const std::string RoiRefFile1, const std::string RoiRefFile2, - const std::string XyzPriorFile0, const std::string XyzPriorFile1, - const std::string TangPriorFile, const std::string CurvPriorFile, - const std::string NeighPriorFile, const std::string NeighIdFile, - const std::string LocalPriorFile, const std::string LocalIdFile) { +void Coffin::SetPathway(const string InitFile, + const string RoiFile1, const string RoiFile2, + const string RoiMeshFile1, const string RoiMeshFile2, + const string RoiRefFile1, const string RoiRefFile2, + const string XyzPriorFile0, const string XyzPriorFile1, + const string TangPriorFile, const string CurvPriorFile, + const string NeighPriorFile, const string NeighIdFile, + const string LocalPriorFile, const string LocalIdFile) { int dirs[45] = { 0, 0, 0, 1, 0, 0, -1, 0, 0, @@ -1365,9 +1356,8 @@ void Coffin::SetPathway(const std::string InitFile, // Read end ROI if (!RoiFile2.empty()) { - if (mRoi2) { + if (mRoi2) MRIfree(&mRoi2); - } cout << "Loading end ROI from " << RoiFile2 << endl; mRoi2 = MRIread(RoiFile2.c_str()); @@ -1397,10 +1387,9 @@ void Coffin::SetPathway(const std::string InitFile, } // Read spatial path priors - if ((!XyzPriorFile0.empty()) && (!XyzPriorFile1.empty())) { - if (mXyzPrior0) { + if (!(XyzPriorFile0.empty() || XyzPriorFile1.empty())) { + if (mXyzPrior0) MRIfree(&mXyzPrior0); - } cout << "Loading spatial path prior from " << XyzPriorFile0 << endl; mXyzPrior0 = MRIread(XyzPriorFile0.c_str()); @@ -1409,9 +1398,8 @@ void Coffin::SetPathway(const std::string InitFile, exit(1); } - if (mXyzPrior1) { + if (mXyzPrior1) MRIfree(&mXyzPrior1); - } cout << "Loading spatial path prior from " << XyzPriorFile1 << endl; mXyzPrior1 = MRIread(XyzPriorFile1.c_str()); @@ -1438,7 +1426,7 @@ void Coffin::SetPathway(const std::string InitFile, cout << "Loading tangent prior from " << TangPriorFile << endl; - prfile.open(TangPriorFile, ios::in); + prfile.open(TangPriorFile.c_str(), ios::in); if (!prfile) { cout << "ERROR: Could not open " << TangPriorFile << endl; exit(1); @@ -1507,7 +1495,7 @@ void Coffin::SetPathway(const std::string InitFile, } // Read neighbor aseg priors - if ((!NeighPriorFile.empty()) && (!NeighIdFile.empty())) { + if (!(NeighPriorFile.empty() || NeighIdFile.empty())) { mPriorNear.clear(); mIdsNear.clear(); mDirNear.clear(); @@ -1521,31 +1509,25 @@ void Coffin::SetPathway(const std::string InitFile, for (vector::const_iterator idir = mDirNear.begin(); idir < mDirNear.end(); idir += 3) { const int idx = idir[0], idy = idir[1], idz = idir[2]; - std::stringstream prname, idname; + char prname[PATH_MAX], idname[PATH_MAX]; string prline, idline; ifstream prfile, idfile; - prname << NeighPriorFile << '_' - << idx << '_' - << idy << '_' - << idz << ".txt"; - idname << NeighIdFile << '_' - << idx << '_' - << idy << '_' - << idz << ".txt"; + sprintf(prname, "%s_%d_%d_%d.txt", NeighPriorFile.c_str(), idx, idy, idz); + sprintf(idname, "%s_%d_%d_%d.txt", NeighIdFile.c_str(), idx, idy, idz); - cout << "Loading nearest neighbor prior from " << prname.str() - << " with label IDs from " << idname.str() << endl; + cout << "Loading nearest neighbor prior from " << prname + << " with label IDs from " << idname << endl; - prfile.open(prname.str(), ios::in); + prfile.open(prname, ios::in); if (!prfile) { - cout << "ERROR: Could not open " << prname.str() << endl; + cout << "ERROR: Could not open " << prname << endl; exit(1); } - idfile.open(idname.str(), ios::in); + idfile.open(idname, ios::in); if (!idfile) { - cout << "ERROR: Could not open " << idname.str() << endl; + cout << "ERROR: Could not open " << idname << endl; exit(1); } @@ -1564,8 +1546,8 @@ void Coffin::SetPathway(const std::string InitFile, if (prior.size() != idlist.size() + 1) { cout << "ERROR: Line length mismatch between " - << prname.str() << " (" << prline << ") and " - << idname.str() << " (" << idline << ")" << endl; + << prname << " (" << prline << ") and " + << idname << " (" << idline << ")" << endl; exit(1); } @@ -1593,7 +1575,7 @@ void Coffin::SetPathway(const std::string InitFile, } // Read local aseg priors - if ((!LocalPriorFile.empty()) && (!LocalIdFile.empty())) { + if (!(LocalPriorFile.empty() || LocalIdFile.empty())) { mPriorLocal.clear(); mIdsLocal.clear(); mDirLocal.clear(); @@ -1609,25 +1591,25 @@ void Coffin::SetPathway(const std::string InitFile, for (vector::const_iterator idir = mDirLocal.begin(); idir < mDirLocal.end(); idir += 3) { const int idx = idir[0], idy = idir[1], idz = idir[2]; - std::stringstream prname, idname; + char prname[PATH_MAX], idname[PATH_MAX]; string prline, idline; ifstream prfile, idfile; - prname << LocalPriorFile << "_" << idx << "_" << idy << '_' << idz << ".txt"; - idname << LocalIdFile << '_' << idx << "_" << idy << '_' << idz << ".txt"; + sprintf(prname, "%s_%d_%d_%d.txt", LocalPriorFile.c_str(), idx, idy, idz); + sprintf(idname, "%s_%d_%d_%d.txt", LocalIdFile.c_str(), idx, idy, idz); - cout << "Loading local prior from " << prname.str() - << " with label IDs from " << idname.str() << endl; + cout << "Loading local prior from " << prname + << " with label IDs from " << idname << endl; - prfile.open(prname.str(), ios::in); + prfile.open(prname, ios::in); if (!prfile) { - cout << "ERROR: Could not open " << prname.str() << endl; + cout << "ERROR: Could not open " << prname << endl; exit(1); } - idfile.open(idname.str(), ios::in); + idfile.open(idname, ios::in); if (!idfile) { - cout << "ERROR: Could not open " << idname.str() << endl; + cout << "ERROR: Could not open " << idname << endl; exit(1); } @@ -1638,18 +1620,16 @@ void Coffin::SetPathway(const std::string InitFile, vector prior; istringstream prstr(prline), idstr(idline); - while (prstr >> pr) { + while (prstr >> pr) prior.push_back(pr); - } - while (idstr >> id) { + while (idstr >> id) idlist.push_back(id); - } if (prior.size() != idlist.size() + 1) { cout << "ERROR: Line length mismatch between " - << prname.str() << " (" << prline << ") and " - << idname.str() << " (" << idline << ")" << endl; + << prname << " (" << prline << ") and " + << idname << " (" << idline << ")" << endl; exit(1); } @@ -1661,9 +1641,9 @@ void Coffin::SetPathway(const std::string InitFile, idfile.close(); } - if (mNumArc == 0) { + if (mNumArc == 0) mNumArc = (int) (mPriorLocal.size() / mPriorSetLocal); - } else if (mNumArc != (int) (mPriorLocal.size() / mPriorSetLocal)) { + else if (mNumArc != (int) (mPriorLocal.size() / mPriorSetLocal)) { cout << "ERROR: Mismatch between the numbers of arc segments in "; if (!TangPriorFile.empty()) cout << TangPriorFile @@ -1686,7 +1666,7 @@ void Coffin::SetPathway(const std::string InitFile, // void Coffin::SetMcmcParameters(const int NumBurnIn, const int NumSample, const int KeepSampleNth, const int UpdatePropNth, - const std::string PropStdFile) { + const string PropStdFile) { ostringstream infostr; // Save input info for logging @@ -1694,9 +1674,8 @@ void Coffin::SetMcmcParameters(const int NumBurnIn, const int NumSample, << "Number of post-burn-in samples: " << NumSample << endl << "Keep every: " << KeepSampleNth << "-th sample" << endl << "Update proposal every: " << UpdatePropNth << "-th sample" << endl; - if (!PropStdFile.empty()) { + if (!PropStdFile.empty()) infostr << "Initial proposal SD file: " << PropStdFile << endl; - } mInfoMcmc = infostr.str(); // Set sampling parameters @@ -1717,7 +1696,7 @@ void Coffin::SetMcmcParameters(const int NumBurnIn, const int NumSample, // // Read initial control points // -void Coffin::ReadControlPoints(const std::string ControlPointFile) { +void Coffin::ReadControlPoints(const string ControlPointFile) { float coord; ifstream infile(ControlPointFile, ios::in); @@ -1931,7 +1910,7 @@ void Coffin::ReadControlPoints(const std::string ControlPointFile) { // // Read initial proposal standard deviations for control point perturbations // -void Coffin::ReadProposalStds(const std::string PropStdFile) { +void Coffin::ReadProposalStds(const string PropStdFile) { mProposalStdInit.clear(); if (!PropStdFile.empty()) { @@ -1954,9 +1933,8 @@ void Coffin::ReadProposalStds(const std::string PropStdFile) { istd = mProposalStdInit.begin(); copy(mResolution.begin(), mResolution.end(), istd); //x5.0 - for (istd += 3; istd < mProposalStdInit.end() - 3; istd +=3) { + for (istd += 3; istd < mProposalStdInit.end() - 3; istd +=3) copy(mResolution.begin(), mResolution.end(), istd); //x1.0 - } copy(mResolution.begin(), mResolution.end(), istd); //x5.0 } } @@ -1966,11 +1944,11 @@ void Coffin::ReadProposalStds(const std::string PropStdFile) { // bool Coffin::RunMcmcFull() { int iprop, ikeep; - std::string fname; + char fname[PATH_MAX]; string cmdline; // Open log file in first time point's output directory - fname = mOutDir + "/log.txt"; + sprintf(fname, "%s/log.txt", mOutDir.c_str()); mLog.open(fname, ios::out | ios::app); if (!mLog) { cout << "ERROR: Could not open " << fname << " for writing" << endl; @@ -1989,8 +1967,8 @@ bool Coffin::RunMcmcFull() { } if (mDebug) { - fname = mOutDir + "/Finit.nii.gz"; - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Finit.nii.gz", mOutDir.c_str()); + mSpline.WriteVolume(string(fname), true); } cout << "Running MCMC burn-in jumps" << endl; @@ -2002,26 +1980,18 @@ bool Coffin::RunMcmcFull() { UpdateAcceptanceRateFull(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Faccept_b" - << std::setw(5) << std::setfill('0') << mNumBurnIn-ijump+1 - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Faccept_b%05d.nii.gz", + mOutDir.c_str(), mNumBurnIn-ijump+1); + mSpline.WriteVolume(string(fname), true); } } else { // Reject new path UpdateRejectionRateFull(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Freject_b" - << std::setw(5) << std::setfill('0') << mNumBurnIn-ijump+1 - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Freject_b%05d.nii.gz", + mOutDir.c_str(), mNumBurnIn-ijump+1); + mSpline.WriteVolume(string(fname), true); } } @@ -2046,13 +2016,9 @@ bool Coffin::RunMcmcFull() { UpdateAcceptanceRateFull(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Faccept_" - << std::setw(5) << std::setfill('0') << mNumSample-ijump+1 - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Faccept_%05d.nii.gz", + mOutDir.c_str(), mNumSample-ijump+1); + mSpline.WriteVolume(string(fname), true); } } else { // Reject new path @@ -2060,13 +2026,9 @@ bool Coffin::RunMcmcFull() { UpdateRejectionRateFull(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Freject_" - << std::setw(5) << std::setfill('0') << mNumSample-ijump+1 - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Freject_%05d.nii.gz", + mOutDir.c_str(), mNumSample-ijump+1); + mSpline.WriteVolume(string(fname), true); } } @@ -2109,13 +2071,13 @@ bool Coffin::RunMcmcFull() { // bool Coffin::RunMcmcSingle() { int iprop, ikeep; - std::string fname; + char fname[PATH_MAX]; string cmdline; vector cptorder(mNumControl); vector::const_iterator icpt; // Open log file in first time point's output directory - fname = mOutDir + "/log.txt"; + sprintf(fname, "%s/log.txt", mOutDir.c_str()); mLog.open(fname, ios::out | ios::app); if (!mLog) { cout << "ERROR: Could not open " << fname << " for writing" << endl; @@ -2134,8 +2096,8 @@ bool Coffin::RunMcmcSingle() { } if (mDebug) { - fname = mOutDir + "/Finit.nii.gz"; - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Finit.nii.gz", mOutDir.c_str()); + mSpline.WriteVolume(string(fname), true); } cout << "Running MCMC burn-in jumps" << endl; @@ -2143,9 +2105,8 @@ bool Coffin::RunMcmcSingle() { iprop = 1; for (int ijump = mNumBurnIn; ijump > 0; ijump--) { // Perturb control points in random order - for (int k = 0; k < mNumControl; k++) { + for (int k = 0; k < mNumControl; k++) cptorder[k] = k; - } random_shuffle(cptorder.begin(), cptorder.end()); fill(mRejectControl.begin(), mRejectControl.end(), false); @@ -2162,30 +2123,18 @@ bool Coffin::RunMcmcSingle() { UpdatePath(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Faccept_b" - << std::setw(5) << std::setfill('0') << mNumBurnIn-ijump+1 - << '_' - << *icpt - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Faccept_b%05d_%d.nii.gz", + mOutDir.c_str(), mNumBurnIn-ijump+1, *icpt); + mSpline.WriteVolume(string(fname), true); } } else { // Reject point mRejectControl[*icpt] = true; if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Freject_b" - << std::setw(5) << std::setfill('0') << mNumBurnIn-ijump+1 - << '_' - << *icpt - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Freject_b%05d_%d.nii.gz", + mOutDir.c_str(), mNumBurnIn-ijump+1, *icpt); + mSpline.WriteVolume(string(fname), true); } } } @@ -2227,14 +2176,9 @@ bool Coffin::RunMcmcSingle() { UpdatePath(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Faccept_" - << std::setw(5) << std::setfill('0') << mNumSample-ijump+1 - << '_' - << *icpt; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Faccept_%05d_%d.nii.gz", + mOutDir.c_str(), mNumSample-ijump+1, *icpt); + mSpline.WriteVolume(string(fname), true); } } else { // Reject point @@ -2242,14 +2186,9 @@ bool Coffin::RunMcmcSingle() { mRejectControl[*icpt] = true; if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Freject_" - << std::setw(5) << std::setfill('0') << mNumSample-ijump+1 - << '_' - << *icpt; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Freject_%05d_%d.nii.gz", + mOutDir.c_str(), mNumSample-ijump+1, *icpt); + mSpline.WriteVolume(string(fname), true); } } } @@ -2525,20 +2464,16 @@ bool Coffin::InitializeFixOffWhite(int FailSegment) { int failseg = FailSegment, perturbfirst = failseg, perturblast = (failseg == mNumControl-1) ? failseg : failseg+1; - std::string fname; + char fname[PATH_MAX]; vector controlorig(mControlPoints); // Set proposal standard deviations to a conservative value for this - if (mMaxTryWhite > 0) { + if (mMaxTryWhite > 0) for (vector::iterator istd = mProposalStd.begin(); - istd < mProposalStd.end(); istd += 3) { - for (int k = 0; k < 3; k++) { - if (istd[k] > mResolution[k]) { + istd < mProposalStd.end(); istd += 3) + for (int k = 0; k < 3; k++) + if (istd[k] > mResolution[k]) istd[k] = mResolution[k]; - } - } - } - } // Perturb control points to find a valid initial path for (unsigned int itry = 0; itry < mMaxTryWhite; itry++) { @@ -2578,23 +2513,16 @@ bool Coffin::InitializeFixOffWhite(int FailSegment) { improved = ( (noffnew / (float) ntotnew) < (noff / (float) ntot) && AcceptPath(true) ); } - else { + else improved = success; - } if (success || improved) { // Accept point UpdatePath(); if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Faccept_f" - << std::setw(5) << std::setfill('0') << itry+1 - << '_' - << icpt - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Faccept_f%05d_%d.nii.gz", + mOutDir.c_str(), itry+1, icpt); + mSpline.WriteVolume(string(fname), true); } if (success) @@ -2616,15 +2544,9 @@ bool Coffin::InitializeFixOffWhite(int FailSegment) { mRejectControl[icpt] = true; if (mDebug) { - std::stringstream tmp; - tmp << mOutDir << '/' - << "Freject_f" - << std::setw(5) << std::setfill('0') << itry+1 - << '_' - << icpt - << ".nii.gz"; - fname = tmp.str(); - mSpline.WriteVolume(fname.c_str(), true); + sprintf(fname, "%s/Freject_f%05d_%d.nii.gz", + mOutDir.c_str(), itry+1, icpt); + mSpline.WriteVolume(string(fname), true); } } } @@ -2756,12 +2678,11 @@ bool Coffin::ProposePathFull() { if (!IsInMask(cpoint)) { *isrej = true; - if (mDebug) { + if (mDebug) mLog << "Reject due to control point " << isrej - mRejectControl.begin() << " off mask at " << cpoint[0] << " " << cpoint[1] << " " << cpoint[2] << endl; - } - LogObjectiveNaN(0); + LogObjectiveNaN(0); } cpoint += 3; diff --git a/trc/coffin.h b/trc/coffin.h index 89a1a10d1d8..f5e52fdafbd 100644 --- a/trc/coffin.h +++ b/trc/coffin.h @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011-2016 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -48,11 +48,11 @@ class Aeon { // One point in time static void SavePathPriors(std::vector &Priors); static void SaveBasePath(std::vector &PathPoints); static void SetPathMap(unsigned int PathIndex); - void ReadData(const std::string RootDir, const std::string DwiFile, - const std::string GradientFile, const std::string BvalueFile, - const std::string MaskFile, const std::string BedpostDir, + void ReadData(const string RootDir, const string DwiFile, + const string GradientFile, const string BvalueFile, + const string MaskFile, const string BedpostDir, const int NumTract, const float FminPath, - const std::string BaseXfmFile); + const string BaseXfmFile); MRI *GetMask() const; MRI *GetBaseMask() const; float GetDx() const; @@ -60,7 +60,7 @@ class Aeon { // One point in time float GetDz() const; unsigned int GetNumSample() const; void FreeMask(); - void SetOutputDir(const std::string OutDir); + void SetOutputDir(const string OutDir); const string &GetOutputDir() const; void ClearPath(); bool MapPathFromBase(Spline &BaseSpline); @@ -133,42 +133,42 @@ class Aeon { // One point in time }; class Coffin { // The main container - public: - Coffin(const std::string OutDir, std::vector InDirList, - const std::string DwiFile, - const std::string GradientFile, const std::string BvalueFile, - const std::string MaskFile, const std::string BedpostDir, - const int NumTract, const float FminPath, - const std::string BaseXfmFile, const std::string BaseMaskFile, - const std::string InitFile, - const std::string RoiFile1, const std::string RoiFile2, - const std::string RoiMeshFile1, const std::string RoiMeshFile2, - const std::string RoiRefFile1, const std::string RoiRefFile2, - const std::string XyzPriorFile0, const std::string XyzPriorFile1, - const std::string angPriorFile, const std::string CurvPriorFile, - const std::string NeighPriorFile, const std::string NeighIdFile, - const int NeighPriorSet, - const std::string LocalPriorFile, const std::string LocalIdFile, - const int LocalPriorSet, - const std::vector AsegList, - const std::string AffineXfmFile, const std::string NonlinXfmFile, - const int NumBurnIn, const int NumSample, - const int KeepSampleNth, const int UpdatePropNth, - const std::string PropStdFile, - const bool Debug=false); + public: + Coffin(const string OutDir, std::vector InDirList, + const string DwiFile, + const string GradientFile, const string BvalueFile, + const string MaskFile, const string BedpostDir, + const int NumTract, const float FminPath, + const string BaseXfmFile, const string BaseMaskFile, + const string InitFile, + const string RoiFile1, const string RoiFile2, + const string RoiMeshFile1, const string RoiMeshFile2, + const string RoiRefFile1, const string RoiRefFile2, + const string XyzPriorFile0, const string XyzPriorFile1, + const string TangPriorFile, const string CurvPriorFile, + const string NeighPriorFile, const string NeighIdFile, + const int NeighPriorSet, + const string LocalPriorFile, const string LocalIdFile, + const int LocalPriorSet, + const std::vectorAsegList, + const string AffineXfmFile, const string NonlinXfmFile, + const int NumBurnIn, const int NumSample, + const int KeepSampleNth, const int UpdatePropNth, + const string PropStdFile, + const bool Debug=false); ~Coffin(); - void SetOutputDir(const std::string OutDir); - void SetPathway(const std::string InitFile, - const std::string RoiFile1, const std::string RoiFile2, - const std::string RoiMeshFile1, const std::string RoiMeshFile2, - const std::string RoiRefFile1, const std::string RoiRefFile2, - const std::string XyzPriorFile0, const std::string XyzPriorFile1, - const std::string TangPriorFile, const std::string CurvPriorFile, - const std::string NeighPriorFile, const std::string NeighIdFile, - const std::string LocalPriorFile, const std::string LocalIdFile); + void SetOutputDir(const string OutDir); + void SetPathway(const string InitFile, + const string RoiFile1, const string RoiFile2, + const string RoiMeshFile1, const string RoiMeshFile2, + const string RoiRefFile1, const string RoiRefFile2, + const string XyzPriorFile0, const string XyzPriorFile1, + const string TangPriorFile, const string CurvPriorFile, + const string NeighPriorFile, const string NeighIdFile, + const string LocalPriorFile, const string LocalIdFile); void SetMcmcParameters(const int NumBurnIn, const int NumSample, const int KeepSampleNth, const int UpdatePropNth, - const std::string PropStdFile); + const string PropStdFile); bool RunMcmcFull(); bool RunMcmcSingle(); void WriteOutputs(); @@ -191,7 +191,7 @@ class Coffin { // The main container mShapePrior, mShapePriorNew, mPosteriorOnPath, mPosteriorOnPathNew, mPosteriorOnPathMap, mPosteriorOffPath, mPosteriorOffPathNew; - std::string mOutDir, mInfoGeneral, mInfoPathway, mInfoMcmc; + string mOutDir, mInfoGeneral, mInfoPathway, mInfoMcmc; std::vector mRejectControl; // [mNumControl] std::vector mAcceptCount, mRejectCount, // [mNumControl] mControlPoints, mControlPointsNew, @@ -217,8 +217,8 @@ class Coffin { // The main container std::vector mAseg; std::vector mDwi; - void ReadControlPoints(const std::string ControlPointFile); - void ReadProposalStds(const std::string PropStdFile); + void ReadControlPoints(const string ControlPointFile); + void ReadProposalStds(const string PropStdFile); bool InitializeMcmc(); bool InitializeFixOffMask(int FailSegment); bool InitializeFixOffWhite(int FailSegment); diff --git a/trc/dmri_forrest.cxx b/trc/dmri_forrest.cxx index be27615dbb6..f7c89f976d7 100644 --- a/trc/dmri_forrest.cxx +++ b/trc/dmri_forrest.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2031 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -63,8 +63,8 @@ int main(int argc, char *argv[]); const char *Progname = "dmri_forrest"; -std::string testDir, trainListFile, maskFile, asegFile, orientFile; -vector tractFileList; +string testDir, trainListFile, maskFile, asegFile, orientFile; +vector tractFileList; struct utsname uts; char *cmdline, cwd[2000]; @@ -101,7 +101,7 @@ int main(int argc, char **argv) { cputimer.reset(); cout << "Reading test subject data..." << endl; - myforrest.ReadTestSubject(testDir.c_str(), maskFile.c_str(), asegFile.c_str(), orientFile.c_str()); + myforrest.ReadTestSubject(testDir, maskFile, asegFile, orientFile); // Get volume dimensions from test subject nx = myforrest.GetNx(); @@ -109,7 +109,7 @@ int main(int argc, char **argv) { nz = myforrest.GetNz(); cout << "Reading training subject data..." << endl; - myforrest.ReadTrainingSubjects(trainListFile.c_str(), maskFile.c_str(), asegFile.c_str(), orientFile.c_str(), + myforrest.ReadTrainingSubjects(trainListFile, maskFile, asegFile, orientFile, tractFileList); // Get total number of training samples @@ -348,20 +348,18 @@ static void dump_options() { cout << "Location of streamline files relative to subject directory:"; - for (vector::const_iterator istr = tractFileList.begin(); + for (vector::const_iterator istr = tractFileList.begin(); istr < tractFileList.end(); istr++) cout << " " << *istr; cout << endl; - if (!asegFile.empty()) { + if (!asegFile.empty()) cout << "Location of aparc+aseg's relative to subject directory: " << asegFile << endl; - } - if (!orientFile.empty()) { + if (!orientFile.empty()) cout << "Location of diffusion orientations relative to subject directory: " << orientFile << endl; - } return; } diff --git a/trc/dmri_group.cxx b/trc/dmri_group.cxx index 676d16a6b3c..0a094c33183 100644 --- a/trc/dmri_group.cxx +++ b/trc/dmri_group.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2013 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -68,7 +68,7 @@ const char *Progname = "dmri_group"; int nSection = 0; -std::string inListFile, outRefFile, outBase; +string inListFile, outRefFile, outBase; struct utsname uts; char *cmdline, cwd[2000]; @@ -97,7 +97,7 @@ int main(int argc, char **argv) { ifstream listfile; ofstream pathfile, pathrasfile; MATRIX *outv2r; - MRI *outref = 0; + MRI *outref = 0, *outvol = 0; nargs = handleVersionOption(argc, argv, "dmri_group"); if (nargs && argc - nargs == 1) exit (0); @@ -187,13 +187,13 @@ int main(int argc, char **argv) { // Fourth input on each line is a nonlinear transform #ifndef NO_CVS_UP_IN_HERE if (inputs.size() > 3) { - affinereg.ReadXfm(inputs[2].c_str(), inref, 0); - nonlinreg.ReadXfm(inputs[3].c_str(), outref); + affinereg.ReadXfm(inputs[2], inref, outref); + nonlinreg.ReadXfm(inputs[3], outref); } else #endif if (inputs.size() > 2) - affinereg.ReadXfm(inputs[2].c_str(), inref, outref); + affinereg.ReadXfm(inputs[2], inref, outref); // Read measures along the path while (getline(infile, measline)) { @@ -368,7 +368,7 @@ int main(int argc, char **argv) { if (0) { // Write points of most representative path to file as RAS coords - filename = string(outBase) + ".median.txt"; + filename = outBase + ".median.txt"; cout << "Writing median path to " << filename << endl; pathrasfile.open(filename.c_str(), ios::out); @@ -585,12 +585,12 @@ if (0) { } // Write points of mean path to file as voxel and RAS coords - filename = string(outBase) + ".coords.mean.txt"; + filename = outBase + ".coords.mean.txt"; cout << "Writing mean path voxel coords to " << filename << endl; pathfile.open(filename.c_str(), ios::out); - filename = string(outBase) + ".path.mean.txt"; + filename = outBase + ".path.mean.txt"; cout << "Writing mean path RAS coords to " << filename << endl; pathrasfile.open(filename.c_str(), ios::out); @@ -619,15 +619,22 @@ if (0) { npt++; } + npt--; + pathfile.close(); pathrasfile.close(); // Write output files + outvol = MRIallocSequence(npt, 1, 1, MRI_FLOAT, subjlist.size()); + if (outref) + MRIcopyHeader(outref, outvol); + ntot = allmeasint[0].size(); for (vector::const_iterator imeas = measlist.begin(); imeas < measlist.end(); imeas++) { - string outname = string(outBase) + "." + *imeas + ".txt"; + int jpt = 0; + string outname = outBase + "." + *imeas + ".txt"; ofstream outfile; cout << "Writing group table to " << outname << endl; @@ -640,8 +647,12 @@ if (0) { outfile << endl; + MRIclear(outvol); + // Write interpolated values of this measure for (unsigned ipt = imeas - measlist.begin(); ipt < ntot; ipt += nmeas) { + int jsubj = 0; + for (iallm = allmeasint.begin(); iallm < allmeasint.end(); iallm++) { vector::const_iterator ival = iallm->begin() + ipt; @@ -649,20 +660,24 @@ if (0) { outfile << "NaN "; else outfile << *ival << " "; + + MRIsetVoxVal(outvol, jpt, 0, 0, jsubj, *ival); + jsubj++; } outfile << endl; + jpt++; } outfile.close(); + + outname = outBase + "." + *imeas + ".nii.gz"; + cout << "Writing group table to " << outname << endl; + MRIwrite(outvol, outname.c_str()); } // Average measures over sections along the path if (nSection > 0) { - char nsec[PATH_MAX]; - - sprintf(nsec, "%dsec", nSection); - darc = (arcmax - arcmin) / nSection; iallm = allmeas.begin(); @@ -715,7 +730,9 @@ if (0) { for (vector::const_iterator imeas = measlist.begin(); imeas < measlist.end(); imeas++) { - string outname = string(outBase) + "." + *imeas + "." + nsec + ".txt"; + string outname = outBase + "." + *imeas + "." + + to_string(nSection) + "sec.txt"; + ofstream outfile; cout << "Writing group table to " << outname << endl; @@ -746,6 +763,7 @@ if (0) { } } + MRIfree(&outvol); if (outref) { MRIfree(&outref); MatrixFree(&outv2r); @@ -824,7 +842,7 @@ static void print_usage(void) << " --ref :" << endl << " Reference volume for output path" << endl << " --out :" << endl - << " Base name of output text files" << endl + << " Base name of output stats files" << endl << endl << "Optional arguments" << endl << " --sec :" << endl @@ -887,6 +905,10 @@ static void dump_options(FILE *fp) { cout << "Base name of output files: " << outBase << endl; cout << "Text file with list of individual inputs: " << inListFile << endl; + if (!outRefFile.empty()) + cout << "Reference volume for output path: " << outRefFile << endl; + if (nSection > 0) + cout << "Number of path sections: " << nSection << endl; return; } diff --git a/trc/dmri_mergepaths.cxx b/trc/dmri_mergepaths.cxx index 2e1a85ae402..36b78ba9e51 100644 --- a/trc/dmri_mergepaths.cxx +++ b/trc/dmri_mergepaths.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -65,8 +65,8 @@ const char *Progname = "dmri_mergepaths"; int nframe = 0; float dispThresh = 0; -std::string inDir, outFile, ctabFile; -std::vector inFile; +string inDir, outFile, ctabFile; +vector inFile; struct utsname uts; char *cmdline, cwd[2000]; @@ -76,7 +76,7 @@ Timer cputimer; /*--------------------------------------------------*/ int main(int argc, char **argv) { int nargs, cputime; - std::string fname; + string fname, pname; MRI *invol = 0, *outvol = 0; nargs = handleVersionOption(argc, argv, "dmri_mergepaths"); @@ -108,14 +108,14 @@ int main(int argc, char **argv) { cout << "Merging volume " << iframe+1 << " of " << nframe << "... " << endl; // Read input volume - if (!inDir.empty()) { - fname = inDir + "/" + inFile.at(iframe); - } else { - fname = inFile.at(iframe); - } + fname = inFile[iframe]; + + if (!inDir.empty()) + fname = inDir + "/" + fname; invol = MRIread(fname.c_str()); + // Copy input volume to output volume series if (invol) { if (!outvol) { // Allocate output 4D volume @@ -127,19 +127,27 @@ int main(int argc, char **argv) { MRIcopyFrame(invol, outvol, 0, iframe); - if (dispThresh > 0) { + if (dispThresh > 0) inmax = (float) MRIfindPercentile(invol, .99, 0); // Robust max - } } + // Set display threshold for current volume outvol->frames[iframe].thresh = dispThresh * inmax; + // Look up pathway name for current volume + pname = inFile[iframe]; + pname = pname.substr(0, pname.rfind("/")); + if (pname.rfind("/") != string::npos) + pname = pname.substr(pname.rfind("/")+1, string::npos); + pname = pname.substr(0, pname.find("_")); + outvol->frames[iframe].label = 0; for (int ict = outvol->ct->nentries; ict > 0; ict--) { CTE *cte = outvol->ct->entries[ict]; - if (cte != NULL && strstr(inFile.at(iframe).c_str(), cte->name)) { + if (cte != NULL && strstr(pname.c_str(), cte->name) + && strlen(pname.c_str()) == strlen(cte->name)) { outvol->frames[iframe].label = ict; strcpy(outvol->frames[iframe].name, cma_label_to_name(ict)); @@ -152,9 +160,9 @@ int main(int argc, char **argv) { } // Write output file - if (outvol) { + if (outvol) MRIwrite(outvol, outFile.c_str()); - } else { + else { cout << "ERROR: could not open any of the input files" << endl; exit(1); } @@ -198,9 +206,8 @@ static int parse_commandline(int argc, char **argv) { if (nargc < 1) CMDargNErr(option,1); nargsused = 0; while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { - inFile.push_back( std::string(pargv[nargsused]) ); + inFile.push_back(pargv[nargsused]); nargsused++; - nframe++; } } else if (!strcmp(option, "--out")) { @@ -280,6 +287,8 @@ static void print_version(void) { /* --------------------------------------------- */ static void check_options(void) { + nframe = inFile.size(); + if(nframe == 0) { printf("ERROR: must specify input volume(s)\n"); exit(1); @@ -310,13 +319,11 @@ static void dump_options(FILE *fp) { fprintf(fp,"machine %s\n",uts.machine); fprintf(fp,"user %s\n",VERuser()); - if (!inDir.empty()) { + if (!inDir.empty()) fprintf(fp, "Input directory: %s\n", inDir.c_str()); - } fprintf(fp, "Input files:"); - for (int k = 0; k < nframe; k++) { + for (int k = 0; k < nframe; k++) fprintf(fp, " %s", inFile[k].c_str()); - } fprintf(fp, "\n"); fprintf(fp, "Output file: %s\n", outFile.c_str()); fprintf(fp, "Color table file: %s\n", ctabFile.c_str()); diff --git a/trc/dmri_motion.cxx b/trc/dmri_motion.cxx index f97f6b4ff49..797fe2ef9f6 100644 --- a/trc/dmri_motion.cxx +++ b/trc/dmri_motion.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2013 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -68,8 +68,8 @@ const char *Progname = "dmri_motion"; float T = 100, D = .001; -vector inDwiList, inBvalList; -std::string inMatFile, outFile, outFrameFile; +string inMatFile, outFile, outFrameFile; +vector inDwiList, inBvalList; MRI *dwi; @@ -616,26 +616,24 @@ static void dump_options() { cout << "Output motion measure file: " << outFile << endl; - if (!outFrameFile.empty()) { + if (!outFrameFile.empty()) cout << "Output frame-by-frame motion measure file: " << outFrameFile << endl; - } - if (!inMatFile.empty()) { + if (!inMatFile.empty()) cout << "Input transform file: " << inMatFile << endl; - } if (!inDwiList.empty()) { cout << "Input DWI file(s):"; - for (auto ifile = inDwiList.begin(); ifile < inDwiList.end(); ifile++) { + for (vector::const_iterator ifile = inDwiList.begin(); + ifile < inDwiList.end(); ifile++) cout << " " << *ifile; - } cout << endl; cout << "Input b-value table(s):"; - for (auto ifile = inBvalList.begin(); ifile < inBvalList.end(); ifile++) { + for (vector::const_iterator ifile = inBvalList.begin(); + ifile < inBvalList.end(); ifile++) cout << " " << *ifile; - } cout << endl; cout << "Low-b image intensity threshold: " << T << endl; diff --git a/trc/dmri_paths.cxx b/trc/dmri_paths.cxx index eb73091d650..f0ff21310c1 100644 --- a/trc/dmri_paths.cxx +++ b/trc/dmri_paths.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -68,9 +68,9 @@ unsigned int nTract = 1, nBurnIn = 5000, nSample = 5000, nKeepSample = 10, nUpdateProp = 40, localPriorSet = 15, neighPriorSet = 14; float fminPath = 0; -std::string dwiFile, gradFile, bvalFile, maskFile, bedpostDir, - baseXfmFile, baseMaskFile, affineXfmFile, nonlinXfmFile; -vector outDir, inDirList, initFile, roiFile1, roiFile2, +string dwiFile, gradFile, bvalFile, maskFile, bedpostDir, + baseXfmFile, baseMaskFile, affineXfmFile, nonlinXfmFile; +vector outDir, inDirList, initFile, roiFile1, roiFile2, roiMeshFile1, roiMeshFile2, roiRefFile1, roiRefFile2, xyzPriorFile0, xyzPriorFile1, tangPriorFile, curvPriorFile, neighPriorFile, neighIdFile, localPriorFile, localIdFile, @@ -83,7 +83,9 @@ Timer cputimer; /*--------------------------------------------------*/ int main(int argc, char **argv) { - bool doxyzprior = true, + bool islabel1 = false, + islabel2 = false, + doxyzprior = true, dotangprior = true, docurvprior = true, doneighprior = true, @@ -122,6 +124,9 @@ int main(int argc, char **argv) { if (localPriorFile.empty()) dolocalprior = false; if (stdPropFile.empty()) dopropinit = false; + islabel1 = (roiFile1[0].find(".label") != string::npos); + islabel2 = (roiFile2[0].find(".label") != string::npos); + Coffin mycoffin(outDir[0], inDirList, dwiFile, gradFile, bvalFile, maskFile, bedpostDir, @@ -129,51 +134,54 @@ int main(int argc, char **argv) { baseXfmFile, baseMaskFile, initFile[0], roiFile1[0], roiFile2[0], - strstr(roiFile1[0].c_str(), ".label") ? roiMeshFile1[ilab1] : std::string(), - strstr(roiFile2[0].c_str(), ".label") ? roiMeshFile2[ilab2] : std::string(), - strstr(roiFile1[0].c_str(), ".label") ? roiRefFile1[ilab1] : std::string(), - strstr(roiFile2[0].c_str(), ".label") ? roiRefFile2[ilab2] : std::string(), - doxyzprior ? xyzPriorFile0[0] : std::string(), - doxyzprior ? xyzPriorFile1[0] : std::string(), - dotangprior ? tangPriorFile[0] : std::string(), - docurvprior ? curvPriorFile[0] : std::string(), - doneighprior ? neighPriorFile[0] : std::string(), - doneighprior ? neighIdFile[0] : std::string(), + islabel1 ? roiMeshFile1[ilab1] : string(), + islabel2 ? roiMeshFile2[ilab2] : string(), + islabel1 ? roiRefFile1[ilab1] : string(), + islabel2 ? roiRefFile2[ilab2] : string(), + doxyzprior ? xyzPriorFile0[0] : string(), + doxyzprior ? xyzPriorFile1[0] : string(), + dotangprior ? tangPriorFile[0] : string(), + docurvprior ? curvPriorFile[0] : string(), + doneighprior ? neighPriorFile[0] : string(), + doneighprior ? neighIdFile[0] : string(), doneighprior ? neighPriorSet : 0, - dolocalprior ? localPriorFile[0] : std::string(), - dolocalprior ? localIdFile[0] : std::string(), + dolocalprior ? localPriorFile[0] : string(), + dolocalprior ? localIdFile[0] : string(), dolocalprior ? localPriorSet : 0, asegList, affineXfmFile, nonlinXfmFile, nBurnIn, nSample, nKeepSample, nUpdateProp, - dopropinit ? stdPropFile[0] : std::string(), + dopropinit ? stdPropFile[0] : string(), debug); - if (strstr(roiFile1[0].c_str(), ".label")) ilab1++; - if (strstr(roiFile2[0].c_str(), ".label")) ilab2++; + if (islabel1) ilab1++; + if (islabel2) ilab2++; for (unsigned int iout = 0; iout < outDir.size(); iout++) { if (iout > 0) { + islabel1 = (roiFile1[iout].find(".label") != string::npos); + islabel2 = (roiFile2[iout].find(".label") != string::npos); + mycoffin.SetOutputDir(outDir[iout]); mycoffin.SetPathway(initFile[iout], - roiFile1[iout], roiFile2[iout], - strstr(roiFile1[iout].c_str(), ".label") ? roiMeshFile1[ilab1] : std::string(), - strstr(roiFile2[iout].c_str(), ".label") ? roiMeshFile2[ilab2] : std::string(), - strstr(roiFile1[iout].c_str(), ".label") ? roiRefFile1[ilab1] : std::string(), - strstr(roiFile2[iout].c_str(), ".label") ? roiRefFile2[ilab2] : std::string(), - doxyzprior ? xyzPriorFile0[iout] : std::string(), - doxyzprior ? xyzPriorFile1[iout] : std::string(), - dotangprior ? tangPriorFile[iout] : std::string(), - docurvprior ? curvPriorFile[iout] : std::string(), - doneighprior ? neighPriorFile[iout] : std::string(), - doneighprior ? neighIdFile[iout] : std::string(), - dolocalprior ? localPriorFile[iout] : std::string(), - dolocalprior ? localIdFile[iout] : std::string()); + roiFile1[iout], roiFile2[iout], + islabel1 ? roiMeshFile1[ilab1] : string(), + islabel2 ? roiMeshFile2[ilab2] : string(), + islabel1 ? roiRefFile1[ilab1] : string(), + islabel2 ? roiRefFile2[ilab2] : string(), + doxyzprior ? xyzPriorFile0[iout] : string(), + doxyzprior ? xyzPriorFile1[iout] : string(), + dotangprior ? tangPriorFile[iout] : string(), + docurvprior ? curvPriorFile[iout] : string(), + doneighprior ? neighPriorFile[iout] : string(), + doneighprior ? neighIdFile[iout] : string(), + dolocalprior ? localPriorFile[iout] : string(), + dolocalprior ? localIdFile[iout] : string()); mycoffin.SetMcmcParameters(nBurnIn, nSample, nKeepSample, nUpdateProp, - dopropinit ? stdPropFile[iout] : std::string()); + dopropinit ? stdPropFile[iout] : string()); - if (strstr(roiFile1.at(iout).c_str(), ".label")) ilab1++; - if (strstr(roiFile2.at(iout).c_str(), ".label")) ilab2++; + if (islabel1) ilab1++; + if (islabel2) ilab2++; } cout << "Processing pathway " << iout+1 << " of " << outDir.size() << "..." @@ -181,11 +189,10 @@ int main(int argc, char **argv) { cputimer.reset(); //if (mycoffin.RunMcmcFull()) - if (mycoffin.RunMcmcSingle()) { + if (mycoffin.RunMcmcSingle()) mycoffin.WriteOutputs(); - } else { + else cout << "ERROR: Pathway reconstruction failed" << endl; - } cputime = cputimer.milliseconds(); printf("Done in %g sec.\n", cputime/1000.0); @@ -284,7 +291,7 @@ static int parse_commandline(int argc, char **argv) { nargsused = 0; while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { roiFile1.push_back(fio_fullpath(pargv[nargsused])); - if(strstr(roiFile1.back().c_str(), ".label")) + if ((roiFile1.end()-1)->find(".label") != string::npos) nlab1++; nargsused++; } @@ -294,7 +301,7 @@ static int parse_commandline(int argc, char **argv) { nargsused = 0; while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { roiFile2.push_back(fio_fullpath(pargv[nargsused])); - if(strstr(roiFile2.back().c_str(), ".label")) + if ((roiFile2.end()-1)->find(".label") != string::npos) nlab2++; nargsused++; } @@ -665,7 +672,7 @@ static void check_options(void) { /* --------------------------------------------- */ static void dump_options() { - vector::const_iterator istr; + vector::const_iterator istr; cout << endl << getVersion() << endl @@ -683,9 +690,8 @@ static void dump_options() { if (!inDirList.empty()) { cout << "Input directory:"; - for (istr = inDirList.begin(); istr < inDirList.end(); istr++) { + for (istr = inDirList.begin(); istr < inDirList.end(); istr++) cout << " " << *istr; - } cout << endl; } @@ -698,76 +704,65 @@ static void dump_options() { << "Tract volume fraction threshold: " << fminPath << endl; cout << "Initial control point file:"; - for (istr = initFile.begin(); istr < initFile.end(); istr++) { + for (istr = initFile.begin(); istr < initFile.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "End ROI 1:"; - for (istr = roiFile1.begin(); istr < roiFile1.end(); istr++) { + for (istr = roiFile1.begin(); istr < roiFile1.end(); istr++) cout << " " << *istr; - } cout << endl; if (nlab1 > 0) { cout << "End ROI 1 mesh:"; - for (istr = roiMeshFile1.begin(); istr < roiMeshFile1.end(); istr++) { + for (istr = roiMeshFile1.begin(); istr < roiMeshFile1.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "End ROI 1 reference volume:"; - for (istr = roiRefFile1.begin(); istr < roiRefFile1.end(); istr++) { + for (istr = roiRefFile1.begin(); istr < roiRefFile1.end(); istr++) cout << " " << *istr; - } cout << endl; } cout << "End ROI 2:"; - for (istr = roiFile2.begin(); istr < roiFile2.end(); istr++) { + for (istr = roiFile2.begin(); istr < roiFile2.end(); istr++) cout << " " << *istr; - } cout << endl; if (nlab2 > 0) { cout << "End ROI 2 mesh:"; - for (istr = roiMeshFile2.begin(); istr < roiMeshFile2.end(); istr++) { + for (istr = roiMeshFile2.begin(); istr < roiMeshFile2.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "End ROI 2 reference volume:"; - for (istr = roiRefFile2.begin(); istr < roiRefFile2.end(); istr++) { + for (istr = roiRefFile2.begin(); istr < roiRefFile2.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!xyzPriorFile0.empty()) { cout << "Spatial prior (off path):"; - for (istr = xyzPriorFile0.begin(); istr < xyzPriorFile0.end(); istr++) { + for (istr = xyzPriorFile0.begin(); istr < xyzPriorFile0.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Spatial prior (on path):"; - for (istr = xyzPriorFile1.begin(); istr < xyzPriorFile1.end(); istr++) { + for (istr = xyzPriorFile1.begin(); istr < xyzPriorFile1.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!neighPriorFile.empty()) { cout << "Neighbor aseg prior:"; - for (istr = neighPriorFile.begin(); istr < neighPriorFile.end(); istr++) { + for (istr = neighPriorFile.begin(); istr < neighPriorFile.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Neighbor aseg label ID list:"; - for (istr = neighIdFile.begin(); istr < neighIdFile.end(); istr++) { + for (istr = neighIdFile.begin(); istr < neighIdFile.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Neighbor aseg prior set: " << neighPriorSet << endl; @@ -775,15 +770,13 @@ static void dump_options() { if (!localPriorFile.empty()) { cout << "Local aseg prior:"; - for (istr = localPriorFile.begin(); istr < localPriorFile.end(); istr++) { + for (istr = localPriorFile.begin(); istr < localPriorFile.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Local aseg label ID list:"; - for (istr = localIdFile.begin(); istr < localIdFile.end(); istr++) { + for (istr = localIdFile.begin(); istr < localIdFile.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Local aseg prior set: " << localPriorSet << endl; @@ -791,19 +784,16 @@ static void dump_options() { if (!asegList.empty()) { cout << "Segmentation map: "; - for (istr = asegList.begin(); istr < asegList.end(); istr++) { + for (istr = asegList.begin(); istr < asegList.end(); istr++) cout << " " << *istr; - } cout << endl; } - if (!affineXfmFile.empty()) { + if (!affineXfmFile.empty()) cout << "DWI-to-atlas affine registration: " << affineXfmFile << endl; - } - if (!nonlinXfmFile.empty()) { + if (!nonlinXfmFile.empty()) cout << "DWI-to-atlas nonlinear registration: " << nonlinXfmFile << endl; - } cout << "Number of burn-in samples: " << nBurnIn << endl << "Number of post-burn-in samples: " << nSample << endl @@ -812,9 +802,8 @@ static void dump_options() { if (!stdPropFile.empty()) { cout << "Initial proposal SD file:"; - for (istr = stdPropFile.begin(); istr < stdPropFile.end(); istr++) { + for (istr = stdPropFile.begin(); istr < stdPropFile.end(); istr++) cout << " " << *istr; - } cout << endl; } diff --git a/trc/dmri_pathstats.cxx b/trc/dmri_pathstats.cxx index 418213ad2b4..2580e95c2b3 100644 --- a/trc/dmri_pathstats.cxx +++ b/trc/dmri_pathstats.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -60,7 +60,7 @@ static void usage_exit(void); static void print_help(void) ; static void print_version(void) ; static void dump_options(FILE *fp); -static void WriteHeader(const std::string OutFile); +static void WriteHeader(const string OutFile); int debug = 0, checkoptsonly = 0; @@ -69,9 +69,10 @@ int main(int argc, char *argv[]) ; const char *Progname = "dmri_pathstats"; float probThresh = .2, faThresh = 0; -char PathMAP[] = "path.map.txt"; -std::string inTrkFile, inRoi1File, inRoi2File, inTrcDir, inVoxFile = std::string(PathMAP), - dtBase, outFile, outVoxFile, outMedianFile, outEndBase, refVolFile, fname; +string inTrkFile, inRoi1File, inRoi2File, + inTrcDir, inVoxFile = "path.map.txt", inXfmFile, dtBase, + outFile, outVoxFile, outMedianFile, outEndBase, refVolFile, fname; +vector measFileList, measNameList; MRI *l1, *l2, *l3, *v1; @@ -85,6 +86,7 @@ int main(int argc, char **argv) { int nargs, cputime, count, volume, lenmin, lenmax, lencent; float lenavg; vector avg, wavg, cavg; + vector measname; vector meas; ofstream fout; @@ -109,37 +111,70 @@ int main(int argc, char **argv) { dump_options(stdout); - printf("Computing statistics on %s...\n", !inTrcDir.empty()?inTrcDir.c_str():inTrkFile.c_str()); + cout << "Computing statistics on " + << (inTrcDir.empty() ? inTrkFile : inTrcDir) << "..." << endl; cputimer.reset(); + // Read microstructural measure volumes + for (vector::const_iterator istr = measFileList.begin(); + istr < measFileList.end(); istr++) + meas.push_back(MRIread((*istr).c_str())); + + for (vector::const_iterator istr = measNameList.begin(); + istr < measNameList.end(); istr++) + measname.push_back(*istr); + + if (meas.size() > 0 && measname.size() == 0) { + int k = 1; + + for (vector::const_iterator imeas = meas.begin(); + imeas < meas.end(); imeas++) { + measname.push_back("Meas" + to_string(k)); + k++; + } + } + if (!dtBase.empty()) { fname = dtBase + "_L1.nii.gz"; l1 = MRIread(fname.c_str()); - fname = dtBase + "_L2.nii.gz"; + fname = dtBase + "_L2.nii.gz"; l2 = MRIread(fname.c_str()); - fname = dtBase + "_L3.nii.gz"; + fname = dtBase + "_L3.nii.gz"; l3 = MRIread(fname.c_str()); - fname = dtBase + "_v1.nii.gz"; + fname = dtBase + "_V1.nii.gz"; v1 = MRIread(fname.c_str()); - fname = dtBase + "_L1.nii.gz"; - meas.push_back(MRIread(fname.c_str())); // Axial diffusivity - fname = dtBase + "_L2.nii.gz"; + fname = dtBase + "_L1.nii.gz"; // Axial diffusivity + meas.push_back(MRIread(fname.c_str())); + measname.push_back("AD"); + fname = dtBase + "_L2.nii.gz"; // Radial diffusivity + meas.push_back(MRIread(fname.c_str())); + MRIadd(l3, *(meas.end()-1), *(meas.end()-1)); + MRIscalarMul(*(meas.end()-1), *(meas.end()-1), .5); + measname.push_back("RD"); + fname = dtBase + "_MD.nii.gz"; // Mean diffusivity meas.push_back(MRIread(fname.c_str())); - MRIadd(l3, meas[1], meas[1]); - MRIscalarMul(meas[1], meas[1], .5); // Radial diffusivity - fname = dtBase + "_MD.nii.gz"; - meas.push_back(MRIread(fname.c_str())); // Mean diffusivity - fname = dtBase + "_FA.nii.gz"; - meas.push_back(MRIread(fname.c_str())); // Fractional anisotropy + measname.push_back("MD"); + fname = dtBase + "_FA.nii.gz"; // Fractional anisotropy + meas.push_back(MRIread(fname.c_str())); + measname.push_back("FA"); } - if (!outVoxFile.c_str()) { + if (!outVoxFile.empty()) { WriteHeader(outVoxFile); ofstream fvox(outVoxFile, ios::app); + fvox << "# pathway start" << endl - << "x y z AD RD MD FA AD_Avg RD_Avg MD_Avg FA_Avg" << endl; + << "x y z"; + for (vector::const_iterator iname = measname.begin(); + iname < measname.end(); iname++) + fvox << " " << *iname; + for (vector::const_iterator iname = measname.begin(); + iname < measname.end(); iname++) + fvox << " " << *iname << "_Avg"; + fvox << endl; + fvox.close(); } @@ -215,20 +250,16 @@ int main(int argc, char **argv) { } } - if (nvox > 0) { - for (iavg = avg.begin(); iavg < avg.end(); iavg++) { + if (nvox > 0) + for (iavg = avg.begin(); iavg < avg.end(); iavg++) *iavg /= nvox; - } - } - if (wtot > 0) { - for (iwavg = wavg.begin(); iwavg < wavg.end(); iwavg++) { + if (wtot > 0) + for (iwavg = wavg.begin(); iwavg < wavg.end(); iwavg++) *iwavg /= wtot; - } - } // Read maximum a posteriori path coordinates - fname = inTrcDir + '/' + inVoxFile; + fname = inTrcDir + "/" + inVoxFile; infile.open(fname, ios::in); if (!infile) { cout << "ERROR: Could not open " << fname << " for reading" << endl; @@ -261,7 +292,7 @@ int main(int argc, char **argv) { lenavg = ( (lenavg > 0) ? (lenavg / (float) lengths.size()) : 0 ); lencent = pathmap.size() / 3; - if (!dtBase.empty()) { + if (!meas.empty()) { vector::iterator iavg; cavg.resize(meas.size()); @@ -412,11 +443,19 @@ int main(int argc, char **argv) { } else { // Deterministic paths // Read .trk file - Blood myblood(inTrkFile, inRoi1File, inRoi2File); + Blood myblood(inTrkFile, + inRoi1File.empty() ? refVolFile : inRoi1File, inRoi2File); + cout << "Computing path histograms" << endl; myblood.ComputeHistogram(); + + cout << "Matching streamline ends" << endl; myblood.MatchStreamlineEnds(); - myblood.FindCenterStreamline(); + + if (!(outVoxFile.empty() && outMedianFile.empty())) { + cout << "Finding median streamline" << endl; + myblood.FindCenterStreamline(); + } // Overall measures count = myblood.GetNumStr(); @@ -426,37 +465,41 @@ int main(int argc, char **argv) { lenavg = myblood.GetLengthAvg(); lencent = myblood.GetLengthCenter(); - if (!dtBase.empty()) { + if (!meas.empty()) { avg = myblood.ComputeAvgPath(meas); wavg = myblood.ComputeWeightAvgPath(meas); cavg = myblood.ComputeAvgCenter(meas); } // Measures by voxel on median streamline - if (!outVoxFile.empty()) { + if (!outVoxFile.empty()) myblood.WriteValuesPointwise(meas, outVoxFile); - } // Save median streamline - if (!outMedianFile.empty()) { + if (!outMedianFile.empty()) myblood.WriteCenterStreamline(outMedianFile, inTrkFile); - } // Save streamline end points if (!outEndBase.empty()) { MRI *refvol; - if (!refVolFile.empty()) { + if (!refVolFile.empty()) refvol = MRIread(refVolFile.c_str()); - } else { - refvol = l1; - } + else + refvol = meas[0]; myblood.WriteEndPoints(outEndBase, refvol); + + if (!refVolFile.empty()) + MRIfree(&refvol); } } if (!outFile.empty()) { + vector::const_iterator iavg = avg.begin(), iwavg = wavg.begin(), + icavg = cavg.begin(); + vector::const_iterator iname = measname.begin(); + WriteHeader(outFile); fout.open(outFile, ios::app); @@ -468,19 +511,15 @@ int main(int argc, char **argv) { << "Len_Avg " << lenavg << endl << "Len_Center " << lencent << endl; - if (!dtBase.empty()) - fout << "AD_Avg " << avg[0] << endl - << "AD_Avg_Weight " << wavg[0] << endl - << "AD_Avg_Center " << cavg[0] << endl - << "RD_Avg " << avg[1] << endl - << "RD_Avg_Weight " << wavg[1] << endl - << "RD_Avg_Center " << cavg[1] << endl - << "MD_Avg " << avg[2] << endl - << "MD_Avg_Weight " << wavg[2] << endl - << "MD_Avg_Center " << cavg[2] << endl - << "FA_Avg " << avg[3] << endl - << "FA_Avg_Weight " << wavg[3] << endl - << "FA_Avg_Center " << cavg[3] << endl; + for (vector::const_iterator imeas = meas.begin(); + imeas < meas.end(); imeas++) { + fout << *iname << "_Avg " << *iavg << endl + << *iname << "_Avg_Weight " << *iwavg << endl + << *iname << "_Avg_Center " << *icavg << endl; + + iname++; + iavg++; iwavg++; icavg++; + } fout.close(); } @@ -542,6 +581,27 @@ static int parse_commandline(int argc, char **argv) { inVoxFile = pargv[0]; nargsused = 1; } + else if (!strcmp(option, "--inlta")) { + if (nargc < 1) CMDargNErr(option,1); + inXfmFile = fio_fullpath(pargv[0]); + nargsused = 1; + } + else if (!strcmp(option, "--meas")) { + if (nargc < 1) CMDargNErr(option,1); + nargsused = 0; + while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { + measFileList.push_back(fio_fullpath(pargv[nargsused])); + nargsused++; + } + } + else if (!strcmp(option, "--measname")) { + if (nargc < 1) CMDargNErr(option,1); + nargsused = 0; + while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { + measNameList.push_back(pargv[nargsused]); + nargsused++; + } + } else if (!strcmp(option, "--dtbase")) { if (nargc < 1) CMDargNErr(option,1); dtBase = fio_fullpath(pargv[0]); @@ -611,13 +671,17 @@ static void print_usage(void) printf("USAGE: ./dmri_pathstats\n"); printf("\n"); printf(" --intrk :\n"); - printf(" Input trackvis .trk file\n"); + printf(" Input .trk file\n"); printf(" --rois :\n"); printf(" Input labeling ROIs for .trk file (optional)\n"); printf(" --intrc :\n"); printf(" Input tracula directory\n"); + printf(" --meas [...]:\n"); + printf(" Input microstructural measure volume(s) (optional)\n"); + printf(" --measname [...]:\n"); + printf(" Name(s) of microstructural measure(s) (as many as volumes)\n"); printf(" --dtbase :\n"); - printf(" Base name of input dtifit files (optional)\n"); + printf(" Base name of input dtifit volumes (optional)\n"); printf(" --path :\n"); printf(" Name of pathway (optional, written to output files)\n"); printf(" --subj :\n"); @@ -677,14 +741,20 @@ static void check_options(void) { printf("ERROR: must specify input .trk file or tracula directory\n"); exit(1); } - if(outFile.empty() && outVoxFile.empty() && outMedianFile.empty() && outEndBase.empty()) { + if(outFile.empty() && outVoxFile.empty() && + outMedianFile.empty() && outEndBase.empty()) { printf("ERROR: must specify at least one type of output\n"); exit(1); } - if((!outVoxFile.empty()) && dtBase.empty()) { - printf("ERROR: must specify dtifit base name for voxel-by-voxel output\n"); + if((!outVoxFile.empty()) && measFileList.empty() && dtBase.empty()) { + printf("ERROR: must specify microstructure volumes for voxel-by-voxel output\n"); exit(1); } + if (!measFileList.empty() && !measNameList.empty() && + measFileList.size() != measNameList.size()) { + printf("ERROR: must specify equal number of microstructural measure volumes and names\n"); + exit(1); + } if((!outMedianFile.empty()) && inTrkFile.empty()) { printf("ERROR: must specify input .trk file to use --median\n"); exit(1); @@ -693,7 +763,8 @@ static void check_options(void) { printf("ERROR: must specify input .trk file to use --ends\n"); exit(1); } - if((!outEndBase.empty()) && refVolFile.empty() && dtBase.empty()) { + if((!outEndBase.empty()) && refVolFile.empty() && + dtBase.empty() && measFileList.empty()) { printf("ERROR: must specify reference volume to use --ends\n"); exit(1); } @@ -709,7 +780,7 @@ static void check_options(void) { } /* --------------------------------------------- */ -static void WriteHeader(const std::string OutFile) { +static void WriteHeader(string OutFile) { ofstream fout(OutFile, ios::out); fout << "# Title Pathway Statistics" << endl @@ -740,42 +811,50 @@ static void dump_options(FILE *fp) { fprintf(fp,"machine %s\n",uts.machine); fprintf(fp,"user %s\n",VERuser()); - if (!inTrkFile.empty()) { + if (!inTrkFile.empty()) fprintf(fp, "Input .trk file: %s\n", inTrkFile.c_str()); - } if (!inRoi1File.empty()) { fprintf(fp, "Input end ROI 1: %s\n", inRoi1File.c_str()); fprintf(fp, "Input end ROI 2: %s\n", inRoi2File.c_str()); } - if (!inTrcDir.empty()) { + if (!inTrcDir.empty()) fprintf(fp, "Input tracula directory: %s\n", inTrcDir.c_str()); + if (!measFileList.empty()) { + cout << "Microstructural measure files:"; + for (vector::const_iterator istr = measFileList.begin(); + istr < measFileList.end(); istr++) + cout << " " << *istr; + cout << endl; } - if (!dtBase.empty()) { - fprintf(fp, "Input DTI fit base: %s\n", dtBase.c_str()); + if (!measNameList.empty()) { + cout << "Microstructural measure names:"; + for (vector::const_iterator istr = measNameList.begin(); + istr < measNameList.end(); istr++) + cout << " " << *istr; + cout << endl; } + if (!dtBase.empty()) + fprintf(fp, "Input DTI fit base: %s\n", dtBase.c_str()); // if (pathName) - fprintf(fp, "Pathway name: %s\n", pathName); + fprintf(fp, "Pathway name: %s\n", pathName); // if (subjName) - fprintf(fp, "Subject name: %s\n", subjName); - if (!outFile.empty()) { + fprintf(fp, "Subject name: %s\n", subjName); + if (!outFile.empty()) fprintf(fp, "Output file for overall measures: %s\n", outFile.c_str()); - } - if (!outVoxFile.empty()) { - fprintf(fp, "Output file for voxel-by-voxel measures: %s\n", outVoxFile.c_str()); - } - if (!outMedianFile.c_str()) { + if (!outVoxFile.empty()) + fprintf(fp, "Output file for voxel-by-voxel measures: %s\n", + outVoxFile.c_str()); + if (!outMedianFile.empty()) fprintf(fp, "Output median streamline file: %s\n", outMedianFile.c_str()); - } - if (!outEndBase.c_str()) { - fprintf(fp, "Base name of output end point volumes: %s\n", outEndBase.c_str()); - } - if (!refVolFile.c_str()) { - fprintf(fp, "Reference for output end point volumes: %s\n", refVolFile.c_str()); - } + if (!outEndBase.empty()) + fprintf(fp, "Base name of output end point volumes: %s\n", + outEndBase.c_str()); + if (!refVolFile.empty()) + fprintf(fp, "Reference for output end point volumes: %s\n", + refVolFile.c_str()); fprintf(fp, "Lower threshold for probability: %f\n", probThresh); - if (faThresh > 0) { + if (faThresh > 0) fprintf(fp, "Lower threshold for FA: %f\n", faThresh); - } return; } diff --git a/trc/dmri_spline.cxx b/trc/dmri_spline.cxx index 1d36870d351..f61a7dc78fa 100644 --- a/trc/dmri_spline.cxx +++ b/trc/dmri_spline.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -65,7 +65,7 @@ int main(int argc, char *argv[]); const char *Progname = "dmri_spline"; bool showControls = false; -std::string inFile, outVolFile, outVecBase, maskFile, outTextFile; +string inFile, maskFile, outVolFile, outTextFile, outVecBase; struct utsname uts; char *cmdline, cwd[2000]; @@ -97,7 +97,7 @@ int main(int argc, char **argv) { dump_options(); - Spline myspline(inFile.c_str(), maskFile.c_str()); + Spline myspline(inFile, maskFile); printf("Computing spline...\n"); cputimer.reset(); @@ -107,16 +107,14 @@ int main(int argc, char **argv) { cputime = cputimer.milliseconds(); printf("Done in %g sec.\n", cputime/1000.0); - if (!outVolFile.empty() ) { - myspline.WriteVolume(outVolFile.c_str(), showControls); - } + if (!outVolFile.empty()) + myspline.WriteVolume(outVolFile, showControls); - if (!outTextFile.empty()) { - myspline.WriteAllPoints(outTextFile.c_str()); - } + if (!outTextFile.empty()) + myspline.WriteAllPoints(outTextFile); if (!outVecBase.empty()) { - std::string fname; + string fname; printf("Computing analytical tangent, normal, and curvature...\n"); cputimer.reset(); @@ -130,11 +128,11 @@ int main(int argc, char **argv) { // Write tangent, normal, and curvature (analytical) to text files fname = outVecBase + "_tang.txt"; - myspline.WriteTangent(fname.c_str()); + myspline.WriteTangent(fname); fname = outVecBase + "_norm.txt"; - myspline.WriteNormal(fname.c_str()); + myspline.WriteNormal(fname); fname = outVecBase + "_curv.txt"; - myspline.WriteCurvature(fname.c_str()); + myspline.WriteCurvature(fname); printf("Computing discrete tangent, normal, and curvature...\n"); cputimer.reset(); @@ -148,11 +146,11 @@ int main(int argc, char **argv) { // Write tangent, normal, and curvature (discrete) to text files fname = outVecBase + "_tang_diff.txt"; - myspline.WriteTangent(fname.c_str()); + myspline.WriteTangent(fname); fname = outVecBase + "_norm_diff.txt"; - myspline.WriteNormal(fname.c_str()); + myspline.WriteNormal(fname); fname = outVecBase + "_curv_diff.txt"; - myspline.WriteCurvature(fname.c_str()); + myspline.WriteCurvature(fname); } printf("dmri_spline done\n"); @@ -276,15 +274,15 @@ static void print_version(void) { /* --------------------------------------------- */ static void check_options(void) { - if(inFile.size() == 0) { + if(inFile.empty()) { cout << "ERROR: Must specify input text file" << endl; exit(1); } - if(maskFile.size() == 0) { + if(maskFile.empty()) { cout << "ERROR: Must specify mask volume" << endl; exit(1); } - if((outVolFile.size() + outTextFile.size() + outVecBase.size()) == 0) { + if(outVolFile.empty() && outTextFile.empty() && outVecBase.empty()) { cout << "ERROR: Must specify at least one type of output file" << endl; exit(1); } @@ -304,16 +302,14 @@ static void dump_options() { cout << "Control points: " << inFile << endl; cout << "Mask volume: " << maskFile << endl; - if (outVolFile.size() != 0) { + if (!outVolFile.empty()) { cout << "Output volume: " << outVolFile << endl << "Show controls: " << showControls << endl; } - if (outTextFile.size() != 0) { + if (!outTextFile.empty()) cout << "Output text file: " << outTextFile << endl; - } - if (outVecBase.size() != 0 ) { + if (!outVecBase.empty()) cout << "Output tangent vector file base name: " << outVecBase << endl; - } return; } diff --git a/trc/dmri_train.cxx b/trc/dmri_train.cxx index e142599066e..b464c09dec3 100644 --- a/trc/dmri_train.cxx +++ b/trc/dmri_train.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -63,14 +63,17 @@ int main(int argc, char *argv[]); const char *Progname = "dmri_train"; -bool useTrunc = false, excludeStr = false; +bool useTrunc = false, useAnatomy = false, useShape = false, excludeStr = false; +int numStrMax = INT_MAX; vector trainMaskLabel; -vector> nControl; -vector outBase, trainTrkList, trainRoi1List, trainRoi2List, +vector< vector > nControl; +vector outTrkList, outPriorBase, + trainTrkList, trainRoi1List, trainRoi2List, testMaskList, testFaList, testBaseXfmList; -std::string outDir, outTestDir, trainListFile, - trainAsegFile, trainMaskFile, testAffineXfmFile, - testNonlinXfmFile, testNonlinRefFile, testBaseMaskFile; +string outPriorDir, outTestDir, + trainListFile, trainAsegFile, trainMaskFile, + testAffineXfmFile, testNonlinXfmFile, + testNonlinRefFile, testBaseMaskFile; struct utsname uts; char *cmdline, cwd[2000]; @@ -80,7 +83,7 @@ Timer cputimer; /*--------------------------------------------------*/ int main(int argc, char **argv) { int nargs, cputime; - std::string excfile, fbase; + string excfile, fbase; nargs = handleVersionOption(argc, argv, "dmri_train"); if (nargs && argc - nargs == 1) exit (0); @@ -104,69 +107,85 @@ int main(int argc, char **argv) { dump_options(); if (excludeStr) { - if (!outDir.empty()) { - excfile = outDir + '/' + outBase.at(0) + "_cpts_all.bad.txt"; - } else { - excfile = outBase.at(0) + "_cpts_all.bad.txt"; - } + excfile = outPriorBase[0] + "_cpts_all.bad.txt"; + + if (!outPriorDir.empty()) + excfile = outPriorDir + "/" + excfile; + } + + if (trainRoi1List.empty()) { + trainRoi1List.resize(trainTrkList.size()); + fill(trainRoi1List.begin(), trainRoi1List.end(), string()); + } + + if (trainRoi2List.empty()) { + trainRoi2List.resize(trainTrkList.size()); + fill(trainRoi2List.begin(), trainRoi2List.end(), string()); } - + + if (trainMaskLabel.empty()) { + trainMaskLabel.resize(trainTrkList.size()); + fill(trainMaskLabel.begin(), trainMaskLabel.end(), 0.0f); + } + + if (nControl.empty()) + nControl.push_back(vector()); + Blood myblood(trainListFile, trainTrkList[0], - trainRoi1List.size() ? trainRoi1List[0] : std::string(), - trainRoi2List.size() ? trainRoi2List[0] : std::string(), - trainAsegFile, trainMaskFile, - trainMaskLabel.size() ? trainMaskLabel[0] : 0.0f, - excludeStr ? excfile : std::string(), + trainRoi1List[0], trainRoi2List[0], + trainAsegFile, trainMaskFile, trainMaskLabel[0], + excfile, testMaskList, testFaList, testAffineXfmFile, testNonlinXfmFile, testNonlinRefFile, testBaseXfmList, testBaseMaskFile, - useTrunc, nControl[0], + useTrunc, useAnatomy, useShape, nControl[0], numStrMax, debug); for (unsigned int itrk = 0; itrk < trainTrkList.size(); itrk++) { if (itrk > 0) { if (excludeStr) { - if (!outDir.empty()) { - excfile = outDir + '/' + outBase.at(itrk) + "_cpts_all.bad.txt"; - } else { - excfile = outBase.at(itrk) + "_cpts_all.bad.txt"; - } + excfile = outPriorBase[itrk] + "_cpts_all.bad.txt"; + + if (!outPriorDir.empty()) + excfile = outPriorDir + "/" + excfile; } - if (nControl.size() > 1) // Variable number of controls + if (nControl.size() > 1) // Variable number of control points myblood.SetNumControls(nControl[itrk]); myblood.ReadStreamlines(trainListFile, trainTrkList[itrk], - trainRoi1List.size() ? trainRoi1List[itrk] : 0, - trainRoi2List.size() ? trainRoi2List[itrk] : 0, - trainMaskLabel.size() ? trainMaskLabel[itrk] : 0, - excludeStr ? excfile : 0); + trainRoi1List[itrk], trainRoi2List[itrk], + trainMaskLabel[itrk], excfile); } cout << "Processing pathway " << itrk+1 << " of " << trainTrkList.size() << "..." << endl; cputimer.reset(); - myblood.ComputePriors(); + if (!outTrkList.empty()) { // Prep training streamlines + myblood.PrepStreamlines(); - if (!outDir.empty()) { - fbase = outDir + '/' + outBase.at(itrk); - } else { - fbase = outBase.at(itrk); + myblood.WriteStreamlines(trainListFile, outTrkList[itrk]); } + else { // Compute priors for test subject + myblood.ComputePriors(); - if (!outTestDir.empty()) { - std::string ftbase; + fbase = outPriorBase[itrk]; - ftbase = outTestDir + outBase.at(itrk); - myblood.WriteOutputs(fbase.c_str(), ftbase.c_str()); - } - else { - myblood.WriteOutputs(fbase.c_str()); - } + if (!outPriorDir.empty()) + fbase = outPriorDir + "/" + fbase; + + if (!outTestDir.empty()) { + string ftbase = outTestDir + "/" + outPriorBase[itrk]; - cputime = cputimer.milliseconds(); - cout << "Done in " << cputime/1000.0 << " sec." << endl; + myblood.WriteOutputs(fbase.c_str(), ftbase.c_str()); + } + else + myblood.WriteOutputs(fbase.c_str()); + + cputime = cputimer.milliseconds(); + cout << "Done in " << cputime/1000.0 << " sec." << endl; + } } cout << "dmri_train done" << endl; @@ -198,7 +217,7 @@ static int parse_commandline(int argc, char **argv) { else if (!strcasecmp(option, "--nocheckopts")) checkoptsonly = 0; else if (!strcmp(option, "--outdir")) { if (nargc < 1) CMDargNErr(option,1); - outDir = fio_fullpath(pargv[0]); + outPriorDir = fio_fullpath(pargv[0]); nargsused = 1; } else if (!strcmp(option, "--cptdir")) { @@ -209,7 +228,14 @@ static int parse_commandline(int argc, char **argv) { else if (!strcmp(option, "--out")) { if (nargc < 1) CMDargNErr(option,1); while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { - outBase.push_back(pargv[nargsused]); + outPriorBase.push_back(pargv[nargsused]); + nargsused++; + } + } + else if (!strcmp(option, "--outtrk")) { + if (nargc < 1) CMDargNErr(option,1); + while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { + outTrkList.push_back(pargv[nargsused]); nargsused++; } } @@ -306,8 +332,17 @@ static int parse_commandline(int argc, char **argv) { nargsused++; } } + else if (!strcmp(option, "--max")) { + if (nargc < 1) CMDargNErr(option,1); + sscanf(pargv[0], "%d", &numStrMax); + nargsused = 1; + } else if (!strcmp(option, "--trunc")) useTrunc = true; + else if (!strcmp(option, "--aprior")) + useAnatomy = true; + else if (!strcmp(option, "--sprior")) + useShape = true; else if (!strcmp(option, "--xstr")) excludeStr = true; else { @@ -326,15 +361,7 @@ static int parse_commandline(int argc, char **argv) { static void print_usage(void) { cout << endl << "USAGE: " << Progname << endl << endl - << "Basic inputs (all must be in common space)" << endl - << " --out [...]:" << endl - << " Base name(s) of output(s), one per path" << endl - << " --outdir :" << endl - << " Output directory (optional)" << endl - << " --cptdir :" << endl - << " Output directory for control points in test subject's space" << endl - << " (optional, requires registration files)" << endl - << " If specified, base names of outputs are relative to this" << endl + << "Basic inputs (all volumes in common space)" << endl << " --slist :" << endl << " Text file with list of training subject directories" << endl << " --trk [...]:" << endl @@ -351,6 +378,15 @@ static void print_usage(void) { << " --lmask [...]:" << endl << " Add a label ID from aparc+aseg to cortex mask, one per path" << endl << " (0 doesn't add any label)" << endl + << endl + << "Inputs used to prep training data (all volumes in common space)" << endl + << " --bmask [...]:" << endl + << " Input brain mask volume(s)" << endl + << " --outtrk [...]:" << endl + << " Name(s) of output, pre-sorted .trk file(s), one per path" << endl + << " (Names relative to training subject directory)" << endl + << endl + << "Inputs used to compute priors (all volumes in common space)" << endl << " --bmask [...]:" << endl << " Input brain mask volume(s) for test subject" << endl << " --fa [...]:" << endl @@ -368,11 +404,25 @@ static void print_usage(void) { << " --ncpts [...]:" << endl << " Number of control points for initial spline, one per path" << endl << " or one for all paths" << endl + << " --max :" << endl + << " Maximum number of training streamlines to keep per path" << endl << " --xstr:" << endl << " Exclude previously chosen center streamline(s) (Default: No)" << endl + << " --aprior:" << endl + << " Compute priors on underlying anatomy (Default: No)" << endl + << " --sprior:" << endl + << " Compute priors on shape (Default: No)" << endl << " --trunc:" << endl - << " Also save results using all streamlines, truncated or not" << endl + << " Use all training streamlines, truncated or not" << endl << " (Default: Only save results using non-truncated streamlines)" << endl + << " --out [...]:" << endl + << " Base name(s) of output(s) for test subject, one per path" << endl + << " --outdir :" << endl + << " Output directory (optional)" << endl + << " --cptdir :" << endl + << " Output directory for control points in test subject's space" << endl + << " (optional, requires registration files)" << endl + << " If specified, base names of outputs are relative to this" << endl << endl << "Other options" << endl << " --debug: turn on debugging" << endl @@ -407,7 +457,7 @@ static void print_version(void) { /* --------------------------------------------- */ static void check_options(void) { - if (outBase.empty()) { + if (outTrkList.empty() && outPriorBase.empty()) { cout << "ERROR: Must specify at least one output name" << endl; exit(1); } @@ -420,11 +470,16 @@ static void check_options(void) { << endl; exit(1); } - if (trainTrkList.size() != outBase.size()) { + if (!outPriorBase.empty() && (trainTrkList.size() != outPriorBase.size())) { cout << "ERROR: Numbers of input .trk files and output names must match" << endl; exit(1); } + if (!outTrkList.empty() && (trainTrkList.size() != outTrkList.size())) { + cout << "ERROR: Numbers of input and output .trk files must match" + << endl; + exit(1); + } if (trainAsegFile.empty()) { cout << "ERROR: Must specify location of aparc+aseg volume" << endl; exit(1); @@ -448,46 +503,44 @@ static void check_options(void) { << endl; exit(1); } - if (testMaskList.empty()) { - cout << "ERROR: Must specify brain mask volume for output subject" << endl; - exit(1); - } - if (!testFaList.empty() && (testFaList.size() != testMaskList.size())) { - cout << "ERROR: Must specify as many FA volumes as brain masks" << endl; - exit(1); - } - if (nControl.empty()) { - cout << "ERROR: Must specify number of control points for initial spline" - << endl; - exit(1); - } - if (nControl.size() > 1 && nControl.size() != trainTrkList.size()) { - cout << "ERROR: Must specify number of control points for each .trk file" - << "ERROR: or a single number of control points for all .trk files" - << endl; - exit(1); - } - if ((!testNonlinXfmFile.empty()) && testNonlinRefFile.empty()) { - cout << "ERROR: Must specify source reference volume for nonlinear warp" - << endl; - exit(1); - } - if (!testBaseXfmList.empty() && testBaseMaskFile.empty()) { - cout << "ERROR: Must specify reference volume for base space" << endl; - exit(1); - } - if (!testBaseXfmList.empty() && - (testBaseXfmList.size() != testFaList.size())) { - cout << "ERROR: Must specify as many base registrations as FA volumes" - << endl; - exit(1); + if (!outPriorBase.empty()) { + if (!testFaList.empty() && (testFaList.size() != testMaskList.size())) { + cout << "ERROR: Must specify as many FA volumes as brain masks" << endl; + exit(1); + } + if (nControl.empty()) { + cout << "ERROR: Must specify number of control points for initial spline" + << endl; + exit(1); + } + if (nControl.size() > 1 && nControl.size() != trainTrkList.size()) { + cout << "ERROR: Must specify number of control points for each .trk file" + << "ERROR: or a single number of control points for all .trk files" + << endl; + exit(1); + } + if (!testNonlinXfmFile.empty() && testNonlinRefFile.empty()) { + cout << "ERROR: Must specify source reference volume for nonlinear warp" + << endl; + exit(1); + } + if (!testBaseXfmList.empty() && testBaseMaskFile.empty()) { + cout << "ERROR: Must specify reference volume for base space" << endl; + exit(1); + } + if (!testBaseXfmList.empty() && + (testBaseXfmList.size() != testFaList.size())) { + cout << "ERROR: Must specify as many base registrations as FA volumes" + << endl; + exit(1); + } } return; } /* --------------------------------------------- */ static void dump_options() { - vector::const_iterator istr; + vector::const_iterator istr; cout << endl << getVersion() << endl @@ -498,39 +551,42 @@ static void dump_options() { << "machine " << uts.machine << endl << "user " << VERuser() << endl; - if (!outDir.empty()) { - cout << "Output directory: " << outDir << endl; - } + if (!outPriorDir.empty()) + cout << "Output directory: " << outPriorDir << endl; - if (!outTestDir.empty()) { + if (!outTestDir.empty()) cout << "Output directory in test subject's space: " << outTestDir << endl; - } - cout << "Output base:"; - for (istr = outBase.begin(); istr < outBase.end(); istr++) { - cout << " " << *istr; + if (!outPriorBase.size()) { + cout << "Output base for anatomical priors:"; + for (istr = outPriorBase.begin(); istr < outPriorBase.end(); istr++) + cout << " " << *istr; + cout << endl; } - cout << endl; cout << "Training subject directory list: " << trainListFile << endl; + if (!outTrkList.empty()) { + cout << "Location of output, pre-sorted streamline files relative to base:"; + for (istr = outTrkList.begin(); istr < outTrkList.end(); istr++) + cout << " " << *istr; + cout << endl; + } + cout << "Location of streamline files relative to base:"; - for (istr = trainTrkList.begin(); istr < trainTrkList.end(); istr++) { + for (istr = trainTrkList.begin(); istr < trainTrkList.end(); istr++) cout << " " << *istr; - } cout << endl; if (!trainRoi1List.empty()) { cout << "Location of start ROI files relative to base:"; - for (istr = trainRoi1List.begin(); istr < trainRoi1List.end(); istr++) { + for (istr = trainRoi1List.begin(); istr < trainRoi1List.end(); istr++) cout << " " << *istr; - } cout << endl; cout << "Location of end ROI files relative to base:"; - for (istr = trainRoi2List.begin(); istr < trainRoi2List.end(); istr++) { + for (istr = trainRoi2List.begin(); istr < trainRoi2List.end(); istr++) cout << " " << *istr; - } cout << endl; } @@ -540,9 +596,8 @@ static void dump_options() { if (!trainMaskLabel.empty()) { cout << "Label ID's from aparc+aseg to add to cortex mask:"; for (vector::const_iterator ilab = trainMaskLabel.begin(); - ilab < trainMaskLabel.end(); ilab++) { + ilab < trainMaskLabel.end(); ilab++) cout << " " << (int) *ilab; - } cout << endl; } @@ -550,61 +605,58 @@ static void dump_options() { << endl; cout << "Brain mask for output subject:"; - for (auto ifile = testMaskList.begin(); - ifile < testMaskList.end(); ifile++) { + for (vector::const_iterator ifile = testMaskList.begin(); + ifile < testMaskList.end(); ifile++) cout << " " << *ifile; - } cout << endl; if (!testFaList.empty()) { cout << "FA map for output subject:"; - for (auto ifile = testFaList.begin(); - ifile < testFaList.end(); ifile++) { + for (vector::const_iterator ifile = testFaList.begin(); + ifile < testFaList.end(); ifile++) cout << " " << *ifile; - } cout << endl; } - if (!testAffineXfmFile.empty()) { + if (!testAffineXfmFile.empty()) cout << "Affine registration from atlas to base for output subject: " << testAffineXfmFile << endl; - } - if (!testNonlinXfmFile.empty()) { + if (!testNonlinXfmFile.empty()) cout << "Nonlinear registration from atlas to base for output subject: " << testNonlinXfmFile << endl; - } - if (!testNonlinRefFile.empty()) { + if (!testNonlinRefFile.empty()) cout << "Nonlinear registration source reference for output subject: " << testNonlinRefFile << endl; - } if (!testBaseXfmList.empty()) { cout << "Affine registration from base to FA map for output subject:"; - for (auto ifile = testBaseXfmList.begin(); - ifile < testBaseXfmList.end(); ifile++) { + for (vector::const_iterator ifile = testBaseXfmList.begin(); + ifile < testBaseXfmList.end(); ifile++) cout << " " << *ifile; - } cout << endl; } - if (!testBaseMaskFile.c_str()) { + if (!testBaseMaskFile.empty()) cout << "Base mask for output subject: " << testBaseMaskFile << endl; - } cout << "Number of control points for initial spline:"; for (vector< vector >::const_iterator inlist = nControl.begin(); - inlist < nControl.end(); inlist++) { + inlist < nControl.end(); inlist++) for (vector::const_iterator inum = inlist->begin(); - inum < inlist->end(); inum++) { + inum < inlist->end(); inum++) cout << " " << *inum; - } - } cout << endl; + if (numStrMax < INT_MAX) + cout << "Maximum number of training streamlines per path: " + << numStrMax << endl; + cout << "Exclude previously chosen center streamlines: " << excludeStr << endl - << "Use truncated streamlines: " << useTrunc << endl; + << "Use truncated streamlines: " << useTrunc << endl + << "Compute priors on underlying anatomy: " << useAnatomy << endl + << "Compute priors on shape: " << useShape << endl; return; } diff --git a/trc/dmri_trk2trk.cxx b/trc/dmri_trk2trk.cxx index 30c05dffaaf..5c97adc345e 100644 --- a/trc/dmri_trk2trk.cxx +++ b/trc/dmri_trk2trk.cxx @@ -8,7 +8,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -67,13 +67,14 @@ int main(int argc, char *argv[]) ; const char *Progname = "dmri_trk2trk"; -int doInvNonlin = 0, doFill = 0, doMean = 0, doNth = 0, strNum = -1, - lengthMin = -1, lengthMax = -1; +bool doMerge = false; +int doInvXfm = 0, doFill = 0, doMean = 0, doNth = 0, strNum = -1, + doEvery = 0, everyNum = -1, lengthMin = -1, lengthMax = -1; unsigned int nTract = 0; -std::string inDir, outDir, inRefFile, outRefFile, affineXfmFile, nonlinXfmFile; -vector inTrkList, inAscList, outTrkList, outAscList, outVolList, - incMaskList, excMaskList; -vector incMask, excMask; +string inDir, outDir, inRefFile, outRefFile, affineXfmFile, nonlinXfmFile; +vector inTrkList, inAscList, outTrkList, outAscList, outVolList, + incMaskList, excMaskList, incTermMaskList, excTermMaskList; +vector incMask, excMask, incTermMask, excTermMask; struct utsname uts; char *cmdline, cwd[2000]; @@ -84,8 +85,9 @@ Timer cputimer; int main(int argc, char **argv) { int nargs, cputime; char outorient[4]; - std::string fname; + string fname; vector point(3), step(3, 0); + vector< vector > streamlines, properties; MATRIX *outv2r; MRI *inref = 0, *outref = 0, *outvol = 0; AffineReg affinereg; @@ -114,62 +116,82 @@ int main(int argc, char **argv) { dump_options(stdout); + if (doEvery) + strNum = 0; + // Read reference volumes inref = MRIread(inRefFile.c_str()); outref = MRIread(outRefFile.c_str()); - if (!outVolList.empty()) { + if (!outVolList.empty()) outvol = MRIclone(outref, NULL); - } // Output space orientation information outv2r = MRIgetVoxelToRasXform(outref); MRIdircosToOrientationString(outref, outorient); // Read transform files -#ifndef NO_CVS_UP_IN_HERE - if (!nonlinXfmFile.empty()) { - if (!affineXfmFile.empty()) { - affinereg.ReadXfm(affineXfmFile.c_str(), inref, 0); - } - nonlinreg.ReadXfm(nonlinXfmFile.c_str(), outref); - } else { -#endif - if (!affineXfmFile.empty()) { - affinereg.ReadXfm(affineXfmFile.c_str(), inref, outref); + if (!affineXfmFile.empty()) { + if (doInvXfm) { + affinereg.ReadXfm(affineXfmFile, outref, inref); + + if (affinereg.IsInvEmpty()) { + cout << "ERROR: For --inv, use LTA format" << endl; + exit(1); + } } + else + affinereg.ReadXfm(affineXfmFile, inref, outref); + } + #ifndef NO_CVS_UP_IN_HERE + if (!nonlinXfmFile.empty()) { + if (doInvXfm) + nonlinreg.ReadXfm(nonlinXfmFile, inref); + else + nonlinreg.ReadXfm(nonlinXfmFile, outref); } #endif // Read inclusion masks - for (auto imask = incMaskList.begin(); - imask < incMaskList.end(); imask++) { + for (vector::const_iterator imask = incMaskList.begin(); + imask < incMaskList.end(); imask++) incMask.push_back(MRIread((*imask).c_str())); - } // Read exclusion masks - for (auto imask = excMaskList.begin(); - imask < excMaskList.end(); imask++) { + for (vector::const_iterator imask = excMaskList.begin(); + imask < excMaskList.end(); imask++) excMask.push_back(MRIread((*imask).c_str())); - } + + // Read terminal inclusion masks + for (vector::const_iterator imask = incTermMaskList.begin(); + imask < incTermMaskList.end(); imask++) + incTermMask.push_back(MRIread((*imask).c_str())); + + // Read terminal exclusion masks + for (vector::const_iterator imask = excTermMaskList.begin(); + imask < excTermMaskList.end(); imask++) + excTermMask.push_back(MRIread((*imask).c_str())); for (unsigned int itract = 0; itract < nTract; itract++) { int npts, nstr = 0; CTrackReader trkreader; TRACK_HEADER trkheadin; - vector< vector > streamlines; cout << "Processing input file " << itract+1 << " of " << nTract << "..." << endl; cputimer.reset(); + if (!doMerge) { + streamlines.clear(); + properties.clear(); + } + if (!inTrkList.empty()) { // Read streamlines from .trk file - if (!inDir.empty()) { - fname = inDir + "/" + inTrkList.at(itract); - } else { - fname = inTrkList.at(itract); - } + fname = inTrkList[itract]; + + if (!inDir.empty()) + fname = inDir + "/" + fname; if (!trkreader.Open(fname.c_str(), &trkheadin)) { cout << "ERROR: Cannot open input file " << fname << endl; @@ -179,20 +201,25 @@ int main(int argc, char **argv) { while (trkreader.GetNextPointCount(&npts)) { const int veclen = npts*3; - float *iraw, *rawpts = new float[veclen]; - vector newpts(veclen); + float *iraw, *rawpts = new float[veclen], + *props = new float [trkheadin.n_properties]; + vector newpts(veclen), newprops(trkheadin.n_properties); // Read a streamline from input file - trkreader.GetNextTrackData(npts, rawpts); + trkreader.GetNextTrackData(npts, rawpts, NULL, props); - if ( (doNth && nstr != strNum) || + if ( ((doNth || doEvery) && nstr != strNum) || (lengthMin > -1 && npts <= lengthMin) || (lengthMax > -1 && npts >= lengthMax) ) { delete[] rawpts; + delete[] props; nstr++; continue; } + if (doEvery && nstr == strNum) + strNum += everyNum; + iraw = rawpts; // Divide by input voxel size and make 0-based to get voxel coords @@ -206,6 +233,16 @@ int main(int argc, char **argv) { delete[] rawpts; streamlines.push_back(newpts); + // Store properties of input streamlines + if (trkheadin.n_properties > 0) { + vector newprops(trkheadin.n_properties); + + copy(props, props+trkheadin.n_properties, newprops.begin()); + + delete[] props; + properties.push_back(newprops); + } + nstr++; } } @@ -214,11 +251,10 @@ int main(int argc, char **argv) { ifstream infile; vector newpts; - if (!inDir.empty()) { - fname = inDir + '/' + inAscList.at(itract); - } else { - fname = inAscList.at(itract); - } + fname = inAscList[itract]; + + if (!inDir.empty()) + fname = inDir + "/" + fname; infile.open(fname, ios::in); if (!infile) { @@ -235,11 +271,14 @@ int main(int argc, char **argv) { point.push_back(val); if (point.empty()) { // Empty line marks end of streamline - if ( (!doNth || nstr == strNum) && + if ( (!(doNth || doEvery) || nstr == strNum) && (lengthMin == -1 || (int) newpts.size()/3 > lengthMin) && (lengthMax == -1 || (int) newpts.size()/3 < lengthMax) ) streamlines.push_back(newpts); + if (doEvery && nstr == strNum) + strNum += everyNum; + newpts.clear(); nstr++; } @@ -255,8 +294,12 @@ int main(int argc, char **argv) { infile.close(); } + if (doMerge && itract < nTract-1) + continue; + nstr = streamlines.size(); + // Apply transformations for (int kstr = nstr-1; kstr >= 0; kstr--) { vector newpts; @@ -264,19 +307,28 @@ int main(int argc, char **argv) { ipt < streamlines[kstr].end(); ipt += 3) { copy(ipt, ipt+3, point.begin()); - // Apply affine transform - if (!affinereg.IsEmpty()) - affinereg.ApplyXfm(point, point.begin()); - + if (doInvXfm) { #ifndef NO_CVS_UP_IN_HERE - // Apply nonlinear transform - if (!nonlinreg.IsEmpty()) { - if (doInvNonlin) + // Apply inverse of nonlinear transform + if (!nonlinreg.IsEmpty()) nonlinreg.ApplyXfmInv(point, point.begin()); - else - nonlinreg.ApplyXfm(point, point.begin()); +#endif + + // Apply inverse of affine transform + if (!affinereg.IsEmpty()) + affinereg.ApplyXfmInv(point, point.begin()); } + else { + // Apply affine transform + if (!affinereg.IsEmpty()) + affinereg.ApplyXfm(point, point.begin()); + +#ifndef NO_CVS_UP_IN_HERE + // Apply nonlinear transform + if (!nonlinreg.IsEmpty()) + nonlinreg.ApplyXfm(point, point.begin()); #endif + } copy(point.begin(), point.end(), ipt); } @@ -318,12 +370,59 @@ int main(int argc, char **argv) { copy(newpts.begin(), newpts.end(), streamlines[kstr].begin()); } - // Apply inclusion masks + // Apply inclusion/exclusion masks nstr = streamlines.size(); for (int kstr = nstr-1; kstr >= 0; kstr--) { bool dokeep = true; + // There must be an endpoint that intersects each terminal inclusion mask + for (vector::const_iterator imask = incTermMask.begin(); + imask < incTermMask.end(); imask++) { + vector::const_iterator ipt = streamlines[kstr].begin(); + int ix = (int) round(ipt[0]), + iy = (int) round(ipt[1]), + iz = (int) round(ipt[2]); + + if (ix < 0) ix = 0; + if (ix >= (*imask)->width) ix = (*imask)->width-1; + if (iy < 0) iy = 0; + if (iy >= (*imask)->height) iy = (*imask)->height-1; + if (iz < 0) iz = 0; + if (iz >= (*imask)->depth) iz = (*imask)->depth-1; + + dokeep = false; + + if (MRIgetVoxVal(*imask, ix, iy, iz, 0) > 0) + dokeep = true; + else { + ipt = streamlines[kstr].end() - 3; + ix = (int) round(ipt[0]); + iy = (int) round(ipt[1]); + iz = (int) round(ipt[2]); + + if (ix < 0) ix = 0; + if (ix >= (*imask)->width) ix = (*imask)->width-1; + if (iy < 0) iy = 0; + if (iy >= (*imask)->height) iy = (*imask)->height-1; + if (iz < 0) iz = 0; + if (iz >= (*imask)->depth) iz = (*imask)->depth-1; + + if (MRIgetVoxVal(*imask, ix, iy, iz, 0) > 0) + dokeep = true; + } + + if (!dokeep) + break; + } + + if (!dokeep) { + streamlines.erase(streamlines.begin() + kstr); + if (!properties.empty()) + properties.erase(properties.begin() + kstr); + continue; + } + // There must be at least one point that intersects each inclusion mask for (vector::const_iterator imask = incMask.begin(); imask < incMask.end(); imask++) { @@ -355,6 +454,53 @@ int main(int argc, char **argv) { if (!dokeep) { streamlines.erase(streamlines.begin() + kstr); + if (!properties.empty()) + properties.erase(properties.begin() + kstr); + continue; + } + + // There must be no endpoint that intersects any terminal exclusion mask + for (vector::const_iterator imask = excTermMask.begin(); + imask < excTermMask.end(); imask++) { + vector::const_iterator ipt = streamlines[kstr].begin(); + int ix = (int) round(ipt[0]), + iy = (int) round(ipt[1]), + iz = (int) round(ipt[2]); + + if (ix < 0) ix = 0; + if (ix >= (*imask)->width) ix = (*imask)->width-1; + if (iy < 0) iy = 0; + if (iy >= (*imask)->height) iy = (*imask)->height-1; + if (iz < 0) iz = 0; + if (iz >= (*imask)->depth) iz = (*imask)->depth-1; + + if (MRIgetVoxVal(*imask, ix, iy, iz, 0) > 0) + dokeep = false; + else { + ipt = streamlines[kstr].end() - 3; + ix = (int) round(ipt[0]), + iy = (int) round(ipt[1]), + iz = (int) round(ipt[2]); + + if (ix < 0) ix = 0; + if (ix >= (*imask)->width) ix = (*imask)->width-1; + if (iy < 0) iy = 0; + if (iy >= (*imask)->height) iy = (*imask)->height-1; + if (iz < 0) iz = 0; + if (iz >= (*imask)->depth) iz = (*imask)->depth-1; + + if (MRIgetVoxVal(*imask, ix, iy, iz, 0) > 0) + dokeep = false; + } + + if (!dokeep) + break; + } + + if (!dokeep) { + streamlines.erase(streamlines.begin() + kstr); + if (!properties.empty()) + properties.erase(properties.begin() + kstr); continue; } @@ -385,8 +531,11 @@ int main(int argc, char **argv) { break; } - if (!dokeep) + if (!dokeep) { streamlines.erase(streamlines.begin() + kstr); + if (!properties.empty()) + properties.erase(properties.begin() + kstr); + } } if (doMean && !streamlines.empty()) { @@ -575,15 +724,21 @@ int main(int argc, char **argv) { // Keep only the chosen streamline for writing to disk streamlines.erase(streamlines.begin(), streamlines.begin() + kstrmean); streamlines.erase(streamlines.begin() + 1, streamlines.end()); + + if (!properties.empty()) + properties.erase(properties.begin(), properties.begin() + kstrmean); + properties.erase(properties.begin() + 1, properties.end()); } // Write transformed streamlines to volume if (!outVolList.empty()) { - if (!outDir.empty()) { - fname = outDir + "/" + outVolList.at(itract); - } else { - fname = outVolList.at(itract); - } + if (doMerge) + fname = outVolList[0]; + else + fname = outVolList[itract]; + + if (!outDir.empty()) + fname = outDir + "/" + fname; MRIclear(outvol); @@ -614,11 +769,13 @@ int main(int argc, char **argv) { if (!outAscList.empty()) { ofstream outfile; - if (!outDir.empty()) { - fname = outDir + "/" + outAscList.at(itract); - } else { - fname = outAscList.at(itract); - } + if (doMerge) + fname = outAscList[0]; + else + fname = outAscList[itract]; + + if (!outDir.empty()) + fname = outDir + "/" + fname; outfile.open(fname, ios::out); if (!outfile) { @@ -626,10 +783,10 @@ int main(int argc, char **argv) { exit(1); } - for (auto istr = streamlines.begin(); - istr < streamlines.end(); - istr++) { - for (auto ipt = istr->begin(); + for (vector< vector >::const_iterator istr = streamlines.begin(); + istr < streamlines.end(); + istr++) { + for (vector::const_iterator ipt = istr->begin(); ipt < istr->end(); ipt += 3) outfile << (int) round(ipt[0]) << " " << (int) round(ipt[1]) << " " @@ -645,6 +802,7 @@ int main(int argc, char **argv) { if (!outTrkList.empty()) { CTrackWriter trkwriter; TRACK_HEADER trkheadout; + vector< vector >::iterator iprop = properties.begin(); // Set output .trk header if (inTrkList.empty()) { @@ -653,9 +811,9 @@ int main(int argc, char **argv) { trkheadout.origin[0] = 0; trkheadout.origin[1] = 0; trkheadout.origin[2] = 0; - } else { - trkheadout = trkheadin; } + else + trkheadout = trkheadin; trkheadout.voxel_size[0] = outref->xsize; trkheadout.voxel_size[1] = outref->ysize; @@ -665,11 +823,9 @@ int main(int argc, char **argv) { trkheadout.dim[1] = outref->height; trkheadout.dim[2] = outref->depth; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) trkheadout.vox_to_ras[i][j] = outv2r->rptr[i+1][j+1]; - } - } strcpy(trkheadout.voxel_order, outorient); @@ -692,11 +848,13 @@ int main(int argc, char **argv) { trkheadout.n_count = (int) streamlines.size(); // Open output .trk file - if (!outDir.empty()) { - fname = outDir + "/" + outTrkList.at(itract); - } else { - fname = outTrkList.at(itract); - } + if (doMerge) + fname = outTrkList[0]; + else + fname = outTrkList[itract]; + + if (!outDir.empty()) + fname = outDir + "/" + fname; if (!trkwriter.Initialize(fname.c_str(), trkheadout)) { cout << "ERROR: Cannot open output file " << fname << endl; @@ -712,7 +870,14 @@ int main(int argc, char **argv) { for (int k = 0; k < 3; k++) ipt[k] = (ipt[k] + .5) * trkheadout.voxel_size[k]; - trkwriter.WriteNextTrack(istr->size()/3, &(istr->at(0))); + if (properties.empty()) + trkwriter.WriteNextTrack(istr->size()/3, &(istr->at(0))); + else { + // Transfer properties from input to output streamlines + trkwriter.WriteNextTrack(istr->size()/3, &(istr->at(0)), + NULL, &(iprop->at(0))); + iprop++; + } } trkwriter.Close(); @@ -733,6 +898,12 @@ int main(int argc, char **argv) { for (vector::iterator imask = excMask.begin(); imask < excMask.end(); imask++) MRIfree(&(*imask)); + for (vector::iterator imask = incTermMask.begin(); + imask < incTermMask.end(); imask++) + MRIfree(&(*imask)); + for (vector::iterator imask = excTermMask.begin(); + imask < excTermMask.end(); imask++) + MRIfree(&(*imask)); cout << "dmri_trk2trk done" << endl; return(0); @@ -831,8 +1002,8 @@ static int parse_commandline(int argc, char **argv) { nonlinXfmFile = fio_fullpath(pargv[0]); nargsused = 1; } - else if (!strcasecmp(option, "--invnl")) - doInvNonlin = 1; + else if (!strcasecmp(option, "--inv")) + doInvXfm = 1; else if (!strcasecmp(option, "--fill")) doFill = 1; else if (!strcmp(option, "--imask")) { @@ -851,6 +1022,22 @@ static int parse_commandline(int argc, char **argv) { nargsused++; } } + else if (!strcmp(option, "--itmask")) { + if (nargc < 1) CMDargNErr(option,1); + nargsused = 0; + while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { + incTermMaskList.push_back(pargv[nargsused]); + nargsused++; + } + } + else if (!strcmp(option, "--etmask")) { + if (nargc < 1) CMDargNErr(option,1); + nargsused = 0; + while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { + excTermMaskList.push_back(pargv[nargsused]); + nargsused++; + } + } else if (!strcasecmp(option, "--lmin")) { if (nargc < 1) CMDargNErr(option,1); sscanf(pargv[0], "%d", &lengthMin); @@ -869,6 +1056,12 @@ static int parse_commandline(int argc, char **argv) { nargsused = 1; doNth = 1; } + else if (!strcasecmp(option, "--every")) { + if (nargc < 1) CMDargNErr(option,1); + sscanf(pargv[0], "%d", &everyNum); + nargsused = 1; + doEvery = 1; + } else { fprintf(stderr,"ERROR: Option %s unknown\n",option); if (CMDsingleDash(option)) @@ -896,11 +1089,11 @@ static void print_usage(void) << " Input directory (optional)" << endl << " If specified, names of input .trk files are relative to this" << endl << " --out [...]:" << endl - << " Output .trk file(s), as many as inputs" << endl + << " Output .trk file(s), as many as inputs (or 1 to merge inputs)" << endl << " --outasc [...]:" << endl - << " Output ASCII plain text file(s), as many as inputs" << endl + << " Output ASCII plain text file(s), as many as inputs (or 1 to merge inputs)" << endl << " --outvol [...]:" << endl - << " Output volume(s), as many as inputs" << endl + << " Output volume(s), as many as inputs (or 1 to merge inputs)" << endl << " --outdir :" << endl << " Output directory (optional)" << endl << " If specified, names of output .trk files and volumes are relative to this)" << endl @@ -909,11 +1102,11 @@ static void print_usage(void) << " --outref :" << endl << " Output reference volume" << endl << " --reg :" << endl - << " Affine registration (.mat), applied first" << endl + << " Affine registration file (.lta or .mat), applied first" << endl << " --regnl :" << endl - << " Nonlinear registration (.m3z), applied second" << endl - << " --invnl:" << endl - << " Apply inverse of nonlinear warp (with --regnl, default: no)" << endl + << " Nonlinear registration file (.m3z), applied second" << endl + << " --inv:" << endl + << " Apply inverse of registration (default: no)" << endl << " --fill:" << endl << " Fill gaps b/w mapped points by linear interpolation" << endl << " (Default: don't fill)" << endl @@ -921,6 +1114,10 @@ static void print_usage(void) << " Inclusion mask(s), applied to all input .trk files" << endl << " --emask [...]:" << endl << " Exclusion mask(s), applied to all input .trk files" << endl + << " --itmask [...]:" << endl + << " Terminal inclusion mask(s), applied to all input .trk files" << endl + << " --etmask [...]:" << endl + << " Terminal exclusion mask(s), applied to all input .trk files" << endl << " --lmin :" << endl << " Only save streamlines with length greater than this number" << endl << " --lmax :" << endl @@ -929,6 +1126,8 @@ static void print_usage(void) << " Only save the mean streamline (Default: save all)" << endl << " --nth :" << endl << " Only save the n-th (0-based) streamline (Default: save all)" << endl + << " --every :" << endl + << " Only save every n-th streamline (Default: save all)" << endl << endl << "Other options" << endl << " --debug: turn on debugging" << endl @@ -937,7 +1136,7 @@ static void print_usage(void) << " --version: print out version and exit" << endl << endl << "Order of operations (all optional):" << endl - << " 1. Keep n-th streamline only" << endl + << " 1. Keep the n-th streamline or every n-th streamline" << endl << " 2. Apply streamline length threshold(s)" << endl << " 3. Apply affine transform" << endl << " 4. Apply non-linear transform" << endl @@ -983,23 +1182,27 @@ static void check_options(void) { nTract = inTrkList.size() + inAscList.size(); + if (nTract > 1 && (outTrkList.size() == 1 || outAscList.size() == 1 + || outVolList.size() == 1)) + doMerge = true; + if (outTrkList.empty() && outAscList.empty() && outVolList.empty()) { cout << "ERROR: must specify output .trk or text or volume file(s)" << endl; exit(1); } - if (!outTrkList.empty() && outTrkList.size() != nTract) { - cout << "ERROR: must specify as many output .trk files as input files" - << endl; + if (outTrkList.size() > 1 && outTrkList.size() != nTract) { + cout << "ERROR: number of output .trk files (" << outTrkList.size() + << ") does not match number of input files (" << nTract << ")" << endl; exit(1); } - if (!outAscList.empty() && outAscList.size() != nTract) { - cout << "ERROR: must specify as many output text files as input .trk files" - << endl; + if (outAscList.size() > 1 && outAscList.size() != nTract) { + cout << "ERROR: number of output text files (" << outAscList.size() + << ") does not match number of input files (" << nTract << ")" << endl; exit(1); } - if (!outVolList.empty() && outVolList.size() != nTract) { - cout << "ERROR: must specify as many output volumes as input .trk files" - << endl; + if (outVolList.size() > 1 && outVolList.size() != nTract) { + cout << "ERROR: number of output volumes (" << outVolList.size() + << ") does not match number of input files (" << nTract << ")" << endl; exit(1); } if (inRefFile.empty()) { @@ -1014,6 +1217,10 @@ static void check_options(void) { cout << "ERROR: cannot use both --mean and --nth" << endl; exit(1); } + if (doEvery && doNth) { + cout << "ERROR: cannot use both --every and --nth" << endl; + exit(1); + } return; } @@ -1028,59 +1235,71 @@ static void dump_options(FILE *fp) { << "machine " << uts.machine << endl << "user " << VERuser() << endl; - if (!inDir.empty()) { + if (!inDir.empty()) cout << "Input directory: " << inDir << endl; - } if (!inTrkList.empty()) { cout << "Input .trk files:"; - for (auto istr = inTrkList.begin(); istr < inTrkList.end(); istr++) { + for (vector::const_iterator istr = inTrkList.begin(); + istr < inTrkList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!inAscList.empty()) { cout << "Input text files:"; - for (auto istr = inAscList.begin(); istr < inAscList.end(); istr++) { + for (vector::const_iterator istr = inAscList.begin(); + istr < inAscList.end(); istr++) cout << " " << *istr; - } cout << endl; } - if (!outDir.empty()) { + if (!outDir.empty()) cout << "Output directory: " << outDir << endl; - } if (!outTrkList.empty()) { cout << "Output .trk files:"; - for (auto istr = outTrkList.begin(); istr < outTrkList.end(); istr++) { + for (vector::const_iterator istr = outTrkList.begin(); + istr < outTrkList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!outAscList.empty()) { cout << "Output text files:"; - for (auto istr = outAscList.begin(); istr < outAscList.end(); istr++) { + for (vector::const_iterator istr = outAscList.begin(); + istr < outAscList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!outVolList.empty()) { cout << "Output volumes:"; - for (auto istr = outVolList.begin(); istr < outVolList.end(); istr++) { + for (vector::const_iterator istr = outVolList.begin(); + istr < outVolList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!incMaskList.empty()) { cout << "Inclusion mask volumes:"; - for (auto istr = incMaskList.begin(); istr < incMaskList.end(); istr++) { + for (vector::const_iterator istr = incMaskList.begin(); + istr < incMaskList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (!excMaskList.empty()) { cout << "Exclusion mask volumes:"; - for (auto istr = excMaskList.begin(); istr < excMaskList.end(); istr++) { + for (vector::const_iterator istr = excMaskList.begin(); + istr < excMaskList.end(); istr++) + cout << " " << *istr; + cout << endl; + } + if (!incTermMaskList.empty()) { + cout << "Terminal inclusion mask volumes:"; + for (vector::const_iterator istr = incTermMaskList.begin(); + istr < incTermMaskList.end(); istr++) + cout << " " << *istr; + cout << endl; + } + if (!excTermMaskList.empty()) { + cout << "Terminal exclusion mask volumes:"; + for (vector::const_iterator istr = excTermMaskList.begin(); + istr < excTermMaskList.end(); istr++) cout << " " << *istr; - } cout << endl; } if (lengthMin > -1) @@ -1089,21 +1308,23 @@ static void dump_options(FILE *fp) { cout << "Upper length threshold: " << lengthMax << endl; cout << "Input reference: " << inRefFile << endl; cout << "Output reference: " << outRefFile << endl; - if (!affineXfmFile.empty()) { + if (!affineXfmFile.empty()) cout << "Affine registration: " << affineXfmFile << endl; - } - if (!nonlinXfmFile.empty()) { + if (!nonlinXfmFile.empty()) cout << "Nonlinear registration: " << nonlinXfmFile << endl; - cout << "Invert nonlinear morph: " << doInvNonlin << endl; - } + if (!(affineXfmFile.empty() && nonlinXfmFile.empty())) + cout << "Invert registration: " << doInvXfm << endl; cout << "Fill gaps between points: " << doFill << endl; - if (doMean) { - cout << "Saving mean streamline" << endl; - } else if (doNth) { - cout << "Saving single streamline: " << strNum << endl; - } else { - cout << "Saving all streamlines" << endl; + if (doNth) + cout << "Keeping n-th streamline only: " << strNum << endl; + else { + if (doEvery) + cout << "Keeping every n-th streamline: " << everyNum << endl; + if (doMean) + cout << "Keeping mean streamline" << endl; } + if (doMerge) + cout << "Merging multiple inputs into a single output" << endl; return; } diff --git a/trc/dmri_vox2vox.cxx b/trc/dmri_vox2vox.cxx index cc71354553c..5c64866ffc4 100644 --- a/trc/dmri_vox2vox.cxx +++ b/trc/dmri_vox2vox.cxx @@ -6,7 +6,7 @@ /* * Original Author: Anastasia Yendiki * - * Copyright © 2021 The General Hospital Corporation (Boston, MA) "MGH" + * Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH" * * Terms and conditions for use, reproduction, distribution and contribution * are found in the 'FreeSurfer Software License Agreement' contained @@ -63,9 +63,10 @@ int main(int argc, char *argv[]) ; const char *Progname = "dmri_vox2vox"; -int doInvNonlin = 0, nin = 0, nout = 0; -std::string inDir, outDir, inRefFile, outRefFile, affineXfmFile, nonlinXfmFile; -std::vector inFile, outFile; +int doInvNonlin = 0; +unsigned int nFile = 0; +string inDir, outDir, inRefFile, outRefFile, affineXfmFile, nonlinXfmFile; +vector inFile, outFile; struct utsname uts; char *cmdline, cwd[2000]; @@ -75,7 +76,7 @@ Timer cputimer; /*--------------------------------------------------*/ int main(int argc, char **argv) { int nargs, cputime; - std::string fname; + string fname; vector point(3); MRI *inref = 0, *outref = 0; AffineReg affinereg; @@ -111,34 +112,29 @@ int main(int argc, char **argv) { // Read transform files #ifndef NO_CVS_UP_IN_HERE if (!nonlinXfmFile.empty()) { - if (!affineXfmFile.empty()) { - affinereg.ReadXfm(affineXfmFile.c_str(), inref, 0); - } - nonlinreg.ReadXfm(nonlinXfmFile.c_str(), outref); - } else { -#endif - if (!affineXfmFile.empty()) { - affinereg.ReadXfm(affineXfmFile.c_str(), inref, outref); - } -#ifndef NO_CVS_UP_IN_HERE + if (!affineXfmFile.empty()) + affinereg.ReadXfm(affineXfmFile, inref, outref); + nonlinreg.ReadXfm(nonlinXfmFile, outref); } + else #endif + if (!affineXfmFile.empty()) + affinereg.ReadXfm(affineXfmFile, inref, outref); - for (int k = 0; k < nout; k++) { + for (unsigned int ifile = 0; ifile < nFile; ifile++) { float coord; ifstream infile; ofstream outfile; vector inpts; - printf("Processing coordinate file %d of %d...\n", k+1, nout); + printf("Processing coordinate file %d of %d...\n", ifile+1, nFile); cputimer.reset(); // Read input text file - if (!inDir.empty()) { - fname = inDir + '/' + inFile.at(k); - } else { - fname = inFile.at(k); - } + fname = inFile[ifile]; + + if (!inDir.empty()) + fname = inDir + "/" + fname; infile.open(fname, ios::in); if (!infile) { @@ -180,11 +176,10 @@ int main(int argc, char **argv) { } // Write output text file - if (!outDir.empty()) { - fname = outDir + '/' + outFile.at(k); - } else { - fname = outFile.at(k); - } + fname = outFile[ifile]; + + if (!outDir.empty()) + fname = outDir + "/" + fname; outfile.open(fname, ios::out); if (!outfile) { @@ -243,7 +238,6 @@ static int parse_commandline(int argc, char **argv) { while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { inFile.push_back(pargv[nargsused]); nargsused++; - nin++; } } else if (!strcmp(option, "--outdir")) { @@ -257,7 +251,6 @@ static int parse_commandline(int argc, char **argv) { while (nargsused < nargc && strncmp(pargv[nargsused], "--", 2)) { outFile.push_back(pargv[nargsused]); nargsused++; - nout++; } } else if (!strcmp(option, "--inref")) { @@ -353,15 +346,13 @@ static void print_version(void) { /* --------------------------------------------- */ static void check_options(void) { - if(nin == 0) { + nFile = inFile.size(); + + if(nFile == 0) { printf("ERROR: must specify input text file(s)\n"); exit(1); } - if(nout == 0) { - printf("ERROR: must specify output text file(s)\n"); - exit(1); - } - if(nout != nin) { + if(outFile.size() != nFile) { printf("ERROR: must specify as many output text files as input files\n"); exit(1); } @@ -387,29 +378,22 @@ static void dump_options(FILE *fp) { fprintf(fp,"machine %s\n",uts.machine); fprintf(fp,"user %s\n",VERuser()); - if (!inDir.empty()) { + if (!inDir.empty()) fprintf(fp, "Input directory: %s\n", inDir.c_str()); - } fprintf(fp, "Input files:"); - for (int k = 0; k < nin; k++) { - fprintf(fp, " %s", inFile.at(k).c_str()); - } + for (unsigned int ifile = 0; ifile < nFile; ifile++) + fprintf(fp, " %s", inFile[ifile].c_str()); fprintf(fp, "\n"); - if (!outDir.empty()) { + if (!outDir.empty()) fprintf(fp, "Output directory: %s\n", outDir.c_str()); - } - if (nout > 0) { - fprintf(fp, "Output files:"); - for (int k = 0; k < nout; k++) { - fprintf(fp, " %s", outFile.at(k).c_str()); - } - fprintf(fp, "\n"); - } + fprintf(fp, "Output files:"); + for (unsigned int ifile = 0; ifile < nFile; ifile++) + fprintf(fp, " %s", outFile[ifile].c_str()); + fprintf(fp, "\n"); fprintf(fp, "Input reference: %s\n", inRefFile.c_str()); fprintf(fp, "Output reference: %s\n", outRefFile.c_str()); - if (!affineXfmFile.empty()) { + if (!affineXfmFile.empty()) fprintf(fp, "Affine registration: %s\n", affineXfmFile.c_str()); - } if (!nonlinXfmFile.empty()) { fprintf(fp, "Nonlinear registration: %s\n", nonlinXfmFile.c_str()); fprintf(fp, "Invert nonlinear morph: %d\n", doInvNonlin); diff --git a/trc/forrest.cxx b/trc/forrest.cxx index 3776980d6ea..ec67bad5db4 100644 --- a/trc/forrest.cxx +++ b/trc/forrest.cxx @@ -63,9 +63,9 @@ Forrest::~Forrest() { // // Read data for test subject // -void Forrest::ReadTestSubject(const char *TestDir, const char *MaskFile, - const char *AsegFile, const char *OrientFile) { - string dirname = string(TestDir) + "/", +void Forrest::ReadTestSubject(const string TestDir, const string MaskFile, + const string AsegFile, const string OrientFile) { + string dirname = TestDir + "/", fname; if (mMask) @@ -86,7 +86,7 @@ void Forrest::ReadTestSubject(const char *TestDir, const char *MaskFile, if (mAseg) MRIfree(&mAseg); - if (AsegFile) { + if (!AsegFile.empty()) { fname = dirname + AsegFile; cout << "Loading test anatomical segmentation from " << fname << endl; mAseg = MRIread(fname.c_str()); @@ -99,7 +99,7 @@ void Forrest::ReadTestSubject(const char *TestDir, const char *MaskFile, if (mOrient) MRIfree(&mOrient); - if (OrientFile) { + if (!OrientFile.empty()) { fname = dirname + OrientFile; cout << "Loading test diffusion orientations from " << fname << endl; mOrient = MRIread(fname.c_str()); @@ -113,11 +113,11 @@ void Forrest::ReadTestSubject(const char *TestDir, const char *MaskFile, // // Read data for training subjects // -void Forrest::ReadTrainingSubjects(const char *TrainListFile, - const char *MaskFile, - const char *AsegFile, - const char *OrientFile, - vector TractFileList) { +void Forrest::ReadTrainingSubjects(const string TrainListFile, + const string MaskFile, + const string AsegFile, + const string OrientFile, + vector TractFileList) { string dirname; vector dirlist; ifstream listfile(TrainListFile, ios::in); @@ -150,7 +150,7 @@ void Forrest::ReadTrainingSubjects(const char *TrainListFile, exit(1); } - if (AsegFile) { + if (!AsegFile.empty()) { fname = *idir + AsegFile; cout << "Loading training anatomical segmentation from " << fname << endl; asegvol = MRIread(fname.c_str()); @@ -160,7 +160,7 @@ void Forrest::ReadTrainingSubjects(const char *TrainListFile, } } - if (OrientFile) { + if (!OrientFile.empty()) { fname = *idir + OrientFile; cout << "Loading training diffusion orientations from " << fname << endl; orientvol = MRIread(fname.c_str()); @@ -170,7 +170,7 @@ void Forrest::ReadTrainingSubjects(const char *TrainListFile, } } - for (vector::const_iterator ifile = TractFileList.begin(); + for (vector::const_iterator ifile = TractFileList.begin(); ifile < TractFileList.end(); ifile++) { MRI *tractvol; diff --git a/trc/forrest.h b/trc/forrest.h index d4bf51075a9..617bb484687 100644 --- a/trc/forrest.h +++ b/trc/forrest.h @@ -22,6 +22,7 @@ #define FORREST_H #include +#include #include #include #include @@ -35,11 +36,15 @@ class Forrest { public: Forrest(); ~Forrest(); - void ReadTestSubject(const char *TestDir, const char *MaskFile, - const char *AsegFile, const char *OrientFile); - void ReadTrainingSubjects(const char *TrainListFile, const char *MaskFile, - const char *AsegFile, const char *OrientFile, - std::vector TractFileList); + void ReadTestSubject(const std::string TestDir, + const std::string MaskFile, + const std::string AsegFile, + const std::string OrientFile); + void ReadTrainingSubjects(const std::string TrainListFile, + const std::string MaskFile, + const std::string AsegFile, + const std::string OrientFile, + std::vector TractFileList); int GetNx(); int GetNy(); int GetNz(); diff --git a/trc/spline.cxx b/trc/spline.cxx index 11f4a5a485d..f382f9cb807 100644 --- a/trc/spline.cxx +++ b/trc/spline.cxx @@ -156,7 +156,7 @@ vector CurveFill(const vector &InPoints) { // // Catmull-Rom cubic spline class // -Spline::Spline(const char *ControlPointFile, const char *MaskFile) { +Spline::Spline(const string ControlPointFile, const string MaskFile) { ReadControlPoints(ControlPointFile); mMask = 0; mVolume = 0; @@ -317,9 +317,9 @@ bool Spline::FitControlPoints(const vector &InputPoints) { mingap = (int) ceil(seglen / 2); float s = 0; vector isfinal(mNumControl, false); - vector peeksegs; - vector peekcurvs, arcparam(npts); - vector< vector::const_iterator > peekpts, dompts(mNumControl); + vector peaksegs; + vector peakcurvs, arcparam(npts); + vector< vector::const_iterator > peakpts, dompts(mNumControl); vector::iterator iarc = arcparam.begin(); cout << "INFO: Minimum allowable distance between dominant points is " @@ -354,8 +354,8 @@ bool Spline::FitControlPoints(const vector &InputPoints) { *(dompts.end() - 1) = mAllPoints.end() - 3; // Last point - // Find points where local peeks in curvature occur - cout << "INFO: Points where local peeks in curvature occur are" << endl; + // Find points where local peaks in curvature occur + cout << "INFO: Points where local peaks in curvature occur are" << endl; for (vector::const_iterator icurv = mCurvature.begin() + mingap; icurv < mCurvature.end() - mingap; @@ -366,9 +366,9 @@ bool Spline::FitControlPoints(const vector &InputPoints) { vector::const_iterator ipt = mAllPoints.begin() + 3*kpt; // Save info for this candidate point - peeksegs.push_back(idx); - peekcurvs.push_back(*icurv); - peekpts.push_back(ipt); + peaksegs.push_back(idx); + peakcurvs.push_back(*icurv); + peakpts.push_back(ipt); cout << " " << *ipt << " " << *(ipt+1) << " " << *(ipt+2) << " (curv = " << *icurv << ")" << endl; @@ -379,15 +379,15 @@ bool Spline::FitControlPoints(const vector &InputPoints) { *(isfinal.end() - 1) = true; // Go down the list of candidate points to pick out dominant points - while (!peekcurvs.empty()) { + while (!peakcurvs.empty()) { // Find candidate point with maximum curvature - const int ipeek = max_element(peekcurvs.begin(), peekcurvs.end()) - - peekcurvs.begin(), - iseg = peeksegs.at(ipeek); + const int ipeak = max_element(peakcurvs.begin(), peakcurvs.end()) - + peakcurvs.begin(), + iseg = peaksegs.at(ipeak); const bool isLfinal = isfinal.at(iseg), isRfinal = isfinal.at(iseg+1); vector::iterator imatch; - vector::const_iterator ipt = peekpts.at(ipeek), + vector::const_iterator ipt = peakpts.at(ipeak), iptL = dompts.at(iseg), iptR = dompts.at(iseg+1); const int distL = (ipt - iptL) / 3, @@ -406,21 +406,21 @@ bool Spline::FitControlPoints(const vector &InputPoints) { } // Remove point from list of candidate points - peeksegs.erase(peeksegs.begin() + ipeek); - peekcurvs.erase(peekcurvs.begin() + ipeek); - peekpts.erase(peekpts.begin() + ipeek); + peaksegs.erase(peaksegs.begin() + ipeak); + peakcurvs.erase(peakcurvs.begin() + ipeak); + peakpts.erase(peakpts.begin() + ipeak); // Also remove any other candidate points that are in the same segment - imatch = find(peeksegs.begin(), peeksegs.end(), iseg); + imatch = find(peaksegs.begin(), peaksegs.end(), iseg); - while (imatch != peeksegs.end()) { - int irem = imatch - peeksegs.begin(); + while (imatch != peaksegs.end()) { + int irem = imatch - peaksegs.begin(); - peeksegs.erase(peeksegs.begin() + irem); - peekcurvs.erase(peekcurvs.begin() + irem); - peekpts.erase(peekpts.begin() + irem); + peaksegs.erase(peaksegs.begin() + irem); + peakcurvs.erase(peakcurvs.begin() + irem); + peakpts.erase(peakpts.begin() + irem); - imatch = find(peeksegs.begin(), peeksegs.end(), iseg); + imatch = find(peaksegs.begin(), peaksegs.end(), iseg); } } @@ -709,7 +709,7 @@ void Spline::ComputeCurvature(const bool DoAnalytical) { // // Read control points from file // -void Spline::ReadControlPoints(const char *ControlPointFile) { +void Spline::ReadControlPoints(const string ControlPointFile) { float coord; ifstream infile(ControlPointFile, ios::in); @@ -735,12 +735,12 @@ void Spline::ReadControlPoints(const char *ControlPointFile) { // // Read mask volume from file // -void Spline::ReadMask(const char *MaskFile) { +void Spline::ReadMask(const string MaskFile) { if (mMask) MRIfree(&mMask); if (mVolume) MRIfree(&mVolume); cout << "Loading spline mask from " << MaskFile << endl; - mMask = MRIread(MaskFile); + mMask = MRIread(MaskFile.c_str()); mVolume = MRIclone(mMask, NULL); } @@ -768,20 +768,20 @@ void Spline::SetMask(MRI *Mask) { // // Write spline to volume // -void Spline::WriteVolume(const char *VolumeFile, const bool ShowControls) { +void Spline::WriteVolume(const string VolumeFile, const bool ShowControls) { if (ShowControls) for (vector::const_iterator icpt = mControlPoints.begin(); icpt != mControlPoints.end(); icpt += 3) MRIsetVoxVal(mVolume, icpt[0], icpt[1], icpt[2], 0, 2); cout << "Writing spline volume to " << VolumeFile << endl; - MRIwrite(mVolume, VolumeFile); + MRIwrite(mVolume, VolumeFile.c_str()); } // // Write spline coordinates to file // -void Spline::WriteAllPoints(const char *TextFile) { +void Spline::WriteAllPoints(const string TextFile) { ofstream outfile(TextFile, ios::out); if (!outfile) { cout << "ERROR: Could not open " << TextFile << " for writing" << endl; @@ -798,7 +798,7 @@ void Spline::WriteAllPoints(const char *TextFile) { // // Write tangent vectors along spline to file // -void Spline::WriteTangent(const char *TextFile) { +void Spline::WriteTangent(const string TextFile) { ofstream outfile(TextFile, ios::out); if (!outfile) { cout << "ERROR: Could not open " << TextFile << " for writing" << endl; @@ -815,7 +815,7 @@ void Spline::WriteTangent(const char *TextFile) { // // Write normal vectors along spline to file // -void Spline::WriteNormal(const char *TextFile) { +void Spline::WriteNormal(const string TextFile) { ofstream outfile(TextFile, ios::out); if (!outfile) { cout << "ERROR: Could not open " << TextFile << " for writing" << endl; @@ -832,7 +832,7 @@ void Spline::WriteNormal(const char *TextFile) { // // Write curvatures along spline to file // -void Spline::WriteCurvature(const char *TextFile) { +void Spline::WriteCurvature(const string TextFile) { ofstream outfile(TextFile, ios::out); if (!outfile) { cout << "ERROR: Could not open " << TextFile << " for writing" << endl; @@ -849,7 +849,7 @@ void Spline::WriteCurvature(const char *TextFile) { // // Write the intensity values of each of a set of input volumes along the spline // -void Spline::WriteValues(vector &ValueVolumes, const char *TextFile) { +void Spline::WriteValues(vector &ValueVolumes, const string TextFile) { ofstream outfile(TextFile, ios::app); if (!outfile) { cout << "ERROR: Could not open " << TextFile << " for writing" << endl; diff --git a/trc/spline.h b/trc/spline.h index 2cb5d14dbb8..0b0e6e65d09 100644 --- a/trc/spline.h +++ b/trc/spline.h @@ -42,7 +42,7 @@ std::vector CurveFill(const std::vector &InPoints); class Spline { public: - Spline(const char *ControlPointFile, const char *MaskFile); + Spline(const std::string ControlPointFile, const std::string MaskFile); Spline(const std::vector &ControlPoints, MRI *Mask); Spline(const int NumControl, MRI *Mask); Spline(); @@ -54,16 +54,18 @@ class Spline { void ComputeTangent(const bool DoAnalytical=true); void ComputeNormal(const bool DoAnalytical=true); void ComputeCurvature(const bool DoAnalytical=true); - void ReadControlPoints(const char *ControlPointFile); - void ReadMask(const char *MaskFile); + void ReadControlPoints(const std::string ControlPointFile); + void ReadMask(const std::string MaskFile); void SetControlPoints(const std::vector &ControlPoints); void SetMask(MRI *Mask); - void WriteVolume(const char *VolumeFile, const bool ShowControls=false); - void WriteAllPoints(const char *TextFile); - void WriteTangent(const char *TextFile); - void WriteNormal(const char *TextFile); - void WriteCurvature(const char *TextFile); - void WriteValues(std::vector &ValueVolumes, const char *TextFile); + void WriteVolume(const std::string VolumeFile, + const bool ShowControls=false); + void WriteAllPoints(const std::string TextFile); + void WriteTangent(const std::string TextFile); + void WriteNormal(const std::string TextFile); + void WriteCurvature(const std::string TextFile); + void WriteValues(std::vector &ValueVolumes, + const std::string TextFile); std::vector ComputeAvg(std::vector &ValueVolumes); void PrintControlPoints(); void PrintAllPoints(); diff --git a/trc/vial.cxx b/trc/vial.cxx index f909c8c3d37..51299bb4d1a 100644 --- a/trc/vial.cxx +++ b/trc/vial.cxx @@ -41,15 +41,21 @@ AffineReg::~AffineReg() {} bool AffineReg::IsEmpty() { return mInToOut.empty(); } +bool AffineReg::IsInvEmpty() { return mOutToIn.empty(); } + // // Read affine registration matrix from file and set input/output resolutions // -void AffineReg::ReadXfm(const char *XfmFile, const MRI *InRefVol, - const MRI *OutRefVol) { +void AffineReg::ReadXfm(const string XfmFile, const MRI *InRefVol, + const MRI *OutRefVol) { + bool islta = false; + string matline; + // Read registration matrix from file mInToOut.clear(); + mOutToIn.clear(); - if (XfmFile) { + if (!XfmFile.empty()) { float val; ifstream infile(XfmFile, ios::in); @@ -59,12 +65,69 @@ void AffineReg::ReadXfm(const char *XfmFile, const MRI *InRefVol, } cout << "Loading affine registration from " << XfmFile << endl; - while (infile >> val) - mInToOut.push_back(val); + while (getline(infile, matline)) + if (strcmp(matline.c_str(), "src volume info") == 0) { + islta = true; + infile.close(); + break; + } + + if (islta) { // LTA format + MATRIX *mat; + LTA *lta; + + cout << "LTA registration format detected" << endl; + + lta = LTAread(XfmFile.c_str()); + if (lta == NULL) { + cout << "ERROR: cannot read " << XfmFile << endl; + exit(1); + } + + if (lta->type != LINEAR_RAS_TO_RAS) { + LTAchangeType(lta, LINEAR_RAS_TO_RAS); + + if (lta->type != LINEAR_RAS_TO_RAS) { + cout << "ERROR: cannot change LTA type to RAS_TO_RAS" << endl; + exit(1); + } + } + + getVolGeom(InRefVol, <a->xforms[0].src); + getVolGeom(OutRefVol, <a->xforms[0].dst); + + // Extract vox-to-vox transform matrix from LTA + LTAchangeType(lta, FSLREG_TYPE); + + mat = lta->xforms[0].m_L; + for (int i = 1; i < 5; i++) + for (int j = 1; j < 5; j++) + mInToOut.push_back(mat->rptr[i][j]); + + // Extract inverse transform matrix + LTAinvert(lta, lta); + + mat = lta->xforms[0].m_L; + for (int i = 1; i < 5; i++) + for (int j = 1; j < 5; j++) + mOutToIn.push_back(mat->rptr[i][j]); + + LTAfree(<a); + } + else { // FSL format + infile.clear(); + infile.seekg(0, ios::beg); - if (mInToOut.size() != 16) { - cout << "ERROR: File " << XfmFile << " must contain a 4x4 matrix" << endl; - exit(1); + while (infile >> val) + mInToOut.push_back(val); + + if (mInToOut.size() != 16) { + cout << "ERROR: Unrecognized transform format in " << XfmFile + << " - LTA or FSL format expected" << endl; + exit(1); + } + + cout << "FSL registration format detected" << endl; } } else { // Identity by default @@ -121,6 +184,34 @@ void AffineReg::ApplyXfm(vector &OutPoint, OutPoint[i] = pout[i] / pout[3] / mOutVoxelSize[i]; } +// +// Apply the inverse of an affine transform to a single point +// +void AffineReg::ApplyXfmInv(vector &OutPoint, + vector::const_iterator InPoint) { + vector::const_iterator in2out = mOutToIn.begin(); + vector pin, pout; + + pin.resize(4); + pout.resize(4); + + for (int i = 0; i < 3; i++) + pin[i] = InPoint[i] * mOutVoxelSize[i]; + pin[3] = 1; + + for (int i = 0; i < 4; i++) { + float psum = 0; + for (int j = 0; j < 4; j++) { + psum += (*in2out) * pin[j]; + in2out++; + } + pout[i] = psum; + } + + for (int i = 0; i < 3; i++) + OutPoint[i] = pout[i] / pout[3] / mInVoxelSize[i]; +} + // // Decompose an affine transform into its parameters // @@ -300,7 +391,7 @@ bool NonlinReg::IsEmpty() { return (mMorph->m_template == 0); } // // Read a non-linear transform from file // -void NonlinReg::ReadXfm(const char *XfmFile, MRI *OutRefVol) { +void NonlinReg::ReadXfm(const string XfmFile, MRI *RefVol) { unsigned int zlibBuffer = 5; ifstream xfile(XfmFile, ios::in); // Just to check if file exists @@ -311,10 +402,10 @@ void NonlinReg::ReadXfm(const char *XfmFile, MRI *OutRefVol) { xfile.close(); cout << "Loading non-linear registration from " << XfmFile << endl; - mMorph->m_template = OutRefVol; + mMorph->m_template = RefVol; try { - mMorph->load(XfmFile, zlibBuffer); + mMorph->load(XfmFile.c_str(), zlibBuffer); } catch (const char* msg) { cout << "Exception caught while loading registration: " << msg << endl; @@ -347,14 +438,19 @@ void NonlinReg::ApplyXfm(vector &OutPoint, // NonlinReg::NonlinReg() : mMorph(0) {} -NonlinReg::~NonlinReg() {} +NonlinReg::~NonlinReg() { + if (mMorph != NULL) { + GCAfree(&(mMorph->gca)); + GCAMfree(&mMorph); + } +} bool NonlinReg::IsEmpty() { return (mMorph == 0); } // // Read a non-linear transform from file // -void NonlinReg::ReadXfm(const char *XfmFile, MRI *OutRefVol) { +void NonlinReg::ReadXfm(const string XfmFile, MRI *RefVol) { ifstream xfile(XfmFile, ios::in); // Just to check if file exists if (!xfile) { cout << "ERROR: Could not open " << XfmFile << endl; @@ -363,12 +459,12 @@ void NonlinReg::ReadXfm(const char *XfmFile, MRI *OutRefVol) { xfile.close(); cout << "Loading non-linear registration from " << XfmFile << endl; - mMorph = GCAMreadAndInvertNonTal(XfmFile); + mMorph = GCAMreadAndInvertNonTal(XfmFile.c_str()); if (mMorph == NULL) exit(1); - mMorph->gca = gcaAllocMax(1, 1, 1, OutRefVol->width, OutRefVol->height, - OutRefVol->depth, 0, 0); + mMorph->gca = gcaAllocMax(1, 1, 1, RefVol->width, RefVol->height, + RefVol->depth, 0, 0); } // diff --git a/trc/vial.h b/trc/vial.h index e7eb8a190e8..5af3bc04df4 100644 --- a/trc/vial.h +++ b/trc/vial.h @@ -47,10 +47,13 @@ class AffineReg { AffineReg(std::vector &InToOut); ~AffineReg(); bool IsEmpty(); - void ReadXfm(const char *XfmFile, const MRI *InRefVol, - const MRI *OutRefVol); + bool IsInvEmpty(); + void ReadXfm(const std::string XfmFile, const MRI *InRefVol, + const MRI *OutRefVol); void ApplyXfm(std::vector &OutPoint, std::vector::const_iterator InPoint); + void ApplyXfmInv(std::vector &OutPoint, + std::vector::const_iterator InPoint); void DecomposeXfm(); void PrintScale(); void PrintShear(); @@ -61,7 +64,7 @@ class AffineReg { std::vector::const_iterator GetScale(); private: - std::vector mInToOut, // [4 x 4] + std::vector mInToOut, mOutToIn, // [4 x 4] mInVoxelSize, mOutVoxelSize, // [3] mTranslate, mRotate, mScale, mShear; // [3] }; @@ -72,7 +75,7 @@ class NonlinReg { NonlinReg(); ~NonlinReg(); bool IsEmpty(); - void ReadXfm(const char *XfmFile, MRI *OutRefVol); + void ReadXfm(const std::string XfmFile, MRI *RefVol); void ApplyXfm(std::vector &OutPoint, std::vector::const_iterator InPoint); void ApplyXfmInv(std::vector &OutPoint, diff --git a/utils/gca.cpp b/utils/gca.cpp index 4eea685c969..2230ae8a7f7 100644 --- a/utils/gca.cpp +++ b/utils/gca.cpp @@ -9652,6 +9652,39 @@ const char *cma_label_to_name(int label) return ("Tumor"); } + if (label == cc_body) { + return ("Corpus Callosum - Body"); + } + if (label == cc_bodypf) { + return ("Corpus Callosum - Body - Prefrontal"); + } + if (label == cc_bodypm) { + return ("Corpus Callosum - Body - Premotor"); + } + if (label == cc_bodyc) { + return ("Corpus Callosum - Body - Central"); + } + if (label == cc_bodyp) { + return ("Corpus Callosum - Body - Parietal"); + } + if (label == cc_bodyt) { + return ("Corpus Callosum - Body - Temporal"); + } + if (label == cc_genu) { + return ("Corpus Callosum - Genu"); + } + if (label == cc_rostrum) { + return ("Corpus Callosum - Rostrum"); + } + if (label == cc_splenium) { + return ("Corpus Callosum - Splenium"); + } + if (label == lh_af) { + return ("Left Arcuate Fasciculus"); + } + if (label == rh_af) { + return ("Right Arcuate Fasciculus"); + } if (label == lh_cst) { return ("Left Corticospinal Tract"); } @@ -9676,12 +9709,24 @@ const char *cma_label_to_name(int label) if (label == fminor) { return ("Corpus Callosum Forceps Minor"); } + if (label == acomm) { + return ("Anterior Commissure"); + } + if (label == mcp) { + return ("Middle Cerebellar Peduncle"); + } if (label == lh_atr) { return ("Left Anterior Thalamic Radiation"); } if (label == rh_atr) { return ("Right Anterior Thalamic Radiation"); } + if (label == lh_cb) { + return ("Left Cingulum Bundle"); + } + if (label == rh_cb) { + return ("Right Cingulum Bundle"); + } if (label == lh_ccg) { return ("Left Cingulum - Cingulate Gyrus"); } @@ -9694,6 +9739,30 @@ const char *cma_label_to_name(int label) if (label == rh_cab) { return ("Right Cingulum - Angular Bundle"); } + if (label == lh_slf) { + return ("Left Superior Longitudinal Fasciculus"); + } + if (label == rh_slf) { + return ("Right Superior Longitudinal Fasciculus"); + } + if (label == lh_slf1) { + return ("Left Superior Longitudinal Fasciculus - I"); + } + if (label == rh_slf1) { + return ("Right Superior Longitudinal Fasciculus - I"); + } + if (label == lh_slf2) { + return ("Left Superior Longitudinal Fasciculus - II"); + } + if (label == rh_slf2) { + return ("Right Superior Longitudinal Fasciculus - II"); + } + if (label == lh_slf3) { + return ("Left Superior Longitudinal Fasciculus - III"); + } + if (label == rh_slf3) { + return ("Right Superior Longitudinal Fasciculus - III"); + } if (label == lh_slfp) { return ("Left Superior Longitudinal Fasciculus - Parietal"); } @@ -9712,12 +9781,72 @@ const char *cma_label_to_name(int label) if (label == rh_ifof) { return ("Right Inferior Fronto-Occipital Fasciculus "); } - if (label == lh_fornix) { + if (label == lh_fx) { return ("Left Fornix"); } - if (label == rh_fornix) { + if (label == rh_fx) { return ("Right Fornix"); } + if (label == lh_fat) { + return ("Left Frontal Aslant Tract"); + } + if (label == rh_fat) { + return ("Right Frontal Aslant Tract"); + } + if (label == lh_or) { + return ("Left Optic Radiation"); + } + if (label == rh_or) { + return ("Right Optic Radiation"); + } + if (label == lh_mlf) { + return ("Left Middle Longitudinal Fasciculus"); + } + if (label == rh_mlf) { + return ("Right Middle Longitudinal Fasciculus"); + } + if (label == lh_afd) { + return ("Left Arcuate Fasciculus - Dorsal"); + } + if (label == rh_afd) { + return ("Right Arcuate Fasciculus - Dorsal"); + } + if (label == lh_afv) { + return ("Left Arcuate Fasciculus - Ventral"); + } + if (label == rh_afv) { + return ("Right Arcuate Fasciculus - Ventral"); + } + if (label == lh_ar) { + return ("Left Acoustic Radiation"); + } + if (label == rh_ar) { + return ("Right Acoustic Radiation"); + } + if (label == lh_cbd) { + return ("Left Cingulum Bundle - Dorsal"); + } + if (label == rh_cbd) { + return ("Right Cingulum Bundle - Dorsal"); + } + if (label == lh_cbv) { + return ("Left Cingulum Bundle - Ventral"); + } + if (label == rh_cbv) { + return ("Right Cingulum Bundle - Ventral"); + } + if (label == lh_emc) { + return ("Left Extreme Capsule"); + } + if (label == rh_emc) { + return ("Right Extreme Capsule"); + } + if (label == lh_uf) { + return ("Left Uncinate Fasciculus"); + } + if (label == rh_uf) { + return ("Right Uncinate Fasciculus"); + } if (label == Cbm_Left_I_IV) { return ("Cbm_Left_I_IV"); }