From 2dfbc61a953015da90d8be452a2a126c74ce354c Mon Sep 17 00:00:00 2001
From: Saad Jbabdi <saad@fmrib.ox.ac.uk>
Date: Tue, 17 Nov 2009 15:25:50 +0000
Subject: [PATCH] allows for two seperate transforms: one for resampling and
 one for reorienting + changes to the options

---
 vecreg.cc | 438 +++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 303 insertions(+), 135 deletions(-)

diff --git a/vecreg.cc b/vecreg.cc
index 820b3b2..29fba7b 100755
--- a/vecreg.cc
+++ b/vecreg.cc
@@ -16,36 +16,33 @@ using namespace Utilities;
 string title="vecreg (Version 1.0)\nVector Affine/non linear Tranformation with Orientation Preservation";
 string examples="vecreg -i <input4Dvector> -o <output4D> -t <transformation>";
 
-Option<bool> verbose(string("-v,--verbose"),false,
+Option<bool>   verbose(string("-v,--verbose"),false,
 		       string("switch on diagnostic messages"),
 		       false,no_argument);
-Option<bool> help(string("-h,--help"),false,
-		       string("display this message"),
-		       false,no_argument);
-Option<string> ivector(string("-i,--input"),string(""),
-		       string("filename of input vector"),
-		       false,requires_argument);
-Option<string> itensor(string("--tensor"),string(""),
-		       string("full tensor"),
-		       false,requires_argument);
-Option<string> ovector(string("-o,--output"),string(""),
-		       string("filename of output registered vector"),
-		       true,requires_argument);
+Option<bool>   help(string("-h,--help"),false,
+		    string("display this message"),
+		    false,no_argument);
+Option<string> infilename(string("-i,--input"),string(""),
+			  string("filename of input vector or tensor field"),
+			  true,requires_argument);
+Option<string> outfilename(string("-o,--output"),string(""),
+			   string("filename of output registered vector or tensor field"),
+			   true,requires_argument);
 Option<string> ref(string("-r,--ref"),string(""),
-		       string("filename of reference (target) volume"),
-		       true,requires_argument);
-Option<string> matrix(string("-t,--affine"),string(""),
-		       string("filename of affine transformation matrix"),
-		       false,requires_argument);
-Option<string> warp(string("-w,--warpfield"),string(""),
-		       string("filename of 4D warp field for nonlinear registration"),
-		       false,requires_argument);
-Option<string> interpmethod(string("--interp"),"",
-		       string("interpolation method : nearestneighbour, trilinear (default) or sinc"),
+		   string("filename of reference (target) volume"),
+		   true,requires_argument);
+Option<string> transformation(string("-t,--transform"),string(""),
+			 string("filename of transformation matrix/warpfield"),
+			 true,requires_argument);
+Option<string> rotform(string("-w,--rotation"),string(""),
+		       string("filename of rotation matrix/warpfield (default=estimate from transform)"),
 		       false,requires_argument);
 Option<string> maskfile(string("-m,--mask"),string(""),
 		       string("brain mask in input space"),
 		       false,requires_argument);
+Option<string> interpmethod(string("--interp"),"",
+		       string("interpolation method : nearestneighbour, trilinear (default), sinc or spline"),
+		       false,requires_argument);
 ////////////////////////////////////////////////////////
 
 ReturnMatrix rodrigues(const float& angle,ColumnVector& w){
@@ -137,19 +134,48 @@ ReturnMatrix ppd(const Matrix& F,ColumnVector& e1){
   return R;
 }
 
+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 vecreg_aff(const volume4D<float>& tens,
 		volume4D<float>& oV1,
 		const volume<float>& refvol,
-		const Matrix& M,
-		const volume<float>& mask){
+		const Matrix& M1,const Matrix& M2,
+		const volume<float>& mask,bool istensor){
+
 
   Matrix iM(4,4),R(3,3);
-  iM=M.i();
+  iM=M1.i();
   // extract rotation matrix from M
   Matrix F(3,3),u(3,3),v(3,3);
   DiagonalMatrix d(3);
-  F=M.SubMatrix(1,3,1,3);
+  F=M2.SubMatrix(1,3,1,3);
   SVD(F*F.t(),d,u,v);
   R=(u*sqrt(d)*v.t()).i()*F;
 
@@ -180,13 +206,13 @@ void vecreg_aff(const volume4D<float>& tens,
 		     << tens[5].interpolate(X_seed(1),X_seed(2),X_seed(3));
 
 
-	if(ivector.set()){
+	if(!istensor){
 	  // compute first eigenvector
 	  EigenValues(Tens,d,v);
 	  V_seed = v.Column(3);
 	  
 	  // rotate vector
-	  V_target=F*V_seed;
+	  V_target=R*V_seed;
 	  if(V_target.MaximumAbsoluteValue()>0)
 	    V_target/=sqrt(V_target.SumSquare());
 
@@ -194,9 +220,8 @@ void vecreg_aff(const volume4D<float>& tens,
 	  oV1(x,y,z,1)=V_target(2);
 	  oV1(x,y,z,2)=V_target(3);
 	}
-	
 	// create tensor
-	if(ivector.unset()){
+	else{
 	  Tens << R*Tens*R.t();
 	  
 	  oV1(x,y,z,0)=Tens(1,1);
@@ -211,59 +236,117 @@ void vecreg_aff(const volume4D<float>& tens,
       }
   
 }
-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 vecreg_aff(const volume4D<float>& tens,
+		volume4D<float>& oV1,
+		const volume<float>& refvol,
+		const Matrix& M1,const volume4D<float>& warpvol2,
+		const volume<float>& mask,bool istensor){
+
+  Matrix iM(4,4),R(3,3);
+  iM=M1.i();
+
+
+  // compute transformation jacobian
+  volume4D<float> jx(mask.xsize(),mask.ysize(),mask.zsize(),3);
+  volume4D<float> jy(mask.xsize(),mask.ysize(),mask.zsize(),3);
+  volume4D<float> jz(mask.xsize(),mask.ysize(),mask.zsize(),3);
+  sjgradient(warpvol2[0],jx);
+  sjgradient(warpvol2[1],jy);
+  sjgradient(warpvol2[2],jz);
+
+
+
+  Matrix I(3,3);I<<1<<0<<0<<0<<1<<0<<0<<0<<1;
+  Matrix F(3,3),Jw(3,3),u(3,3),v(3,3);
+  DiagonalMatrix d(3);  
 
+  ColumnVector seeddim(3),targetdim(3);
+  seeddim << tens.xdim() << tens.ydim() << tens.zdim();
+  targetdim  << refvol.xdim() << refvol.ydim() << refvol.zdim();
+  SymmetricMatrix Tens(3);
+  ColumnVector X_seed(3),X_target(3); 
+  ColumnVector V_seed(3),V_target(3);
+  for(int z=0;z<oV1.zsize();z++)
+    for(int y=0;y<oV1.ysize();y++)
+      for(int x=0;x<oV1.xsize();x++){
+
+	// compute seed coordinates
+	X_target << x << y << z;
+	X_seed=vox_to_vox(X_target,targetdim,seeddim,iM);
+	
+	if(mask((int)X_seed(1),(int)X_seed(2),(int)X_seed(3))==0){
+	  continue;
+	}
+
+	 // compute interpolated tensor
+	 Tens.Row(1) << tens[0].interpolate(X_seed(1),X_seed(2),X_seed(3));
+	 Tens.Row(2) << tens[1].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[3].interpolate(X_seed(1),X_seed(2),X_seed(3));
+	 Tens.Row(3) << tens[2].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[4].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[5].interpolate(X_seed(1),X_seed(2),X_seed(3));
+
+
+	 // Local Jacobian of the backward warpfield
+	 Jw <<   jx(x,y,z,0) <<  jx(x,y,z,1) << jx(x,y,z,2)
+	    <<   jy(x,y,z,0) <<  jy(x,y,z,1) << jy(x,y,z,2)
+	    <<   jz(x,y,z,0) <<  jz(x,y,z,1) << jz(x,y,z,2);
+	 
+	 // compute local forward affine transformation	
+	 F = (I + Jw).i();
+	 
+
+	if(!istensor){
+	  // compute first eigenvector
+	  EigenValues(Tens,d,v);
+	  V_seed = v.Column(3);
+	  
+	  // rotate vector
+	  V_target=F*V_seed;
+	  if(V_target.MaximumAbsoluteValue()>0)
+	    V_target/=sqrt(V_target.SumSquare());
+
+	  oV1(x,y,z,0)=V_target(1);
+	  oV1(x,y,z,1)=V_target(2);
+	  oV1(x,y,z,2)=V_target(3);
+	}
+	// create tensor
+	else{	   
+	  EigenValues(Tens,d,v);
+	  R=ppd(F,v.Column(3),v.Column(2));
+	  Tens << R*Tens*R.t();
+	  
+	  oV1(x,y,z,0)=Tens(1,1);
+	  oV1(x,y,z,1)=Tens(2,1);
+	  oV1(x,y,z,2)=Tens(3,1);
+	  oV1(x,y,z,3)=Tens(2,2);
+	  oV1(x,y,z,4)=Tens(3,2);
+	  oV1(x,y,z,5)=Tens(3,3);
+	  
+	}
+	
+      }
+  
 }
 
 
+
 void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
-		   const volume<float>& refvol,volume4D<float>& warpvol,
-		   const volume<float>& mask){
+		   const volume<float>& refvol,volume4D<float>& warpvol1,const volume4D<float>& warpvol2,
+		   const volume<float>& mask,bool istensor){
+
 
   ColumnVector X_seed(3),X_target(3);
   
-  //float dxx=tens.xdim(),dyy=tens.ydim(),dzz=tens.zdim();
-  //float dx=oV1.xdim(),dy=oV1.ydim(),dz=oV1.zdim();
-  //float nxx=(float)tens.xsize()/2.0,nyy=(float)tens.ysize()/2.0,nzz=(float)tens.zsize()/2.0;
-  //float nx=(float)oV1.xsize()/2.0,ny=(float)oV1.ysize()/2.0,nz=(float)oV1.zsize()/2.0;
-
   
-  // read warp field created by Jesper
-  FnirtFileReader ffr(warp.value());
-  warpvol=ffr.FieldAsNewimageVolume4D(true);
- 
-
   // compute transformation jacobian
   volume4D<float> jx(mask.xsize(),mask.ysize(),mask.zsize(),3);
   volume4D<float> jy(mask.xsize(),mask.ysize(),mask.zsize(),3);
   volume4D<float> jz(mask.xsize(),mask.ysize(),mask.zsize(),3);
-  sjgradient(warpvol[0],jx);
-  sjgradient(warpvol[1],jy);
-  sjgradient(warpvol[2],jz);
+  sjgradient(warpvol2[0],jx);
+  sjgradient(warpvol2[1],jy);
+  sjgradient(warpvol2[2],jz);
 
 
   ColumnVector V_seed(3),V_target(3);
@@ -277,11 +360,8 @@ void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
     for(int y=0;y<oV1.ysize();y++)
        for(int x=0;x<oV1.xsize();x++){
 	 
-
-
 	 X_target << x << y << z;
-	 X_seed = NewimageCoord2NewimageCoord(warpvol,false,oV1[0],mask,X_target);
-
+	 X_seed = NewimageCoord2NewimageCoord(warpvol1,false,oV1[0],mask,X_target);
 
 	 if(mask((int)X_seed(1),(int)X_seed(2),(int)X_seed(3))==0){
 	   continue;
@@ -304,7 +384,7 @@ void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
 	 F = (I + Jw).i();
 	 
 
-	 if(ivector.set()){
+	 if(!istensor){
 	   // reorient according to affine reorientation scheme
 	   //SVD(F*F.t(),d,u,v);
 	   //R=(u*sqrt(d)*v.t()).i()*F;
@@ -322,7 +402,89 @@ void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
 	   oV1(x,y,z,2)=V_target(3);
 	 }
 	 // create tensor
-	 if(ivector.unset()){
+	 else{
+	   //SVD(F*F.t(),d,u,v);
+	   //R=(u*sqrt(d)*v.t()).i()*F;
+
+	   EigenValues(Tens,d,v);
+	   R=ppd(F,v.Column(3),v.Column(2));
+	   Tens << R*Tens*R.t();
+
+	   oV1(x,y,z,0)=Tens(1,1);
+	   oV1(x,y,z,1)=Tens(2,1);
+	   oV1(x,y,z,2)=Tens(3,1);
+	   oV1(x,y,z,3)=Tens(2,2);
+	   oV1(x,y,z,4)=Tens(3,2);
+	   oV1(x,y,z,5)=Tens(3,3);
+
+	 }
+	 
+
+       }
+  
+  
+}
+
+
+
+void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
+		   const volume<float>& refvol,volume4D<float>& warpvol1,const Matrix& M2,
+		   const volume<float>& mask,bool istensor){
+
+  ColumnVector X_seed(3),X_target(3);
+  
+  // extract rotation matrix from M
+  Matrix F(3,3),R(3,3),u(3,3),v(3,3);
+  DiagonalMatrix d(3);
+  F=M2.SubMatrix(1,3,1,3);
+  SVD(F*F.t(),d,u,v);
+  R=(u*sqrt(d)*v.t()).i()*F;
+
+  ColumnVector V_seed(3),V_target(3);
+  ColumnVector V1_seed(3),V2_seed(3);
+  ColumnVector V1_target(3),V2_target(3),V3_target(3);
+  Matrix I(3,3);I<<1<<0<<0<<0<<1<<0<<0<<0<<1;
+  Matrix Jw(3,3);
+  SymmetricMatrix Tens(3);
+  for(int z=0;z<oV1.zsize();z++)
+    for(int y=0;y<oV1.ysize();y++)
+       for(int x=0;x<oV1.xsize();x++){
+	 
+	 X_target << x << y << z;
+	 X_seed = NewimageCoord2NewimageCoord(warpvol1,false,oV1[0],mask,X_target);
+
+	 if(mask((int)X_seed(1),(int)X_seed(2),(int)X_seed(3))==0){
+	   continue;
+	 }
+	
+	 // compute interpolated tensor
+	 Tens.Row(1) << tens[0].interpolate(X_seed(1),X_seed(2),X_seed(3));
+	 Tens.Row(2) << tens[1].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[3].interpolate(X_seed(1),X_seed(2),X_seed(3));
+	 Tens.Row(3) << tens[2].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[4].interpolate(X_seed(1),X_seed(2),X_seed(3))
+		     << tens[5].interpolate(X_seed(1),X_seed(2),X_seed(3));
+
+
+	 if(!istensor){
+	   // reorient according to affine reorientation scheme
+	   //SVD(F*F.t(),d,u,v);
+	   //R=(u*sqrt(d)*v.t()).i()*F;
+
+	   // compute first eigenvector
+	   EigenValues(Tens,d,v);
+	   V_seed = v.Column(3);
+	 
+	   V_target=R*V_seed;
+	   if(V_target.MaximumAbsoluteValue()>0)
+	     V_target/=sqrt(V_target.SumSquare());
+
+	   oV1(x,y,z,0)=V_target(1);
+	   oV1(x,y,z,1)=V_target(2);
+	   oV1(x,y,z,2)=V_target(3);
+	 }
+	 // create tensor
+	 else{
 	   //SVD(F*F.t(),d,u,v);
 	   //R=(u*sqrt(d)*v.t()).i()*F;
 
@@ -348,50 +510,74 @@ void vecreg_nonlin(const volume4D<float>& tens,volume4D<float>& oV1,
 
 
 int do_vecreg(){
-  volume4D<float> ivol,warpvol;
+  volume4D<float> ivol,warpvol1,warpvol2;
   volume<float> refvol,mask;
-  Matrix Aff(4,4);
+  Matrix Aff1,Aff2;
+ 
+  bool iswarp1=false,iswarp2=false;
+  if(fsl_imageexists(transformation.value()))iswarp1=true;
+  if(rotform.set())
+    if(fsl_imageexists(rotform.value()))iswarp2=true;
 
-  if((matrix.set())){
-    Aff = read_ascii_matrix(matrix.value());
+  if(verbose.value()) cout << "Load transformations" << endl;
+
+  if(!iswarp1)
+    Aff1 = read_ascii_matrix(transformation.value());
+  else{
+    FnirtFileReader ffr(transformation.value());
+    warpvol1=ffr.FieldAsNewimageVolume4D(true);
   }
-  if((warp.set())){
-    if(verbose.value()) cerr << "Loading warpfield" << endl;
-    read_volume4D(warpvol,warp.value());
+  if(rotform.set()){
+    if(!iswarp2) Aff2 = read_ascii_matrix(rotform.value());
+    else{
+      FnirtFileReader ffr(rotform.value());
+      warpvol2=ffr.FieldAsNewimageVolume4D(true);
+    }
   }
-  if(verbose.value()) cerr << "Loading volumes" << endl;
-  if(ivector.set())
-    read_volume4D(ivol,ivector.value());
-  else
-    read_volume4D(ivol,itensor.value());
+  else{
+    if(!iswarp1)Aff2=Aff1;
+    else warpvol2=warpvol1;
+  }
+    
+  
+  if(verbose.value()) cout << "Load input data" << endl;
+  bool istensor=false;
+  read_volume4D(ivol,infilename.value());
+  if(ivol.tsize()==6)istensor=true;
+  
   read_volume(refvol,ref.value());
 
   volume4D<float> ovol;
-  if(ivector.set())
+  if(!istensor)
     ovol.reinitialize(refvol.xsize(),refvol.ysize(),refvol.zsize(),3);
   else
     ovol.reinitialize(refvol.xsize(),refvol.ysize(),refvol.zsize(),6);
-  copybasicproperties(refvol,ovol);
+
 
   // set interpolation method
   if(interpmethod.value()=="nearestneighbour")
     ivol.setinterpolationmethod(nearestneighbour);
   else if(interpmethod.value()=="sinc")
     ivol.setinterpolationmethod(sinc);
+  else if(interpmethod.value()=="spline")
+    ivol.setinterpolationmethod(spline);
   else
     ivol.setinterpolationmethod(trilinear);
 
+  copybasicproperties(ivol,ovol);
+
+  // if a mask is not provided, set it to voxels where the input vectors are non-zero
   if(maskfile.value()!="")
     read_volume(mask,maskfile.value());
   else{
     mask.reinitialize(ivol[0].xsize(),ivol[0].ysize(),ivol[0].zsize());
-    copybasicproperties(ivol,mask);
     for(int z=0;z<mask.zsize();z++)
       for(int y=0;y<mask.ysize();y++)
 	for(int x=0;x<mask.xsize();x++){
-	  if(ivol(x,y,z,0)*ivol(x,y,z,0)
-	     +ivol(x,y,z,1)*ivol(x,y,z,1)
-	     +ivol(x,y,z,2)*ivol(x,y,z,2) != 0)
+	  float s=0;
+	  for(int t=0;t<ivol.tsize();t++)
+	    s+=std::abs(ivol(x,y,z,t));
+	  if(s>0)
 	    mask(x,y,z) = 1;
 	  else
 	    mask(x,y,z) = 0;
@@ -400,9 +586,10 @@ int do_vecreg(){
 
   ///////////////////////
   // tensor for interpolation
-  volume4D<float> tens(ivol.xsize(),ivol.ysize(),ivol.zsize(),6);
+  volume4D<float> tens(ivol.xsize(),ivol.ysize(),ivol.zsize(),6);  
   copybasicproperties(ivol,tens);
-  if(ivector.set())
+
+  if(!istensor)
     for(int z=0;z<ivol.zsize();z++) 
       for(int y=0;y<ivol.ysize();y++)  
 	for(int x=0;x<ivol.xsize();x++){
@@ -418,17 +605,24 @@ int do_vecreg(){
   }
 
   //time_t _time=time(NULL);
-  if(matrix.set()){
-    if(verbose.value()) cerr << "Affine registration" << endl;
-    vecreg_aff(tens,ovol,refvol,Aff,mask);
+  if(!iswarp1){
+    if(verbose.value()) cout << "Affine registration" << endl;
+    if(rotform.set() && iswarp2)
+      vecreg_aff(tens,ovol,refvol,Aff1,warpvol2,mask,istensor);
+    else
+      vecreg_aff(tens,ovol,refvol,Aff1,Aff2,mask,istensor);
   }
   else{
-    if(verbose.value()) cerr << "Nonlinear registration" << endl;
-    vecreg_nonlin(tens,ovol,refvol,warpvol,mask);
+    if(verbose.value()) cout << "Nonlinear registration" << endl;
+    if(rotform.set() && !iswarp2)
+      vecreg_nonlin(tens,ovol,refvol,warpvol1,Aff2,mask,istensor);
+    else
+      vecreg_nonlin(tens,ovol,refvol,warpvol1,warpvol2,mask,istensor);
+
   }
   //cout<<"elapsed time:"<<time(NULL)-_time<<" sec"<<endl;
 
-  save_volume4D(ovol,ovector.value());
+  save_volume4D(ovol,outfilename.value());
 
   return 0;
 
@@ -443,14 +637,14 @@ int main(int argc,char *argv[]){
   try{
     options.add(verbose);
     options.add(help);
-    options.add(ivector);
-    options.add(itensor);
-    options.add(ovector);
+    options.add(infilename);
+    options.add(outfilename);
     options.add(ref);
-    options.add(matrix);
-    options.add(warp);
-    options.add(interpmethod);
+    options.add(transformation);
+    options.add(rotform);
     options.add(maskfile);
+    options.add(interpmethod);
+
 
     options.parse_command_line(argc,argv);
 
@@ -459,33 +653,7 @@ int main(int argc,char *argv[]){
       options.usage();
       exit(EXIT_FAILURE);
     }
-    if( (matrix.set()) && (warp.set()) ){
-      options.usage();
-      cerr << endl
-	   << "Cannot specify both --affine AND --warpfield"
-	   << endl << endl;
-      exit(EXIT_FAILURE);
-    }
-    if( (matrix.unset()) && (warp.unset()) ){
-      options.usage();
-      cerr << endl
-	   << "Please Specify either --affine OR --warpfield"
-	   << endl << endl;
-      exit(EXIT_FAILURE);
-    }
-    if(ivector.unset()){
-      if(itensor.unset()){
-	cerr << endl;
-	cerr << "Please entre either an input vector or a tensor" << endl << endl;
-	exit(EXIT_FAILURE);
-      }
-    }
-    if(ivector.set()){
-      if(itensor.set()){
-	cerr << endl;
-	cerr << "Warning: warping the input vector, and ignoring the tensor" << endl << endl;
-      }
-    }
+    
   }
   catch(X_OptionError& e) {
     options.usage();
-- 
GitLab