Skip to content
Snippets Groups Projects
melreport.h 11.1 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);
Christian Beckmann's avatar
Christian Beckmann committed
	  				report.makeDir(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>"
							<<"<pre>../melodic.log</pre>" <<endl;		
						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;";
			//			if(opts.guireport.value()=="")
			//				navigator << "<A HREF=\"log.html\" target=\"_top\">Log</A>&nbsp;-&nbsp;";
						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 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>), an implementation for the estimation of a Probabilistic Independent Component Analysis model [Beckmann 2004]."<<endl;
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << "The following melodic pre-processing was applied to the input data file: "<< 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; ";
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
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 was whitened and projected into a " 
		 				<< melodat.get_mix().Ncols()<< "-dimensional subspace using ";
	  			if(melodat.get_PPCA().Storage()>0){	    
	    			report << "probabilistic Principal Component Analysis where the number of dimensions was estimated using ";
	    			if(opts.pca_est.value() == string("lap"))
	      			report << "the Laplace approximation to the Bayesian evidence of the model order [Minka 2000, Beckmann 2004]. " << endl;
	    			else
	      			if(opts.pca_est.value() == string("bic"))
							report << "the <em> Bayesian Information Criterion</em> (BIC) [Kass 1993]. " << endl;
	      		else
							if(opts.pca_est.value() == string("mdl"))
		  				report << "<em> Minimum Description Length</em> (MDL) [Rissanen 1978]. " << endl;
						else
		  				if(opts.pca_est.value() == string("aic"))
		    			report << "the <em> Akaike Information Criterion</em> (AIC) [Akaike 1969]. " << endl;
		  			else
		    			report << "a committee of approximations to Bayesian the model order [Beckmann 2004]. " << endl;
	  			}	  
	  			else
	    			report << "Principal Component Analysis. ";
Mark Jenkinson's avatar
Mark Jenkinson committed
	  
Christian Beckmann's avatar
Christian Beckmann committed
	  			report << " The whitened observations were decomposed into a set of time-courses and spatial 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())
	    			report << " and thresholded by fitting a mixture model to the histogram of intensity values [Beckmann 2004]. <p>" << endl;
	  			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(melodat.get_PPCA().Storage()>0){	    
	    			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;*/
	    			if(opts.pca_est.value() == string("lap"))
	      			report << "[Minka 2000] T. Minka. Automatic choice of dimensionality for PCA. Technical Report 514, MIT Media Lab Vision and Modeling Group, 2000. <BR>"<< endl;
	    			else
	      			if(opts.pca_est.value() == string("bic"))
							report << "[Kass 1995] R.E. Kass and A. E. Raftery. Bayes factors. Journal of the American Statistical Association, 90:733-795, 1995 <br>" << endl;
	      		else
							if(opts.pca_est.value() == string("mdl"))
		  				report << "[Rissanen 1978]. J. Rissanen. Modelling by shortest data description. Automatica, 14:465-471, 1978. <br>" << endl;
						else
		  				if(opts.pca_est.value() == string("aic"))
		    			report << "[Akaike 1974]. H. Akaike. A new look at statistical model identification. IEEE Transactions on Automatic Control, 19:716-723, 1974. <br>" << endl;
		  			else
		    			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