diff --git a/fsl_sbca.cc b/fsl_sbca.cc
index 8ff23769603a489512c27bc02e46d5317763d979..e0cd66ebeff0fe7978e67cacc0060aeeb3eb5b5a 100644
--- a/fsl_sbca.cc
+++ b/fsl_sbca.cc
@@ -11,7 +11,6 @@
 #include "miscmaths/miscprob.h"
 #include "utils/options.h"
 #include <vector>
-#include <time.h>
 #include "newimage/newimageall.h"
 #include "melhlprfns.h"
 
@@ -26,8 +25,9 @@ using namespace std;
   string title=string("fsl_sbca (Version 1.0)")+
 		string("\nCopyright(c) 2008, University of Oxford (Christian F. Beckmann)\n")+
 		string(" \n Performs seed-based correlation analysis on FMRI data\n")+
-		string(" using either a single seed coordinate or a seed mask ");
-  string examples="fsl_sbca -i <input> -o <basename> [options]";
+		string(" using either a single seed coordinate or a seed mask \n")+
+		string(" ");
+  string examples="fsl_sbca -i <input> -s <seed> -t <target> -o <basename> [options]";
 
 //Command line Options {
   Option<string> fnin(string("-i,--in"), string(""),
@@ -38,10 +38,13 @@ using namespace std;
 		true, requires_argument);
   Option<string> fnseed(string("-s,--seed"), string(""),
 		string("seed voxel coordinate or file name of seed mask (3D file)"),
-		false, requires_argument);
+		true, requires_argument);
   Option<string> fntarget(string("-t,--target"), string(""),
 		string("file name of target mask(s) (3D or 4D file)"),
-		false, requires_argument);
+		true, requires_argument);
+  Option<bool> regress_only(string("-r,--reg"), false,
+		string("perform time series regression rather than classification to targets"),
+		false, no_argument);
   Option<string> fnconf(string("--conf"), string(""),
 		string("        file name (or comma-separated list of file name) for confound ascii txt files"),
 		false, requires_argument);
@@ -54,56 +57,162 @@ using namespace std;
   Option<bool> tc_mean(string("--mean"), false,
 		string("        use mean instead of Eigenvariates for calculation of time courses"),
 		false, no_argument);
-  Option<int> tc_order(string("--mean"), 1,
+  Option<int> tc_order(string("--order"), 1,
 		string("        number of Eigenvariates (default 1)"),
 		false, requires_argument);		
+  Option<bool> out_seeds(string("--out_seeds"), false,
+		string("output seed mask image as <basename>_seeds"),
+		false, no_argument);
+  Option<bool> out_seedmask(string("--out_seedmask"), false,
+		string("output seed mask image as <basename>_seedmask"),
+		false, no_argument);
+  Option<bool> out_ttcs(string("--out_ttcs"), false,
+		string("output target time courses as <basename>_ttc<X>.txt"),
+		false, no_argument);
+  Option<bool> out_conf(string("--out_conf"), false,
+		string("output confound time courses as <basename>_confounds.txt"),
+		false, no_argument);
+  Option<bool> out_tcorr(string("--out_tcorr"), false,
+		string("output target correlations as <basename>_tcorr.txt"),
+		false, no_argument, false);
   Option<int> help(string("-h,--help"), 0,
 		string("display this help text"),
 		false,no_argument);
+  Option<bool> debug(string("--debug"), false,
+		string("        switch on debug messages"),
+		false, no_argument, false);
 		/*
 }
 */
 //Globals {
 	Matrix data, confounds;
 	volume4D<float> orig_data;
-	volume<float> mask;
+	volume<float> maskS, maskT;
 	volumeinfo volinf; 
 	int voxels = 0;
-	Matrix seeds, corrs;
+	Matrix seeds, coords;
 	vector<Matrix> ttcs;
+	
+	Matrix out1, out2;
 	 /*
 }
 */
 ////////////////////////////////////////////////////////////////////////////
 
 // Local functions
-void save4D(Matrix what, string fname){
-		if(what.Ncols()==data.Ncols()||what.Nrows()==data.Nrows()){
-			volume4D<float> tempVol;
-			if(what.Nrows()>what.Ncols())
-				tempVol.setmatrix(what.t(),mask);
-			else
-				tempVol.setmatrix(what,mask);
-			save_volume4D(tempVol,fname,volinf);
-		}
+void save4D(Matrix what, volume<float>& msk, string fname){
+  if(debug.value()) 
+	cerr << "DBG: in save4D" << endl;
+  volume4D<float> tempVol;
+  tempVol.setmatrix(what,msk);
+  save_volume4D(tempVol,fname,volinf);
 }
 
-bool isimage(Matrix what){
-	if((voxels > 0)&&(what.Ncols()==voxels || what.Nrows()==voxels))
-		return TRUE;
-	else
-		return FALSE;
+void save4D(volume<float>& in, string fname){
+  if(debug.value()) 
+	cerr << "DBG: in save4D" << endl;
+  volume4D<float> tempVol;
+  tempVol.addvolume(in);
+  save_volume4D(tempVol,fname,volinf);
+}
+
+ReturnMatrix create_coords(string what){
+  if(debug.value()) 
+	cerr << "DBG: in create_coords" << endl;
+  Matrix res;
+  ifstream fs(what.c_str());
+  if (!fs) { 
+	Matrix tmp(1,3);
+	char *p;
+	char t[1024];
+	const char *discard = ", [];{(})abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*_-=+|\':><./?";	  
+	strcpy(t, what.c_str());
+	p=strtok(t,discard);
+	tmp(1,1) = atoi(p);
+	p=strtok(NULL,discard);
+	tmp(1,2) = atoi(p);
+	p=strtok(NULL,discard);
+	tmp(1,3) = atoi(p);
+	res = tmp;
+	
+	do{
+	  p=strtok(NULL,discard);
+	  if(p){
+		tmp(1,1) = atoi(p);
+		p=strtok(NULL,discard);
+		tmp(1,2) = atoi(p);
+		p=strtok(NULL,discard);
+		tmp(1,3) = atoi(p);
+		res &= tmp;   	
+      }
+    }while(p);			
+  }else{
+    res = read_ascii_matrix(fs);
+    fs.close();
+  }
+
+  if(res.Ncols()!=3){
+	cerr << "ERROR: incorrect format " << what << endl;
+	exit(1);
+  }
+
+ // if(verbose.value())
+//	cout << " Created seed coordinates (size: " << res.Nrows() << " x " << res.Ncols() << ")" << endl;
+  res.Release();
+	
+  return res;	
 }
 
-void saveit(Matrix what, string fname){
-	if(isimage(what))
-		save4D(what,fname);
-	else
-		write_ascii_matrix(what,fname);
+void create_mask(string what){
+  if(debug.value()) 
+	cerr << "DBG: in create_mask" << endl;
+  
+  coords = create_coords(what);
+  maskS = orig_data[0] * 0.0;
+  for(int ctr = 1; ctr <= coords.Nrows(); ctr++)
+	maskS(coords(ctr,1),coords(ctr,2),coords(ctr,3)) = 1.0;
+  maskS.binarise(1e-8);
+}	
+
+void create_seeds(string what){
+  if(debug.value()) 
+	cerr << "DBG: in create_seeds" << endl;
+  
+  if(fsl_imageexists(what)){
+	read_volume(maskS,what);
+    if(!samesize(orig_data[0],maskS)){
+	  cerr << "ERROR: Seed mask image does not match input image" << endl;
+      exit(1);
+    }
+  }  
+  else
+    create_mask(what);	
+  
+  volume4D<float> tmp_mask;
+  tmp_mask.addvolume(maskS);
+  maskS.binarise(1e-8);
+
+  Matrix scales = tmp_mask.matrix(maskS);
+  seeds = remmean(orig_data.matrix(maskS),1);	
+  if(!map_bin.value())
+    seeds = SP(seeds, ones(seeds.Nrows(),1) * scales);
+	
+  voxels = seeds.Ncols();
+  if(debug.value()){
+	cerr << "DBG: " << voxels << " voxels" << endl;
+	cerr << "DBG: seeds matrix is " << seeds.Nrows() << " x " << seeds.Ncols() << endl;
+  }
+
+  if(verbose.value())
+	cout << " Created seed time courses "  << endl;
+
 }
 
 ReturnMatrix create_confs(string what){
-  Matrix res;    
+  if(debug.value()) 
+	cerr << "DBG: in create_confs" << endl;
+  
+  Matrix res, tmp;    
   char *p;
   char t[1024];
   const char *discard = ",";
@@ -114,15 +223,25 @@ ReturnMatrix create_confs(string what){
   do{
     p=strtok(NULL,discard);
     if(p){
-    	res |= remmean(read_ascii_matrix(string(p)),1);	
+		tmp = read_ascii_matrix(string(p));
+		if(tmp.Nrows()!=res.Nrows()){
+			cerr << "ERROR: confound matrix" << string(p) << " is of wrong size "<< endl;
+			exit(1);
+		}
+    	res |= remmean(tmp,1);	
     }
   }while(p);
-	
+
+  if(verbose.value())
+	cout << " Created confound matrix (size: " << res.Nrows() << " x " << res.Ncols() << ")" << endl;
   res.Release();
   return res;
 }
 
 ReturnMatrix calc_ttc(volume<float>& in){
+	if(debug.value()) 
+	cerr << "DBG: in calc_ttc" << endl;
+  
 	Matrix res, tmp, scales;
 	
 	volume<float> tmp1;
@@ -130,6 +249,8 @@ ReturnMatrix calc_ttc(volume<float>& in){
 
 	tmp1 = in;
 	tmp1.binarise(1e-8);
+	maskT += tmp1;
+	
 	tmp2.addvolume(in);	
 	scales = tmp2.matrix(tmp1);
 	tmp = remmean(orig_data.matrix(tmp1),1);
@@ -146,74 +267,208 @@ ReturnMatrix calc_ttc(volume<float>& in){
 	    EigenValues(Corr,tmpD,res);	
 		res = fliplr(res.Columns(res.Ncols()-tc_order.value()+1 , res.Ncols())) * std::sqrt(tmp.Nrows());	
 	}
+	
+	if(debug.value())
+		cerr << "DBG: size is " << res.Nrows() << " x " << res.Ncols() << endl;
 	res.Release();
 	return res;
 }
 
 void create_target_tcs(){
-	
+	if(debug.value()) 
+	cerr << "DBG: in create_target_tcs" << endl;
+  
 	volume4D<float> tmptarg;
 	read_volume4D(tmptarg,fntarget.value());	
+    maskT = orig_data[0] * 0.0;
 
 	for(int ctr=0; ctr < tmptarg.tsize(); ctr++){
 	   ttcs.push_back(calc_ttc(tmptarg[ctr]));
 	}	
+	
+	if(debug.value()) {
+		cerr << "DBG: " << ttcs.size() << " target matrices created " << endl;
+	}
+	if(verbose.value())
+	  cout << " Created target mask time courses "  << endl;
+	
 }
 
 int setup(){
-	if(fsl_imageexists(fnin.value())){//read data
-		//input is 3D/4D vol
-		read_volume4D(orig_data,fnin.value(),volinf);
+  if(debug.value()) 
+	cerr << "DBG: in setup" << endl;
+  if(fsl_imageexists(fnin.value())){ //read data
+	if(verbose.value())
+      cout << " Reading input file " << fnin.value() << endl;
+    read_volume4D(orig_data,fnin.value(),volinf);
+  }
+  else{
+	cerr << "ERROR: Invalid input file " << fnin.value() << endl;       
+	exit(1);
     }
 
-    if(fnconf.value()>"")
-      confounds = create_confs(fnconf.value());
+  create_seeds(fnseed.value());
+
+  if(!regress_only.value())
+    create_target_tcs();
+  else{
+   	volume4D<float> tmptarg;
+	read_volume4D(tmptarg,fntarget.value());	
+	maskT = tmptarg[0];
+	maskT.binarise(1e-8);
+	data = orig_data.matrix(maskT);
+	data = remmean(data,1);
+  }
 
+  if(fnconf.value()>"")
+    confounds = create_confs(fnconf.value());
 
-    if(fnseed.value()>""){
-	  read_volume(mask,fnseed.value());
-      if(!samesize(orig_data[0],mask)){
-	    cerr << "ERROR: Seed mask image does not match input image" << endl;
-        return 1;
-      };
+  return 0;	
+}
 
-	  volume4D<float> tmp_mask;
-	  tmp_mask.addvolume(mask);
-	  mask.binarise(1e-8);
+ReturnMatrix calc_tcorr(int in){
+  if(debug.value()) 
+	cerr << "DBG: in calc_tcorr" << endl;
 
-	  Matrix scales = tmp_mask.matrix(mask);
-	  seeds = remmean(orig_data.matrix(mask),1);	
-	  if(!map_bin.value())
-	    seeds = SP(seeds, ones(seeds.Nrows(),1) * scales);
-    }
+	Matrix res = zeros(1,seeds.Ncols()), partial_conf, targetcol;
 	
-	create_target_tcs();
-	voxels = seeds.Ncols();
-	return 0;	
+	for(int ctr = 0; ctr < (int)ttcs.size(); ctr++)
+	  if(ctr != in){
+	  	if(partial_conf.Storage() == 0)
+	    	partial_conf = ttcs.at(ctr);
+	  	else	
+    		partial_conf |= ttcs.at(ctr);
+      }
+
+    if(ttcs.at(in).Ncols()>1)
+      if(partial_conf.Storage()>0)
+        partial_conf = ttcs.at(in).Columns(2,ttcs.at(in).Ncols()) | partial_conf;
+      else
+		partial_conf = ttcs.at(in).Columns(2,ttcs.at(in).Ncols());
+		
+ 	if(confounds.Storage() > 0)
+      if(partial_conf.Storage()>0)
+        partial_conf |= confounds;	
+      else
+        partial_conf = confounds;	
+
+    if(debug.value() && partial_conf.Storage()>0) 
+      cerr << "DBG: partial_conf " << partial_conf.Nrows() << " x " << partial_conf.Ncols() << endl;
+
+	targetcol = ttcs.at(in).Column(1);
+    if(debug.value()) 
+      cerr << "DBG: targetcol " << targetcol.Nrows() << " x " << targetcol.Ncols() << endl;
+
+	for(int ctr = 1; ctr <= seeds.Ncols(); ctr++)
+      res(1,ctr) = Melodic::corrcoef(targetcol, seeds.Column(ctr), partial_conf).AsScalar();
+    
+	res.Release();
+	return res;	
 }
 
 void calc_res(){
-  	
+  if(debug.value()) 
+	cerr << "DBG: in calc_res" << endl;
+
+  out2 = zeros(1,seeds.Ncols());	
+
+  if(!regress_only.value()){
+	//Target TCs exist
+	if(verbose.value())
+	  cout << " Calculating partial correlation scores between seeds and targets "  << endl;
+
+	Matrix tmp;
+	int tmp2;
+	out1=zeros(ttcs.size(),seeds.Ncols());
+	for(int ctr = 0 ;ctr < (int)ttcs.size(); ctr++)
+	  out1.Row(ctr+1) = calc_tcorr(ctr);					
+
+    for(int ctr = 1 ;ctr <= out1.Ncols(); ctr++){
+	  out1.Column(ctr).Maximum1(tmp2);
+      out2(1,ctr) = tmp2;
+    }
+      
+	if(debug.value()){ 
+      cerr << "DBG: out1 " << out1.Nrows() << " x " << out1.Ncols() << endl;
+      cerr << "DBG: out2 " << out2.Nrows() << " x " << out2.Ncols() << endl;
+	}
+  }
+  else{
+	//no Target TCs
+	if(verbose.value())
+	  cout << " Calculating partial correlation maps "  << endl;
+
+	out1 = zeros(seeds.Ncols(), data.Ncols());
+	if(confounds.Storage()>0){
+	  data = data - confounds * pinv(confounds) * data;
+      seeds = seeds - confounds * pinv(confounds) * seeds;
+    }
+
+	if(debug.value()){ 
+      cerr << "DBG: seeds " << seeds.Nrows() << " x " << seeds.Ncols() << endl;
+      cerr << "DBG: data " << data.Nrows() << " x " << data.Ncols() << endl;
+    }
+
+	for(int ctr = 1 ;ctr <= seeds.Ncols(); ctr++){
+	  Matrix tmp;
+	  if(coords.Storage()>0){
+	    tmp = orig_data.voxelts(coords(ctr,1), coords(ctr,2), coords(ctr,3));
+		volume4D<float> tmpVol;
+		tmpVol.setmatrix(out2,maskS);
+		tmpVol( coords(ctr,1), coords(ctr,2), coords(ctr,3), 0) = ctr; 
+		out2 = tmpVol.matrix(maskS); 
+     	if(confounds.Storage()>0)
+		  tmp = tmp - confounds * pinv(confounds) * tmp;
+	  }
+	  else{
+		tmp = seeds.Column(ctr);
+     	out2(1,ctr) = ctr;
+	  }
+	  for(int ctr2 =1; ctr2 <= data.Ncols(); ctr2++)
+        out1(ctr,ctr2) = Melodic::corrcoef(tmp,data.Column(ctr2)).AsScalar();      
+    }
+
+	if(debug.value()){ 
+      cerr << "DBG: out1 " << out1.Nrows() << " x " << out1.Ncols() << endl;
+      cerr << "DBG: out2 " << out2.Nrows() << " x " << out2.Ncols() << endl;
+    }
+  }
 }
 
-void write_res(){	
+void write_res(){
+  if(verbose.value())
+    cout << " Saving results " << endl;
+		
+  if(debug.value()) 
+	cerr << "DBG: in write_res" << endl;
+    
+  if(regress_only.value()){
+	save4D(out2,maskS, fnout.value()+"_index");
+	save4D(out1,maskT, fnout.value()+"_corr");
+  }
+  else{
+	save4D(out1,maskS, fnout.value()+"_corr");
+	save4D(out2,maskS, fnout.value()+"_index");
+  }
+
+  if(out_ttcs.value() && ttcs.size()>0)
+    for(int ctr = 0 ;ctr < (int)ttcs.size(); ctr++)
+      write_ascii_matrix(ttcs.at(ctr),fnout.value()+"_ttc"+num2str(ctr+1)+".txt");	
+  
+  if(out_conf.value() && confounds.Storage()>0)
+	write_ascii_matrix(confounds, fnout.value()+"_confounds.tx");
 	
+  if(out_seeds.value())   	
+    save4D(seeds, maskS, fnout.value()+"_seeds");
+  if(out_seedmask.value())   
+    save4D(maskS,fnout.value()+"_seedmask");
+  	
 }
 
 int do_work(int argc, char* argv[]) {
-
-  double tmptime = time(NULL);
-  srand((unsigned int) tmptime);
-
-cerr << (unsigned int) tmptime << endl << endl;
-
-cerr << unifrnd(2,2) << endl;
-exit(1);
   if(setup())
 	exit(1);
-	
   calc_res();
-
   write_res();
   return 0;
 }
@@ -227,15 +482,22 @@ int main(int argc,char *argv[]){
 	    // must include all wanted options here (the order determines how
 	    //  the help message is printed)
 		options.add(fnin);
-		options.add(fnout);
 		options.add(fnseed);
+		options.add(fnout);
 		options.add(fntarget);
+		options.add(regress_only);
 		options.add(fnconf);
 		options.add(map_bin);
 		options.add(tc_mean);
 		options.add(tc_order);
+		options.add(out_seeds);
+		options.add(out_seedmask);
+		options.add(out_ttcs);
+		options.add(out_conf);
+		options.add(out_tcorr);
 		options.add(verbose);
 		options.add(help);
+		options.add(debug);
 	    options.parse_command_line(argc, argv);
 
 	    // line below stops the program if the help was requested or 
diff --git a/melhlprfns.cc b/melhlprfns.cc
index d160abcd32f0486eac96a8560f86e3bd48003f1d..820b857373a7dda16f8a9cd1eaa310527443f54f 100644
--- a/melhlprfns.cc
+++ b/melhlprfns.cc
@@ -175,7 +175,18 @@ namespace Melodic{
 		Matrix out;
 		out=MISCMATHS::corrcoef(tmp,0);
 		return out.SubMatrix(1,in1.Ncols(),in1.Ncols()+1,out.Ncols());
+  }
+
+  Matrix corrcoef(const Matrix& in1, const Matrix& in2, const Matrix& part){
+	Matrix tmp1 = in1, tmp2 = in2, out;	
+	if(part.Storage()){
+		tmp1 = tmp1 - part * pinv(part) * tmp1;
+		tmp2 = tmp2 - part * pinv(part) * tmp2;
 	}
+	
+	out = corrcoef(tmp1,tmp2);
+	return out;
+  }
 
   Matrix calc_corr(const Matrix& in, bool econ)
   {
diff --git a/melhlprfns.h b/melhlprfns.h
index 791b4d27c1f1a1a8a39a09bd07c56b61f8b7eab3..7b4dcbef5d24578b9708aa453071ac1593f14873 100644
--- a/melhlprfns.h
+++ b/melhlprfns.h
@@ -38,6 +38,7 @@ namespace Melodic{
   RowVector cumsum(const RowVector& Inp);
 
   Matrix corrcoef(const Matrix& in1, const Matrix& in2);
+  Matrix corrcoef(const Matrix& in1, const Matrix& in2, const Matrix& part);
   Matrix calc_corr(const Matrix& in, bool econ = 0);
   Matrix calc_corr(const Matrix& in, const Matrix& weights, bool econ = 0);