Skip to content
Snippets Groups Projects
melreport.h 12.6 KiB
Newer Older
Mark Jenkinson's avatar
Mark Jenkinson committed
/*  MELODIC - Multivariate exploratory linear optimized decomposition into 
              independent components
    
    melreport.h - report generation

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

/*  CCOPYRIGHT */


#ifndef __MELODICREPORT_h
#define __MELODICREPORT_h
#include "newimage/newimageall.h"
#include "utils/log.h"
Mark Jenkinson's avatar
Mark Jenkinson committed
#include "melpca.h"
#include "meloptions.h"
#include "meldata.h"
#include "melgmix.h"
#include "melodic.h"
#include "newmatap.h"
#include "newmatio.h"
#include <time.h>
#include <strstream>
#include "libvis/miscplot.h"
#include "libvis/miscpic.h"
#include "utils/options.h"
Mark Jenkinson's avatar
Mark Jenkinson committed

using namespace Utilities;
using namespace NEWIMAGE;
using namespace MISCPLOT;
using namespace MISCPIC;

namespace Melodic{
  
Christian Beckmann's avatar
Christian Beckmann committed
  class MelodicReport{
Mark Jenkinson's avatar
Mark Jenkinson committed
    public:
      MelodicReport(MelodicData &pmelodat, MelodicOptions &popts, Log &plogger):  
Christian Beckmann's avatar
Christian Beckmann committed
				melodat(pmelodat),
				opts(popts),
				logger(plogger){
	  			if( bool(opts.genreport.value()) ){
	  				const time_t tmptime = time(NULL);
		    		system(("mkdir "+ logger.appendDir("report") + " 2>/dev/null").c_str());
	  				report.setDir(logger.appendDir("report"),"00index.html");
Christian Beckmann's avatar
Christian Beckmann committed
						report << "<HTML><HEAD><link REL=stylesheet TYPE=text/css href=file:" +
							(string) getenv("FSLDIR") +"/doc/fsl.css>" 
						  << "<TITLE>MELODIC report</TITLE></HEAD><BODY>"
							<< endl <<endl;
						loghtml.setDir(report.getDir(),"log.html");
						loghtml << "<HTML><HEAD><link REL=stylesheet TYPE=text/css href=file:" +
							(string) getenv("FSLDIR") +"/doc/fsl.css>" 
						  << "<TITLE>MELODIC report</TITLE></HEAD><BODY>"
							<< endl <<endl;						
						navigator.setDir(report.getDir(),"nav.html");
						head.setDir(report.getDir(),"head.html");
	  				navigator << "<link REL=stylesheet TYPE=text/css href=file:"+
							(string) getenv("FSLDIR") +"/doc/fsl.css>"  << endl;
						head << "<link REL=stylesheet TYPE=text/css href=file:"+
							(string) getenv("FSLDIR") +"/doc/fsl.css>"  << endl;
						head  <<"<TABLE BORDER=0><TR>" << endl
							<<" <TD ALIGN=CENTER WIDTH=100%>"<< endl
							<<"<TABLE BORDER=0>"<< endl
							<<"<tr><td align=center><font size=+3><b>MELODIC Report</b>"<< endl
							<<"</font><tr><td valign=center align=center> <p>"<< endl
							<< report.getDir() << "/" << report.getLogFileName() << "<br>"
							<< ctime(&tmptime) << "</tr>"<< endl
							<<"<tr valign=bottom><td align=center>"<< endl
							<< "</tr></table>" << endl
							<< "<TD ALIGN=RIGHT>" << endl
							<< "<a href=http://www.fmrib.ox.ac.uk/fsl target=_top>" << endl
						  << "<IMG BORDER=0 SRC=file:"<< getenv("FSLDIR")
							<< "/doc/images/fsl-logo-big.jpg WIDTH=165></a>" << endl
							<< "</TD>"<<endl<<"</TR></TABLE> <hr>"<<endl;
						if(opts.guireport.value()==""){
							report <<"<OBJECT data=head.html></OBJECT>" <<  endl;
							loghtml <<"<OBJECT data=head.html></OBJECT>" <<  endl;
						}else{
				   		report <<"<OBJECT data="<<opts.guireport.value()<< "></OBJECT>"<< endl;
							loghtml <<"<OBJECT data="<<opts.guireport.value()<< "></OBJECT>"<< endl;
						}
						report << "<IFRAME  height=80px width=100% src=nav.html frameborder=0></IFRAME><p>"<< endl;		
Christian Beckmann's avatar
Christian Beckmann committed
						loghtml << "<IFRAME  height=100px width=100% src=nav.html frameborder=0></IFRAME><p>"
Christian Beckmann's avatar
Christian Beckmann committed
							<<"<IFRAME width=100% height=100% src=\"../log.txt\"></IFRAME>" <<endl;		
Christian Beckmann's avatar
Christian Beckmann committed
						navigator <<"<CENTER><TABLE BORDER=0><TR>" << endl
							<<"<TD ALIGN=CENTER WIDTH=100%><FONT SIZE=-1>"<<endl
							<<"<A HREF=\"00index.html\" target=\"_top\">Main</A>&nbsp;-&nbsp;";
Christian Beckmann's avatar
Christian Beckmann committed
						if(opts.guireport.value()=="")
							navigator << "<A HREF=\"log.html\" target=\"_top\">Log</A>&nbsp;-&nbsp;";
Christian Beckmann's avatar
Christian Beckmann committed
						navigator	<<"Components: ";
						navigator.flush();
Mark Jenkinson's avatar
Mark Jenkinson committed

      ~MelodicReport(){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
Christian Beckmann's avatar
Christian Beckmann committed
					report << "<HR><CENTER><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;
					loghtml << "<HR><CENTER><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;
  				navigator << "</FONT></TD>"<<endl<<"</TR></TABLE></CENTER><hr>" <<endl;
Christian Beckmann's avatar
Christian Beckmann committed
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }

      inline void analysistxt(){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
Mark Jenkinson's avatar
Mark Jenkinson committed

Christian Beckmann's avatar
Christian Beckmann committed
	  			report << "<b>Analysis methods</b> <br>"<<endl;
Christian Beckmann's avatar
Christian Beckmann committed
					report << "Analysis was carried out using ";
	
					if(opts.approach.value() != string("tica"))
						report << "Probabilistic Independent Component Analysis"
						  <<" [Beckmann 2004] as implemented in "<<endl;
					else	
						report << "Tensorial Independent Component Analysis "
					  	<<"[Beckmann 2005] as implemented in "<< endl;
	
					report << " MELODIC (Multivariate"
						<<" Exploratory Linear Decomposition into Independent Components)"
						<<" Version "<< version <<", part of FSL (FMRIB's Software"
						<<" Library, <A HREF=\"http://www.fmrib.ox.ac.uk/fsl/\">"
						<<"www.fmrib.ox.ac.uk/fsl</A>).<br>";
			
	  			report << "The following data pre-processing was applied to"
						<<" the input data: "<< endl;
Mark Jenkinson's avatar
Mark Jenkinson committed

Christian Beckmann's avatar
Christian Beckmann committed
	  			if(opts.use_mask.value())
	    			report << " masking of non-brain voxels;";
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << " voxel-wise de-meaning of the data;" << endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			if(opts.varnorm.value())
	    			report << " normalisation of the voxel-wise variance; ";
Christian Beckmann's avatar
Christian Beckmann committed
	  	    if(opts.pbsc.value())
						report << " conversion to %BOLD signal change; ";
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << "<br>"<<endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << " Pre-processed data were whitened and projected into a " 
Christian Beckmann's avatar
Christian Beckmann committed
		 				<< melodat.get_mix().Ncols()<< "-dimensional subspace using ";
	  			if(melodat.get_PPCA().Storage()>0){	    
Christian Beckmann's avatar
Christian Beckmann committed
	    			report << "probabilistic Principal Component Analysis where the"
							<<" number of dimensions was estimated using ";
Christian Beckmann's avatar
Christian Beckmann committed
	    			if(opts.pca_est.value() == string("lap"))
Christian Beckmann's avatar
Christian Beckmann committed
	      			report << "the Laplace approximation to the Bayesian"
							<<" evidence of the model order [Minka 2000, Beckmann 2004]. " << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	    			else
	      			if(opts.pca_est.value() == string("bic"))
Christian Beckmann's avatar
Christian Beckmann committed
							  report << "the <em> Bayesian Information Criterion</em>"
								  <<" (BIC) [Kass 1993]. " << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	      		else
							if(opts.pca_est.value() == string("mdl"))
Christian Beckmann's avatar
Christian Beckmann committed
		  				  report << "<em> Minimum Description Length</em> (MDL)"
						    	<<" [Rissanen 1978]. " << endl;
Christian Beckmann's avatar
Christian Beckmann committed
						else
		  				if(opts.pca_est.value() == string("aic"))
Christian Beckmann's avatar
Christian Beckmann committed
		    			report << "the <em> Akaike Information Criterion</em>"
								<<" (AIC) [Akaike 1969]. " << endl;
Christian Beckmann's avatar
Christian Beckmann committed
		  			else
Christian Beckmann's avatar
Christian Beckmann committed
		    			report << " approximations to Bayesian the"
								<<" model order [Beckmann 2004]. " << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	  			}	  
	  			else
	    			report << "Principal Component Analysis. ";
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << " <BR>The whitened observations were decomposed into "
						<<" sets of vectors which describe signal variation across"
						<<" the temporal domain (time-courses)";
					if(opts.approach.value() == string("tica") ||
						opts.approach.value() == string("concat"))
						report << ", the session/subject domain ";
					report <<"  and across the spatial domain (maps) by optimising for"
						<<" non-Gaussian spatial source distributions using a"
						<<" fixed-point iteration technique [Hyv&auml;rinen 1999]. " << endl;	  
	  			report << "Estimated Component maps were divided by the standard"
						<<" deviation of the residual noise";
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			if(opts.perf_mm.value())
Christian Beckmann's avatar
Christian Beckmann committed
	    			report << " and thresholded by fitting a mixture model "
	 						<<"to the histogram of intensity values [Beckmann 2004]. <p>" << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	  			else
	    			report <<".<p>" << endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
	 
Christian Beckmann's avatar
Christian Beckmann committed
	  			refstxt(); 
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }

      inline void refstxt(){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << "<b>References</b> <br>"<<endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << "[Hyv&auml;rinen 1999] A. Hyv&auml;rinen. Fast and"
						<<" Robust Fixed-Point Algorithms for Independent Component"
						<<" Analysis. IEEE Transactions on Neural Networks 10(3):"
						<<"626-634, 1999.<br> " << endl;
 						report << "[Beckmann 2004] C.F. Beckmann and S.M. Smith."
							<<" Probabilistic Independent Component Analysis for Functional"
							<<" Magnetic Resonance Imaging. IEEE Transactions on Medical"
							<<" Imaging 23(2):137-152 2004. <br>" << endl;
					if(opts.approach.value() == string("tica") || 
						opts.approach.value() == string("concat") )
						report << "[Beckmann 2005] C.F. Beckmann and S.M. Smith."
							<<" Tensorial extensions of independent component analysis"
							<< " for multisubject FMRI analysis. Neuroimage "
							<< " 25(1):294-311 2005. <br>";
Christian Beckmann's avatar
Christian Beckmann committed

	  			if(melodat.get_PPCA().Storage()>0){	    
Christian Beckmann's avatar
Christian Beckmann committed
	    			report << "[Everson 2000] R. Everson and S. Roberts."
							<<" Inferring the eigenvalues of covariance matrices from"
							<<" limited, noisy data. IEEE Trans Signal Processing,"
							<<" 48(7):2083-2091, 2000<br>"<<endl;
	    			report << "[Tipping 1999] M.E. Tipping and C.M.Bishop."
							<<" Probabilistic Principal component analysis. J Royal"
							<<" Statistical Society B, 61(3), 1999. <br>" << endl;
	    		  report << "[Beckmann 2001] C.F. Beckmann, J.A. Noble and"
							<<" S.M. Smith. Investigating the intrinsic dimensionality"
							<<" of FMRI data for ICA. In Seventh Int. Conf. on Functional"
							<<" Mapping of the Human Brain, 2001. <br>" << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	    			if(opts.pca_est.value() == string("lap"))
Christian Beckmann's avatar
Christian Beckmann committed
	      			report << "[Minka 2000] T. Minka. Automatic choice of"
							  <<" dimensionality for PCA. Technical Report 514, MIT"
								<<" Media Lab Vision and Modeling Group, 2000. <BR>"<< endl;
Christian Beckmann's avatar
Christian Beckmann committed
	    			else
	      			if(opts.pca_est.value() == string("bic"))
Christian Beckmann's avatar
Christian Beckmann committed
							report << "[Kass 1995] R.E. Kass and A. E. Raftery. Bayes"
								<<" factors. Journal of the American Statistical"
								<<" Association, 90:733-795, 1995 <br>" << endl;
Christian Beckmann's avatar
Christian Beckmann committed
	      		else
							if(opts.pca_est.value() == string("mdl"))
Christian Beckmann's avatar
Christian Beckmann committed
		  				report << "[Rissanen 1978]. J. Rissanen. Modelling by"
							  <<" shortest data description. Automatica,"
								<<" 14:465-471, 1978. <br>" << endl;
Christian Beckmann's avatar
Christian Beckmann committed
						else
		  				if(opts.pca_est.value() == string("aic"))
Christian Beckmann's avatar
Christian Beckmann committed
		    			report << "[Akaike 1974]. H. Akaike. A new look at"
							  <<" statistical model identification. IEEE Transactions"
								<<" on Automatic Control, 19:716-723, 1974. <br>" << endl;
Christian Beckmann's avatar
Christian Beckmann committed
		  			else
Christian Beckmann's avatar
Christian Beckmann committed
		    			report << "[Minka 2000]. T. Minka. Automatic choice of"
								<<" dimensionality for PCA. Technical Report 514, MIT"
								<<" Media Lab Vision and Modeling Group, 2000. <BR>" << endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
      }

      inline void addtxt(string what){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
	  			report << what << endl;
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
      
      inline void addpar(string what){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
	  			report << "<p>" << what << endl;
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }
      
      inline void addlink(string where, string what){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
Christian Beckmann's avatar
Christian Beckmann committed
	  			navigator << "<A HREF=\"" << where << " \"target=\"_top\"> " << what << "</A> ";
					navigator.flush();
Christian Beckmann's avatar
Christian Beckmann committed
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }

      inline void addpic(string what, string link = ""){
Christian Beckmann's avatar
Christian Beckmann committed
				if( bool(opts.genreport.value()) ){
	  			if( link.length() > 0)
	    			report << "<A HREF=\"" << link << "\"> ";

	  			report << "<img BORDER=0 SRC=\"" << what<< ".png\"><p>";
	  			if( link.length() > 0)
	    			report << "</A> ";
				}
Mark Jenkinson's avatar
Mark Jenkinson committed
      }

      inline string getDir(){
Christian Beckmann's avatar
Christian Beckmann committed
				return report.getDir();
      void IC_rep(MelGMix &mmodel, int cnum, int dim, Matrix ICstats);
Mark Jenkinson's avatar
Mark Jenkinson committed
      void IC_simplerep(string prefix, int cnum, int dim);

      void PPCA_rep();
      void Smode_rep();
Mark Jenkinson's avatar
Mark Jenkinson committed

    private:
      MelodicData &melodat;
      MelodicOptions &opts;
      Log &logger;
      Log report;
Christian Beckmann's avatar
Christian Beckmann committed
			Log navigator;
			Log head;
			Log loghtml;
Mark Jenkinson's avatar
Mark Jenkinson committed

      Log IChtml;
      Log IChtml2;

      void IC_rep_det(MelGMix &mmodel, int cnum, int dim);
      
Christian Beckmann's avatar
Christian Beckmann committed
      string int2str(int n){
	  		ostrstream os;
	  	//    os.fill(' ');
	  	//    os.width(width);
	  		os.setf(ios::internal, ios::adjustfield);
	  		os << n << '\0';
	  		return os.str();
			}
Mark Jenkinson's avatar
Mark Jenkinson committed
      
Christian Beckmann's avatar
Christian Beckmann committed
      string float2str(float f, int width, int prec, int scientif){
	    	ostrstream os;
	    	int redw = int(std::abs(std::log10(std::abs(f))))+1;
	    	if(width>0)
	      	os.width(width);
	    	if(scientif>0)
	      	os.setf(ios::scientific);
	    	os.precision(redw+std::abs(prec));
	    	os.setf(ios::internal, ios::adjustfield);
	    	os << f << '\0';
	    	return os.str();
			}
  };   
Mark Jenkinson's avatar
Mark Jenkinson committed

}
#endif