From 3210c57418a1a6b7476420a59fc18b94c3ae5b3e Mon Sep 17 00:00:00 2001
From: Matthew Webster <mwebster@fmrib.ox.ac.uk>
Date: Wed, 14 Oct 2015 14:59:39 +0000
Subject: [PATCH] current changes merged

---
 meldata.cc    |  16 +-
 melhlprfns.cc | 912 ++++++++++++++++++++++++++++++++++++++++++++++++++
 melodic.h     |  88 +++++
 meloptions.cc |  10 +-
 meloptions.h  | 527 +++++++++++++++++++++++++++++
 melreport.cc  | 807 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 2350 insertions(+), 10 deletions(-)
 create mode 100644 melhlprfns.cc
 create mode 100644 melodic.h
 create mode 100644 meloptions.h
 create mode 100644 melreport.cc

diff --git a/meldata.cc b/meldata.cc
index 128050d..2856999 100644
--- a/meldata.cc
+++ b/meldata.cc
@@ -568,7 +568,7 @@ namespace Melodic{
 	dbgmsg(string("START: setup") << endl);	
 		
 	numfiles = (int)opts.inputfname.value().size();
-    setup_misc();
+	setup_misc();
 	if(opts.debug.value())
 		memmsg(" after setup_misc ");
 		
@@ -576,12 +576,14 @@ namespace Melodic{
 		Data = process_file(opts.inputfname.value().at(0));
 	}
 	else{
-		if((numfiles > 1) && (opts.approach.value()==string("defl") || opts.approach.value()==string("symm")))
-	       opts.approach.set_T("concat");
-		if(opts.migp.value())
-			setup_migp();
-		else
-			setup_classic();   
+	  if((numfiles > 1) && (opts.approach.value()==string("defl") || opts.approach.value()==string("symm")))
+	    opts.approach.set_T("concat");
+	  if  (opts.approach.value()==string("tica"))
+	    opts.migp.set_T(false);
+	  if( opts.approach.value()==string("concat") && opts.migp.value() )
+	    setup_migp();
+	  else
+	    setup_classic();   
     }
 
     message(endl << "  Data size : "<<Data.Nrows()<<" x "<<Data.Ncols()<<endl<<endl);
diff --git a/melhlprfns.cc b/melhlprfns.cc
new file mode 100644
index 0000000..07c32a4
--- /dev/null
+++ b/melhlprfns.cc
@@ -0,0 +1,912 @@
+/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
+              independent components
+    
+    melhlprfns.cc - misc functions
+
+    Christian F. Beckmann, FMRIB Analysis Group
+    
+    Copyright (C) 1999-2013 University of Oxford */
+
+/*  CCOPYRIGHT  */
+
+#include "melhlprfns.h"
+#include "libprob.h"
+#include "miscmaths/miscprob.h"
+#include "miscmaths/t2z.h"
+#include "miscmaths/f2z.h"
+
+namespace Melodic{
+
+  void update_mask(volume<float>& mask, Matrix& Data)
+  {
+    Matrix DStDev=stdev(Data);
+    volume4D<float> tmpMask, RawData;
+    tmpMask.setmatrix(DStDev,mask);
+
+    float tMmax;
+    volume<float> tmpMask2;
+    tmpMask2 = tmpMask[0];
+
+    tMmax = tmpMask2.max();
+    double st_mean = DStDev.Sum()/DStDev.Ncols();
+    double st_std  = stdev(DStDev.t()).AsScalar();
+      
+	volume4D<float> newmask;
+    newmask = binarise(tmpMask2,(float) max((float) st_mean-3*st_std,(float) 0.01*st_mean),tMmax);
+
+	Matrix newmaskM,newData;
+	newmaskM = newmask.matrix(mask);
+	int N = Data.Nrows();
+	
+	if(int(newmaskM.Row(1).SumAbsoluteValue() + 0.3) < newmaskM.Ncols()){
+		RawData.setmatrix(Data.Row(1),mask);
+		newData = RawData.matrix(newmask[0]);
+		for(int r=2; r <= N; r++){
+			RawData.setmatrix(Data.Row(r),mask);
+			newData &= RawData.matrix(newmask[0]);
+		}
+		Data = newData;
+		mask = newmask[0];  
+	}
+  }
+
+  void del_vols(volume4D<float>& in, int howmany)
+  {
+    for(int ctr=1; ctr<=howmany; ctr++){
+	in.deletevolume(ctr);
+    }    
+  }
+
+  Matrix calc_FFT(const Matrix& Mat, const bool logpwr)
+  {
+    Matrix res;
+      for(int ctr=1; ctr <= Mat.Ncols(); ctr++){
+	      ColumnVector tmpCol;  
+	      tmpCol=Mat.Column(ctr);
+	      ColumnVector FtmpCol_real;
+	      ColumnVector FtmpCol_imag;
+	      ColumnVector tmpPow;
+	      if(tmpCol.Nrows()%2 != 0){
+	        Matrix empty(1,1); empty=0;
+	        tmpCol &= empty;
+	      }
+	      RealFFT(tmpCol,FtmpCol_real,FtmpCol_imag);
+	      tmpPow = pow(FtmpCol_real,2)+pow(FtmpCol_imag,2);
+	      tmpPow = tmpPow.Rows(2,tmpPow.Nrows());
+	      if(logpwr) tmpPow = log(tmpPow);
+	      if(res.Storage()==0){res= tmpPow;}else{res|=tmpPow;}
+      }
+      return res;
+  }  //Matrix calc_FFT()
+
+  Matrix smoothColumns(const Matrix& inp)
+  {
+    Matrix temp(inp);
+    int ctr1 = temp.Nrows();
+    Matrix temp2(temp);
+    temp2=0;
+    
+    temp = temp.Row(4) & temp.Row(3) & temp.Row(2) & temp & temp.Row(ctr1-1) 
+      & temp.Row(ctr1-2) &temp.Row(ctr1-3);
+    
+    double kern[] ={0.0045 , 0.055, 0.25, 0.4, 0.25, 0.055, 0.0045};
+    double fac = 0.9090909;
+
+    
+    for(int cc=1;cc<=temp2.Ncols();cc++){
+      for(int cr=1;cr<=temp2.Nrows();cr++){
+	temp2(cr,cc) = fac*( kern[0] * temp(cr,cc) + kern[1] * temp(cr+1,cc) + 
+			     kern[2] * temp(cr+2,cc) + kern[3] * temp(cr+3,cc) + 
+			     kern[4] * temp(cr+4,cc) + kern[5] * temp(cr+5,cc) + 
+			     kern[6] * temp(cr+6,cc));
+      }
+    }
+    return temp2;
+  }  //Matrix smoothColumns()
+
+  Matrix convert_to_pbsc(Matrix& inp)
+  {
+    Matrix meanimg;
+    meanimg = mean(inp);
+    float eps = 0.00001;
+
+    for(int ctr=1; ctr <= inp.Ncols(); ctr++){
+      if(meanimg(1,ctr) < eps) 
+	meanimg(1,ctr) = eps;
+    }
+
+    for(int ctr=1; ctr <= inp.Nrows(); ctr++){
+      Matrix tmp;
+      tmp << inp.Row(ctr);
+      inp.Row(ctr) << 100 * SP((tmp - meanimg),pow(meanimg,-1));   
+    }
+
+    inp = remmean(inp);
+    return meanimg;
+  }  //void convert_to_pbsc   
+
+  RowVector varnorm(Matrix& in, int dim, float level, int econ)
+  {
+    SymmetricMatrix Corr(cov_r(in,false,econ));
+    RowVector out;
+    out = varnorm(in,Corr,dim,level, econ);
+    return out;
+  }  //RowVector varnorm
+
+  void varnorm(Matrix& in, const RowVector& vars)
+  {
+    for(int ctr=1; ctr <=in.Nrows();ctr++)
+      in.Row(ctr) = SD(in.Row(ctr),vars);
+  }
+	
+  RowVector varnorm(Matrix& in, SymmetricMatrix& Corr, int dim, float level, int econ)
+  { 
+	
+    Matrix tmpE, white, dewhite;
+    RowVector tmpD, tmpD2;
+
+    std_pca(remmean(in,2), Corr, tmpE, tmpD, econ);
+    calc_white(tmpE,tmpD, dim, white, dewhite);
+    
+    Matrix ws = white * in;
+    for(int ctr1 = 1; ctr1<=ws.Ncols(); ctr1++)
+      for(int ctr2 = 1; ctr2<=ws.Nrows(); ctr2++)
+				if(std::abs(ws(ctr2,ctr1)) < level)
+	  			ws(ctr2,ctr1)=0;
+    tmpD = stdev(in - dewhite*ws);
+    for(int ctr1 = 1; ctr1<=tmpD.Ncols(); ctr1++)
+      if(tmpD(ctr1) < 0.01){
+				tmpD(ctr1) = 1.0;
+				in.Column(ctr1) = 0.0*in.Column(ctr1);
+      }
+	  varnorm(in,tmpD);
+
+    return tmpD;
+  }  //RowVector varnorm
+
+
+
+  Matrix SP2(const Matrix& in, const Matrix& weights, int econ)
+  {
+    Matrix Res;
+    Res = in;
+    if(econ>0){
+      ColumnVector tmp;
+      for(int ctr=1; ctr <= in.Ncols(); ctr++){
+	tmp = in.Column(ctr);
+	tmp = tmp * weights(1,ctr);
+	Res.Column(ctr) = tmp;
+      }
+    }
+    else{
+      Res = ones(in.Nrows(),1)*weights.Row(1);
+      Res = SP(in,Res);
+    }
+    return Res;
+  }  //Matrix SP2
+
+  void SP3(Matrix& in, const Matrix& weights)
+  {
+	for(int ctr=1; ctr <= in.Nrows(); ctr++){
+		in.Row(ctr) << SP(in.Row(ctr),weights.AsRow());
+	} 
+  }
+
+  Matrix corrcoef(const Matrix& in1, const Matrix& in2){
+		Matrix tmp = in1;
+		tmp |= in2;
+		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;
+  }
+
+  float calc_white(const Matrix& tmpE, const RowVector& tmpD, const RowVector& PercEV,  int dim, Matrix& param, Matrix& paramS, Matrix& white, Matrix& dewhite)
+  {
+
+//	tmpD2= tmpD | tmpPD.AsRow().Columns(tmpPE.Ncols()-param.Ncols()+1,tmpPE.Ncols());
+//  cerr << tmpPD.AsRow().Columns(tmpPE.Ncols()-param.Ncols()+1,tmpPE.Ncols()) << endl;
+
+//    
+
+//	Matrix tmpPE;
+//	tmpPE = SP(param,ones(param.Nrows(),1)*pow(stdev(param,1)*std::sqrt((float)param.Nrows()),-1));
+
+//	RE |= tmpPE;
+//	RowVector tmpD2;
+//	tmpD2 = tmpD | stdev(param,1).AsRow()*std::sqrt((float)param.Nrows());
+//	RD << abs(diag(tmpD2.t()));
+//    RD << RD.SymSubMatrix(N-dim+1,N);
+
+	Matrix RE;
+    DiagonalMatrix RD;
+    int N = tmpE.Ncols();
+    dim = std::min(dim,N);
+
+//	cerr << stdev(param) << endl;
+    RE = tmpE.Columns(std::min(N-dim+1+param.Ncols(),N-2),N);
+	RE |= param;
+
+//	cerr << paramS.Nrows() << " x " << paramS.Ncols() << endl;
+//	cerr << paramS << endl;
+	RowVector tmpD2;
+	tmpD2 = tmpD | pow(paramS,2).AsRow();
+    RD << abs(diag(tmpD2.t()));
+
+//	cerr << " " <<tmpD2.Ncols() << " " << N << " " << dim << endl;
+    RD << RD.SymSubMatrix(N-dim+1+param.Ncols(),N+param.Ncols());    
+
+    float res = 1.0;    
+    white = sqrt(abs(RD.i()))*RE.t();
+    dewhite = RE*sqrt(RD);
+
+    if(dim < N)
+      res = PercEV(dim);
+    return res;
+  }  //Matrix calc_white
+
+  float calc_white(const Matrix& tmpE, const RowVector& tmpD, const RowVector& PercEV, int dim, Matrix& white, Matrix& dewhite)
+  {
+    Matrix RE;
+    DiagonalMatrix RD;
+    int N = tmpE.Ncols();
+    dim = std::min(dim,N);
+    RE = tmpE.Columns(N-dim+1,N);
+    RD << abs(diag(tmpD.t()));
+    RD << RD.SymSubMatrix(N-dim+1,N);    
+
+    float res = 1.0;    
+    white = sqrt(abs(RD.i()))*RE.t();
+    dewhite = RE*sqrt(RD);
+
+    if(dim < N)
+      res = PercEV(dim);
+    return res;
+  }  //Matrix calc_white
+
+  void calc_white(const Matrix& tmpE, const RowVector& tmpD, int dim, Matrix& white, Matrix& dewhite)
+  {
+    RowVector tmp(tmpE.Ncols());
+    float tmp2;
+    tmp2 = calc_white(tmpE,tmpD, tmp, dim, white, dewhite); 
+  }  //Matrix calc_white
+
+  void calc_white(const Matrix& tmpE, const RowVector& tmpD, int dim, Matrix& param, Matrix& paramS, Matrix& white, Matrix& dewhite)
+  {
+    RowVector tmp(tmpE.Ncols());
+    float tmp2;
+    tmp2 = calc_white(tmpE,tmpD, tmp, dim, param, paramS, white, dewhite); 
+  }  //Matrix calc_white
+
+  void calc_white(const SymmetricMatrix& Corr, int dim, Matrix& white, Matrix& dewhite)
+  {
+    Matrix RE;
+    DiagonalMatrix RD;
+    RowVector tmp2;
+    EigenValues(Corr,RD,RE);
+    tmp2 = diag(RD).t();
+    calc_white(RE,tmp2, dim, white, dewhite); 
+  }  //Matrix calc_white
+  
+ 
+  void std_pca(const Matrix& Mat, const Matrix& weights, SymmetricMatrix& Corr, Matrix& evecs, RowVector& evals, int econ)
+  {
+    if(weights.Storage()>0)
+      Corr = cov_r(Mat, weights, econ);
+    else
+      Corr = cov_r(Mat,false,econ);
+
+    DiagonalMatrix tmpD;
+    EigenValues(Corr,tmpD,evecs);
+    evals = tmpD.AsRow();
+  }  //void std_pca
+
+  void std_pca(const Matrix& Mat, SymmetricMatrix& Corr, Matrix& evecs, RowVector& evals, int econ)
+  {
+    Matrix weights;
+    std_pca(Mat,weights,Corr,evecs,evals, econ);
+  }  //void std_pca
+
+  void em_pca(const Matrix& Mat, Matrix& evecs, RowVector& evals, int num_pc, int iter)
+  {
+    Matrix guess;
+    guess = normrnd(Mat.Nrows(),num_pc);
+    em_pca(Mat,guess,evecs,evals,num_pc,iter);
+  }  //void em_pca
+
+  void em_pca(const Matrix& Mat, Matrix& guess, Matrix& evecs, RowVector& evals, int num_pc, int iter)
+  {
+    Matrix C;
+    if(guess.Ncols() < num_pc){
+      C=normrnd(Mat.Nrows(),num_pc);
+      C.Columns(1,guess.Ncols()) = guess;
+    }
+    else
+      C = guess;
+
+    Matrix tmp, tmp2;
+    for(int ctr=1; ctr <= iter; ctr++){
+      // E-Step
+      tmp = C.t()*C;
+      tmp = tmp.i();
+      tmp = tmp * C.t();
+      tmp = tmp * Mat;
+      // M-Step
+      tmp2 = tmp * tmp.t();
+      tmp2 = tmp2.i();
+      tmp2 = Mat*tmp.t()*tmp2;
+      C = tmp2;
+    }
+    
+    symm_orth(C);
+    Matrix Evc;
+    SymmetricMatrix tmpC;
+    RowVector Evl;
+    tmp = C.t() * Mat;
+    std_pca(tmp,tmpC,Evc,Evl);
+    evals = Evl;
+    evecs = C * Evc;
+  }  //void em_pca
+
+  float rankapprox(const Matrix& Mat, Matrix& cols, Matrix& rows, int dim)
+  { 
+    SymmetricMatrix Corr;
+    Matrix Evecs, tmpWM, tmpDWM, tmp;
+    RowVector Evals;
+    std_pca(Mat.t(), Corr, Evecs, Evals);
+    calc_white(Corr, dim, tmpWM, tmpDWM);
+    tmp = tmpWM * Mat.t();
+    cols = tmp.t();
+    rows << tmpDWM;
+		float res;
+		Evals=fliplr(Evals);
+		res = sum(Evals.Columns(1,dim),2).AsScalar()/sum(Evals,2).AsScalar()*100;
+		return res;
+  } // rankapprox
+
+  RowVector krfact(const Matrix& Mat, Matrix& cols, Matrix& rows)
+  {
+		Matrix out; RowVector res(Mat.Ncols());
+    for(int ctr1 = 1; ctr1 <= Mat.Ncols(); ctr1++){
+			Matrix tmpVals(cols.Nrows(),rows.Nrows());
+			for(int ctr2 = 1; ctr2 <= rows.Nrows(); ctr2++)
+	  		tmpVals.Column(ctr2) << Mat.SubMatrix(cols.Nrows() * 
+				(ctr2 - 1) + 1,cols.Nrows()*ctr2 ,ctr1,ctr1);
+	
+			Matrix tmpcols, tmprows;
+	 		res(ctr1) =rankapprox(tmpVals, tmpcols, tmprows);
+			cols.Column(ctr1) = tmpcols;
+			rows.Column(ctr1) = tmprows;
+    }
+		return res;
+  } // krfact
+
+  RowVector krfact(const Matrix& Mat, int colnum, Matrix& cols, Matrix& rows)
+  {
+		RowVector res;
+    cols = zeros(colnum,Mat.Ncols());
+    rows = zeros(int(Mat.Nrows() / colnum),Mat.Ncols());
+    res = krfact(Mat,cols,rows);
+		return res;
+  } // krfact
+
+  Matrix krprod(const Matrix& cols, const Matrix& rows)
+  {
+    Matrix out;
+    out = zeros(cols.Nrows()*rows.Nrows(),cols.Ncols());
+    for(int ctr1 = 1; ctr1 <= cols.Ncols(); ctr1++)
+      for(int ctr2 = 1; ctr2 <= rows.Nrows(); ctr2++)
+	{
+	  out.SubMatrix(cols.Nrows()*(ctr2-1)+1,cols.Nrows()*ctr2,ctr1,ctr1) << cols.Column(ctr1) * rows(ctr2,ctr1);
+	}
+    return out;
+  } // krprod
+
+  Matrix krapprox(const Matrix& Mat, int size_cols, int dim)
+  {
+    Matrix out, cols, rows;
+    out = zeros(Mat.Nrows(), Mat.Ncols());
+    cols = zeros(size_cols,Mat.Ncols());
+    rows = zeros(int(Mat.Nrows() / size_cols), Mat.Ncols());
+    krfact(Mat,cols,rows);
+    out = krprod(cols, rows);
+    return out;
+  } // krapprox
+
+  void adj_eigspec(const RowVector& in, RowVector& out1, RowVector& out2, RowVector& out3, int& out4, int num_vox, float resels)
+  {
+    RowVector AdjEV;
+    AdjEV << in.AsRow();
+    AdjEV = AdjEV.Columns(3,AdjEV.Ncols());
+    AdjEV = AdjEV.Reverse();
+
+    RowVector CircleLaw;
+    int NumVox = (int) floor(num_vox/(2.5*resels));
+
+    CircleLaw = Feta(int(AdjEV.Ncols()), NumVox);
+
+    for(int ctr=1;ctr<=CircleLaw.Ncols(); ctr++){
+      if(CircleLaw(ctr)<5*10e-10){CircleLaw(ctr) = 5*10e-10;}
+    } 
+
+    /*    float slope;
+    slope = CircleLaw.Columns(int(AdjEV.Ncols()/4),AdjEV.Ncols() - 
+			      int(AdjEV.Ncols()/4)).Sum() /  
+      AdjEV.Columns(int(AdjEV.Ncols()/4),AdjEV.Ncols() - 
+      int(AdjEV.Ncols()/4)).Sum();*/
+
+    RowVector PercEV(AdjEV);
+    PercEV = cumsum(AdjEV / sum(AdjEV,2).AsScalar());
+
+    AdjEV << SP(AdjEV,pow(CircleLaw.Columns(1,AdjEV.Ncols()),-1));
+
+    SortDescending(AdjEV);
+    int maxEV = 1;
+    float threshold = 0.98;
+    for(int ctr_i = 1; ctr_i < PercEV.Ncols(); ctr_i++){ 
+      if((PercEV(ctr_i)<threshold)&&(PercEV(ctr_i+1)>=threshold)){maxEV=ctr_i;}
+    }
+
+    if(maxEV<3){maxEV=PercEV.Ncols()/2;}
+    RowVector NewEV;
+    Matrix temp1;
+    temp1 = abs(AdjEV);
+    NewEV << temp1.SubMatrix(1,1,1,maxEV);
+
+    AdjEV = (AdjEV - min(AdjEV).AsScalar())/(max(AdjEV).AsScalar() - min(AdjEV).AsScalar());
+
+    out1 = AdjEV;
+    out2 = PercEV;
+    out3 = NewEV;
+    out4 = maxEV;
+  }  //adj_eigspec
+
+ void adj_eigspec(const RowVector& in, RowVector& out1, RowVector& out2)
+  {
+    RowVector AdjEV, PercEV;
+    AdjEV = in.Reverse();
+    SortDescending(AdjEV);
+  
+    PercEV = cumsum(AdjEV / sum(AdjEV,2).AsScalar());
+    AdjEV = (AdjEV - min(AdjEV).AsScalar())/(max(AdjEV).AsScalar() - min(AdjEV).AsScalar());
+    out1 = AdjEV;
+    out2 = PercEV;
+  }  //adj_eigspec
+
+  RowVector Feta(int n1, int n2)
+  {
+    float nu = (float) n1/n2; 
+    float bm = pow((1-sqrt(nu)),2.0);
+    float bp = pow((1+sqrt(nu)),2.0);
+
+    float lrange = 0.9*bm;
+    float urange = 1.1*bp;
+
+    RowVector eta(30*n1);
+    float rangestepsize = (urange - lrange) / eta.Ncols(); 
+    for(int ctr_i = 1; ctr_i <= eta.Ncols(); ctr_i++){ 
+      eta(ctr_i) = lrange + rangestepsize * (ctr_i);
+    }
+
+    RowVector teta(10*n1);
+    teta = 0;
+    float stepsize = (bp - bm) / teta.Ncols();
+    for(int ctr_i = 1; ctr_i <= teta.Ncols(); ctr_i++){ 
+      teta(ctr_i) = stepsize*(ctr_i);
+    }  
+    
+    RowVector feta(teta);
+    feta = SP(pow(2*M_PI*nu*(teta + bm),-1), pow(SP(teta, bp-bm-teta),0.5));
+   
+    teta = teta + bm;
+
+    RowVector claw(eta);
+    claw = 0;
+    double tmpval(0);
+    int ctr_j(1);
+    for(int ctr_i = 1; ctr_i <= eta.Ncols(); ctr_i++){
+      for(; ctr_j <= teta.Ncols() &&  teta(ctr_j) < eta(ctr_i) ; ctr_j++)
+	  tmpval += feta(ctr_j);
+      claw(ctr_i) = max(n1*(1-stepsize*tmpval),0.0);
+    }
+    
+    RowVector Res(n1); //invert the CDF
+    Res = 0;
+    for(int ctr_i = 1; ctr_i < eta.Ncols(); ctr_i++){
+      if(floor(claw(ctr_i))>floor(claw(ctr_i+1))){
+	Res(int(floor(claw(ctr_i)))) = eta(ctr_i);
+      }
+    }
+ 
+    return Res;
+  }  //RowVector Feta
+
+  RowVector cumsum(const RowVector& Inp)
+  {
+    UpperTriangularMatrix UT(Inp.Ncols());
+    UT=1.0;
+    RowVector Res;
+    Res = Inp * UT;
+    return Res;
+  }  //RowVector cumsum
+
+  int ppca_dim(const Matrix& in, const Matrix& weights, Matrix& PPCA, RowVector& AdjEV, RowVector& PercEV,  SymmetricMatrix& Corr, Matrix& tmpE, RowVector &tmpD, float resels, string which)
+  {   
+    std_pca(in,weights,Corr,tmpE,tmpD);
+
+    int maxEV = 1;
+    RowVector NewEV;
+    adj_eigspec(tmpD.AsRow(),AdjEV,PercEV,NewEV,maxEV,in.Ncols(),resels);
+    
+    int res;
+		PPCA = ppca_est(NewEV, in.Ncols(),resels);
+    ColumnVector tmp = ppca_select(PPCA, res, maxEV, which);
+		
+		PPCA = tmp | PPCA;
+    return res;
+  }  //int ppca_dim
+
+  int ppca_dim(const Matrix& in, const Matrix& weights, Matrix& PPCA, RowVector& AdjEV, RowVector& PercEV, float resels, string which)
+  {   
+    RowVector tmpD;
+    Matrix tmpE;
+    SymmetricMatrix Corr;
+
+    int res = ppca_dim(in, weights, PPCA, AdjEV, PercEV, Corr, tmpE, tmpD, resels, which);
+    return res;
+  }  //int ppca_dim
+
+  int ppca_dim(const Matrix& in, const Matrix& weights, float resels, string which)
+  {
+    ColumnVector PPCA;
+    RowVector AdjEV, PercEV;
+    int res = ppca_dim(in,weights,PPCA,AdjEV,PercEV,resels,which);
+    return res;
+  }  //int ppca_dim
+
+  ColumnVector ppca_select(Matrix& PPCAest, int& dim, int maxEV, string which)
+  {
+    RowVector estimators(5);
+    estimators = 1.0;
+    
+    for(int ctr=1; ctr<=PPCAest.Ncols(); ctr++){
+      PPCAest.Column(ctr) = (PPCAest.Column(ctr) - 
+			   min(PPCAest.Column(ctr)).AsScalar()) / 
+	( max(PPCAest.Column(ctr)).AsScalar() - 
+	  min(PPCAest.Column(ctr)).AsScalar());
+    }
+    
+    int ctr_i = 1;
+    while((ctr_i< PPCAest.Nrows()-1)&&
+	  (PPCAest(ctr_i,2) < PPCAest(ctr_i+1,2))&&(ctr_i<maxEV))
+      {estimators(1)=ctr_i+1;ctr_i++;}
+    ctr_i = 1;
+    while((ctr_i< PPCAest.Nrows()-1)&&
+	  (PPCAest(ctr_i,3) < PPCAest(ctr_i+1,3))&&(ctr_i<maxEV))
+      {estimators(2)=ctr_i+1;ctr_i++;}
+    ctr_i = 1;
+    while((ctr_i< PPCAest.Nrows()-1)&&
+	  (PPCAest(ctr_i,4) < PPCAest(ctr_i+1,4))&&(ctr_i<maxEV))
+      {estimators(3)=ctr_i+1;ctr_i++;}
+    ctr_i = 1;
+    while((ctr_i< PPCAest.Nrows()-1)&&
+	  (PPCAest(ctr_i,5) < PPCAest(ctr_i+1,5))&&(ctr_i<maxEV))
+      {estimators(4)=ctr_i+1;ctr_i++;}
+    ctr_i = 1;
+    while((ctr_i< PPCAest.Nrows()-1)&&
+	  (PPCAest(ctr_i,6) < PPCAest(ctr_i+1,6))&&(ctr_i<maxEV))
+      {estimators(5)=ctr_i+1;ctr_i++;}
+
+    int res = 0;
+    ColumnVector PPCA;
+ 		RowVector PercEV(PPCAest.Column(1).t());
+	  PercEV = cumsum(PercEV / sum(PercEV,2).AsScalar());
+
+	  if(which == string("aut")) {
+			if(int(estimators(2)) < int(estimators(1)) && 
+				float(PercEV(int(estimators(2))))>0.8){
+				res=int(estimators(2));
+	      PPCA << PPCAest.Column(3);
+			}else{
+				res = int(estimators(1));
+	      PPCA << PPCAest.Column(2);
+			}
+	  }			
+    if(which == string("lap")){
+      res = int(estimators(1));
+      PPCA << PPCAest.Column(2);
+    }
+    if(which == string("bic")){
+      res = int(estimators(2));
+      PPCA << PPCAest.Column(3);
+    }
+    if(which == string("mdl")){
+      res = int(estimators(3));
+      PPCA << PPCAest.Column(4);
+    }
+    if(which == string("rrn")){
+      res = int(estimators(4));
+      PPCA << PPCAest.Column(5);
+    }
+    if(which == string("aic")){
+      res = int(estimators(5));
+      PPCA << PPCAest.Column(6);
+    }
+		if(which == string("median")){
+			RowVector unsorted(estimators);	
+			SortAscending(unsorted);
+			ctr_i=1;
+			res=int(unsorted(3));
+			while(res != int(estimators(ctr_i)))			
+				ctr_i++;
+			PPCA << PPCAest.Column(ctr_i);
+		}
+    if(res==0 || which == string("mean")){//median estimator
+      PPCA = mean(PPCAest.Columns(2,6),2);
+			res=int(mean(estimators,2).AsScalar());
+    }
+
+    dim = res;
+    return PPCA;
+  }  //RowVector ppca_select
+
+  Matrix ppca_est(const RowVector& eigenvalues, const int N1, const float N2)
+  { 
+    Matrix Res;
+    Res = ppca_est(eigenvalues, (int) floor(N1/(2.5*N2)));
+    return Res;
+  }  //Matrix ppca_est
+
+  Matrix ppca_est(const RowVector& eigenvalues, const int N)
+  {
+    RowVector logLambda(eigenvalues);
+    logLambda = log(eigenvalues);
+
+    int d = logLambda.Ncols();
+
+    RowVector k(d);
+    for(int ctr_i = 1; ctr_i <=d; ctr_i++){
+      k(ctr_i)=ctr_i;
+    }
+   
+    RowVector m(d);
+    m=d*k-0.5*SP(k,k+1); 
+
+    RowVector loggam(d);
+    loggam = 0.5*k.Reverse();
+    for(int ctr_i = 1; ctr_i <=d; ctr_i++){
+      loggam(ctr_i)=lgam(loggam(ctr_i));
+    }
+    loggam = cumsum(loggam); 
+
+    RowVector l_probU(d);
+    l_probU = -log(2)*k + loggam - cumsum(0.5*log(M_PI)*k.Reverse());
+
+    RowVector tmp1;
+    tmp1 = -cumsum(eigenvalues).Reverse()+sum(eigenvalues,2).AsScalar();
+    tmp1(1) = 0.95*tmp1(2);
+    tmp1=tmp1.Reverse();
+
+    RowVector tmp2;
+    tmp2 = -cumsum(logLambda).Reverse()+sum(logLambda,2).AsScalar();
+    tmp2(1)=tmp2(2);
+    tmp2=tmp2.Reverse();
+
+    RowVector tmp3;
+    tmp3 = d-k;
+    tmp3(d) = 1.0;
+
+    RowVector tmp4;
+    tmp4 = SP(tmp1,pow(tmp3,-1));    
+    for(int ctr_i = 1; ctr_i <=d; ctr_i++){
+      if(tmp4(ctr_i)<0.01){tmp4(ctr_i)=0.01;}
+      if(tmp3(ctr_i)<0.01){tmp3(ctr_i)=0.01;}
+      if(tmp1(ctr_i)<0.01){tmp1(ctr_i)=0.01;}
+    }
+
+    RowVector l_nu;
+    l_nu = SP(-N/2*(d-k),log(tmp4));
+    l_nu(d) = 0;
+
+    RowVector l_lam;
+    l_lam = -(N/2)*cumsum(logLambda);
+
+    RowVector l_lhood;
+    l_lhood = SP(pow(tmp3,-1),tmp2)-log(SP(pow(tmp3,-1),tmp1));
+
+    Matrix t1,t2, t3;
+    UpperTriangularMatrix triu(d);
+    triu = 1.0;
+    for(int ctr_i = 1; ctr_i <= triu.Ncols(); ctr_i++){
+      triu(ctr_i,ctr_i)=0.0;
+    }
+    t1 = (ones(d,1) * eigenvalues);
+    t1 = SP(triu,t1.t() - t1);
+    t2 = pow(tmp4,-1).t()*ones(1,d);
+    t3 = ones(d,1)*pow(eigenvalues,-1);
+    t2 = SP(triu, t2.t()-t3.t());
+    for(int ctr_i = 1; ctr_i <= t1.Ncols(); ctr_i++){
+      for(int ctr_j = 1; ctr_j <= t1.Nrows(); ctr_j++){
+	if(t1(ctr_j,ctr_i)<=0){t1(ctr_j,ctr_i)=1;}
+      } 
+    }
+    for(int ctr_i = 1; ctr_i <= t2.Ncols(); ctr_i++){
+      for(int ctr_j = 1; ctr_j <= t2.Nrows(); ctr_j++){
+	if(t2(ctr_j,ctr_i)<=0){t2(ctr_j,ctr_i)=1;}
+      }
+    } 
+    t1 = cumsum(sum(log(t1),2).AsRow());
+    t2 = cumsum(sum(log(t2),2).AsRow());
+
+    RowVector l_Az(d);
+    l_Az << (t1+t2);
+
+    RowVector l_lap;
+    l_lap = l_probU + l_nu +l_Az + l_lam + 0.5*log(2*M_PI)*(m+k)-0.5*log(N)*k;
+ 
+    RowVector l_BIC;
+    l_BIC = l_lam + l_nu - 0.5*log(N)*(m+k);
+
+    RowVector l_RRN;
+    l_RRN = -0.5*N*SP(k,log(SP(cumsum(eigenvalues),pow(k,-1))))+l_nu;
+
+    RowVector l_AIC;
+    l_AIC = -2*N*SP(tmp3,l_lhood)+ 2*(1+d*k+0.5*(k-1));
+    l_AIC = -l_AIC;
+
+    RowVector l_MDL;
+    l_MDL = -N*SP(tmp3,l_lhood)+ 0.5*(1+d*k+0.5*(k-1))*log(N);
+    l_MDL = -l_MDL;
+
+    Matrix Res;
+
+    Res = eigenvalues.t();
+    Res |= l_lap.t();
+    Res |= l_BIC.t();
+    Res |= l_MDL.t();
+    Res |= l_RRN.t();
+    Res |= l_AIC.t();
+    
+   
+    return Res;
+  }  //Matrix ppca_est
+
+  ColumnVector acf(const ColumnVector& in, int order)
+  {
+    double meanval;
+    meanval = mean(in).AsScalar();
+    int tpoints = in.Nrows();
+    
+    ColumnVector y, res;
+    Matrix X, tmp;
+
+    y = in.Rows(order+1,tpoints) - meanval;
+    X = zeros(order + 1, order);
+    for(int ctr1 = 1; ctr1 <= order; ctr1++)
+      X.Column(ctr1) = in.Rows(order + 1 - ctr1, tpoints - ctr1) - meanval;
+    tmp = X.t()*X;
+    tmp = tmp.i();
+    tmp = tmp * X.t();
+    res << tmp * y;
+    return res;
+  }  //ColumnVector acf
+
+  ColumnVector pacf(const ColumnVector& in, int maxorder)
+  {
+    int tpoint = in.Nrows();
+    ColumnVector res;
+    res = acf(in, maxorder);
+    for(int ctr1 = 1; ctr1 <= maxorder; ctr1++)
+      if ( res.Column(ctr1).AsScalar() <  (1/tpoint) + 2/(float)std::pow(tpoint,0.5)) 
+	res.Column(ctr1) = 0;
+    return res;
+  }  //ColumnVector pacf
+  
+  Matrix est_ar(const Matrix& Mat, int maxorder)
+  {
+    Matrix res;
+    res = zeros(maxorder, Mat.Ncols());
+    ColumnVector tmp;
+    for (int ctr = 1; ctr <= Mat.Ncols(); ctr++){
+      tmp = pacf(Mat.Column(ctr));
+      res.Column(ctr) = tmp;
+    }
+    return res;
+  }  //Matrix est_ar
+
+  ColumnVector gen_ar(const ColumnVector& in, int maxorder)
+  {
+    float sdev;
+    sdev = stdev(in).AsScalar();
+    ColumnVector x, arcoeff, scaled;
+    scaled = in / sdev;
+    arcoeff = pacf( scaled, maxorder);
+    x = normrnd(in.Nrows(),1).AsColumn() * sdev;
+    for(int ctr1=2; ctr1 <= in.Nrows(); ctr1++)
+      for(int ctr2 = 1; ctr2 <= maxorder; ctr2++)
+	x(ctr1) = arcoeff(ctr2) * x(std::max(1,int(ctr1-ctr2))) + x(ctr1);
+    return x;
+  }  //ColumnVector gen_ar
+
+  Matrix gen_ar(const Matrix& in, int maxorder)
+  {
+    Matrix res;
+    res = in;
+    ColumnVector tmp;
+    for(int ctr=1; ctr <= in.Ncols(); ctr++){
+      tmp = in.Column(ctr);
+      res.Column(ctr) = gen_ar(tmp, maxorder);
+    } 
+    return res;
+  }  //Matrix gen_ar
+
+  Matrix gen_arCorr(const Matrix& in, int maxorder)
+  {
+    Matrix res;
+    res = zeros(in.Nrows(), in.Nrows());
+    ColumnVector tmp;
+    for(int ctr=1; ctr<= in.Ncols(); ctr++){
+      tmp = in.Column(ctr);
+      tmp = gen_ar(tmp, maxorder);
+      res += tmp * tmp.t();
+    }
+    return res;
+  }  //Matrix gen_arCorr
+
+	void basicGLM::olsfit(const Matrix& data, const Matrix& design, 
+		const Matrix& contrasts, int requestedDOF)
+	{
+		beta = zeros(design.Ncols(),1); 
+		residu = zeros(1); sigsq = -1.0*ones(1); varcb = -1.0*ones(1); 
+		t = zeros(1); z = zeros(1); p=-1.0*ones(1);
+		dof = (int)-1; cbeta = -1.0*ones(1); 
+
+		if(data.Nrows()==design.Nrows()){
+			Matrix dat = data;
+			Matrix tmp = design.t()*design;
+			Matrix pinvdes = tmp.i()*design.t();
+			
+			beta = pinvdes * dat;
+			residu = dat - design*beta;
+			dof = ols_dof(design);
+			if ( requestedDOF>0)
+			  dof = requestedDOF;
+			sigsq = sum(SP(residu,residu))/dof;
+			
+			float fact = float(dof) / design.Ncols();
+			f_fmf =  SP(sum(SP(design*beta,design*beta)),pow(sum(SP(residu,residu)),-1)) * fact;
+		
+			pf_fmf = f_fmf.Row(1); 
+			for(int ctr1=1;ctr1<=f_fmf.Ncols();ctr1++)
+				pf_fmf(1,ctr1) = 1.0-MISCMATHS::fdtr(design.Ncols(),dof,f_fmf.Column(ctr1).AsScalar());
+				
+			if(contrasts.Storage()>0 && contrasts.Ncols()==beta.Nrows()){
+				cbeta = contrasts*beta;
+				Matrix tmp = contrasts*pinvdes*pinvdes.t()*contrasts.t();
+				varcb = diag(tmp)*sigsq;
+				t = SP(cbeta,pow(varcb,-0.5));
+				z = t; p=t; 
+				for(int ctr1=1;ctr1<=t.Ncols();ctr1++){
+					ColumnVector tmp = t.Column(ctr1);
+					T2z::ComputeZStats(varcb.Column(ctr1),cbeta.Column(ctr1),dof, tmp);
+					z.Column(ctr1) << tmp;
+					T2z::ComputePs(varcb.Column(ctr1),cbeta.Column(ctr1),dof, tmp);
+					p.Column(ctr1) << exp(tmp);
+				}
+			}
+		}	
+	
+	}
+
+
+}
diff --git a/melodic.h b/melodic.h
new file mode 100644
index 0000000..6721b42
--- /dev/null
+++ b/melodic.h
@@ -0,0 +1,88 @@
+/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
+                 independent components
+    
+    melodic.h - main program header
+
+    Christian F. Beckmann and Matthew Webster, FMRIB Analysis Group
+    
+    Copyright (C) 1999-2013 University of Oxford */
+
+/*  CCOPYRIGHT */
+
+#ifndef __MELODIC_h
+#define __MELODIC_h
+
+#include <strstream>
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#define memmsg(msg) { \
+  MelodicOptions&opt = MelodicOptions::getInstance(); \
+  struct task_basic_info t_info; \
+  mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; \
+  if (KERN_SUCCESS == task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) &t_info, &t_info_count)) \
+	{ \
+		if(opt.debug.value()) {\
+		    cout << " MEM: " << msg << " res: " << t_info.resident_size/1000000 << " virt: " << t_info.virtual_size/1000000 << "\n"; \
+		    cout.flush(); \
+		 } \
+	} \
+}
+#else
+#define memmsg(msg) { \
+  MelodicOptions&opt = MelodicOptions::getInstance(); \
+  if(opt.debug.value()) {\
+		cout << msg; \
+		cout.flush(); \
+  } \
+}
+#endif
+
+
+
+// a simple message macro that takes care of cout and log
+#define message(msg) { \
+  MelodicOptions& opt = MelodicOptions::getInstance(); \
+  if(opt.verbose.value()) \
+    { \
+      cout << msg; \
+    } \
+  Log& logger  =   LogSingleton::getInstance(); \
+  logger.str() << msg; \
+  cout.flush(); \
+}
+
+#define dbgmsg(msg) { \
+  MelodicOptions&opt = MelodicOptions::getInstance(); \
+  if(opt.debug.value()) {\
+		cout << msg; } \
+}
+
+#define outMsize(msg,Mat) { \
+  MelodicOptions& opt = MelodicOptions::getInstance();		\
+  if(opt.debug.value())						\
+    cerr << "     " << msg << "  " <<Mat.Nrows() << " x " << Mat.Ncols() << endl;	\
+}
+
+namespace Melodic{
+
+const string version = "3.14";  
+
+// The two strings below specify the title and example usage that is	
+// printed out as the help or usage message
+const string title=string("MELODIC (Version ")+version+")"+
+		string("\n Multivariate Exploratory Linear Optimised Decomposition into Independent Components\n")+
+		string("\nAuthor: Christian F. Beckmann \n Copyright(c) 2001-2013 University of Oxford");
+
+const string usageexmpl=string(" melodic -i <filename> <options>")+
+		   string("\n \t \t to run melodic")+
+	//	   string("\n melodic -i <filename> --mix=melodic_mix")+
+	//	   string(" --filter=\"string of component numbers\"")+
+	//	   string("\n \t \t to remove estimated ICs from input")+
+		   string("\n melodic -i <filename> --ICs=melodic_IC")+
+		   string(" --mix=melodic_mix <options>")+
+		   string("\n \t \t to run Mixture Model based inference on estimated ICs")+
+		   string("\n melodic --help ");
+}
+
+#endif
diff --git a/meloptions.cc b/meloptions.cc
index b75604f..0cb87bc 100644
--- a/meloptions.cc
+++ b/meloptions.cc
@@ -162,16 +162,20 @@ MelodicOptions* MelodicOptions::gopt = NULL;
   		//in the case of indirect inputs, create the vector of input names here
   		if(!FslFileExists(inputfname.value().at(0))){
     		std::vector< string > tmpfnames;
-    		ifstream fs(inputfname.value().at(0).c_str());
+    		ifstream fs(inputfname.value().at(0).c_str() );
+		if (!fs.good()) {
+		  cerr << "Error reading input file: " << inputfname.value().at(0).c_str() << endl;
+		  exit(1);
+		}
     		string cline;
-    		while (!fs.eof()) {
+    		while (fs.good()) {
 		  getline(fs,cline);
 		  if(cline.length()>0) {
 		    while ( cline.find(' ') != cline.npos )
 		      cline.erase( cline.find(' '),1);
 		    tmpfnames.push_back(cline);
 		  }
-    		}	
+    		}
     		fs.close();
     		inputfname.set_T(tmpfnames);
   		}
diff --git a/meloptions.h b/meloptions.h
new file mode 100644
index 0000000..4b15d17
--- /dev/null
+++ b/meloptions.h
@@ -0,0 +1,527 @@
+ /*  MELODIC - Multivariate exploratory linear optimized decomposition into 
+              independent components
+    
+    meloptions.h - class for command line options
+
+    Christian F. Beckmann, FMRIB Analysis Group
+    
+    Copyright (C) 1999-2013 University of Oxford */
+
+/*  CCOPYRIGHT  */
+
+#ifndef __MELODICOPTIONS_h
+#define __MELODICOPTIONS_h
+
+#include <string>
+#include <strstream>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <stdlib.h>
+#include <stdio.h>
+#include "utils/options.h"
+#include "utils/log.h"
+#include "melodic.h"
+
+using namespace Utilities;
+
+namespace Melodic {
+
+class MelodicOptions {
+	public:
+  	static MelodicOptions& getInstance();
+  	~MelodicOptions() { delete gopt; }
+  
+  	string version;
+  	string binpath;
+  	string logfname;
+  	bool   filtermode;
+  	bool   explicitnums;
+  
+  	Option<string> logdir;
+  	Option< std::vector<string> > inputfname;
+
+  	Option<string> outputfname;
+
+  	Option<string> maskfname;
+  	Option<bool>   use_mask;
+  	Option<bool>   update_mask;
+  	Option<bool>   perf_bet;
+  	Option<float>  threshold;
+
+  	Option<int>    pca_dim;
+  	Option<string> pca_est;
+  	Option<bool>   joined_whiten;
+  	Option<bool>   joined_vn;
+	Option<bool>   dr_pca;
+	Option<bool>   migp;
+	Option<int>    migpN;
+	Option<bool>   migp_shuffle;
+	Option<int>	   migp_factor;
+	Option<bool>   dr;
+	Option<bool>   dr_out;
+	Option<float>  vn_level;
+  	Option<int>    numICs;
+  	Option<string> approach;
+  	Option<string> nonlinearity;
+
+  	Option<bool>   varnorm;
+ 	Option<bool>   varnorm2;
+  	Option<bool>   pbsc;
+  	Option<bool>   pspec;
+  	Option<string> segment;
+  	Option<bool>   tsmooth;
+  	Option<float>  epsilon;
+  	Option<float>  epsilonS;
+  	Option<int>    maxNumItt;
+  	Option<int>    maxRestart;
+  	Option<int>    rank1interval;
+
+  	Option<string> mmthresh;
+  	Option<bool>   perf_mm;
+  	Option<string> ICsfname;
+  	Option<string> filtermix; 
+  	Option<string> smodename; 
+  	Option<string> filter; 
+
+  	Option<bool>   genreport;
+	Option<string> guireport;
+	Option<string> bgimage;
+  	Option<float>  tr;
+  	Option<bool>   logPower;
+	Option<bool>   addsigchng;
+	Option<bool>   allPPCA;
+	Option<bool>   varplots;
+	Option<bool>   varvals;
+
+	Option<string> fn_Tdesign;
+	Option<string> fn_Tcon;
+	Option<string> fn_TconF;
+	Option<string> fn_Sdesign;
+	Option<string> fn_Scon;	
+	Option<string> fn_SconF;	
+	
+  	Option<bool>   output_all;
+  	Option<bool>   output_unmix;
+  	Option<bool>   output_MMstats;
+  	Option<bool>   output_pca;
+  	Option<bool>   output_white;
+  	Option<bool>   output_origIC;
+  	Option<bool>   output_mean;
+
+  	Option<bool> verbose;  
+  	Option<bool> vers;
+  	Option<bool> copyright;
+  	Option<bool> help;
+  	Option<bool> debug;
+
+  	Option<string> guessfname;
+  	Option<string> paradigmfname;
+  	Option<string> axials_str;
+
+  	Option<int>   dummy;
+  	Option<int>   repeats;
+	Option<int>   seed;
+  	Option<float> nlconst1;
+  	Option<float> nlconst2;
+  	Option<float> smooth_probmap;
+	Option<string> insta_fn;
+
+  	Option<bool> remove_meanvol;
+  	Option<bool> remove_meantc;
+ 	Option<bool> remove_endslices;
+  	Option<bool> rescale_nht;
+
+  	Option<bool> guess_remderiv;
+  	Option<bool> temporal;
+
+  	Option<float> retryfactor;
+  	Option<int> econ;
+
+  	void parse_command_line(int argc, char** argv, Log& logger,  const string &p_version);
+
+ 	private:
+  	MelodicOptions();  
+  	const MelodicOptions& operator=(MelodicOptions&);
+  	MelodicOptions(MelodicOptions&);
+
+  	OptionParser options; 
+      
+  	static MelodicOptions* gopt;
+
+  	void print_usage(int argc, char *argv[]);  
+  	void print_version(); 
+  	void print_copyright();
+  	void status();
+
+};
+
+ inline MelodicOptions& MelodicOptions::getInstance(){
+   if(gopt == NULL)
+     gopt = new MelodicOptions();
+   
+   return *gopt;
+ }
+
+ inline MelodicOptions::MelodicOptions() :
+   logdir(string("-o,--outdir"), string("log.txt"),
+	   string("output directory name\n"), 
+	   false, requires_argument),
+   inputfname(string("-i,--in"), std::vector<string>(),
+	   string("input file names (either single file name or comma-separated list or text file)"), 
+	   true, requires_argument),
+   outputfname(string("-O,--out"), string("melodic"),
+	   string("output file name"), 
+	   false, requires_argument,false),
+   maskfname(string("-m,--mask"), string(""),
+	   string("file name of mask for thresholding"), 
+	   false, requires_argument),
+   use_mask(string("--nomask"), true,
+	   string("switch off masking"), 
+	   false, no_argument),
+   update_mask(string("--update_mask"), true,
+	   string("switch off mask updating"), 
+	   false, no_argument),
+   perf_bet(string("--nobet"), true,
+	   string("\tswitch off BET"), 
+	   false, no_argument),
+   threshold(string("--bgthreshold"),  0.01,
+	   string("brain / non-brain threshold (only if --nobet selected)\n"), 
+	   false, requires_argument),
+   pca_dim(string("-d,--dim"), 0,
+	   string("dimensionality reduction into #num dimensions (default: automatic estimation)"), 
+	   false, requires_argument),
+   pca_est(string("--dimest"), string("lap"),
+	   string("use specific dim. estimation technique: lap, bic, mdl, aic, mean (default: lap)"), 
+	   false, requires_argument),
+   joined_whiten(string("--sep_whiten"), false,
+	   string("switch on separate whitening"), 
+	   false, no_argument, false),
+   joined_vn(string("--sep_vn"), true,
+   	   string("switch on separate variance nomalisation (as opposed to separate VN)"), 
+       false, no_argument),
+   dr_pca(string("--mod_pca"), true,
+	   string("switch off modified PCA for concat ICA"),
+	   false, no_argument, false),
+   migp(string("--disableMigp"), true,
+	   string("switch off MIGP data reduction"),
+	   false, no_argument),	
+   migpN(string("--migpN"), 0,
+	   string("Number of internal Eigenmaps"),
+	   false, requires_argument),
+   migp_shuffle(string("--migp_shuffle"), true,
+	   string("Randomise MIGP file order (default: TRUE)"),
+	   false, no_argument),
+   migp_factor(string("--migp_factor"), 2,
+	   string("Internal Factor of mem-threshold relative to number of Eigenmaps (default: 2)"),
+       false, requires_argument),
+   dr(string("--dr"), false,
+	   string("Dual Regression (default: false)"),
+	   false, no_argument, false),
+   dr_out(string("--dr_out"), false,
+	   string("Dual Regression output for MIGP/concat ICA"),
+	   false, no_argument, false),	
+   vn_level(string("--vn_level"), float(2.3),
+	   string("variance nomalisation threshold level (Z> value is ignored)"), 
+	   false, requires_argument, false),
+   numICs(string("-n,--numICs"), -1,
+	   string("numer of IC's to extract (for deflation approach)"), 
+	   false, requires_argument),
+   approach(string("-a,--approach"),  string("symm"),
+	   string("approach for decomposition, 2D: defl, symm (default), 3D: tica, concat (default)"),
+	   false, requires_argument),
+   nonlinearity(string("--nl"), string("pow3"),
+	   string("\tnonlinearity: gauss, tanh, pow3, pow4"), 
+	   false, requires_argument),
+   varnorm(string("--vn,--varnorm"), true,
+	   string("switch off variance normalisation"), 
+	   false, no_argument),
+   varnorm2(string("--vn2"), true,
+		string("switch off 2nd level variance normalisation"), 
+		false, no_argument, false),
+   pbsc(string("--pbsc"), false,
+	   string("        switch on conversion to percent BOLD signal change"), 
+	   false, no_argument, false),
+   pspec(string("--pspec"), false,
+	   string("        switch on conversion to powerspectra"), 
+	   false, no_argument, false),
+   segment(string("--covarweight"), string(""),
+	   string("voxel-wise weights for the covariance matrix (e.g. segmentation information)"),
+	   false, requires_argument),
+   tsmooth(string("--spca"),  false,
+	   string("smooth the eigenvectors prior to IC decomposition"), 
+	    false, no_argument, false),
+   epsilon(string("--eps"), 0.00005,
+	   string("minimum error change"), 
+	   false, requires_argument),
+   epsilonS(string("--epsS"), 0.03,
+	   string("minimum error change for rank-1 approximation in TICA"), 
+	   false, requires_argument),
+   maxNumItt(string("--maxit"),  500,
+	   string("\tmaximum number of iterations before restart"), 
+	   false, requires_argument),
+   maxRestart(string("--maxrestart"),  -1,
+	   string("maximum number of restarts\n"), 
+	   false, requires_argument),
+   rank1interval(string("--rank1interval"),  10,
+	   string("number of iterations between rank-1 approximation (TICA)\n"), 
+		 false, requires_argument,false),
+   mmthresh(string("--mmthresh"), string("0.5"),
+	   string("threshold for Mixture Model based inference"), 
+	   false, requires_argument),
+   perf_mm(string("--no_mm"), true,
+	   string("\tswitch off mixture modelling on IC maps\n "), 
+	   false, no_argument),
+   ICsfname(string("--ICs"), string(""),
+	   string("\tinput filename of the IC components file for mixture modelling"), 
+	   false, requires_argument),
+   filtermix(string("--mix"),  string(""),
+	   string("\tinput filename of mixing matrix for mixture modelling / filtering"), 
+	   false, requires_argument),
+   smodename(string("--smode"),  string(""),
+	   string("\tinput filename of matrix of session modes for report generation"), 
+	   false, requires_argument),
+   filter(string("-f,--filter"),  string(""),
+	   string("list of component numbers to remove\n "), 
+	   false, requires_argument),
+   genreport(string("--report"), false,
+	   string("generate Melodic web report"), 
+	   false, no_argument),
+   guireport(string("--guireport"), string(""),
+	   string("modify report for GUI use"), 
+	   false, requires_argument, false),
+   bgimage(string("--bgimage"),  string(""),
+	   string("specify background image for report (default: mean image)\n "), 
+	   false, requires_argument),
+   tr(string("--tr"),  0.0,
+	   string("\tTR in seconds"), 
+	   false, requires_argument),
+   logPower(string("--logPower"),  false,
+	   string("calculate log of power for frequency spectrum\n"), 
+	   false, no_argument),
+   addsigchng(string("--sigchng"),  false,
+	   string("add signal change estimates to report pages\n"), 
+       false, no_argument, false),
+   allPPCA(string("--allPPCA"),  false,
+	   string("add all PPCA plots\n"), 
+	   false, no_argument, false),
+   varplots(string("--varplots"),  false,
+	   string("add std error envelopes to time course plots\n"), 
+	   false, no_argument, false),
+   varvals(string("--varvals"),  false,
+	   string("add rank1 values after plots\n"), 
+	   false, no_argument, false),
+   fn_Tdesign(string("--Tdes"), string(""),
+	   string("        design matrix across time-domain"),
+	   false, requires_argument),
+   fn_Tcon(string("--Tcon"), string(""),
+       string("        t-contrast matrix across time-domain"),
+	   false, requires_argument),
+   fn_TconF(string("--Tconf"), string(""),
+	   string("        F-contrast matrix across time-domain"),
+	   false, requires_argument, false),
+   fn_Sdesign(string("--Sdes"), string(""),
+	   string("        design matrix across subject-domain"),
+	   false, requires_argument),
+   fn_Scon(string("--Scon"), string(""),
+	   string("        t-contrast matrix across subject-domain"),
+	   false, requires_argument),	
+   fn_SconF(string("--Sconf"), string(""),
+	   string("        F-contrast matrix across subject-domain"),
+	   false, requires_argument,false),	
+   output_all(string("--Oall"),  false,
+	   string("        output everything"), 
+	   false, no_argument),
+   output_unmix(string("--Ounmix"),  false,
+	   string("output unmixing matrix"), 
+	   false, no_argument),
+   output_MMstats(string("--Ostats"),  false,
+	   string("output thresholded maps and probability maps"), 
+	   false, no_argument),
+   output_pca(string("--Opca"),  false,
+	   string("\toutput PCA results"), 
+	   false, no_argument),
+   output_white(string("--Owhite"),  false,
+	   string("output whitening/dewhitening matrices"), 
+	   false, no_argument),
+   output_origIC(string("--Oorig"),  false,
+	   string("\toutput the original ICs"), 
+	   false, no_argument),
+   output_mean(string("--Omean"),  false,
+	   string("\toutput mean volume\n"), 
+	   false, no_argument),
+   verbose(string("-v,--verbose"), false,
+	   string("switch on diagnostic messages"), 
+	   false, no_argument),
+   vers(string("-V,--version"), false,
+	   string("prints version information"), 
+	   false, no_argument),
+   copyright(string("--copyright"), false,
+	   string("prints copyright information"), 
+	   false, no_argument),
+   help(string("-h,--help"),  false,
+	   string("prints this help message"), 
+	   false, no_argument),
+   debug(string("--debug"),  false,
+	   string("        switch on debug messages"), 
+	   false, no_argument),
+   guessfname(string("--init_ica"), string(""),
+	   string("file name of FEAT paradigm file (design.mat) for ICA initialisation"), 
+	   false, requires_argument, false),
+   paradigmfname(string("--init_pca"),  string(""),
+	   string("file name of FEAT paradigm file (design.mat) for PCA initialisation"), 
+	   false, requires_argument, false),
+   axials_str(string("--report_maps"),  string(" -s 2 -A 950 "),
+		   string("control string for spatial map images (see slicer)"), 
+		   false, requires_argument),
+   dummy(string("--dummy"),  0,
+	   string("number of dummy volumes"), 
+	   false, requires_argument,false),
+   repeats(string("--repeats"), 1,
+	   string("number of repeats (multistart)"), 
+	   false, requires_argument, false),
+   seed(string("--seed"), -1,
+	   string("integer seed for random number generator within melodic"), 
+	   false, requires_argument, false),
+   nlconst1(string("--nl1,--nlconst1"),  1.0,
+	   string("nonlinear constant 1"), 
+	   false, requires_argument, false),
+   nlconst2(string("--nl2,--nlconst2"),  1.0,
+	   string("nonlinear constant 2"), 
+	   false, requires_argument, false),
+   smooth_probmap(string("--smooth_pm"),  0.0,
+	   string("width of smoothing kernel for probability maps"), 
+	   false, requires_argument, false),
+   insta_fn(string("--insta_fn"), string(""),
+	   string(" mask file name for instacorr calculation"),
+       false, requires_argument, false),
+   remove_meanvol(string("--keep_meanvol"), true,
+	   string("do not subtract mean volume"), 
+	   false, no_argument, false),
+   remove_meantc(string("--remove_meantc"), false,
+	   string("remove mean time course"), 
+	   false, no_argument, false),
+   remove_endslices(string("--remEndslices"),  false,
+	   string("delete end slices (motion correction artefacts)"), 
+	   false, no_argument,false),
+   rescale_nht(string("--rescale_nht"),  true,
+	   string("switch off map rescaling after mixture-modelling"), 
+	   false, no_argument,false),
+   guess_remderiv(string("--remove_deriv"),  false,
+	   string("removes every second entry in paradigm file (EV derivatives)"), 
+	   false, no_argument, false),
+   temporal(string("--temporal"),  false,
+	   string("perform temporal ICA"), 
+	   false, no_argument, false),
+   retryfactor(string("--retryfactor"), float(0.95),
+		string("multiplicative factor for determining new dim if estimated dim fails to converge"),
+		false, requires_argument, false),
+   econ(string("--econ"), 20000, 
+	   string("set ctrl parameter for helperfns econ mode"),
+       false, requires_argument, false),
+   options(title, usageexmpl)
+   {
+     try {  
+      options.add(logdir);
+	    options.add(inputfname);
+	    options.add(outputfname);
+	    options.add(guessfname);
+	    options.add(maskfname);
+	    options.add(use_mask);
+	    options.add(update_mask);
+	    options.add(perf_bet);
+	    options.add(threshold);
+	    options.add(pca_dim);
+	    options.add(pca_est);
+	    options.add(joined_whiten);
+	    options.add(joined_vn);
+		options.add(dr_pca);
+		options.add(migp);
+		options.add(migpN);
+		options.add(migp_shuffle);
+		options.add(migp_factor);
+		options.add(dr);
+		options.add(dr_out);
+	    options.add(vn_level);
+	    options.add(numICs);
+	    options.add(approach);
+	    options.add(nonlinearity);
+	    options.add(varnorm);
+		options.add(varnorm2);
+	    options.add(pbsc);
+	    options.add(pspec);
+	    options.add(segment);
+	    options.add(tsmooth);
+	    options.add(epsilon);
+	    options.add(epsilonS);
+	    options.add(maxNumItt);
+	    options.add(maxRestart);
+	    options.add(rank1interval);
+	    options.add(mmthresh);
+	    options.add(perf_mm);
+	    options.add(ICsfname);
+	    options.add(filtermix);
+	    options.add(smodename);
+	    options.add(filter);
+	    options.add(genreport);
+	    options.add(guireport);
+		options.add(bgimage);
+	    options.add(tr);
+	    options.add(logPower);
+	    options.add(addsigchng);
+	    options.add(allPPCA);
+	    options.add(varplots);
+	    options.add(varvals);
+		options.add(fn_Tdesign);
+		options.add(fn_Tcon);
+		options.add(fn_TconF);
+		options.add(fn_Sdesign);
+		options.add(fn_Scon);
+		options.add(fn_SconF);
+	    options.add(output_all);
+	    options.add(output_unmix);
+	    options.add(output_MMstats);
+	    options.add(output_pca);
+	    options.add(output_white);
+	    options.add(output_origIC);
+	    options.add(output_mean);
+	    options.add(verbose);
+	    options.add(vers);
+	    options.add(copyright);
+	    options.add(help);
+	    options.add(debug);
+	   
+	    options.add(guessfname);
+	    options.add(paradigmfname); 
+	    options.add(axials_str); 
+	    options.add(dummy);
+	    options.add(repeats);
+	    options.add(seed);
+	    options.add(nlconst1);
+	    options.add(nlconst2);
+	    options.add(smooth_probmap);
+		options.add(insta_fn);
+	    options.add(remove_meanvol);
+	    options.add(remove_meantc);
+	    options.add(remove_endslices);
+	    options.add(rescale_nht);
+	    options.add(guess_remderiv);
+	    options.add(temporal);
+		options.add(retryfactor);
+		options.add(econ);
+     }
+     catch(X_OptionError& e) {
+       options.usage();
+       cerr << endl << e.what() << endl;
+     } 
+     catch(std::exception &e) {
+       cerr << e.what() << endl;
+     }    
+     
+   }
+}
+
+#endif
+
+
+
diff --git a/melreport.cc b/melreport.cc
new file mode 100644
index 0000000..417f3ef
--- /dev/null
+++ b/melreport.cc
@@ -0,0 +1,807 @@
+/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
+    independent components
+   
+    melreport.cc - report generation
+
+    Christian F. Beckmann, FMRIB Analysis Group
+    
+    Copyright (C) 1999-2013 University of Oxford */
+
+/*  CCOPYRIGHT  */
+
+#include "newimage/newimageall.h"
+#include "utils/log.h"
+#include "melreport.h"
+#include "melhlprfns.h"
+#include "miscmaths/miscprob.h"
+
+namespace Melodic{
+  
+	void MelodicReport::IC_rep(MelGMix &mmodel, int cnum, int dim, Matrix ICstats){
+
+		if( bool(opts.genreport.value()) ){
+    	addlink(mmodel.get_prefix()+".html",num2str(cnum));
+			IChtml.setDir(report.getDir(),mmodel.get_prefix()+".html");
+
+      {//start IC page
+				IChtml << "<HTML><HEAD><link REL=stylesheet TYPE=text/css href=file:" +
+					(string) getenv("FSLDIR") +"/doc/fsl.css>" << endl
+					<< "<style type=\"text/css\">OBJECT { width: 100% }</style>"
+	       	<< "<TITLE>FSL</TITLE></HEAD>" << endl
+	  			<< "<IFRAME  height=" << int(melodat.get_numfiles()/30 + 1)*50 
+					<<"px width=100% src=nav.html frameborder=0></IFRAME><BR>"<< endl
+	       	<< "<Center>" << endl;
+			
+				if(cnum>1)
+	  			IChtml << "<a href=\"" << string("IC_")+num2str(cnum-1)
+					<<".html\">&#60;</a>&nbsp;-&nbsp;";
+				else
+	  			IChtml << "<a href=\"" << string("IC_")+num2str(melodat.get_mix().Ncols())
+					<<".html\">&#60;</a>&nbsp;-&nbsp;";
+	
+				if(cnum<dim)
+	  			IChtml << "<a href=\"" << string("IC_")+num2str(cnum+1)
+					<<".html\">&#62;</a>";
+				else 
+	  			IChtml << "<a href=\"" << string("IC_")+num2str(1)
+					<<".html\">&#62;</a>";
+				IChtml << "<p><H3>MELODIC Component " << num2str(cnum)
+				<< "<br></b></H3><hr><p>" << endl;
+			}
+      {//output IC stats
+    		if(ICstats.Storage()>0&&ICstats.Nrows()>=cnum){
+	  			IChtml << fixed << setprecision(2) << std::abs(ICstats(cnum,1)) << " % of explained variance";
+	  			if(ICstats.Ncols()>1)
+	    			IChtml << "; &nbsp; &nbsp; " << std::abs(ICstats(cnum,2)) << " % of total variance";
+					if(ICstats.Ncols()>2&&opts.addsigchng.value()){
+	    			IChtml << "<p>" <<endl;
+	    			IChtml << " &nbsp; &nbsp; " << ICstats(cnum,3) << " % signal change (pos peak voxel); &nbsp; &nbsp;" << ICstats(cnum,4) << "% signal change (peak neg. voxel)" << endl ;
+	  			}
+	  			IChtml << "<hr><p>" << endl;
+				}
+      }
+      
+      volume4D<float> tempVol;       
+      if(mmodel.get_threshmaps().Storage()>0&&
+	    (mmodel.get_threshmaps().Ncols() == mmodel.get_data().Ncols()))
+	    {//Output thresholded IC map	
+				tempVol.setmatrix(mmodel.get_threshmaps().Row(1),melodat.get_mask());
+				volume<float> map1;
+				volume<float> map2;
+				map1 = threshold(tempVol[0],float(0.0), tempVol[0].max());
+				map2 = threshold(tempVol[0],tempVol[0].min(), float(0.0));
+	
+				volume<float> newvol;
+
+				miscpic newpic;
+	
+				float map1min = std::max((map1 + binarise(tempVol[0],tempVol[0].min(), 
+						    	float(0.0)) * map1.max()).min(),float(0.001));
+			  float map1max = std::max(map1.max(),float(0.001));
+				float map2min = std::min(map2.min(),float(-0.001));
+				float map2max = std::min((map2 + binarise(tempVol[0],float(0.0), 
+						  		tempVol[0].max()) * map2.min()).max(),float(-0.001));
+	
+    		newpic.overlay(newvol, melodat.get_bg(), map1, map2, 
+		       		melodat.get_bg().percentile(0.02),
+		       		melodat.get_bg().percentile(0.98),
+		       		map1min, map1max, map2max, map2min, 
+		       		0, 0);
+				char instr[10000];
+	
+				sprintf(instr," ");
+				strcat(instr,axials_instr.c_str());
+				strcat(instr,string(report.appendDir(mmodel.get_prefix()+
+					     	"_thresh.png")).c_str());
+				newpic.set_title(string("Component No. "+num2str(cnum)+
+								" - thresholded IC map  ") + mmodel.get_infstr(1));
+				newpic.set_cbar(string("ysb"));
+	
+				if((std::abs(map1.max()-map1.min())>0.01) || (std::abs(map2.max()-map2.min())>0.01))
+	  			newpic.slicer(newvol, instr); 
+				else
+	  			newpic.slicer(newvol, instr);
+	  		IChtml << "<a href=\""+mmodel.get_prefix()+"_MM.html\">";
+	    	IChtml << "<img BORDER=0 SRC=\""+mmodel.get_prefix()
+	    		+"_thresh.png\" ALT=\"MMfit\"></A><p>" << endl;
+      }		
+			
+      {//plot time course
+    	IChtml << "<H3> Temporal mode </H3><p>" << endl <<endl;     	
+		miscplot newplot;
+		
+			Matrix tmptc = melodat.get_Tmodes(cnum-1).Column(1).t();
+
+			newplot.col_replace(0,0xFF0000);
+
+			newplot.add_label(string("IC ")+num2str(cnum)+" time course");
+			//add GLM OLS fit
+			if(melodat.Tdes.Storage()>0 &&
+		  melodat.glmT.get_beta().Nrows() == melodat.Tdes.Ncols()){
+				tmptc &= melodat.glmT.get_beta().Column(cnum).t() * melodat.Tdes.t();
+				newplot.add_label("full model fit");
+			}
+
+			//add deviation around time course
+			if(melodat.get_Tmodes(cnum-1).Ncols()>1 && opts.varplots.value()){
+				Matrix tmp = stdev(melodat.get_Tmodes(cnum-1).Columns(2,melodat.get_Tmodes(cnum-1).Ncols()).t(),1);
+				tmptc &= melodat.get_Tmodes(cnum-1).Column(1).t()+tmp;
+				tmptc &= melodat.get_Tmodes(cnum-1).Column(1).t()-tmp;
+				newplot.add_label("std error across subjects");
+				newplot.col_replace(tmptc.Nrows()-1,0x808080);
+				newplot.col_replace(tmptc.Nrows()-2,0x808080);				
+			}
+		
+	    if(opts.tr.value()>0.0)
+				newplot.add_xlabel(string("Time (seconds); TR = ")+
+				float2str(opts.tr.value(),0,2,0)+" s");
+			else 
+		  	newplot.add_xlabel(string("Time (TRs)"));
+			
+			newplot.add_ylabel("Normalised Response");
+			newplot.set_yrange(tmptc.Row(1).Minimum()-0.05*(tmptc.Row(1).Maximum() - 
+				tmptc.Row(1).Minimum()),tmptc.Row(1).Maximum()+
+				0.05*(tmptc.Row(1).Maximum()-tmptc.Row(1).Minimum()));
+			newplot.grid_swapdefault();
+			
+			newplot.set_xysize(750,150);
+			
+	        newplot.timeseries(tmptc,
+			  report.appendDir(string("t")+num2str(cnum)+".png"),
+			  string("Timecourse No. ")+num2str(cnum), 
+			  opts.tr.value(),150,12,1,false);
+
+			if(melodat.get_Tmodes(cnum-1).Ncols()>1)
+				tmptc &= melodat.get_Tmodes(cnum-1).Columns(2,melodat.get_Tmodes(cnum-1).Ncols()).t();
+	     write_ascii_matrix(report.appendDir(string("t")
+				+num2str(cnum)+".txt"),tmptc.t());
+	     IChtml << "<A HREF=\"" << string("t")
+	  	  +num2str(cnum)+".txt" << "\"> ";
+			 IChtml << "<img BORDER=0 SRC=\"" 
+	  	  +string("t")+num2str(cnum)+".png\"></A><p>" << endl;	
+	
+			if(melodat.get_numfiles()>1 && melodat.explained_var.Storage()>0 
+				&& melodat.explained_var.Ncols()>=cnum && opts.varvals.value())
+				IChtml << "Rank-1 approximation of individual time courses explains " 
+				<< std::abs(melodat.explained_var(cnum)) << "% of variance.<p>" << endl;
+			}//time series plot
+
+	 		if(!opts.pspec.value())
+	   	{//plot frequency  
+    		miscplot newplot;
+	    	RowVector empty(1);
+	 			empty = 0.0;
+				int fact = int(std::pow(10.0,int(std::log10(float(melodat.get_Tmodes(0).Nrows())))));
+				if(opts.logPower.value())
+					newplot.add_ylabel(string("log-Power"));
+				else
+					newplot.add_ylabel(string("Power"));
+		
+				Matrix fmixtc = calc_FFT(melodat.get_Tmodes(cnum-1).Column(1), opts.logPower.value());
+			  
+				newplot.set_Ylabel_fmt("%.0f");
+				newplot.set_yrange(0.0,1.02*fmixtc.Maximum());
+				newplot.grid_swapdefault();
+				newplot.set_xysize(750,150);
+				
+				if(opts.tr.value()>0.0){
+					newplot.add_xlabel(string("Frequency (in Hz / ")+num2str(fact)+ " )");
+	  			newplot.timeseries(empty | fmixtc.t(),
+			  	report.appendDir(string("f")+
+						num2str(cnum)+".png"),
+			     	string("Powerspectrum of timecourse"),
+			     	fact/(opts.tr.value()*melodat.get_Tmodes(0).Nrows()), 150,0,2);
+				}else{	
+					newplot.add_xlabel(string("Frequency (in cycles); ")
+					+"frequency(Hz)=cycles/("
+			    +num2str(melodat.get_Tmodes(0).Nrows())
+			    +"* TR); period(s)=("
+			    +num2str(melodat.get_Tmodes(0).Nrows())
+			    +"* TR)/cycles"
+					);
+	  			newplot.timeseries(fmixtc.t(),
+			    report.appendDir(string("f")+num2str(cnum)+".png"),
+			     	string("Powerspectrum of timecourse"));
+				}
+				write_ascii_matrix(report.appendDir(string("f")
+			 		+num2str(cnum)+".txt"), fmixtc);
+				IChtml << "<A HREF=\"" << string("f")
+	  			+num2str(cnum)+".txt" << "\"> ";
+				IChtml << "<img BORDER=0 SRC=\"" 
+	  			+string("f")+num2str(cnum)+".png\"></A><p>" << endl;
+      }//frequency plot
+   		{//add T-mode GLM F-stats for full model fit & contrasts
+				if(melodat.Tdes.Storage() > 0 &&
+					melodat.glmT.get_beta().Nrows() == melodat.Tdes.Ncols()){
+							IChtml << " <TABLE border=1 bgcolor=ffffff cellpadding=5>" <<
+								"<CAPTION><EM> <b>GLM (OLS) on time series </b></EM></CAPTION>" << endl
+								<< "<TR valign=middle><TH ><EM>GLM &beta;'s</EM> <TH> <EM> F-test on <br> full model fit </em>";
+							if(melodat.Tcon.Storage() > 0)
+								IChtml << "<TH ><EM>Contrasts</EM>"<<endl;
+							IChtml << "<TR><TD><TABLE border=0><TR><TD align=right>" << endl; 
+							for(int ctr=1;ctr <= melodat.Tdes.Ncols();ctr++)
+								IChtml << " PE(" <<num2str(ctr)+"): <br>" << endl;
+							IChtml << "<TD align=right>" << endl;
+							for(int ctr=1;ctr <= melodat.Tdes.Ncols();ctr++)
+								IChtml << melodat.glmT.get_beta().Column(cnum).Row(ctr) << "<br>" <<endl;
+							IChtml << "</TABLE>" <<
+								" <TD align=center> F = "<< melodat.glmT.get_f_fmf().Column(cnum) << 
+								" <BR> dof1 = " << melodat.Tdes.Ncols() << "; dof2 = " 
+								<< melodat.glmT.get_dof() << "<BR>" <<endl;
+							if(melodat.glmT.get_pf_fmf().Column(cnum).AsScalar() < 0.05)
+								IChtml << fixed << setprecision(5) <<"<b> p < " << melodat.glmT.get_pf_fmf().Column(cnum) <<
+								"<BR> (uncorrected for #comp.)<b></TD>" << endl;
+							else
+								IChtml << fixed << setprecision(5) << " p < " << 
+								melodat.glmT.get_pf_fmf().Column(cnum) << 
+								"<BR> (uncorrected for #comp.)</TD>" << endl;
+						if(melodat.Tcon.Storage() > 0	&&
+						melodat.Tdes.Ncols() == melodat.Tcon.Ncols()){
+							IChtml << fixed << setprecision(2) << "<TD><TABLE border=0><TR><TD align=right>" <<endl;
+							for(int ctr=1; ctr <= melodat.Tcon.Nrows() ; ctr++)
+								IChtml << "COPE(" << num2str(ctr) << "): <br>" << endl;
+							IChtml << "<td align=right>" << endl;
+							for(int ctr=1; ctr <= melodat.Tcon.Nrows() ; ctr++)
+								IChtml <<" z = <BR>" <<endl;
+							IChtml << "<td align=right>" << endl;						
+							for(int ctr=1; ctr <= melodat.Tcon.Nrows() ; ctr++)
+								IChtml << melodat.glmT.get_z().Column(cnum).Row(ctr) <<";<BR>" <<endl;
+							IChtml << "<td align=right>" << endl;
+							for(int ctr=1; ctr <= melodat.Tcon.Nrows() ; ctr++)
+								if(melodat.glmT.get_p().Column(cnum).Row(ctr).AsScalar() < 0.05)
+									IChtml << fixed << setprecision(5) << "<b> p < " << melodat.glmT.get_p().Column(cnum).Row(ctr) << 
+									"</b><BR>" << endl;
+								else
+									IChtml << fixed << setprecision(5) <<" p < " << melodat.glmT.get_p().Column(cnum).Row(ctr) << 
+									"<BR>" << endl;
+							IChtml << "</TABLE></td></tr>" << endl;
+					  }
+					}
+				IChtml << "</TABLE><p>" << endl;
+			}
+  
+      if(cnum <= (int)melodat.get_Smodes().size())
+	    {//plot subject mode 
+			  
+	  		Matrix smode;
+	  		smode = melodat.get_Smodes(cnum-1);
+	
+	  		if(smode.Nrows() > 1){
+	  	  	IChtml << "<hr><H3> Sessions/Subjects mode </H3><p>" << endl <<endl;
+		    	miscplot newplot;
+
+					//add GLM OLS fit
+					//newplot.setscatter(smode,2);
+
+					if(melodat.Sdes.Storage() > 0&&
+					melodat.glmS.get_beta().Nrows() == melodat.Sdes.Ncols()){
+						smode |= melodat.Sdes * melodat.glmS.get_beta().Column(cnum);
+						newplot.add_label(string("IC ")+num2str(cnum)+" subject/session-mode");
+						newplot.add_label("full model fit");
+					}
+					newplot.grid_swapdefault();
+					newplot.set_Ylabel_fmt("%.2f");
+					newplot.add_xlabel(" Subject Number");
+					
+
+					newplot.set_xysize(750,150);
+	      	newplot.timeseries(smode.t(), 
+			    	report.appendDir(string("s")+num2str(cnum)+".png"),
+			      string("Subject/Session mode No. ") + num2str(cnum));
+					newplot.clear_xlabel();
+					newplot.clear_labels();
+					newplot.set_xysize(120,200);
+					newplot.set_minmaxscale(1.1);
+
+					newplot.boxplot((Matrix)smode.Column(1),
+			    	report.appendDir(string("b")+num2str(cnum)+".png"),
+			        string("Subject/Session mode"));
+	      	write_ascii_matrix(report.appendDir(string("s")
+		 				+num2str(cnum)+".txt"),  smode);
+	      	IChtml << "<A HREF=\"" << string("s")
+	        	+num2str(cnum)+".txt" << "\"> ";
+	      	IChtml << "<img BORDER=0 SRC=\"" 
+	      		+string("s")+num2str(cnum)+".png\"></A>" << endl;
+					IChtml << "<A HREF=\"" << string("s")
+	        	+num2str(cnum)+".txt" << "\"> ";
+	      	IChtml << "<img BORDER=0 SRC=\"" 
+	      		+string("b")+num2str(cnum)+".png\"></A><p>" << endl;
+	    	}
+   			{//add S-mode GLM F-stats for full model fit & contrasts
+			  	if(melodat.Sdes.Storage() > 0 &&
+					melodat.glmS.get_beta().Nrows() == melodat.Sdes.Ncols()){
+							IChtml << " <TABLE border=1 bgcolor=ffffff cellpadding=5>" <<
+								"<CAPTION><EM> <b>GLM (OLS) on subject/session-mode </b></EM></CAPTION>" << endl
+								<< "<TR valign=middle><TH ><EM>GLM &beta;'s</EM> <TH> <EM> F-test on <br> full model fit </em>";
+							if(melodat.Scon.Storage() > 0)
+								IChtml << "<TH ><EM>Contrasts</EM>"<<endl;
+							IChtml << "<TR><TD><TABLE border=0><TR><TD align=right>" << endl; 
+							for(int ctr=1;ctr <= melodat.Sdes.Ncols();ctr++)
+								IChtml << " PE(" <<num2str(ctr)+"): <br>" << endl;
+							IChtml << "<TD align=right>" << endl;
+							for(int ctr=1;ctr <= melodat.Sdes.Ncols();ctr++)
+								IChtml << melodat.glmS.get_beta().Column(cnum).Row(ctr) << "<br>" <<endl;
+							IChtml << "</TABLE>" <<
+								" <TD align=center> F = "<< melodat.glmS.get_f_fmf().Column(cnum) << 
+								" <BR> dof1 = " << melodat.Sdes.Ncols() << "; dof2 = " 
+								<< melodat.glmS.get_dof() << "<BR>" <<endl;
+							if(melodat.glmS.get_pf_fmf().Column(cnum).AsScalar() < 0.05)
+								IChtml << fixed << setprecision(5) <<"<b> p < " << melodat.glmS.get_pf_fmf().Column(cnum) <<
+								"<BR> (uncorrected for #comp.)<b></TD>" << endl;
+							else
+								IChtml << fixed << setprecision(5) << " p < " << 
+								melodat.glmS.get_pf_fmf().Column(cnum) << 
+								"<BR> (uncorrected for #comp.)</TD>" << endl;
+				  if(melodat.Scon.Storage() > 0 	&& melodat.Sdes.Storage() > 0 &&
+							melodat.Sdes.Ncols() == melodat.Scon.Ncols()){
+							IChtml << fixed << setprecision(2) << "<TD><TABLE border=0><TR><TD align=right>" <<endl;
+							for(int ctr=1; ctr <= melodat.Scon.Nrows() ; ctr++)
+								IChtml << "COPE(" << num2str(ctr) << "): <br>" << endl;
+							IChtml << "<td align=right>" << endl;
+							for(int ctr=1; ctr <= melodat.Scon.Nrows() ; ctr++)
+								IChtml <<" z = <BR>" <<endl;
+							IChtml << "<td align=right>" << endl;						
+							for(int ctr=1; ctr <= melodat.Scon.Nrows() ; ctr++)
+								IChtml << melodat.glmS.get_z().Column(cnum).Row(ctr) <<";<BR>" <<endl;
+							IChtml << "<td align=right>" << endl;
+							for(int ctr=1; ctr <= melodat.Scon.Nrows() ; ctr++)
+								if(melodat.glmS.get_p().Column(cnum).Row(ctr).AsScalar() < 0.05)
+									IChtml << fixed << setprecision(5) << "<b> p < " << melodat.glmS.get_p().Column(cnum).Row(ctr) << 
+									"</b><BR>" << endl;
+								else
+									IChtml << fixed << setprecision(5) <<" p < " << melodat.glmS.get_p().Column(cnum).Row(ctr) << 
+									"<BR>" << endl;
+							IChtml << "</TABLE></td></tr>" << endl;
+					}
+				}
+				IChtml << "</TABLE><p>" << endl;
+				}
+	    }//subject mode plot
+   
+      if(mmodel.get_threshmaps().Storage()>0&&
+	 			(mmodel.get_threshmaps().Ncols() == mmodel.get_data().Ncols())&&
+	 			(mmodel.get_threshmaps().Nrows()>1))
+	    {//Output other thresholded IC map
+	  
+	  	for(int tctr=2; tctr<=mmodel.get_threshmaps().Nrows(); tctr++){
+	    	tempVol.setmatrix(mmodel.get_threshmaps().Row(tctr),melodat.get_mask());
+	    	volume<float> map1;
+	    	volume<float> map2;
+	    	map1 = threshold(tempVol[0],float(0.0), tempVol[0].max());
+	    	map2 = threshold(tempVol[0],tempVol[0].min(), float(0.0));
+
+	    	volume<float> newvol; 
+	    	miscpic newpic;
+	    
+	    	float map1min = (map1 + binarise(tempVol[0],tempVol[0].min(), 
+					     	float(0.0)) * map1.max()).min();
+	    	float map1max = map1.max();
+	    	float map2min = map2.min();
+	    	float map2max = (map2 + binarise(tempVol[0],float(0.0), 
+					     	tempVol[0].max()) * map2.min()).max();
+	    
+	    	//cerr << endl << map1min << " " << map1max << endl
+	    	//  << map2min << " " << map2max << endl;
+	    
+	    	//	    if(map1.max()-map1.min()>0.01)
+	    	newpic.overlay(newvol, melodat.get_bg(), map1, map2, 
+			   	melodat.get_bg().percentile(0.02),
+			   	melodat.get_bg().percentile(0.98),
+			   	map1min, map1max, map2max, map2min, 
+			   	0, 0);
+	    
+	    	char instr[10000];
+	    
+	    	sprintf(instr," ");
+	    	strcat(instr,axials_instr.c_str());
+	    	strcat(instr,string(report.appendDir(mmodel.get_prefix()+"_thresh"+
+						 	num2str(tctr)+".png")).c_str());
+	    	newpic.set_title(string("Component No. "+num2str(cnum)+
+				    	" - thresholded IC map ("+
+				    	num2str(tctr)+")  ")+
+			     		mmodel.get_infstr(tctr));
+	    	newpic.set_cbar(string("ysb"));
+	    	//cerr << instr << endl;
+	    	newpic.slicer(newvol, instr); 
+	    
+	    	IC_rep_det(mmodel, cnum, dim);
+	    	IChtml << "<a href=\""+mmodel.get_prefix()+"_MM.html\">";
+	    	IChtml << "<img BORDER=0 SRC=\""+mmodel.get_prefix()
+	      		+"_thresh"+num2str(tctr)+".png\" ALT=\"MMfit\"></A><p>" << endl;
+	  	}
+      }
+      
+      { //finish IC page
+	    	IChtml<< "<HR><FONT SIZE=1>This page produced automatically by "
+	      	<< "<A HREF=\"http://www.fmrib.ox.ac.uk/fsl/melodic/index.html\"> MELODIC</A> Version "  
+	      	<< version << " - a part of <A HREF=\"http://www.fmrib.ox.ac.uk/fsl\">FSL - "
+	      	<< "FMRIB Software Library</A>.</FONT></Center>" << endl
+	      		<< "</BODY></HTML>" << endl;
+      } //finish IC page
+      IC_rep_det(mmodel, cnum, dim);
+		}	
+	}
+
+  void MelodicReport::IC_rep_det(MelGMix &mmodel, int cnum, int dim){
+    if( bool(opts.genreport.value()) ){
+
+      {//start IC2 page
+				IChtml2.setDir(report.getDir(),mmodel.get_prefix()+"_MM.html");
+				IChtml2 << "<HTML><HEAD><link REL=stylesheet TYPE=text/css href=file:" +
+					(string) getenv("FSLDIR") +"/doc/fsl.css>" << endl
+					<< "<style type=\"text/css\">OBJECT { width: 100% }</style>"
+	       	<< "<TITLE>FSL</TITLE></HEAD>" << endl
+					<< "<IFRAME  height="<< int(melodat.get_numfiles()/30 + 1)*50 
+					<<"px width=100% src=nav.html frameborder=0></IFRAME><p>"<< endl	
+					<< "<CENTER>";
+				if(cnum>1)
+	  			IChtml2 << "<b><a href=\"" << string("IC_")+num2str(cnum-1)
+					<<"_MM.html\">&#60;</a>&nbsp;-&nbsp;";
+				else
+					IChtml2 << "<b><a href=\"" << string("IC_")+num2str(melodat.get_mix().Ncols())
+					<<"_MM.html\">&#60;</a>&nbsp;-&nbsp;";
+			//	IChtml << "<a href=\"00index.html\">&nbsp;index&nbsp;</a>" ;
+	
+				if(cnum<dim)
+	  			IChtml2 << "<a href=\"" << string("IC_")+num2str(cnum+1)
+					<<"_MM.html\">&#62;</a>";
+				else 
+					IChtml2 << "<a href=\"" << string("IC_")+num2str(1)
+					<<"_MM.html\">&#62;</a>";
+				IChtml2 << "<p><H3>Component " << num2str(cnum)
+				<< " Mixture Model fit <br></b></H3><hr><p>" << endl;
+			}
+
+      volume4D<float> tempVol; 
+
+      if(melodat.get_IC().Storage()>0)
+			{//Output raw IC map
+
+	  		//	tempVol.setmatrix(melodat.get_IC().Row(cnum),
+	  		//	  melodat.get_mask());
+	  		tempVol.setmatrix(mmodel.get_data(),
+			  	melodat.get_mask());
+	  		volume<float> map1;
+	  		volume<float> map2;
+	  		map1 = threshold(tempVol[0],float(0.0), 
+			   	tempVol[0].max());
+	  		map2 = threshold(tempVol[0],tempVol[0].min(), 
+			   	float(-0.0));
+
+	  		volume<float> newvol; 
+	  		miscpic newpic;
+
+	  		//	float map1min = (map1 + binarise(tempVol[0],tempVol[0].min(), 
+	  		//		float(0.0)) * map1.max()).robustmin();
+	  		float map1max = map1.percentile(0.99);
+	  		float map2min = map2.percentile(0.01);
+	  		//float map2max = (map2 + binarise(tempVol[0],float(0.0), 
+	  		//		tempVol[0].max()) * map2.min()).robustmax();
+	
+	  		newpic.overlay(newvol, melodat.get_bg(), map1, map2, 
+			 		float(0.0),
+			 		float(0.0),
+			 		float(0.01), map1max, float(-0.01), map2min, 
+			 		0, 0);
+
+	  		char instr[10000];
+       
+	  		sprintf(instr," ");
+	  		strcat(instr,axials_instr.c_str());
+	  		strcat(instr,string(report.appendDir(mmodel.get_prefix()+
+		 			".png")).c_str());
+	  		newpic.set_title(string("Component No. "+num2str(cnum)+
+				  " - raw Z transformed IC map (1 - 99 percentile)"));
+	  		newpic.set_cbar(string("ysb"));
+		
+	  		newpic.slicer(newvol, instr);
+			}
+      IChtml2 << "<a href=\""+mmodel.get_prefix()+".html\">";
+      IChtml2 << "<img BORDER=0 SRC=\""+ mmodel.get_prefix()+
+				".png\"><A><p>" << endl;
+
+      if(mmodel.get_probmap().Storage()>0&&
+	 			(mmodel.get_probmap().Ncols() == mmodel.get_data().Ncols())&&
+	 			(mmodel.get_probmap().Nrows() == mmodel.get_data().Nrows()))
+			{//Output probmap  
+	  		tempVol.setmatrix(mmodel.get_probmap(),melodat.get_mask());
+	  
+	  		volume<float> map;
+	  		map = tempVol[0];
+      
+	  		volume<float> newvol; 
+	  		miscpic newpic;
+
+	  		newpic.overlay(newvol, melodat.get_bg(), map, map, 
+			 		melodat.get_bg().percentile(0.02),
+			 		melodat.get_bg().percentile(0.98),
+			 		float(0.1), float(1.0), float(0.0), float(0.0),
+			 		0, 0);
+
+	  		char instr[10000];
+
+	  		sprintf(instr," ");
+	  		strcat(instr,"-l render1 ");
+	  		strcat(instr,axials_instr.c_str());
+	  		strcat(instr,string(report.appendDir(mmodel.get_prefix()+
+					"_prob.png")).c_str());      
+	  		newpic.set_title(string("Component No. "+num2str(cnum)+
+				  " - Mixture Model probability map"));
+      
+	  		newpic.set_cbar(string("y"));
+	  		newpic.slicer(newvol, instr); 
+
+	  		IChtml2 << "<a href=\""+mmodel.get_prefix()+".html\">";
+	  		IChtml2 << "<img BORDER=0 SRC=\""+ mmodel.get_prefix()+
+	    		"_prob.png\">" << endl;
+	
+	  		IChtml2 << "</A><p>" << endl;
+			}
+
+			RowVector dat = mmodel.get_data().Row(1);
+			if(dat.Maximum()>dat.Minimum())
+      {//Output GGM/GMM fit
+				miscplot newplot;
+
+				if(mmodel.get_type()=="GGM"){
+	  		newplot.add_label("IC map histogram");
+	  		newplot.add_label("full GGM fit");
+	  		newplot.add_label("background Gaussian");
+	  		newplot.add_label("Gamma distributions");
+	  		newplot.gmmfit(mmodel.get_data().Row(1),
+			 		mmodel.get_means(),
+			 		mmodel.get_vars(),
+			 		mmodel.get_pi(),
+			 		report.appendDir(mmodel.get_prefix()+"_MMfit.png"),
+			 		string(mmodel.get_prefix() +
+					" Gaussian/Gamma Mixture Model("+num2str(mmodel.mixtures())+") fit"),
+			 		true, float(0.0), float(0.0)); 
+   
+			}
+				else{
+	  		newplot.add_label("IC map histogram");
+	  		newplot.add_label("full GMM fit");
+	  		newplot.add_label("individual Gaussians");
+	  		newplot.gmmfit(mmodel.get_data().Row(1),
+			 		mmodel.get_means(),
+			 		mmodel.get_vars(),
+			 		mmodel.get_pi(),
+			 		report.appendDir(mmodel.get_prefix()+"_MMfit.png"),
+			 		string(mmodel.get_prefix() +
+					" Gaussian Mixture Model("+num2str(mmodel.mixtures())+") fit"), 
+			 		false, float(0.0), float(2.0));
+   
+			}
+
+			//	IChtml2 << "<A HREF=\"" +mmodel.get_prefix()+"_MMfit_detail.png\"> ";
+				IChtml2 << "<img BORDER=0 SRC=\""+ mmodel.get_prefix()+
+	  			"_MMfit.png\"><p>" << endl;
+      } //GGM/GMM plot
+      
+      {//MM parameters
+				IChtml2 << "<br> &nbsp;" << mmodel.get_prefix() 
+					<< " Mixture Model fit <br>" << endl
+					<< "<br> &nbsp; Means :  " << mmodel.get_means() << endl
+					<< "<br> &nbsp;  Vars  :  " << mmodel.get_vars()  << endl
+					<< "<br> &nbsp;  Prop. :  " << mmodel.get_pi()    << endl;
+	    }
+
+      { //finish IC2 page
+				IChtml2<< "<HR><FONT SIZE=1>This page produced automatically by "
+	       	<< "<A HREF=\"http://www.fmrib.ox.ac.uk/fsl/melodic/index.html\"> MELODIC</A> Version " 
+	       	<< version << " - a part of <A HREF=\"http://www.fmrib.ox.ac.uk/fsl\">FSL - "
+	       	<< "FMRIB Software Library</A>.</FONT></CENTER>" << endl
+	       		<< "</BODY></HTML>" << endl;
+      } //finish IC2 page
+    }
+  }
+
+  void MelodicReport::IC_simplerep(string prefix, int cnum, int dim){
+    if( bool(opts.genreport.value()) ){
+      addlink(prefix+".html",num2str(cnum));
+      IChtml.setDir(report.getDir(),prefix+".html");
+      
+      {//start IC page
+	
+				IChtml << "<HTML> " << endl
+	       	<< "<TITLE>MELODIC Component " << num2str(cnum)
+	       	<< "</TITLE>" << endl
+	       	<< "<BODY BACKGROUND=\"file:" << getenv("FSLDIR") 
+	    		<< "/doc/images/fsl-bg.jpg\">" << endl 
+	     		<< "<hr><CENTER><H1>MELODIC Component " << num2str(cnum)
+	       	<< "</H1>"<< endl;
+	
+				if(cnum>1)
+	  			IChtml << "<a href=\"" << string("IC_")+num2str(cnum-1)
+		 			<<".html\">previous</a>&nbsp;-&nbsp;";
+	
+				IChtml << "<a href=\"00index.html\">&nbsp;index&nbsp;</a>" ;
+	
+				if(cnum<dim)
+	  			IChtml << "&nbsp;-&nbsp;<a href=\"" << string("IC_")+num2str(cnum+1)
+		 				<<".html\">next</a><p>";
+	
+					IChtml << "<hr><p>" << endl;
+      }
+
+      volume4D<float> tempVol; 
+
+      if(melodat.get_IC().Storage()>0)
+			{//Output raw IC map
+
+	  		tempVol.setmatrix(melodat.get_IC().Row(cnum),
+			    melodat.get_mask());
+	  		volume<float> map1;
+	  		volume<float> map2;
+	  		map1 = threshold(tempVol[0],float(0.0), 
+			   	tempVol[0].max());
+	  		map2 = threshold(tempVol[0],tempVol[0].min(), 
+			   	float(-0.0));
+
+	  		volume<float> newvol; 
+	  		miscpic newpic;
+
+	  		//	float map1min = (map1 + binarise(tempVol[0],tempVol[0].min(), 
+	  		//		float(0.0)) * map1.max()).robustmin();
+	  		float map1max = map1.percentile(0.99);
+	  		float map2min = map2.percentile(0.01);
+	  		//float map2max = (map2 + binarise(tempVol[0],float(0.0), 
+	  		//		tempVol[0].max()) * map2.min()).robustmax();
+	
+	  		newpic.overlay(newvol, melodat.get_bg(), map1, map2, 
+			 		float(0.0),
+			 		float(0.0),
+			 		float(0.01), map1max, float(-0.01), map2min, 
+			 		0, 0);
+
+	  		char instr[10000];
+	
+	  		sprintf(instr," ");
+	  		strcat(instr,axials_instr.c_str());
+	  		strcat(instr,string(report.appendDir(prefix+
+					".png")).c_str());
+	  		newpic.set_title(string("Component No. "+num2str(cnum)+
+				  " - raw Z transformed IC map (1 - 99 percentile)"));
+	  		newpic.set_cbar(string("ysb"));
+	
+	  		newpic.slicer(newvol, instr);
+			}
+     
+      IChtml << "<img BORDER=0 SRC=\""+ prefix+
+				".png\"><p>" << endl;
+	
+      {//plot time course
+				miscplot newplot;
+	
+				if(opts.tr.value()>0.0)
+	  			newplot.timeseries(melodat.get_Tmodes(cnum-1).t(),
+			     	report.appendDir(string("t")+
+				     	num2str(cnum)+".png"),
+			     		string("Timecourse (in seconds); TR = ")+
+			     		float2str(opts.tr.value(),0,2,0)+" s", 
+			     		opts.tr.value(),150,4,1);
+				else
+	  			newplot.timeseries(melodat.get_Tmodes(cnum-1).t(),
+			     	report.appendDir(string("t")+
+					   	num2str(cnum)+".png"),
+			     		string("Timecourse (in TRs)"));
+				write_ascii_matrix(report.appendDir(string("t")
+			 		+num2str(cnum)+".txt"),
+			   	melodat.get_Tmodes(cnum-1));
+				IChtml << "<A HREF=\"" << string("t")
+	  			+num2str(cnum)+".txt" << "\"> ";
+				IChtml << "<img BORDER=0 SRC=\"" 
+	  			+string("t")+num2str(cnum)+".png\"></A><p>" << endl;
+      }//time series plot
+      
+      {//plot frequency 
+				miscplot newplot;
+				int fact = int(std::pow(10.0,
+					int(std::log10(float(melodat.get_Tmodes(0).Nrows())))));
+	
+				if(opts.tr.value()>0.0)
+	  			newplot.timeseries(melodat.get_fmix().Column(cnum).t(),
+			     	report.appendDir(string("f")+
+					  num2str(cnum)+".png"),
+			     	string("FFT of timecourse (in Hz / ") +
+			     	num2str(fact)+")",
+			     	fact/(opts.tr.value()*melodat.get_Tmodes(0).Nrows()),
+			     	150,0,2);
+				else
+	  			newplot.timeseries(melodat.get_fmix().Column(cnum).t(),
+			     	report.appendDir(string("f")+
+			   		num2str(cnum)+".png"),
+			     	string(string("FFT of timecourse (in cycles); ")
+				    +"frequency(Hz)=cycles/("
+				    +num2str(melodat.get_Tmodes(0).Nrows())
+				    +"* TR); period(s)=("
+				    +num2str(melodat.get_Tmodes(0).Nrows())
+				    +"* TR)/cycles"));
+				write_ascii_matrix(report.appendDir(string("f")
+			 		+num2str(cnum)+".txt"),
+			   	melodat.get_Tmodes(cnum-1));
+				IChtml << "<A HREF=\"" << string("f")
+	  			+num2str(cnum)+".txt" << "\"> ";
+				IChtml << "<img BORDER=0 SRC=\"" 
+	  			+string("f")+num2str(cnum)+".png\"></A><p>" << endl;
+      }//frequency plot
+ 
+      { //finish IC page
+				IChtml<< "<HR><FONT SIZE=1>This page produced automatically by "
+	      	<< "<A HREF=\"http://www.fmrib.ox.ac.uk/fsl/melodic/index.html\"> MELODIC</A> Version " 
+	      	<< version << " - a part of <A HREF=\"http://www.fmrib.ox.ac.uk/fsl\">FSL - "
+	      	<< "FMRIB Software Library</A>.</FONT>" << endl
+	      		<< "</BODY></HTML>" << endl;
+      } //finish IC page 
+    } 
+  }
+
+  void MelodicReport::PPCA_rep(){
+    
+    {//plot time course
+      report << "<p><hr><b>PCA estimates </b> <p>" << endl;
+ 
+      Matrix what;
+      miscplot newplot;
+
+      what  = melodat.get_EV();
+      what &= melodat.get_EVP();
+
+      newplot.add_label("ordered Eigenvalues");
+      newplot.add_label("% of expl. variance");
+
+      if(melodat.get_PPCA().Storage()>0){
+				what = what.Columns(1,melodat.get_PPCA().Nrows());
+				if(opts.allPPCA.value()&&melodat.get_PPCA().Ncols()==7){
+					what &= melodat.get_PPCA().Columns(3,7).t();
+					newplot.add_label("Laplace");
+					newplot.add_label("BIC");
+					newplot.add_label("MDL");
+					newplot.add_label("RRN");
+					newplot.add_label("AIC");
+				}else{
+					what &= melodat.get_PPCA().Column(1).t();
+					newplot.add_label("dim. estimate");
+				}
+      }
+			
+			newplot.set_Ylabel_fmt("%.2f");
+			newplot.add_xlabel("Number of included components");
+			newplot.set_yrange(0.0,1.02);
+      newplot.grid_swapdefault();
+      newplot.timeseries(what,
+			 	report.appendDir("EVplot.png"),
+			 	string("Eigenspectrum Analysis"), 
+			 	0,450,4,0);
+
+      report << "<img BORDER=0 SRC=\"EVplot.png\"><p>" << endl;
+    }//time series plot
+  }
+	
+	void MelodicReport::Smode_rep(){
+	  if(melodat.get_Smodes().size()>0){
+		report << "<p><hr><b>TICA Subject/Session modes </b> <br>" << endl;
+		miscplot newplot;
+		report << "Boxplots show the relative response amplitudes across the "
+			<< "session/subject domain (" << melodat.get_numfiles() 
+			<< " input files). Components have been sorted in decreasing order of "
+			<< " the median response per component. <br><br>";
+			
+		outMsize("Smode.at(0)", melodat.get_Smodes().at(0));
+		Matrix allmodes = melodat.get_Smodes().at(0);
+		for(int ctr = 1; ctr < (int)melodat.get_Smodes().size();++ctr)
+			allmodes |= melodat.get_Smodes().at(ctr);
+	
+		outMsize("allmodes", allmodes);
+		newplot.add_xlabel("Component No.");
+		newplot.add_ylabel("");
+		if(allmodes.Ncols()<100)
+			newplot.set_xysize(100+30*allmodes.Ncols(),300);
+		else
+			newplot.set_xysize(1200,300);
+		newplot.boxplot(allmodes,report.appendDir(string("bp_Smodes.png")),
+  			string("Subject/Session modes"));
+  		report << "<img BORDER=0 SRC=\"bp_Smodes.png\"><p>" << endl;
+      }
+	}
+}
-- 
GitLab