Skip to content
Snippets Groups Projects
melpca.cc 3.63 KiB
Newer Older
Mark Jenkinson's avatar
Mark Jenkinson committed
/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
              independent components
    
    melpca.cc - PCA and whitening 

    Christian F. Beckmann, FMRIB Analysis Group
Mark Jenkinson's avatar
Mark Jenkinson committed
    
    Copyright (C) 1999-2013 University of Oxford */
Mark Jenkinson's avatar
Mark Jenkinson committed

/*  CCOPYRIGHT  */
Mark Jenkinson's avatar
Mark Jenkinson committed

#include "newimage/newimageall.h"
#include "utils/log.h"
Mark Jenkinson's avatar
Mark Jenkinson committed
#include "meloptions.h"
#include "meldata.h"
#include "melodic.h"
#include "newmatap.h"
#include "newmatio.h"
Mark Jenkinson's avatar
Mark Jenkinson committed
#include "melpca.h"
#include "melhlprfns.h"
#include "libprob.h"
Mark Jenkinson's avatar
Mark Jenkinson committed

using namespace Utilities;
using namespace NEWIMAGE;

namespace Melodic{

Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicPCA::perf_pca(Matrix& in, Matrix& weights){    
  	message("Starting PCA  ... ");
Mark Jenkinson's avatar
Mark Jenkinson committed

Christian Beckmann's avatar
Christian Beckmann committed
    Matrix Corr;
    Matrix tmpE;
    RowVector tmpD, AdjEV, PercEV;
Christian Beckmann's avatar
Christian Beckmann committed
	if(opts.paradigmfname.value().length()>0)
	{
		basicGLM tmpglm;
		tmpglm.olsfit(in,melodat.get_param(),IdentityMatrix(melodat.get_param().Ncols()));
Christian Beckmann's avatar
Christian Beckmann committed
		std_pca(tmpglm.get_residu(),weights,Corr,tmpE,tmpD);
//		std_pca(in,weights,Corr,tmpE,tmpD,melodat.get_param());
	}
	else{
 		std_pca(in,weights,Corr,tmpE,tmpD); 
	}	
	
Christian Beckmann's avatar
Christian Beckmann committed
    if(opts.tsmooth.value()){
      message(endl << "  temporal smoothing of Eigenvectors " << endl);
      tmpE=smoothColumns(tmpE);
    }
Christian Beckmann's avatar
Christian Beckmann committed
    adj_eigspec(tmpD,AdjEV,PercEV);
    melodat.set_pcaE(tmpE);
    melodat.set_pcaD(tmpD);
    melodat.set_EVP(PercEV); 
    melodat.set_EV((AdjEV));
    write_ascii_matrix(logger.appendDir("eigenvalues_percent"),PercEV);
Christian Beckmann's avatar
Christian Beckmann committed
    message("done" << endl);
  }
Mark Jenkinson's avatar
Mark Jenkinson committed
  
Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicPCA::perf_white(){
Mark Jenkinson's avatar
Mark Jenkinson committed
    int N = melodat.get_pcaE().Ncols();    
    if(opts.pca_dim.value() > N){
      message("dimensionality too large - using -dim " << N << 
              " instead " << endl);
      opts.pca_dim.set_T(N);
    }
    if(opts.pca_dim.value() < 0){
      if(opts.remove_meanvol.value()){
Christian Beckmann's avatar
Christian Beckmann committed
				opts.pca_dim.set_T(N-2);
Mark Jenkinson's avatar
Mark Jenkinson committed
      }else{
Christian Beckmann's avatar
Christian Beckmann committed
   			opts.pca_dim.set_T(N-1);
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
    }
    if(opts.pca_dim.value() ==0){
      opts.pca_dim.set_T(pcadim());
      if(melodat.get_Data().Nrows()<20){
Christian Beckmann's avatar
Christian Beckmann committed
				opts.pca_dim.set_T(N-2);
				message("too few data points for full estimation, using "
					<< opts.pca_dim.value() << " instead"<< endl);
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
    }
    if(opts.approach.value()==string("jade") && opts.pca_dim.value() > 30){
      message("dimensionality too large for jade estimation - using --dim 30 instead" << endl);
      opts.pca_dim.set_T(30);
    }
Mark Jenkinson's avatar
Mark Jenkinson committed
    message("Start whitening using  "<< opts.pca_dim.value()<<" dimensions ... " << endl);
    Matrix tmpWhite;
    Matrix tmpDeWhite;

    float varp = 1.0;
Christian Beckmann's avatar
Christian Beckmann committed

	if (opts.paradigmfname.value().length()>0)
	    varp = calc_white(melodat.get_pcaE(),melodat.get_pcaD(), 
    		melodat.get_EVP(),opts.pca_dim.value(),melodat.get_param(),melodat.get_paramS(),tmpWhite,tmpDeWhite);
	else
		varp = calc_white(melodat.get_pcaE(),melodat.get_pcaD(), 
    		melodat.get_EVP(),opts.pca_dim.value(),tmpWhite,tmpDeWhite);
Mark Jenkinson's avatar
Mark Jenkinson committed

    melodat.set_white(tmpWhite);
    melodat.set_dewhite(tmpDeWhite);
    message("  retaining "<< varp*100 <<" percent of the variability " << endl);
Mark Jenkinson's avatar
Mark Jenkinson committed
    message(" ... done"<< endl << endl);
Christian Beckmann's avatar
Christian Beckmann committed
  }
Mark Jenkinson's avatar
Mark Jenkinson committed

  int MelodicPCA::pcadim()
  { 
    message("Estimating the number of sources from the data (PPCA) ..." << endl);

    ColumnVector PPCA; RowVector AdjEV, PercEV;   
Christian Beckmann's avatar
Christian Beckmann committed
    int res = ppca_dim(melodat.get_Data(),melodat.get_RXweight(), PPCA, 
			AdjEV, PercEV, melodat.get_resels(), opts.pca_est.value());
Mark Jenkinson's avatar
Mark Jenkinson committed
    write_ascii_matrix(logger.appendDir("PPCA"),PPCA);			      
    write_ascii_matrix(logger.appendDir("eigenvalues_adjusted"),AdjEV.t());
    write_ascii_matrix(logger.appendDir("eigenvalues_percent"),PercEV.t());

    melodat.set_EVP(PercEV);
    melodat.set_EV(AdjEV);
    melodat.set_PPCA(PPCA);
    
    return res;
  }

}