From a37eae0fad437398a2b0cadcac9e644a5a1677d4 Mon Sep 17 00:00:00 2001 From: Christian Beckmann <c.beckmann@donders.ru.nl> Date: Thu, 2 Aug 2007 16:07:39 +0000 Subject: [PATCH] MELODIC 3.04 --- meldata.cc | 12 +++++- melodic.cc | 14 +++---- melodic.h | 2 +- melodic.tcl | 2 +- meloptions.h | 7 +++- melreport.cc | 102 +++++++++++++++++++++++++++++---------------------- melreport.h | 84 ++++++++++++++++++++++++++++++++---------- 7 files changed, 148 insertions(+), 75 deletions(-) diff --git a/meldata.cc b/meldata.cc index fb227a1..cabb707 100644 --- a/meldata.cc +++ b/meldata.cc @@ -156,13 +156,15 @@ namespace Melodic{ Matrix alltcs = Tmodes.at(0); for(int ctr=1; ctr < (int)Tmodes.size();ctr++) alltcs|=Tmodes.at(ctr); - glmT.olsfit(alltcs,Tdes,Tcon); + if((alltcs.Nrows()==Tdes.Nrows())&&(Tdes.Nrows()>Tdes.Ncols())) + glmT.olsfit(alltcs,Tdes,Tcon); } if(Sdes.Storage()){ Matrix alltcs = Smodes.at(0); for(int ctr=1; ctr < (int)Smodes.size();ctr++) alltcs|=Smodes.at(ctr); - glmS.olsfit(alltcs,Sdes,Scon); + if((alltcs.Nrows()==Sdes.Nrows())&&(Sdes.Nrows()>Sdes.Ncols())) + glmS.olsfit(alltcs,Sdes,Scon); } } @@ -180,6 +182,12 @@ namespace Melodic{ opts.varnorm.set_T(false); } alldat = process_file(opts.inputfname.value().at(0), numfiles) / numfiles; + + if(opts.pca_dim.value() > alldat.Nrows()-2){ + cerr << "ERROR:: too many components selected \n\n"; + exit(2); + } + if(opts.debug.value()) save4D(alldat,string("preproc_dat") + num2str(1)); for(int ctr = 1; ctr < numfiles; ctr++){ diff --git a/melodic.cc b/melodic.cc index 670f4bb..4aeadd4 100644 --- a/melodic.cc +++ b/melodic.cc @@ -139,6 +139,13 @@ int main(int argc, char *argv[]){ Matrix pmaps;//(melodat.get_IC()); Matrix mmres; + if( bool(opts.genreport.value()) ){ + report.analysistxt(); + if(melodat.get_numfiles()>1) + report.Smode_rep(); + report.PPCA_rep(); + } + if(opts.perf_mm.value()) mmres = mmall(logger,opts,melodat,report,pmaps); else{ @@ -158,13 +165,6 @@ int main(int argc, char *argv[]){ } } - if( bool(opts.genreport.value()) ){ - report.analysistxt(); - if(melodat.get_numfiles()>1) - report.Smode_rep(); - report.PPCA_rep(); - } - message("finished!" << endl << endl); } else { diff --git a/melodic.h b/melodic.h index 0eefaff..6f5134e 100644 --- a/melodic.h +++ b/melodic.h @@ -40,7 +40,7 @@ namespace Melodic{ -const string version = "3.03"; +const string version = "3.04"; // The two strings below specify the title and example usage that is // printed out as the help or usage message diff --git a/melodic.tcl b/melodic.tcl index 4f1582d..2eb6cca 100644 --- a/melodic.tcl +++ b/melodic.tcl @@ -336,7 +336,7 @@ button $w.btns.load -command "feat_file:setup_dialog $w a a a [namespace current button $w.btns.cancel -command "destroy $w" -text "Exit" -button $w.btns.help -command "FmribWebHelp file: ${FSLDIR}/doc/melodic3/index.html" -text "Help" +button $w.btns.help -command "FmribWebHelp file: ${FSLDIR}/doc/melodic/index.html" -text "Help" #{{{ Utils diff --git a/meloptions.h b/meloptions.h index 6ffd12e..9270400 100644 --- a/meloptions.h +++ b/meloptions.h @@ -77,6 +77,7 @@ class MelodicOptions { Option<string> filter; Option<bool> genreport; + Option<string> guireport; Option<string> bgimage; Option<float> tr; Option<bool> logPower; @@ -218,7 +219,7 @@ class MelodicOptions { rank1interval(string("--rank1interval"), 10, string("number of iterations between rank-1 approximation (TICA)\n"), false, requires_argument,false), - mmthresh(string("--mmthresh"), string("0.5"), + mmthresh(string("--mmthresh"), string("0.5"), string("threshold for Mixture Model based inference"), false, requires_argument), perf_mm(string("--no_mm"), true, @@ -239,6 +240,9 @@ class MelodicOptions { 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), @@ -374,6 +378,7 @@ class MelodicOptions { options.add(smodename); options.add(filter); options.add(genreport); + options.add(guireport); options.add(bgimage); options.add(tr); options.add(logPower); diff --git a/melreport.cc b/melreport.cc index 01cf3aa..63e4491 100644 --- a/melreport.cc +++ b/melreport.cc @@ -24,24 +24,29 @@ namespace Melodic{ IChtml.setDir(report.getDir(),mmodel.get_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; + 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\">previous</a> - "; - IChtml << "<a href=\"00index.html\"> index </a>" ; + <<".html\"><</a> - "; + else + IChtml << "<a href=\"" << string("IC_")+num2str(melodat.get_mix().Ncols()) + <<".html\"><</a> - "; if(cnum<dim) - IChtml << " - <a href=\"" << string("IC_")+num2str(cnum+1) - <<".html\">next</a><p>"; - - IChtml << "<hr><p>" << endl; + IChtml << "<a href=\"" << string("IC_")+num2str(cnum+1) + <<".html\">></a>"; + else + IChtml << "<a href=\"" << string("IC_")+num2str(1) + <<".html\">></a>"; + IChtml << "<p><H3>MELODIC Component " << num2str(cnum) + << "<br></b></H3><hr><p>" << endl; } {//output IC stats if(ICstats.Storage()>0&&ICstats.Nrows()>=cnum){ @@ -110,7 +115,8 @@ namespace Melodic{ Matrix tmptc = melodat.get_Tmodes(cnum-1).t(); //add GLM OLS fit - if(melodat.Tdes.Storage() > 0){ + 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(string("IC ")+num2str(cnum)+" time course"); newplot.add_label("full model fit"); @@ -182,7 +188,8 @@ namespace Melodic{ +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){ + 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 β's</EM> <TH> <EM> F-test on <br> full model fit </em>"; @@ -205,8 +212,8 @@ namespace Melodic{ IChtml << fixed << setprecision(5) << " p < " << melodat.glmT.get_pf_fmf().Column(cnum) << "<BR> (uncorrected for #comp.)</TD>" << endl; - } - if(melodat.Tcon.Storage() > 0){ + if(melodat.Tcon.Storage() > 0 && + melodat.Tdes.Ncols() == melodat.Tcon.Nrows()){ 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; @@ -225,7 +232,8 @@ namespace Melodic{ IChtml << fixed << setprecision(5) <<" p < " << melodat.glmT.get_p().Column(cnum).Row(ctr) << "<BR>" << endl; IChtml << "</TABLE></td></tr>" << endl; - } + } + } IChtml << "</TABLE><p>" << endl; } @@ -240,7 +248,8 @@ namespace Melodic{ //add GLM OLS fit //newplot.setscatter(smode,2); - if(melodat.Sdes.Storage() > 0){ + 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"); @@ -272,7 +281,8 @@ namespace Melodic{ +string("b")+num2str(cnum)+".png\"></A><p>" << endl; } {//add S-mode GLM F-stats for full model fit & contrasts - if(melodat.Sdes.Storage() > 0){ + 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 β's</EM> <TH> <EM> F-test on <br> full model fit </em>"; @@ -295,8 +305,8 @@ namespace Melodic{ IChtml << fixed << setprecision(5) << " p < " << melodat.glmS.get_pf_fmf().Column(cnum) << "<BR> (uncorrected for #comp.)</TD>" << endl; - } - if(melodat.Scon.Storage() > 0){ + if(melodat.Scon.Storage() > 0 && melodat.Sdes.Storage() > 0 && + melodat.Sdes.Ncols() == melodat.Scon.Nrows()){ 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; @@ -316,8 +326,8 @@ namespace Melodic{ "<BR>" << endl; IChtml << "</TABLE></td></tr>" << endl; } + } IChtml << "</TABLE><p>" << endl; - } }//subject mode plot @@ -382,7 +392,7 @@ namespace Melodic{ 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 + << "FMRIB Software Library</A>.</FONT></Center>" << endl << "</BODY></HTML>" << endl; } //finish IC page IC_rep_det(mmodel, cnum, dim); @@ -394,24 +404,30 @@ namespace Melodic{ {//start IC2 page IChtml2.setDir(report.getDir(),mmodel.get_prefix()+"_MM.html"); - IChtml2 << "<HTML> " << endl - << "<TITLE>Component " << num2str(cnum) - << " Mixture Model fit </TITLE>" << endl - << "<BODY BACKGROUND=\"file:" << getenv("FSLDIR") - << "/doc/images/fsl-bg.jpg\">" << endl - << "<hr><CENTER><H1>Component " << num2str(cnum) - << " Mixture Model fit </H1>"<< endl; - + 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 << "<a href=\"" << string("IC_")+num2str(cnum-1) - <<"_MM.html\">previous</a> - "; - IChtml2 << "<a href=\""+ mmodel.get_prefix() + - ".html\"> up to IC report </a>"; + IChtml2 << "<b><a href=\"" << string("IC_")+num2str(cnum-1) + <<"_MM.html\"><</a> - "; + else + IChtml2 << "<b><a href=\"" << string("IC_")+num2str(melodat.get_mix().Ncols()) + <<"_MM.html\"><</a> - "; + // IChtml << "<a href=\"00index.html\"> index </a>" ; + if(cnum<dim) - IChtml2 << " - <a href=\"" << string("IC_")+num2str(cnum+1) - <<"_MM.html\">next</a><p>"; - IChtml2 << "<hr><p>" << endl; - } + IChtml2 << "<a href=\"" << string("IC_")+num2str(cnum+1) + <<"_MM.html\">></a>"; + else + IChtml2 << "<a href=\"" << string("IC_")+num2str(1) + <<"_MM.html\">></a>"; + IChtml2 << "<p><H3>Component " << num2str(cnum) + << " Mixture Model fit <br></b></H3><hr><p>" << endl; + } volume4D<float> tempVol; @@ -554,7 +570,7 @@ namespace Melodic{ 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>" << endl + << "FMRIB Software Library</A>.</FONT></CENTER>" << endl << "</BODY></HTML>" << endl; } //finish IC2 page } @@ -706,7 +722,7 @@ namespace Melodic{ void MelodicReport::PPCA_rep(){ {//plot time course - report << "<p> <H3>PCA estimates </H3> <p>" << endl; + report << "<p><hr><b>PCA estimates </b> <br>" << endl; Matrix what; miscplot newplot; @@ -737,7 +753,7 @@ namespace Melodic{ } void MelodicReport::Smode_rep(){ - report << "<p> <H3>TICA Subject/Session modes </H3> <p>" << endl; + report << "<b>TICA Subject/Session modes </b> <p>" << endl; miscplot newplot; Matrix allmodes = melodat.get_Smodes().at(0); for(int ctr = 1; ctr < (int)melodat.get_Smodes().size();++ctr) diff --git a/melreport.h b/melreport.h index 93cd08e..3989f8a 100644 --- a/melreport.h +++ b/melreport.h @@ -44,35 +44,75 @@ namespace Melodic{ const time_t tmptime = time(NULL); report.makeDir(logger.appendDir("report"),"00index.html"); - report << "<HTML>" << endl << endl - << "<TITLE>MELODIC Report</TITLE>"<< endl <<endl - << "<BODY BACKGROUND=\"file:" << getenv("FSLDIR") - << "/doc/images/fsl-bg.jpg\">" << endl - << endl << "<hr><CENTER> " << endl - << "<H1>MELODIC Report</H1>" - << endl - << report.getDir() << "/" << report.getLogFileName() - << "<br>" << endl - << ctime(&tmptime) << "<br>" << endl; - report << "</CENTER>" << endl << endl - << "<hr><H2>Components:</H2> <p>" << endl << endl; + 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=100px width=100% src=nav.html frameborder=0></IFRAME><p>"<< endl; + 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> - "; + // if(opts.guireport.value()=="") + // navigator << "<A HREF=\"log.html\" target=\"_top\">Log</A> - "; + navigator <<"Components: "; + navigator.flush(); } } ~MelodicReport(){ if( bool(opts.genreport.value()) ){ - report << "<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; + 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; } } inline void analysistxt(){ if( bool(opts.genreport.value()) ){ - report << "<hr><h2>Analysis methods</h2> <p>"<<endl; + report << "<b>Analysis methods</b> <br>"<<endl; 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; report << "The following melodic pre-processing was applied to the input data file: "<< endl; @@ -122,7 +162,7 @@ namespace Melodic{ inline void refstxt(){ if( bool(opts.genreport.value()) ){ - report << "<h3>References</h3> <p>"<<endl; + report << "<b>References</b> <br>"<<endl; report << "[Hyvärinen 1999] A. Hyvä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; @@ -163,7 +203,8 @@ namespace Melodic{ inline void addlink(string where, string what){ if( bool(opts.genreport.value()) ){ - report << "<A HREF=\"" << where << "\"> " << what << "</A> "; + navigator << "<A HREF=\"" << where << " \"target=\"_top\"> " << what << "</A> "; + navigator.flush(); } } @@ -193,6 +234,9 @@ namespace Melodic{ MelodicOptions &opts; Log &logger; Log report; + Log navigator; + Log head; + Log loghtml; Log IChtml; Log IChtml2; -- GitLab