diff --git a/probtrackxOptions.h b/probtrackxOptions.h
index f38519e1f01394b2ba918024f1ad0f1f04695867..9327d4c8eaa622ac32fa3bb6fc68f7129c83387b 100644
--- a/probtrackxOptions.h
+++ b/probtrackxOptions.h
@@ -46,6 +46,7 @@ class probtrackxOptions {
   Option<string> stopfile;
   Option<string> prefdirfile;
   Option<string> seeds_to_dti;
+  Option<string> dti_to_seeds;
   FmribOption<string> skipmask;
   Option<string> seedref;
   Option<string> mask2;
@@ -146,7 +147,11 @@ class probtrackxOptions {
 	       string("prefered orientation preset in a 4D mask"),
 	       false, requires_argument),
    seeds_to_dti(string("--xfm"), string(""),
-		string("Transform Matrix taking seed space to DTI space default is to use the identity"),false, requires_argument),
+		string("Transform taking seed space to DTI space (either FLIRT matrix or FNIRT warpfield) - default is identity"),
+		false, requires_argument),
+   dti_to_seeds(string("--invxfm"), string(""),
+		string("Transform taking DTI space to seed space (compulsory when using a warpfield for seeds_to_dti)"),
+		false, requires_argument),
    skipmask(string("--no_integrity"), string(""),
 	   string("no explanation needed"),
 	   false, requires_argument),
@@ -245,6 +250,7 @@ class probtrackxOptions {
        options.add(stopfile);
        options.add(prefdirfile);
        options.add(seeds_to_dti);
+       options.add(dti_to_seeds);
        options.add(nparticles);
        options.add(nsteps);
        options.add(c_thr);
diff --git a/ptx_meshmask.cc b/ptx_meshmask.cc
index 8bd9850717d83a835fe071261348e139cc2e4b79..a86b0f5c1cfeaa9b6bb02a22aa2bc6a9993ec02b 100644
--- a/ptx_meshmask.cc
+++ b/ptx_meshmask.cc
@@ -36,7 +36,7 @@ void meshmask()
 
   ////////////////////////////////
   //  Log& logger = LogSingleton::getInstance();
-  Streamliner stline;
+  Streamliner stline(seeds);
   Counter counter(seeds,stline);
   counter.initialise();
   Seedmanager seedmanager(counter);
diff --git a/ptx_nmasks.cc b/ptx_nmasks.cc
index 67a98a28b64240cb42dcc9bce47e52397e8634b6..c01c08231d470c275b77990f427412146b91d17e 100644
--- a/ptx_nmasks.cc
+++ b/ptx_nmasks.cc
@@ -38,7 +38,7 @@ void nmasks()
     seeds.push_back(tmpvol);
   }
 
-  Streamliner stline;
+  Streamliner stline(seeds[0]);
   Counter counter(seeds[0],stline);
   counter.initialise();
   Seedmanager seedmanager(counter);
diff --git a/ptx_seedmask.cc b/ptx_seedmask.cc
index 0db11c91a4c2fc2ded39b13834629a4d3c0eeaa9..f98871ef01b85dda2fbc0bcaa86d99d60aa3fb68 100644
--- a/ptx_seedmask.cc
+++ b/ptx_seedmask.cc
@@ -22,7 +22,7 @@ void seedmask()
   //  Log& logger = LogSingleton::getInstance();
   volume<float> seeds;
   read_volume(seeds,opts.seedfile.value());
-  Streamliner stline;
+  Streamliner stline(seeds);
   Counter counter(seeds,stline);
   counter.initialise();
   Seedmanager seedmanager(counter);
diff --git a/ptx_simple.cc b/ptx_simple.cc
index 58b23c44b99506f0b66748f83dbf5660863f7be5..258598aa8164e23cbc3e5b4aef463f43f11fd4cc 100644
--- a/ptx_simple.cc
+++ b/ptx_simple.cc
@@ -30,7 +30,7 @@ void track(){
     read_volume(seedref,opts.maskfile.value());
   }
 
-  Streamliner stline;
+  Streamliner stline(seedref);
   Counter counter(seedref,stline);
   counter.initialise();
   Seedmanager seedmanager(counter);
diff --git a/ptx_twomasks.cc b/ptx_twomasks.cc
index d3b05a9b33192b443651cf9846468cb98b3a75fd..59f4c9152d7c61de495c9ba33cb8c34e538dd3dc 100644
--- a/ptx_twomasks.cc
+++ b/ptx_twomasks.cc
@@ -30,7 +30,7 @@ void twomasks()
   seeds2=NEWIMAGE::abs(seeds2);
   seeds2.binarise(0,seeds2.max()+1,exclusive);
 
-  Streamliner stline;
+  Streamliner stline(seeds);
   Counter counter(seeds,stline);
   counter.initialise();
   Seedmanager seedmanager(counter);
diff --git a/streamlines.cc b/streamlines.cc
index b218252ca0e5e934046f1b40645ee9e3dcb233c2..69dac58b61f33b80b8d855be5f634b30e52d27b8 100644
--- a/streamlines.cc
+++ b/streamlines.cc
@@ -1,5 +1,6 @@
 #include "streamlines.h"
-
+#include "warpfns/fnirt_file_reader.h"
+#include "warpfns/warpfns.h"
 
 
 namespace TRACT{
@@ -38,8 +39,8 @@ namespace TRACT{
   }
   
   
-  Streamliner::Streamliner():opts(probtrackxOptions::getInstance()),logger(LogSingleton::getInstance()),
-			     vols(opts.usef.value()){
+  Streamliner::Streamliner(const volume<float>& seeds):opts(probtrackxOptions::getInstance()),logger(LogSingleton::getInstance()),
+						       vols(opts.usef.value()),m_seeds(seeds){
     
     read_volume(m_mask,opts.maskfile.value());
     m_part.initialise(0,0,0,0,0,0,opts.steplength.value(),m_mask.xdim(),m_mask.ydim(),m_mask.zdim(),false);
@@ -77,13 +78,32 @@ namespace TRACT{
 	m_passed_flags.push_back(false);
 	m_own_waymasks.push_back(true);
       }
-    } 
-    if(opts.seeds_to_dti.value()!=""){
-      m_Seeds_to_DTI = read_ascii_matrix(opts.seeds_to_dti.value());
     }
-    else{
-      m_Seeds_to_DTI=IdentityMatrix(4);
+
+    // Allow for either matrix transform (12dof affine) or nonlinear (warpfield)
+    m_Seeds_to_DTI = IdentityMatrix(4);
+    m_DTI_to_Seeds = IdentityMatrix(4);
+
+    m_IsNonlinXfm = false;
+    if(opts.seeds_to_dti.value()!=""){
+      if(!fsl_imageexists(opts.seeds_to_dti.value())){
+	m_Seeds_to_DTI = read_ascii_matrix(opts.seeds_to_dti.value());
+	m_DTI_to_Seeds = m_Seeds_to_DTI.i();
+      }
+      else{
+	m_IsNonlinXfm = true;
+	FnirtFileReader ffr(opts.seeds_to_dti.value());
+	m_Seeds_to_DTI_warp = ffr.FieldAsNewimageVolume4D(true);
+	if(opts.dti_to_seeds.value()==""){
+	  cerr << "Error: DTI -> Seeds transform needed" << endl;
+	  exit(1);
+	}
+	FnirtFileReader iffr(opts.dti_to_seeds.value());
+	m_DTI_to_Seeds_warp = iffr.FieldAsNewimageVolume4D(true);
+      }
     }
+    
+    
     vols.initialise(opts.basename.value());
     m_path.reserve(opts.nparticles.value());
     m_x_s_init=0;
@@ -118,8 +138,12 @@ namespace TRACT{
     ColumnVector th_ph_f;
     float xst,yst,zst,x,y,z,tmp2;
 
-
-    xyz_dti=vox_to_vox(xyz_seeds,dim_seeds,vols.dimensions(),m_Seeds_to_DTI);    
+    // find xyz in dti space
+    if(!m_IsNonlinXfm)
+      xyz_dti = vox_to_vox(xyz_seeds,dim_seeds,vols.dimensions(),m_Seeds_to_DTI);    
+    else{
+      xyz_dti = NewimageCoord2NewimageCoord(m_DTI_to_Seeds_warp,false,m_seeds,m_mask,xyz_seeds);
+    }
 
     xst=xyz_dti(1);yst=xyz_dti(2);zst=xyz_dti(3);
     m_path.clear();
@@ -142,8 +166,6 @@ namespace TRACT{
       m_passed_flags[pf]=false;  /// only keep it if this streamline went through all the masks
     }
 
-    Matrix DTI_to_Seeds(4,4);
-    DTI_to_Seeds = m_Seeds_to_DTI.i();
     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) ){
 	///////////////////////////////////
@@ -169,7 +191,14 @@ namespace TRACT{
 	
 	x=m_part.x();y=m_part.y();z=m_part.z();
 	xyz_dti <<x<<y<<z;
-	xyz_seeds=vox_to_vox(xyz_dti,vols.dimensions(),dim_seeds,DTI_to_Seeds);
+	// now find xyz in seeds space
+	if(!m_IsNonlinXfm)
+	  xyz_seeds = vox_to_vox(xyz_dti,vols.dimensions(),dim_seeds,m_DTI_to_Seeds);    
+	else{
+	  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));
@@ -812,11 +841,11 @@ namespace TRACT{
     if(opts.fibst.set()){
       fibst=opts.fibst.value()-1;
       OUT(fibst);
-   }
+    }
     else{
       if(fibst == -1){
 	fibst=0;//m_seeds(int(round(x)),int(round(y)),int(round(z)))-1;//fibre to start with is taken from seed volume..
-    }
+      }
       if(opts.randfib.value()){
 	float tmp=rand()/RAND_MAX * float(m_stline.nfibres()-1);
 	fibst = (int)round(tmp);
diff --git a/streamlines.h b/streamlines.h
index 39748fc8cba34a58d749ca9da17be11bb1d9ac75..a17e16705fc823de55963b9ecce0b17ecd9d9ef0 100644
--- a/streamlines.h
+++ b/streamlines.h
@@ -1,4 +1,7 @@
 #include <fstream>
+#ifndef EXPOSE_TREACHEROUS
+#define EXPOSE_TREACHEROUS
+#endif
 #include "newimage/newimageall.h"
 #include "utils/log.h"
 #include "meshclass/meshclass.h"
@@ -6,6 +9,9 @@
 #include "particle.h"
 #include "tractvolsx.h"
 
+
+
+
 using namespace std;
 using namespace NEWIMAGE;
 using namespace Utilities;
@@ -35,15 +41,23 @@ namespace TRACT{
     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;
+    volume4D<float> m_DTI_to_Seeds_warp;
+    bool m_IsNonlinXfm;
     Matrix m_rotdir;
     Tractvolsx vols;
     float m_lcrat;
     float m_x_s_init;
     float m_y_s_init;
     float m_z_s_init;
+
+    // we need this class to know about seed space
+    const volume<float>& m_seeds;
+
   public:
     //Constructors
-    Streamliner();
+    Streamliner(const volume<float>&);
     ~Streamliner(){
       for(unsigned int i=0;i<m_waymasks.size();i++)
 	if(m_own_waymasks[i]) delete m_waymasks[i];