From 6593a7625b012cd82a465be2ace25e4ef312bd5e Mon Sep 17 00:00:00 2001
From: Saad Jbabdi <saad@fmrib.ox.ac.uk>
Date: Fri, 8 May 2009 10:49:37 +0000
Subject: [PATCH] nasty bug fix + target masks memory saving

---
 streamlines.cc | 225 ++++++++++++++++++++++++++++++++-----------------
 streamlines.h  |  15 +++-
 2 files changed, 162 insertions(+), 78 deletions(-)

diff --git a/streamlines.cc b/streamlines.cc
index 9868bee..693c366 100644
--- a/streamlines.cc
+++ b/streamlines.cc
@@ -37,33 +37,66 @@ namespace TRACT{
       exit(0);
     }
   }
-  void sjgradient(const volume<float>& im,volume4D<float>& grad){
-  
-  grad.reinitialize(im.xsize(),im.ysize(),im.zsize(),3);
-  copybasicproperties(im,grad[0]);
-
-  int fx,fy,fz,bx,by,bz;
-  float dx,dy,dz; 
-  for (int z=0; z<grad.zsize(); z++){
-    fz = z ==(grad.zsize()-1) ? 0 :  1;
-    bz = z == 0              ? 0 : -1;
-    dz = (fz==0 || bz==0)    ? 1.0 :  2.0;
-    for (int y=0; y<grad.ysize(); y++){
-      fy = y ==(grad.ysize()-1) ? 0 :  1;
-      by = y == 0              ? 0 : -1;
-      dy = (fy==0 || by==0)    ? 1.0 :  2.0;
-      for (int x=0; x<grad.xsize(); x++){
-	fx = x ==(grad.xsize()-1) ? 0 :  1;
-	bx = x == 0              ? 0 : -1;
-	dx = (fx==0 || bx==0)    ? 1.0 :  2.0;
-	grad[0](x,y,z) = (im(x+fx,y,z) - im(x+bx,y,z))/dx;
-	grad[1](x,y,z) = (im(x,y+fy,z) - im(x,y+by,z))/dy;
-	grad[2](x,y,z) = (im(x,y,z+fz) - im(x,y,z+bz))/dz;
+  void imgradient(const volume<float>& im,volume4D<float>& grad){
+    
+    grad.reinitialize(im.xsize(),im.ysize(),im.zsize(),3);
+    copybasicproperties(im,grad[0]);
+    
+    int fx,fy,fz,bx,by,bz;
+    float dx,dy,dz; 
+    for (int z=0; z<grad.zsize(); z++){
+      fz = z ==(grad.zsize()-1) ? 0 :  1;
+      bz = z == 0              ? 0 : -1;
+      dz = (fz==0 || bz==0)    ? 1.0 :  2.0;
+      for (int y=0; y<grad.ysize(); y++){
+	fy = y ==(grad.ysize()-1) ? 0 :  1;
+	by = y == 0              ? 0 : -1;
+	dy = (fy==0 || by==0)    ? 1.0 :  2.0;
+	for (int x=0; x<grad.xsize(); x++){
+	  fx = x ==(grad.xsize()-1) ? 0 :  1;
+	  bx = x == 0              ? 0 : -1;
+	  dx = (fx==0 || bx==0)    ? 1.0 :  2.0;
+	  grad[0](x,y,z) = (im(x+fx,y,z) - im(x+bx,y,z))/dx;
+	  grad[1](x,y,z) = (im(x,y+fy,z) - im(x,y+by,z))/dy;
+	  grad[2](x,y,z) = (im(x,y,z+fz) - im(x,y,z+bz))/dz;
+	}
       }
     }
+    
+  }
+  void imlookup(const volume<float>& im,volume<int>& vol2mat,Matrix& mat2vol){
+    vol2mat.reinitialize(im.xsize(),im.ysize(),im.zsize());
+    vol2mat = 0;
+
+    int nrows=0;
+    for(int Wz=im.minz();Wz<=im.maxz();Wz++)
+      for(int Wy=im.miny();Wy<=im.maxy();Wy++)
+	for(int Wx=im.minx();Wx<=im.maxx();Wx++)
+	  if(im(Wx,Wy,Wz)!=0){
+	    nrows++;
+	  }
+    mat2vol.ReSize(nrows,3);
+    nrows=0;
+    for(int Wz=im.minz();Wz<=im.maxz();Wz++)
+      for(int Wy=im.miny();Wy<=im.maxy();Wy++)
+	for(int Wx=im.minx();Wx<=im.maxx();Wx++)
+	  if(im(Wx,Wy,Wz)!=0){
+	    nrows++;
+	    mat2vol(nrows,1) = Wx;
+	    mat2vol(nrows,2) = Wy;
+	    mat2vol(nrows,3) = Wz;
+	    
+	    vol2mat(Wx,Wy,Wz) = nrows;
+
+	  }
+  }
+  
+  void  imfill(volume<float>& im,const ColumnVector& vec,const Matrix& lookup){
+    im = 0;
+    for(int i=1;i<=vec.Nrows();i++)
+      im(lookup(i,1),lookup(i,2),lookup(i,3)) = vec(i);
   }
 
-}
   
   Streamliner::Streamliner(const volume<float>& seeds):opts(probtrackxOptions::getInstance()),logger(LogSingleton::getInstance()),
 						       vols(opts.usef.value()),m_seeds(seeds){
@@ -143,9 +176,9 @@ namespace TRACT{
 	m_DTI_to_Seeds_warp = iffr.FieldAsNewimageVolume4D(true);
 
 	// now calculate the jacobian of this transformation (useful for rotating vectors)
-	sjgradient(m_Seeds_to_DTI_warp[0],m_jacx);
-	sjgradient(m_Seeds_to_DTI_warp[1],m_jacy);
-	sjgradient(m_Seeds_to_DTI_warp[2],m_jacz);
+	imgradient(m_Seeds_to_DTI_warp[0],m_jacx);
+	imgradient(m_Seeds_to_DTI_warp[1],m_jacy);
+	imgradient(m_Seeds_to_DTI_warp[2],m_jacz);
 
       }
     }
@@ -187,7 +220,13 @@ namespace TRACT{
     m_path.clear();
     x=xst;y=yst;z=zst;
     m_part.change_xyz(x,y,z);
-    m_part.set_dir(dir(1),dir(2),dir(3));//Set the start dir so that we track inwards from cortex
+    
+    //m_part.set_dir(dir(1),dir(2),dir(3));//Set the start dir so that we track inwards from cortex
+
+    if(opts.meshfile.value()!=""){ 
+      m_part.set_dir(dir(1),dir(2),dir(3));//Set the start dir so that we track inwards from cortex 
+    }
+
     
     int partlength=0;
     bool rubbish_passed=false;
@@ -199,8 +238,10 @@ namespace TRACT{
 	m_passed_flags[pf]=false;  /// only keep it if this streamline went through all the masks
       }
       
+
     for( int it = 1 ; it <= opts.nsteps.value()/2; it++){
       if( (m_mask( round(m_part.x()), round(m_part.y()), round(m_part.z())) > 0) ){
+
 	///////////////////////////////////
 	//loopchecking
 	///////////////////////////////////
@@ -231,7 +272,7 @@ namespace TRACT{
 	  xyz_seeds = NewimageCoord2NewimageCoord(m_Seeds_to_DTI_warp,false,m_mask,m_seeds,xyz_dti);
 	}
 
-
+	
 	int x_s =(int)round((float)xyz_seeds(1));
 	int y_s =(int)round((float)xyz_seeds(2));
 	int z_s =(int)round((float)xyz_seeds(3));
@@ -250,7 +291,7 @@ namespace TRACT{
 	    }
 	  }
 
-
+	
 	m_path.push_back(xyz_seeds);
 	partlength++;
 	
@@ -259,6 +300,7 @@ namespace TRACT{
 	if(opts.rubbishfile.value()!=""){
 	  if(m_rubbish(x_s,y_s,z_s)!=0){
 	    rubbish_passed=true;
+	    
 	    break;
 	  }
 	}
@@ -267,7 +309,10 @@ namespace TRACT{
 	    stop_flag=true;
 	  }
 	  //else
-	  if(stop_flag)break;
+	  if(stop_flag){
+	    
+	    break;
+	  }
 	}	  
 	  
 	if(opts.skipmask.value() == ""){
@@ -282,6 +327,7 @@ namespace TRACT{
 	tmp2=rand(); tmp2/=RAND_MAX;
 	if(th_ph_f(3)>tmp2){
 	  if(!m_part.check_dir(th_ph_f(1),th_ph_f(2),opts.c_thr.value())){
+	    
 	    break;
 	  }
 	    
@@ -307,7 +353,8 @@ namespace TRACT{
 	  
 	  
       }
-	
+
+      
     } // Close Step Number Loop
     if(opts.loopcheck.value()){
       m_loopcheck=0;
@@ -348,6 +395,10 @@ namespace TRACT{
   
   
   void Counter::initialise(){
+    // set lookup table for seed mask
+
+    imlookup(m_seeds,m_seeds_vol2mat,m_seeds_mat2vol);
+   
     if(opts.simpleout.value()||opts.matrix1out.value()){
       initialise_path_dist();
     }
@@ -364,47 +415,63 @@ namespace TRACT{
       initialise_maskmatrix();
     }
   }
+
   
   void Counter::initialise_seedcounts(){
     
-    volume<float> tmp;
+    // store only nonzero values of the target masks
+    volume<float> tmptarget,alltargets;
     volume<int> tmpint;
+    int numseeds;
+    numseeds = m_seeds_mat2vol.Nrows();
+    
+    ColumnVector scounter(numseeds);
+    scounter=0;
+
     read_masks(m_targetmasknames,opts.targetfile.value());
     m_targflags.resize(m_targetmasknames.size(),0);
-    //m_particle_numbers.resize(m_targetmasknames.size());
-    //tmpvec.reserve(opts.nparticles.value());
     cout<<"Number of masks "<<m_targetmasknames.size()<<endl;
-    //are they initialised to zero?
+    cout << "loading target masks - stage 1" << endl;
+
+    alltargets.reinitialize(m_seeds.xsize(),m_seeds.ysize(),m_seeds.zsize());
+    alltargets = 0;
+    for(unsigned int m=0;m<m_targetmasknames.size();m++){
+      cout << m+1 << endl;
+      read_volume(tmptarget,m_targetmasknames[m]);
+      alltargets += tmptarget;
+      m_seedcounts.push_back(scounter);
+    }
+    imlookup(alltargets,m_targets_vol2mat,m_targets_mat2vol);
+
+    cout << "loading target masks - stage 2" << endl;
+    m_targetmasks.ReSize(m_targets_mat2vol.Nrows(),m_targetmasknames.size());
+    m_targetmasks = 0;
     for(unsigned int m=0;m<m_targetmasknames.size();m++){
-      read_volume(tmp,m_targetmasknames[m]);
-      m_targetmasks.push_back(tmp);
-      copyconvert(tmp,tmpint);
-      tmpint=0;
-      m_seedcounts.push_back(tmpint);
-      //m_particle_numbers.push_back(tmpvec);
+      cout << m+1 << endl;
+      read_volume(tmptarget,m_targetmasknames[m]);
+      
+      for(int Wz=tmptarget.minz();Wz<=tmptarget.maxz();Wz++)
+	for(int Wy=tmptarget.miny();Wy<=tmptarget.maxy();Wy++)
+	  for(int Wx=tmptarget.minx();Wx<=tmptarget.maxx();Wx++){
+	    if(tmptarget.value(Wx,Wy,Wz)!=0){
+	      m_targetmasks( m_targets_vol2mat(Wx,Wy,Wz), m+1 ) = 1;
+	    }
+	  }
+      
     }
 
     // where we save the seed counts in text files
     if(opts.seedcountastext.value()){
-      
-      int numseeds=0;
-      if(opts.meshfile.value()==""){
-	for(int Wz=m_seeds.minz();Wz<=m_seeds.maxz();Wz++)
-	  for(int Wy=m_seeds.miny();Wy<=m_seeds.maxy();Wy++)
-	    for(int Wx=m_seeds.minx();Wx<=m_seeds.maxx();Wx++)
-	      if(m_seeds.value(Wx,Wy,Wz)!=0)
-		numseeds++;
-      }
-      else{
+      if(!fsl_imageexists(opts.seedfile.value()) && opts.meshfile.value()!=""){
+	numseeds=0;
 	ifstream fs(opts.seedfile.value().c_str());
 	if(fs){
 	  char buffer[1024];
 	  fs.getline(buffer,1024);
 	  fs >>numseeds;
-	  cout<<numseeds<<endl;
+	  //cout<<"numseeds="<<numseeds<<endl;
 	}
       }
-
       m_SeedCountMat.ReSize(numseeds,m_targetmasknames.size());
       m_SeedCountMat=0;
       m_SeedRow=1;
@@ -449,7 +516,7 @@ namespace TRACT{
     m_lrdim.ReSize(3);
     m_lrdim<<m_lrmask.xdim()<<m_lrmask.ydim()<<m_lrmask.zdim();
     int numseeds=0,numnz=0;
-    if(opts.meshfile.value()==""){
+    if(fsl_imageexists(opts.seedfile.value()) && opts.meshfile.value()==""){
     for(int Wz=m_seeds.minz();Wz<=m_seeds.maxz();Wz++)
       for(int Wy=m_seeds.miny();Wy<=m_seeds.maxy();Wy++)
 	for(int Wx=m_seeds.minx();Wx<=m_seeds.maxx();Wx++)
@@ -586,6 +653,7 @@ namespace TRACT{
   }
 
   void Counter::reset_beenhere(const bool& forwardflag,const bool& backwardflag){
+    
     if(forwardflag){
       for(unsigned int i=0;i<m_path.size();i++){
 	int x_s=int(round(float(m_path[i](1)))),y_s=int(round(float(m_path[i](2)))),z_s=int(round(float(m_path[i](3))));
@@ -603,24 +671,24 @@ namespace TRACT{
   
   
   void Counter::update_seedcounts(){
+
     const vector<ColumnVector>& path=m_stline.get_path_ref();
     int xseedvox=int(round(m_stline.get_x_seed()));
     int yseedvox=int(round(m_stline.get_y_seed()));
     int zseedvox=int(round(m_stline.get_z_seed()));
 
+
     if(!opts.pathdist.value()){
       for(unsigned int i=0;i<path.size();i++){
 	int x_s=int(round(float(path[i](1)))),y_s=int(round(float(path[i](2)))),z_s=int(round(float(path[i](3))));
 	for(unsigned int m=0;m<m_targetmasknames.size();m++){
-	  if(m_targetmasks[m](x_s,y_s,z_s)!=0 && m_targflags[m]==0){
-	    m_seedcounts[m](xseedvox,yseedvox,zseedvox)=m_seedcounts[m](xseedvox,yseedvox,zseedvox)+1;
-	    m_targflags[m]=1;
-	    //m_particle_numbers[m].push_back(particle_number);
-
-	    if(opts.seedcountastext.value())
-	      m_SeedCountMat(m_SeedRow,m+1) += 1;
-	    
-	  }
+	  if(m_targets_vol2mat(x_s,y_s,z_s)!=0 && m_targflags[m]==0)
+	    if(m_targetmasks(m_targets_vol2mat(x_s,y_s,z_s),m+1)!=0){
+	      m_seedcounts[m](m_seeds_vol2mat(xseedvox,yseedvox,zseedvox)) += 1;
+	      m_targflags[m]=1;
+	      if(opts.seedcountastext.value())
+		m_SeedCountMat(m_SeedRow,m+1) += 1;	    
+	    }
 	}
       }
     }
@@ -632,20 +700,20 @@ namespace TRACT{
 	if(i>0)
 	  d+=sqrt((path[i]-path[i-1]).SumSquare());
 	for(unsigned int m=0;m<m_targetmasknames.size();m++){
-	  if(m_targetmasks[m](x_s,y_s,z_s)!=0 && m_targflags[m]==0){
-	    m_seedcounts[m](xseedvox,yseedvox,zseedvox)+=(int)d;
-	    m_targflags[m]=1;
-	    //m_particle_numbers[m].push_back(particle_number);
-	    
-	    if(opts.seedcountastext.value())
-	      m_SeedCountMat(m_SeedRow,m+1) += d;
-
-	  }
+	  if(m_targets_vol2mat(x_s,y_s,z_s)!=0 && m_targflags[m]==0)
+	    if(m_targetmasks(m_targets_vol2mat(x_s,y_s,z_s),m+1)!=0){
+	      m_seedcounts[m](m_seeds_vol2mat(xseedvox,yseedvox,zseedvox)) += d;
+	      m_targflags[m]=1;
+	      
+	      if(opts.seedcountastext.value())
+		m_SeedCountMat(m_SeedRow,m+1) += d;
+	      
+	    }
 	}
 	
       }
     }
-    
+
   }
   
 
@@ -755,6 +823,7 @@ namespace TRACT{
   }
 
   void Counter::save(){
+    cout << "now saving various outputs" << endl;
     if(opts.simpleout.value()){
       save_pathdist();
     }
@@ -785,6 +854,9 @@ namespace TRACT{
   }
 
   void Counter::save_seedcounts(){
+    volume<float> seedcounts;
+    seedcounts.reinitialize(m_seeds.xsize(),m_seeds.ysize(),m_seeds.zsize());
+
     for(unsigned int m=0;m<m_targetmasknames.size();m++){
       string tmpname=m_targetmasknames[m];
       
@@ -801,7 +873,9 @@ namespace TRACT{
       //only take things after the last pos
       tmpname=tmpname.substr(lastpos+1,tmpname.length()-lastpos-1);
       
-      save_volume(m_seedcounts[m],logger.appendDir("seeds_to_"+tmpname));
+      imfill(seedcounts,m_seedcounts[m],m_seeds_mat2vol);
+
+      save_volume(seedcounts,logger.appendDir("seeds_to_"+tmpname));
     }
 
     if(opts.seedcountastext.value()){
@@ -913,7 +987,8 @@ namespace TRACT{
     
     // now re-orient dir using xfm transform
     ColumnVector rotdir(3);
-    m_stline.rotdir(dir,rotdir,x,y,z);
+    //m_stline.rotdir(dir,rotdir,x,y,z);
+    rotdir=dir;
 
     int nlines=0;
     for(int p=0;p<opts.nparticles.value();p++){
diff --git a/streamlines.h b/streamlines.h
index 08c5fa8..d6ca67b 100644
--- a/streamlines.h
+++ b/streamlines.h
@@ -32,6 +32,8 @@ namespace TRACT{
     Particle m_part;
     vector<ColumnVector> m_path;
     volume<int> m_mask;
+
+
     volume<int> m_skipmask;
     volume<int> m_rubbish;
     volume<int> m_stop;
@@ -40,6 +42,7 @@ namespace TRACT{
     vector<volume<float>* > m_waymasks;
     vector<bool> m_passed_flags;
     vector<bool> m_own_waymasks;
+
     Matrix m_Seeds_to_DTI;
     Matrix m_DTI_to_Seeds;
     volume4D<float> m_Seeds_to_DTI_warp;
@@ -49,6 +52,7 @@ namespace TRACT{
     volume4D<float> m_jacz;
     bool m_IsNonlinXfm;
     Matrix m_rotdir;
+
     Tractvolsx vols;
     float m_lcrat;
     float m_x_s_init;
@@ -117,14 +121,19 @@ namespace TRACT{
     Matrix m_I;
     vector<ColumnVector> m_path;
     
-    vector<volume<int> > m_seedcounts;
+    vector<ColumnVector> m_seedcounts;
     Matrix m_SeedCountMat;
     int    m_SeedRow;
 
-    vector<volume<float> > m_targetmasks;
+    Matrix m_targetmasks;
     vector<string> m_targetmasknames;
     vector<int> m_targflags;
-    //vector<vector<int> > m_particle_numbers;
+
+
+    volume<int> m_seeds_vol2mat;
+    Matrix      m_seeds_mat2vol;
+    volume<int> m_targets_vol2mat;
+    Matrix      m_targets_mat2vol;
 
     
     volume<int> m_ConMat;
-- 
GitLab