Skip to content
Snippets Groups Projects
melica.cc 16 KiB
Newer Older
Mark Jenkinson's avatar
Mark Jenkinson committed
/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
              independent components
    
    melica.cc - ICA estimation 

    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 <stdlib.h>
#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 "melica.h"
#include "melpca.h"
#include "melhlprfns.h"
#include "miscmaths/miscprob.h"
Mark Jenkinson's avatar
Mark Jenkinson committed

using namespace Utilities;
using namespace NEWIMAGE;

namespace Melodic {
Mark Jenkinson's avatar
Mark Jenkinson committed
    
Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicICA::ica_fastica_symm(const Matrix &Data){
Mark Jenkinson's avatar
Mark Jenkinson committed
    // based on Aapo Hyvrinen's fastica method
    // see www.cis.hut.fi/projects/ica/fastica/
    
    //initialize matrices
Christian Beckmann's avatar
Christian Beckmann committed
    Matrix redUMM_old, rank1_old;
Mark Jenkinson's avatar
Mark Jenkinson committed
    Matrix tmpU;    
Christian Beckmann's avatar
Christian Beckmann committed
    //srand((unsigned int)timer(NULL));
Mark Jenkinson's avatar
Mark Jenkinson committed
    redUMM = melodat.get_white()*
       unifrnd(melodat.get_white().Ncols(),dim); // got to start somewhere
    
Christian Beckmann's avatar
Christian Beckmann committed
	if(opts.debug.value())
		cerr << "redUMM init submatrix : " << endl << redUMM.SubMatrix(1,2,1,2) << endl;
		
Mark Jenkinson's avatar
Mark Jenkinson committed
    if(opts.guessfname.value().size()>1){
      message("  Use columns in " << opts.guessfname.value() 
	      << " as initial values for the mixing matrix " <<endl);
      Matrix guess ;
      guess  = melodat.get_white()*read_ascii_matrix(opts.guessfname.value());
      redUMM.Columns(1,guess.Ncols()) = guess;
    }
    
    symm_orth(redUMM);

Christian Beckmann's avatar
Christian Beckmann committed
    int itt_ctr,itt_ctr2=1,cum_itt=0,newmaxitts = opts.maxNumItt.value(); 
Christian Beckmann's avatar
Christian Beckmann committed
    double minAbsSin = 1.0, minAbsSin2 = 1.0;
Christian Beckmann's avatar
Christian Beckmann committed
    if(opts.approach.value() == string("tica"))
      opts.maxNumItt.set_T(opts.rank1interval.value());
Christian Beckmann's avatar
Christian Beckmann committed

    rank1_old = melodat.get_dewhite()*redUMM;
    rank1_old = melodat.expand_dimred(rank1_old);
    rank1_old = krapprox(rank1_old,int(rank1_old.Nrows()/melodat.get_numfiles())); 
Christian Beckmann's avatar
Christian Beckmann committed
    do{// TICA loop
      itt_ctr = 1;
      do{ // da loop!!!
Christian Beckmann's avatar
Christian Beckmann committed
				redUMM_old = redUMM;      
				//calculate IC estimates
				tmpU = Data.t() * redUMM;
Christian Beckmann's avatar
Christian Beckmann committed
					
Christian Beckmann's avatar
Christian Beckmann committed
				//update redUMM depending on nonlinearity
				if(opts.nonlinearity.value()=="pow4"){
	  			redUMM = (Data * pow(tmpU,3.0)) / samples - 3 * redUMM;
				}
				if(opts.nonlinearity.value()=="pow3"){
	  			tmpU /= opts.nlconst1.value();
	  			redUMM = 3 * (Data * pow(tmpU,2.0)) / samples  - 
	    			(SP(ones(dim,1)*sum(tmpU,1),redUMM))/ samples;
				}
				if(opts.nonlinearity.value()=="tanh"){
	  			Matrix hyptanh;
	  			hyptanh = tanh(opts.nlconst1.value()*tmpU);
	  			redUMM = (Data * hyptanh - opts.nlconst1.value()*SP(ones(dim,1)*
Christian Beckmann's avatar
Christian Beckmann committed
						sum(1-pow(hyptanh,2),1),redUMM))/samples;						
Christian Beckmann's avatar
Christian Beckmann committed
				}
				if(opts.nonlinearity.value()=="gauss"){
	  			Matrix tmpUsq;
	  			Matrix tmpU2;
	  			Matrix gauss;
	  			Matrix dgauss;
	  			tmpUsq = pow(tmpU,2);
	  			tmpU2 = exp(-(opts.nlconst2.value()/2) * tmpUsq);
	  			gauss = SP(tmpU,tmpU2);
	  			dgauss = SP(1-opts.nlconst2.value()*tmpUsq,tmpU2);
	  			redUMM = (Data * gauss - SP(ones(dim,1)*
				    sum(dgauss,1),redUMM))/samples;
				}
Christian Beckmann's avatar
Christian Beckmann committed
           
Christian Beckmann's avatar
Christian Beckmann committed
				// orthogonalize the unmixing-matrix 
				symm_orth(redUMM);
Christian Beckmann's avatar
Christian Beckmann committed
				if(opts.approach.value() == string("tica")){
Christian Beckmann's avatar
Christian Beckmann committed
					message("");
Christian Beckmann's avatar
Christian Beckmann committed
				}
Christian Beckmann's avatar
Christian Beckmann committed

Christian Beckmann's avatar
Christian Beckmann committed
				//termination condition : angle between old and new < epsilon
				minAbsSin = 1 - diag(abs(redUMM.t()*redUMM_old)).Minimum();
Christian Beckmann's avatar
Christian Beckmann committed
				message("  Step no. " << cum_itt + itt_ctr << " change : " << minAbsSin << endl);
		//		if((abs(minAbsSin) < opts.epsilon.value())&&
		//		  (opts.approach.value()!=string("tica"))){ break;}
				if((abs(minAbsSin) < opts.epsilon.value())){ break;}
Christian Beckmann's avatar
Christian Beckmann committed
	
Christian Beckmann's avatar
Christian Beckmann committed
				itt_ctr++;
Christian Beckmann's avatar
Christian Beckmann committed
      } while(itt_ctr < opts.maxNumItt.value());
      cum_itt += itt_ctr;
      itt_ctr2++;
Christian Beckmann's avatar
Christian Beckmann committed
      if(opts.approach.value() == string("tica")){
Christian Beckmann's avatar
Christian Beckmann committed
				message(" Rank-1 approximation of the time courses; ");
Christian Beckmann's avatar
Christian Beckmann committed
	  		Matrix temp(melodat.get_dewhite() * redUMM);
	  		temp = melodat.expand_dimred(temp);
Christian Beckmann's avatar
Christian Beckmann committed
			  temp = krapprox(temp,int(temp.Nrows()/melodat.get_numfiles())); 
				minAbsSin2 = 1 - diag(abs(corrcoef(temp,rank1_old))).Minimum();
Christian Beckmann's avatar
Christian Beckmann committed
				rank1_old = temp;
				temp = melodat.reduce_dimred(temp);
				redUMM = melodat.get_white() * temp;

				message(" change : " << minAbsSin2 << endl);	
				if(abs(minAbsSin2) < opts.epsilonS.value() && abs(minAbsSin) < opts.epsilon.value()){ break;}
Christian Beckmann's avatar
Christian Beckmann committed
			}
Christian Beckmann's avatar
Christian Beckmann committed
    } while(
      (itt_ctr2 < newmaxitts/opts.maxNumItt.value()) && 
			(opts.approach.value() ==  string("tica")) && 
			cum_itt < newmaxitts);
Christian Beckmann's avatar
Christian Beckmann committed
    if((itt_ctr>=opts.maxNumItt.value() && (opts.approach.value()!=string("tica")))
			|| (cum_itt >= newmaxitts && opts.approach.value()==string("tica"))){
Christian Beckmann's avatar
Christian Beckmann committed
      cerr << "  No convergence after " << cum_itt  <<" steps "<<endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
    } else {
Christian Beckmann's avatar
Christian Beckmann committed
      message("  Convergence after " << cum_itt  <<" steps " << endl << endl);
Mark Jenkinson's avatar
Mark Jenkinson committed
      no_convergence = false;
Christian Beckmann's avatar
Christian Beckmann committed

Mark Jenkinson's avatar
Mark Jenkinson committed
      {Matrix temp(melodat.get_dewhite() * redUMM);
       melodat.set_mix(temp);}
      {Matrix temp(redUMM.t()*melodat.get_white());
      melodat.set_unmix(temp);}
    } 
  }
  
Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicICA::ica_fastica_defl(const Matrix &Data){
    if(!opts.explicitnums || opts.numICs.value()>dim){
Mark Jenkinson's avatar
Mark Jenkinson committed
      opts.numICs.set_T(dim); 
      message("  Using numICs:" << opts.numICs.value() << endl);
Christian Beckmann's avatar
Christian Beckmann committed
    }
Mark Jenkinson's avatar
Mark Jenkinson committed
     
Christian Beckmann's avatar
Christian Beckmann committed
    //redUMM = zeros(dim); // got to start somewhere
    redUMM = melodat.get_white()*
      unifrnd(melodat.get_white().Ncols(),opts.numICs.value());
    redUMM = zeros(melodat.get_white().Nrows(),opts.numICs.value());
    Matrix guess;
    int guesses=0;
    if(opts.guessfname.value().size()>1){
Mark Jenkinson's avatar
Mark Jenkinson committed
       message("  Use columns in " << opts.guessfname.value() << " as initial values for the mixing matrix " <<endl);
       guess  = melodat.get_white()*read_ascii_matrix(opts.guessfname.value());
       guesses = guess.Ncols();
Christian Beckmann's avatar
Christian Beckmann committed
    }
Mark Jenkinson's avatar
Mark Jenkinson committed

Christian Beckmann's avatar
Christian Beckmann committed
    int ctrIC = 1;
    int numRestart = 0;
    while(ctrIC<=opts.numICs.value()){   
     	message("  Extracting IC " << ctrIC << "  ... ");
      ColumnVector w;
      ColumnVector w_old;   
      ColumnVector tmpU;
      if(ctrIC <= guesses){
      	w = w - redUMM * redUMM.t() * w;
      	w = w / norm2(w);  
      	w_old = zeros(w.Nrows(),1);
      	int itt_ctr = 1; 
      	do{
	 				w_old = w;
	 				tmpU = Data.t() * w; 
					if(opts.nonlinearity.value()=="pow4"){
	  				w =  (Data * pow(tmpU,3.0)) / samples - 3 * w;
					}
					if(opts.nonlinearity.value()=="tanh"){
	  				ColumnVector hyptanh;
          	hyptanh = tanh(opts.nlconst1.value()*tmpU);
 	  				w = (Data * hyptanh - opts.nlconst1.value()*SP(ones(dim,1)*
          		sum(1-pow(hyptanh,2),1),w))/samples;
					} 
					if(opts.nonlinearity.value()=="pow3"){
	  				tmpU /= opts.nlconst1.value();
 	  				w = 3*(Data * pow(tmpU,2.0)) / samples - 2*(SP(ones(dim,1)*
           		sum(tmpU,1),w))/samples;
					} 
					if(opts.nonlinearity.value()=="gauss"){
	  				ColumnVector tmpUsq;
	  				ColumnVector tmpU2;
	  				ColumnVector gauss;
	  				ColumnVector dgauss;
	  				tmpUsq = pow(tmpU,2);
	  				tmpU2 = exp(-(opts.nlconst2.value()/2) * tmpUsq);
	  				gauss = SP(tmpU,tmpU2);
	  				dgauss = SP(1-opts.nlconst2.value()*tmpUsq,tmpU2);
          	w = (Data * gauss - SP(ones(dim,1)*
				 			sum(dgauss,1),w))/samples;
					}

					// orthogonalize w
					w = w - redUMM * redUMM.t() * w;
					w = w / norm2(w);  

					//termination condition : angle between old and new < epsilon
Matthew Webster's avatar
Matthew Webster committed
					if(((norm2(w-w_old) < 0.001*opts.epsilon.value())&&(itt_ctr>10)) || 
					   ((norm2(w+w_old) < 0.001*opts.epsilon.value())&&(itt_ctr>10))){
Christian Beckmann's avatar
Christian Beckmann committed
	 					break;
Christian Beckmann's avatar
Christian Beckmann committed
				  	}
Christian Beckmann's avatar
Christian Beckmann committed
        	//cout << norm2(w-w_old) << "   " << norm2(w+w_old) << endl;
					itt_ctr++;
Christian Beckmann's avatar
Christian Beckmann committed
     	  } while(itt_ctr <= opts.maxNumItt.value());
Christian Beckmann's avatar
Christian Beckmann committed
      if(itt_ctr<opts.maxNumItt.value()){
Christian Beckmann's avatar
Christian Beckmann committed
				redUMM.Column(ctrIC) = w;
Mark Jenkinson's avatar
Mark Jenkinson committed
        message(" estimated using " << itt_ctr << " iterations " << endl);
        ctrIC++; 
        numRestart = 0;
Christian Beckmann's avatar
Christian Beckmann committed
      } else{
Mark Jenkinson's avatar
Mark Jenkinson committed
        if(numRestart > opts.maxRestart.value()){
Christian Beckmann's avatar
Christian Beckmann committed
	  			message(endl << "  Estimation failed after " 
		  			<< numRestart << " attempts " 
		  			<< " giving up " << endl);
	  			break;
Christian Beckmann's avatar
Christian Beckmann committed
				}else{
Mark Jenkinson's avatar
Mark Jenkinson committed
          numRestart++;
Christian Beckmann's avatar
Christian Beckmann committed
	  			message(endl <<"  Estimation failed - restart " 
		  			<< numRestart << endl);
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
Christian Beckmann's avatar
Christian Beckmann committed
     	}
     	if(numRestart < opts.maxRestart.value()){
       	no_convergence = false;
       	{Matrix temp(melodat.get_dewhite() * redUMM);
       		melodat.set_mix(temp);}
       	{Matrix temp(redUMM.t()*melodat.get_white());
       		melodat.set_unmix(temp);}
     	}
		}
  }
Mark Jenkinson's avatar
Mark Jenkinson committed

Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicICA::ica_maxent(const Matrix &Data){
    // based on Aapo Hyvrinen's fastica method
Christian Beckmann's avatar
Christian Beckmann committed
    // see www.cis.hut.fi/projects/ica/fastica/ 
    message(" MAXENT " << endl);
    //initialize matrices
    Matrix redUMM_old;
    Matrix tmpU;    
    Matrix gtmpU;
    double lambda = 0.015/std::log((double)melodat.get_white().Ncols());
    
Christian Beckmann's avatar
Christian Beckmann committed
    //srand((unsigned int)timer(NULL));
    redUMM = melodat.get_white()*
Christian Beckmann's avatar
Christian Beckmann committed
     	unifrnd(melodat.get_white().Ncols(),dim); // got to start somewhere
    
    if(opts.guessfname.value().size()>1){
      message("  Use columns in " << opts.guessfname.value() 
	      << " as initial values for the mixing matrix " <<endl);
      Matrix guess ;
      guess  = melodat.get_white()*read_ascii_matrix(opts.guessfname.value());
      redUMM.Columns(1,guess.Ncols()) = guess;
    }
    
    //    symm_orth(redUMM);
    int itt_ctr=1; 
    double minAbsSin = 1.0;
    Matrix Id;
    Id = IdentityMatrix(redUMM.Ncols());
Christian Beckmann's avatar
Christian Beckmann committed
    //cerr << " nonlinearity : " <<    opts.nonlinearity.value() << endl;

    do{ // da loop!!!
Christian Beckmann's avatar
Christian Beckmann committed
      redUMM_old = redUMM;      
      //calculate IC estimates
      tmpU = Data.t() * redUMM;
      if(opts.nonlinearity.value()=="tanh"){
Christian Beckmann's avatar
Christian Beckmann committed
				//Matrix hyptanh;
				//hyptanh = tanh(opts.nlconst1.value()*tmpU);
				//redUMM = (Data * hyptanh - opts.nlconst1.value()*SP(ones(dim,1)*
				//sum(1-pow(hyptanh,2),1),redUMM))/samples;
				gtmpU = tanh(opts.nlconst1.value()*tmpU);
				redUMM = redUMM + lambda*(Id+(1-2*gtmpU.t()*tmpU))*redUMM;
      }
      if(opts.nonlinearity.value()=="gauss"){
Christian Beckmann's avatar
Christian Beckmann committed
				gtmpU = pow(1+exp(-(opts.nlconst2.value()/2) * tmpU),-1);
				redUMM = redUMM + lambda*(Id - (gtmpU.t()-tmpU.t())*tmpU)*redUMM;
      //termination condition : angle between old and new < epsilon
      minAbsSin = abs(1 - diag(abs(redUMM.t()*redUMM_old)).Minimum());
      message("  Step no. " << itt_ctr << " change : " << minAbsSin << endl);
      if(abs(minAbsSin) < opts.epsilon.value()){ break;}
      
      itt_ctr++;
    } while(itt_ctr < opts.maxNumItt.value());
    
    if(itt_ctr>=opts.maxNumItt.value()){
      cerr << "  No convergence after " << itt_ctr <<" steps "<<endl;
    } else {
      message("  Convergence after " << itt_ctr <<" steps " << endl << endl);
      no_convergence = false;
      {Matrix temp(melodat.get_dewhite() * redUMM);
       melodat.set_mix(temp);}
      {Matrix temp(redUMM.t()*melodat.get_white());
      melodat.set_unmix(temp);}
    } 
Mark Jenkinson's avatar
Mark Jenkinson committed
  }
Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicICA::ica_jade(const Matrix &Data){ 
Mark Jenkinson's avatar
Mark Jenkinson committed
    int dim_sym = (int) (dim*(dim+1))/2;  
    int num_CM = dim_sym;
    Matrix CM;
    Matrix R; R = IdentityMatrix(dim);
Mark Jenkinson's avatar
Mark Jenkinson committed
    Matrix Qij; Qij = zeros(dim);
    Matrix Xim;
    Matrix Xjm;
    Matrix scale; scale = ones(dim,1)/samples;

    for (int im =1; im <= dim; im++){
      Xim = Data.Row(im);
Christian Beckmann's avatar
Christian Beckmann committed
			write_ascii_matrix("Xim",Data.Row(1));
Mark Jenkinson's avatar
Mark Jenkinson committed
      //Qij = SP((scale * pow(Xim,2)),Data) * Data.t();//- R - 2*R.Column(im)*R.Column(im).t();
      Qij = (pow(Xim,2)) * Data.t();//- R - 2*R.Column(im)*R.Column(im).t();
      if(im==1){CM = Qij; write_ascii_matrix("CM",CM);exit(2);}else{CM |= Qij;}
      for (int jm = 1; jm < im; jm++){
Christian Beckmann's avatar
Christian Beckmann committed
				Xjm = Data.Row(jm);
				Qij = (SP((scale * SP(Xim,Xjm)),Data) * Data.t() - 
					R.Column(im)*R.Column(jm).t() - R.Column(jm)*R.Column(im).t());
				Qij *= sqrt(2);
				CM  |= Qij;
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
    }

    write_ascii_matrix("CM",CM);
    Matrix redUMM; redUMM = IdentityMatrix(dim);
Mark Jenkinson's avatar
Mark Jenkinson committed
  
    bool exitloop = false;
    int ctr_itt = 0;
    int ctr_updates = 0;
    Matrix Givens; Givens = zeros(2,num_CM);
    Matrix Givens_ip; Givens_ip = zeros(2);
    Matrix Givens_ro; Givens_ro = zeros(2);
    double det_on, det_off;
    double cos_theta, sin_theta, theta;

    while(!exitloop && ctr_itt <= opts.maxNumItt.value()){
      ctr_itt++;
      cout << "loop" <<endl;
      for(int ctr_p = 1; ctr_p < dim; ctr_p++){
Christian Beckmann's avatar
Christian Beckmann committed
				for(int ctr_q = ctr_p+1; ctr_q <= dim; ctr_q++){

	  			for(int ctr_i = 0; ctr_i < num_CM; ctr_i++){
	    			int Ip = ctr_p + ctr_i * dim;
	    			int Iq = ctr_q + ctr_i * dim;
	    			Givens(1,ctr_i + 1) = CM(ctr_p,Ip) - CM(ctr_q,Iq);
	    			Givens(2,ctr_i + 1) = CM(ctr_p,Iq) - CM(ctr_q,Ip);
	  			}
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			Givens_ip = Givens * Givens.t();
	  			det_on = Givens_ip(1,1) - Givens_ip(2,2);
	  			det_off = Givens_ip(1,2) + Givens_ip(2,1);
	  			theta = 0.5 * atan2(det_off, det_on + sqrt(det_on*det_on + det_off*det_off));

	  			cout << theta << endl;

	  			if(abs(theta) > opts.epsilon.value()){
	    			ctr_updates++;
	    			message("  Step No. "<< ctr_itt << " change : " << theta << endl);
			
	    			//create Givens rotation matrix
	    			cos_theta = cos(theta);
	    			sin_theta = sin(theta);
	    			Givens_ro(1,1) = cos_theta;
	    			Givens_ro(1,2) = -sin_theta;
	    			Givens_ro(2,1) = sin_theta;
	    			Givens_ro(2,2) = cos_theta;

	    			//update 2 entries of redUMM
	    			{Matrix tmp_redUMM;
	    				tmp_redUMM = redUMM.Column(ctr_p);
	    				tmp_redUMM |= redUMM.Column(ctr_q);
	    				tmp_redUMM *= Givens_ro;
	    				redUMM.Column(ctr_p) = tmp_redUMM.Column(1);
	    				redUMM.Column(ctr_q) = tmp_redUMM.Column(2);}

	    			//update Cumulant matrix
	    			{Matrix tmp_CM;
	    				tmp_CM = CM.Row(ctr_p);
	    				tmp_CM &= CM.Row(ctr_q);
	    				tmp_CM = Givens_ro.t() * tmp_CM;
	    				CM.Row(ctr_p) = tmp_CM.Row(1);
	    				CM.Row(ctr_q) = tmp_CM.Row(2);}

	    			//update Cumulant matrices
	    			for(int ctr_i = 0; ctr_i < num_CM; ctr_i++){
	      			int Ip = ctr_p + ctr_i * dim;
	      			int Iq = ctr_q + ctr_i * dim;
	      			CM.Column(Ip) = cos_theta*CM.Column(Ip)+sin_theta*CM.Column(Iq);
	      			CM.Column(Iq) = cos_theta*CM.Column(Iq)-sin_theta*CM.Column(Ip);
	    			}
	  			}else{
	    			exitloop = true;
	  			}
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
    }//while loop
    if(ctr_itt > opts.maxNumItt.value()){
Christian Beckmann's avatar
Christian Beckmann committed
    	cerr << "  No convergence after " << ctr_itt <<" steps "<<endl;
    } else {
     	message("  Convergence after " << ctr_itt <<" steps " << endl << endl);
      no_convergence = false;
      {Matrix temp(melodat.get_dewhite() * redUMM);
       	melodat.set_mix(temp);}
      {Matrix temp(redUMM.t()*melodat.get_white());
       	melodat.set_unmix(temp);}
    }
Christian Beckmann's avatar
Christian Beckmann committed
  Matrix MelodicICA::sign(const Matrix &Inp){
Mark Jenkinson's avatar
Mark Jenkinson committed
    Matrix Res = Inp;
    Res = 1;
    for(int ctr_i = 1; ctr_i <= Inp.Ncols(); ctr_i++){
      for(int ctr_j = 1; ctr_j <= Inp.Nrows(); ctr_j++){
Christian Beckmann's avatar
Christian Beckmann committed
				if(Inp(ctr_j,ctr_i)<0){Res(ctr_j,ctr_i)=-1;}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
    } 
    return Res;
  }

Christian Beckmann's avatar
Christian Beckmann committed
  void MelodicICA::perf_ica(const Matrix &Data){ 
Mark Jenkinson's avatar
Mark Jenkinson committed
    message("Starting ICA estimation using " << opts.approach.value() 
	    << endl << endl);
    dim = Data.Nrows();
    samples = Data.Ncols();
    no_convergence = true;
Christian Beckmann's avatar
Christian Beckmann committed
    //switch to the chosen method   
Christian Beckmann's avatar
Christian Beckmann committed
    if(opts.approach.value()==string("symm") ||
       opts.approach.value()==string("tica") ||
       opts.approach.value()==string("parafac") ||
Christian Beckmann's avatar
Christian Beckmann committed
       opts.approach.value()==string("concat"))
      ica_fastica_symm(Data);
    if(opts.approach.value()==string("defl"))
      ica_fastica_defl(Data);
    if(opts.approach.value()==string("jade"))
      ica_jade(Data);
    if(opts.approach.value()==string("maxent"))
      ica_maxent(Data);
Mark Jenkinson's avatar
Mark Jenkinson committed
    
    if(!no_convergence){//calculate the IC
      Matrix temp(melodat.get_unmix()*melodat.get_Data());
      //  Add the mean time course again  
      //      temp += melodat.get_unmix()*melodat.get_meanC()*ones(1,temp.Ncols());
Mark Jenkinson's avatar
Mark Jenkinson committed

      //re-normalise the decomposition to std(mix)=1
      Matrix scales;
      scales = stdev(melodat.get_mix());   

Christian Beckmann's avatar
Christian Beckmann committed
      //cerr << " SCALES 1 " << scales << endl;
Christian Beckmann's avatar
Christian Beckmann committed
      Matrix tmp, tmp2;
      tmp = SP(melodat.get_mix(),ones(melodat.get_mix().Nrows(),1)*pow(scales,-1));
      temp = SP(temp,scales.t()*ones(1,temp.Ncols()));

      scales = scales.t();
  
      melodat.set_mix(tmp);
Mark Jenkinson's avatar
Mark Jenkinson committed
      melodat.set_IC(temp);
      melodat.set_ICstats(scales);
      melodat.sort();
Christian Beckmann's avatar
Christian Beckmann committed
	  //message("Calculating T- and S-modes " << endl);
      melodat.set_TSmode();