From 4c237f7d96db3e99dd36fa88e5be927d1eef57fe Mon Sep 17 00:00:00 2001 From: Christian Beckmann <c.beckmann@donders.ru.nl> Date: Wed, 14 Feb 2007 13:38:07 +0000 Subject: [PATCH] ggmix added --- ggmix.cc | 721 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ggmix.h | 203 ++++++++++++++++ 2 files changed, 924 insertions(+) create mode 100644 ggmix.cc create mode 100644 ggmix.h diff --git a/ggmix.cc b/ggmix.cc new file mode 100644 index 0000000..d14d7fe --- /dev/null +++ b/ggmix.cc @@ -0,0 +1,721 @@ +/* MELODIC - Multivariate exploratory linear optimized decomposition into + independent components + + ggmix.cc - Gaussian & Gaussian/Gamma Mixture Model + + Christian F. Beckmann, FMRIB Image Analysis Group + + Copyright (C) 1999-2007 University of Oxford */ + +/* CCOPYRIGHT */ + +#include "newimage/newimageall.h" +#include "ggmix.h" +#include "miscmaths/miscprob.h" +#include <time.h> +#include <strstream> + + +using namespace NEWIMAGE; + +string float2str(float f,int width, int prec, bool scientif) + { + ostrstream os; + int redw = int(std::abs(std::log10(std::abs(f))))+1; + if(width>0) + os.width(width); + if(scientif) + os.setf(ios::scientific); + os.precision(redw+std::abs(prec)); + os.setf(ios::internal, ios::adjustfield); + os << f << '\0'; + return os.str(); + } + +namespace GGMIX{ + + void ggmix::setup(const RowVector& dat, volumeinfo inf, + const string dirname, + int cnum, volume<float> themask, + volume<float> themean, + int num_mix, float eps, bool fixit) + { + bginfo = inf; + cnumber = cnum; + Mask = themask; + Mean = themean; + prefix = string("IC_")+num2str(cnum); + + fitted = false; + nummix = num_mix; + numdata = dat.Ncols(); + + //normalise data + datamean = mean(dat,2).AsScalar(); + datastdev= stdev(dat,2).AsScalar(); + data=(dat - datamean)/datastdev; + + props=zeros(1,nummix); + vars=zeros(1,nummix); + means=zeros(1,nummix); + Params=zeros(1,nummix); + logprobY = 1.0; + + props = std::pow(float(nummix),float(-1.0)); + + Matrix tmp1; + tmp1 = data * data.t() / numdata; + vars = tmp1.AsScalar(); + + float Dmin, Dmax, IntSize; + Dmin = min(data).AsScalar(); Dmax = max(data).AsScalar(); + IntSize = Dmax / nummix; + + means(1)=mean(data,2).AsScalar(); + for (int ctr=2; ctr <= means.Ncols(); ctr++){ + means(ctr) = Dmax - (ctr - 1.5) * IntSize; + } + means(2)=means(1)+2*sqrt(vars(1)); + //means(2)=means(1)+ 0.6*(Dmax-means(1)); + if(nummix>2) + //means(3)=means(1)-0.6*(means(1)-Dmin); + means(3)=means(1)-2*sqrt(vars(1)); + + epsilon = eps; + if(epsilon >=0 && epsilon < 0.0000001) + {epsilon = std::log(float(dat.Ncols()))/1000 ;} + fixdim = fixit; + + } + + + Matrix ggmix::threshold(const RowVector& dat, string levels) + { + Matrix Res; + Res = 1.0; + string tmpstr; + tmpstr = levels; + //cerr << " Levels : " << levels << endl << endl; + Matrix levls(1,4); + levls = 0; + Matrix fpr; + Matrix fdr; + Matrix nht; + + char *p; + char t[1024]; + const char *discard = ", [];{(})abcdeghijklmopqstuvwxyzABCEGHIJKLMNOQSTUVWXYZ~!@#$%^&*_-=+|\':></?"; + + strcpy(t, tmpstr.c_str()); + p=strtok(t,discard); + while(p){ + Matrix New(1,1); + New(1,1) = atof(p); + if(strchr(p,'d')){ + levls(1,3)++; + if(fdr.Storage()>0){ + fdr = fdr | New;} + else{ + fdr = New; + } + }else{ + if(strchr(p,'p')){ + levls(1,2)++; + if(fpr.Storage()>0){ + fpr = fpr | New; + }else{ + fpr = New; + } + }else{ + if(strchr(p,'n')){ + levls(1,4)++; + if(nht.Storage()>0){ + nht = nht | New; + }else{ + nht = New; + } + }else{ + levls(1,1)++; + levls = levls | New; + } + } + } + p=strtok(NULL,discard); + } + + if(fpr.Storage()>0){levls = levls | fpr;} + if(fdr.Storage()>0){levls = levls | fdr;} + if(nht.Storage()>0){levls = levls | nht;} + + + //cerr << " levles : " << levls << endl << endl; + Res = threshold(data, levls); + set_threshmaps(Res); + + return Res; + } + + Matrix ggmix::threshold(const RowVector& dat, Matrix& levels) + { + Matrix tests; + tests=levels; + Matrix Nprobs; + + //if only single Gaussian: resort to nht + if(nummix==1||props(1)>0.999||probmap.Sum()<0.05){ + if(levels(1,4)==0){ + Matrix New(1,6); + New(1,5)=0.05; + New(1,6)=0.01; + New(1,4)=2;New(1,1)=0;New(1,2)=0;New(1,3)=0;tests=New; + }else{ + Matrix New; + New = levels.Columns(int(1+levels(1,1)+levels(1,2) + +levels(1,3)),levels.Ncols()); + New(1,4) = levels(1,4); + New(1,1)=0;New(1,1)=0;New(1,3)=0; + tests=New; + } + } + + int numtests = int(tests(1,1)+tests(1,2)+tests(1,3)+tests(1,4)); + + Matrix Res(numtests,numdata); + Res = 0.0; + + int next = 1; + + for(int ctr1=1;ctr1<=tests(1,1);ctr1++){ + if(4+next <= tests.Ncols()){ + // message(" alternative hypothesis test at p > " << tests(1,4+next) << endl); + add_infstr(" alternative hypothesis test at p > "+float2str(tests(1,4+next),0,2,false)); + Matrix tmpNull; + tmpNull = dat; + + float cutoffpos, cutoffneg; + // cutoffpos = max(dat).AsScalar()+0.1; + // cutoffneg = min(dat).AsScalar()-0.1; + cutoffpos = means(1)+6*std::sqrt(vars(1)+0.0000001); + cutoffneg = means(1)-6*std::sqrt(vars(1)+0.0000001); + + for(int ctr=1; ctr<=tmpNull.Ncols(); ctr++) + if( probmap(ctr) > tests(1,4+next) ){ + if( dat(ctr) > means(1) ) + cutoffpos = std::min(cutoffpos, float(dat(ctr))); + else + cutoffneg = std::max(cutoffneg, float(dat(ctr))); + } + + // cerr << " Cutoff " << cutoffneg << " " << cutoffpos << endl; + + for(int ctr=1; ctr<=tmpNull.Ncols(); ctr++) + if( (dat(ctr) > cutoffneg) && (dat(ctr) < cutoffpos) ) + tmpNull(1,ctr)=0.0; + + // for(int ctr=1; ctr<=tmpNull.Ncols(); ctr++) + // if( probmap(ctr) < tests(1,4+next)) + // tmpNull(1,ctr)=0.0; + Res.Row(next) << tmpNull; + } + next++; + } + + for(int ctr1=1;ctr1<=tests(1,2);ctr1++){ + if(4+next <=tests.Ncols()){ + cerr << " false positives control " << tests(1,4+next)<<endl; + Matrix tmp1; + tmp1 = normcdf(dat,means(1),vars(1)); + Matrix tmpNull; + tmpNull = dat; + for(int ctr=1; ctr<=tmp1.Ncols(); ctr++) + if(tmp1(1,ctr) < tests(1,4+next)) + tmpNull(1,ctr)=0.0; + Res.Row(next) << tmpNull; + } + next++; + } + + for(int ctr1=1;ctr1<=tests(1,3);ctr1++){ + if(4+next <=tests.Ncols()){ + cerr << " false discovery rate " << tests(1,4+next)<< endl; + Matrix newcdf(Nprobs); + for(int ctr=1;ctr<=Nprobs.Nrows();ctr++){ + newcdf.Row(ctr) << 1-props(ctr)*normcdf(dat,means(ctr),vars(ctr)); + } + Matrix tmpNull; + tmpNull = newcdf.Row(1); + Matrix tmpAlt; + tmpAlt = sum(newcdf.Rows(2,Nprobs.Nrows()),1); + Matrix tmp; + tmp = dat; + for(int ctr=1; ctr<=tmp.Ncols(); ctr++) + if(tmpNull(1,ctr) > (1-tests(1,4+next)) * tmpAlt(1,ctr)) + tmp(1,ctr)=0.0; + Res.Row(next) << tmp; + next++; + } + } + + for(int ctr1=1;ctr1<=tests(1,4);ctr1++){ + if(4+next <=tests.Ncols()){ + // message(" 2-sided null hypothesis test at " << tests(1,4+next)<<endl); + add_infstr(" 2-sided null hypothesis test at "+float2str(tests(1,4+next),0,2,false)); + double mu, sig; + mu = dat.Sum()/numdata; + sig = var(dat,2).AsScalar(); + Matrix tmp1; + tmp1 = normcdf(dat,mu,std::abs(sig)); + Matrix tmpNull; + tmpNull = dat; + for(int ctr=1; ctr<=tmp1.Ncols(); ctr++) + if((tmp1(1,ctr) < 1-0.5*(tests(1,4+next))&& + (tmp1(1,ctr) > 0.5*(tests(1,4+next))))) + tmpNull(1,ctr)=0.0; + Res.Row(next) << tmpNull; + } + next++; + } + + return Res; + } + + + /* GMM fitting */ + + + void ggmix::gmmupdate() + { + int it_ctr = 1; + bool exitloop = false; + float oldll; + + // cerr << " fit with : " << means.Ncols() << endl; + + Matrix tmp0;Matrix tmp1;Matrix prob_K__y_theta; + Matrix kdata; + RowVector prob_Y__theta;RowVector Nbar; + RowVector mubar;RowVector sigmabar;RowVector pibar; + + do{ + oldll = logprobY; + + //make sure all variances are acceptable + for(int ctr1=1; ctr1 <=vars.Ncols(); ctr1++) + if(vars(ctr1)<0.0001){ + vars(ctr1) = 0.0001; + } + + tmp0 = normpdf(data,means,vars); + tmp1 = SP(props.t()*ones(1,numdata),tmp0); + prob_Y__theta << sum(tmp1,1); + logprobY = log(prob_Y__theta).Sum(); + prob_K__y_theta = SP(tmp1,pow(ones(nummix,1)*prob_Y__theta,-1)); + Nbar << sum(prob_K__y_theta,2).t(); + pibar = Nbar / numdata; + kdata = ones(nummix,1)*data; + mubar <<SP(sum(SP(kdata,prob_K__y_theta),2).t(),pow(Nbar,-1)); + kdata -= mubar.t()*ones(1,numdata); + kdata = pow(kdata,2); + sigmabar << SP(sum(SP(kdata,prob_K__y_theta),2).t(),pow(Nbar,-1)); + + means = mubar; + vars = sigmabar; + props = pibar; + + + if(epsilon<0){exitloop = it_ctr >= -epsilon;} + else{exitloop = (((logprobY-oldll < epsilon)&&(it_ctr>20)) + ||(it_ctr>400));} + it_ctr++; + }while(!exitloop); + } + + + void ggmix::gmmfit() + { + int i,j; + + //cerr << means << " " << vars << " " << props << endl; + //cerr << fixdim << endl; + if(fixdim){ + if(nummix>1){ + gmmupdate(); + add_params(means,vars,props,logprobY,MDL,Evi,true); + }else{ + means.ReSize(1); + means = data.Sum()/numdata; + vars.ReSize(1); + vars = var(data,2); + props.ReSize(1); + props = 1.0; + gmmevidence(); + } + }else{ + RowVector Score(Params.Ncols()); + do{ + //cerr << " fitting GMM with " << nummix << endl; + //cerr << means << " " << vars << " " << props << endl; + + gmmupdate(); + + // cerr << means << " " << vars << " " << props << endl; + + Score(nummix) = gmmevidence(); + + int idx1,idx2; + RowVector pitmp = props; + + pitmp.MaximumAbsoluteValue1(idx1); + pitmp(idx1)=0.0; + pitmp.MaximumAbsoluteValue1(idx2); + + //status(" "); + if(props.MaximumAbsoluteValue1(i)<0.9){ + if((vars(idx2)>0.15)&& + (std::abs(means(idx2)-means(idx1))<0.5*vars(idx1))){ + Score(nummix) = Score(nummix)/(2*(means(idx1))); + } + } + + add_params(means,vars,props,logprobY,MDL,Evi,true); + //cerr << " Evi : " << evidence() << " ("<< nummix << ")" << endl; + + gmmreducemm(); + means = means.Columns(1,nummix); + vars = vars.Columns(1,nummix); + props = props.Columns(1,nummix); + + }while(nummix>1); + means.ReSize(1); + means = data.Sum()/numdata; + vars.ReSize(1); + vars = var(data,2); + props.ReSize(1); + props = 1.0; + Score(nummix) = gmmevidence(); + add_params(means,vars,props,logprobY,MDL,Evi,true); + //identify best MM + Score.MinimumAbsoluteValue2(i,j); + means.ReSize(j); + vars.ReSize(j); + props.ReSize(j); + nummix = j; + int index; index = 3 + (j-1)*5; + means = Params.SubMatrix(index,index,1,j); + vars = Params.SubMatrix(index+1,index+1,1,j); + props = Params.SubMatrix(index+2,index+2,1,j); + } + + //make sure that maximum mode is first + // cerr <<" Max Abs : " << props.MaximumAbsoluteValue2(i,j) << " " << j << endl; + + props.MaximumAbsoluteValue2(i,j); + if(j>1){ + float tmp; + tmp = means(1);means(1) = means(j);means(j)=tmp; + tmp = vars(1);vars(1) = vars(j);vars(j)=tmp; + tmp = props(1);props(1) = props(j);props(j)=tmp; + } + + add_params(means,vars,props,logprobY,MDL,Evi,true); + //write_ascii_matrix(mainhtml.appendDir(prefix+"-GMM_params.txt"),Params); + + if(nummix==1) + probmap << normcdf(data,means(1),vars(1)); + else{ + Matrix Nprobs; + Matrix tmp0; + tmp0 = normpdf(data,means,vars); + Nprobs = SP(props.t()*ones(1,numdata),tmp0); + tmp0 = ones(Nprobs.Nrows(),1)*pow(sum(Nprobs,1),-1); + Nprobs = SP(tmp0,Nprobs); + probmap << SP(sum(Nprobs.Rows(2,Nprobs.Nrows()),1), + pow(sum(Nprobs,1),-1)); + } + } + + + float ggmix::gmmevidence() + { + Matrix tmp0; + if(means.Ncols()>1){ + tmp0 = normpdf(data,means,vars); + }else{ + tmp0 = normpdf(data,means.AsScalar(),vars.AsScalar()); + } + Matrix tmp1; + tmp1 = SP(props.t()*ones(1,numdata),tmp0); + tmp0 = SP(tmp0,pow(ones(nummix,1)*sum(tmp1,1),-1)); + tmp0 = pow(tmp0-ones(nummix,1)*tmp0.Row(nummix),2); + float logH = 0; + if(means.Ncols()>1){ + logH = sum(log(sum(tmp0.Rows(1,nummix-1),2)),1).AsScalar(); + } + logH = logH + 2*sum(log(std::sqrt(2.0)*numdata*props),2).AsScalar(); + logH = logH - 2*sum(props,2).AsScalar(); + + RowVector prob_Y__theta; + prob_Y__theta << sum(tmp1,1); + + logprobY = log(prob_Y__theta).Sum(); + + MDL = -logprobY + (1.5*nummix-0.5)* std::log(float(numdata)); + + Evi = -logprobY +nummix*std::log(2.0)-std::log(MISCMATHS::gamma(nummix)) + -3*nummix/2*std::log(M_PI)+0.5*logH; + + return Evi; + } + + void ggmix::gmmreducemm() + { + Matrix dlm(nummix,nummix); + Matrix mus(nummix,nummix); + Matrix rs(nummix,nummix); + + for(int ctri=1;ctri<=nummix; ctri++){ + for(int ctrj=1;ctrj<=nummix; ctrj++){ + mus(ctri,ctrj) = (props(ctri)*means(ctri)+props(ctrj)*means(ctrj)) + /(props(ctri)+props(ctrj)); + rs(ctri,ctrj) = (props(ctri)*(vars(ctri)+ + std::pow(means(ctri)-mus(ctri,ctrj),2) ) + + props(ctrj)*(vars(ctrj) + + std::pow(means(ctrj)-mus(ctri,ctrj),2))) + / (props(ctri)+props(ctrj)); + dlm(ctri,ctrj) = 0.5*numdata*( + props(ctri)*std::log( + std::abs(rs(ctri,ctrj))/std::abs(vars(ctri))) + + props(ctrj)*std::log(std::abs(rs(ctri,ctrj)) + / std::abs(vars(ctrj)))); + } + } + + dlm += Identity(nummix)*dlm.Maximum(); + + int i,j; + float val; + val=dlm.MinimumAbsoluteValue2(i,j); + //cerr << " " << val << " " << i << " " << j << endl; + + nummix--; + //cerr << "NumMix" << nummix << endl; + + RowVector newmean(nummix); + RowVector newvars(nummix); + RowVector newprop(nummix); + + int ctr0 = 1; + for(int ctr=1; ctr<=nummix+1; ctr++){ + if(ctr!=i&&ctr!=j){ + newmean(ctr0) = means(ctr); + newvars(ctr0) = vars(ctr); + newprop(ctr0) = props(ctr); + ctr0++; + } + } + //cerr << "ctr0 " << ctr0 << endl; + if(ctr0<=nummix){ + newmean(ctr0) = mus(i,j); + newvars(ctr0) = rs(i,j); + newprop(ctr0) = props(i)+props(j); + + means = newmean; + vars=newvars; + props=newprop; + } + } + + void ggmix::ggmfit() + {// fit a mixture of a Gaussian and multiple Gamma functions to the histogram + + float log_p_y_theta = 1.0; + float old_ll = 2.0; + float g_eps = 0.000001; + int it_ctr = 0; + double Dmax, Dmin; + + Dmax = 2 * data.Maximum(); + Dmin = -2 * data.Minimum(); + + //resize means, vars and props + if(nummix > 3) + nummix = 3; + means = means.Columns(1,nummix); + vars = vars.Columns(1,nummix); + props = props.Columns(1,nummix); + + means(1) = -2*mean(data,2).AsScalar(); + + Matrix tmp1;Matrix prob_K__y_theta; + Matrix kdata; + RowVector prob_Y__theta;RowVector Nbar; + RowVector mubar;RowVector sigmabar;RowVector pibar; + Matrix p_ygx(nummix,numdata); + offset = 0.0; + float const2; + Matrix negdata(data); + negdata = -data; + + while((it_ctr<30) || + ((std::abs(old_ll - log_p_y_theta)>g_eps) && (it_ctr<500))) + { // fit GGM + + it_ctr++; + //offset = (std::min(0.2,1-props(1)))*std::sqrt(vars(1)); + +// //make sure all variances are acceptable + for(int ctr1=1; ctr1 <=nummix; ctr1++) + if(vars(ctr1)<0.0001){ + vars(ctr1) = 0.0001; + } + + p_ygx = 0.0; + p_ygx.Row(1) << normpdf(data,means(1),vars(1)); + + const2 = (2.6-props(1))*sqrt(vars(1))+means(1); //min. nht level + + means(2) = (std::max(means(2), std::max(0.001, + 0.5 * ( const2 + std::sqrt( const2*const2 + 4*vars(2)))))); + vars(2) = std::max(std::min(vars(2), 0.5*std::pow(means(2),2)),0.0001); + p_ygx.Row(2) << gammapdf(data,means(2),vars(2)); + + if(nummix>2){ + const2 = (2.6-props(1))*sqrt(vars(1))-means(1); + + means(3) = -(std::max(-means(3), std::max(0.001, + 0.5 * ( const2 + std::sqrt( const2*const2 + 4*vars(3)))))); + vars(3) = std::max(std::min(vars(3), 0.5*std::pow(means(3),2)),0.0001); + p_ygx.Row(3) << gammapdf(negdata,-means(3),vars(3)); + } + + tmp1 = SP(props.t()*ones(1,numdata),p_ygx); + prob_Y__theta << sum(tmp1,1); + + //deal with non-modelled voxels + for(int ctr=1; ctr<=tmp1.Ncols(); ctr++) + if(prob_Y__theta(ctr) < 0.0001) + prob_Y__theta(ctr) = 0.0001; + + old_ll = log_p_y_theta; + log_p_y_theta = log(prob_Y__theta).Sum(); + // cerr << "calculated log_prob_Y__theta" <<endl; + // cerr << old_ll << " " << log_p_y_theta << " " + // cerr << float(std::abs(old_ll - log_p_y_theta)) << endl; + if((it_ctr<30) || + ((std::abs(old_ll - log_p_y_theta)>g_eps) && (it_ctr<300))){//update + + prob_K__y_theta = SP(tmp1,pow(ones(nummix,1)*prob_Y__theta,-1)); + Nbar << sum(prob_K__y_theta,2).t(); + for(int ctr=1; ctr<=Nbar.Ncols(); ctr++) + if(Nbar(ctr) < 0.0001 * numdata) + Nbar = Nbar + 0.0001; + pibar= Nbar / numdata; + // cerr << "pibar :" << pibar << endl; + kdata = ones(nummix,1)*data; + mubar <<SP(sum(SP(kdata,prob_K__y_theta),2).t(),pow(Nbar,-1)); + // cerr << "mubar :" << mubar << endl; + + kdata -= mubar.t()*ones(1,numdata); + kdata = pow(kdata,2); + sigmabar << SP(sum(SP(kdata,prob_K__y_theta),2).t(),pow(Nbar,-1)); + + means = mubar; + vars = sigmabar; + props = pibar; + }//update + } //while loop + + props = props / sum(props,2).AsScalar(); + add_params(means,vars,props,logprobY,MDL,Evi,true); + + probmap << SP(sum(tmp1.Rows(2,tmp1.Nrows()),1), + pow(sum(tmp1,1),-1)); + + //if(probmap.Sum() < 0.01){ + // message(" no Gamma survived " << endl); + // probmap << normcdf(data,means(1),vars(1)); + // }|| std::abs(mean(data,2).AsScalar()) > 1.0 + + if(props(1)<0.4 ){ + //set up GMM + // message(" try Gaussian Mixture Model " << endl); + props=zeros(1,nummix); + vars=zeros(1,nummix); + means=zeros(1,nummix); + Params=zeros(1,nummix); + logprobY = 1.0; + + props = std::pow(float(nummix),float(-1.0)); + + tmp1 = data * data.t() / numdata; + vars = tmp1.AsScalar(); + + float Dmin, Dmax, IntSize; + Dmin = min(data).AsScalar(); Dmax = max(data).AsScalar(); + IntSize = Dmax / nummix; + + means(1)=mean(data,2).AsScalar(); + for (int ctr=2; ctr <= means.Ncols(); ctr++){ + means(ctr) = Dmax - (ctr - 1.5) * IntSize; + } + means(2)=means(1)+sqrt(vars(1)); + if(nummix>2) + means(3)=means(1)-sqrt(vars(1)); + + fit(string("GMM")); + } + + //cerr << prefix << " " << it_ctr << endl; + + } + + /* INPUT / OUTPUT */ + + void ggmix::add_params(Matrix& mu, Matrix& sig, Matrix& pi, + float logLH, float MDL, float Evi, bool advance) + { + int size = Params.Ncols(); + if(size<2){size=2;} + Matrix New(5,size); + New = 0; + + New.SubMatrix(3,3,1,mu.Ncols())=mu; + New.SubMatrix(4,4,1,mu.Ncols())=sig; + New.SubMatrix(5,5,1,mu.Ncols())=pi; + New(1,1)=nummix; + + New(1,2)=-logLH; + New(2,1)=Evi; + New(2,2)=MDL; + if(Params.Storage()>nummix){ + Params = New & Params; + }else{ + Params = New; + } + } + + void ggmix::get_params(int index, Matrix& mu, Matrix& sig, Matrix& pi, + float logLH, float MDL, float Evi) + { + + } + + void ggmix::save() + { + + } + + void ggmix::status(const string &txt) + { + cerr << txt << "epsilon " << epsilon << endl; + cerr << txt << "nummix " << nummix << endl; + cerr << txt << "numdata " << numdata << endl; + cerr << txt << "means " << means << endl; + cerr << txt << "vars " << vars << endl; + cerr << txt << "props " << props << endl; + } + +} + + + diff --git a/ggmix.h b/ggmix.h new file mode 100644 index 0000000..53af01e --- /dev/null +++ b/ggmix.h @@ -0,0 +1,203 @@ +/* MELODIC - Multivariate exploratory linear optimized decomposition into + independent components + + ggmix.h - class for Gaussian/Gamma Mixture Model + + Christian F. Beckmann, FMRIB Image Analysis Group + + Copyright (C) 1999-2007 University of Oxford */ + +/* CCOPYRIGHT */ + +#ifndef __GGMIX_h +#define __GGMIX_h + +#include "newimage/newimageall.h" +/*#include "utils/log.h" +#include "melodic.h" +#include "utils/options.h" +#include "meloptions.h" +*/ + +//using namespace Utilities; +using namespace NEWIMAGE; + +namespace GGMIX{ + + class ggmix + { + public: + + ggmix(){} + //MelodicOptions &popts, Log &plogger): + // opts(popts), + // logger(plogger) + // { + // } + + ~ggmix() { + } + + void save(); + + void setup(const RowVector& dat, volumeinfo inf, const string dirname, + int here, volume<float> themask, + volume<float> themean, int num_mix = 3, + float eps = 0.0, bool fixdim = false); + + void gmmfit(); + void ggmfit(); + + inline void fit(string mtype = string("GGM")) + { + mmtype = mtype; + if(mmtype==string("GGM")) + this->ggmfit(); + else + this->gmmfit(); + + //re-insert mean and stdev + + data = data*datastdev + datamean; + //threshmaps = threshmaps*datastdev + datamean; + means = means*datastdev + datamean; + vars = vars*datastdev*datastdev; + } + + inline Matrix threshold(string levels) + {return this->threshold(data, levels);} + inline Matrix threshold(RowVector& levels) + {return this->threshold(data, levels);} + Matrix threshold(const RowVector& dat, Matrix& levels); + Matrix threshold(const RowVector& dat, string levels); + + void status(const string &txt); + + inline RowVector& get_means() {return means;} + inline void set_means(RowVector& Arg) {means = Arg;} + + inline RowVector& get_vars() {return vars;} + inline void set_vars(RowVector& Arg) {vars = Arg;} + + inline RowVector& get_pi() {return props;} + inline void set_pi(RowVector& Arg) {props = Arg;} + + inline RowVector& get_data() {return data;} + inline void set_data(RowVector& Arg) {data = Arg;} + + inline RowVector& get_prob() {return probmap;} + + inline float get_eps() {return epsilon;} + inline void set_eps(float Arg) {epsilon = Arg;} + + inline Matrix& get_threshmaps() {return threshmaps;} + inline void set_threshmaps(Matrix& Arg) {threshmaps = Arg;} + + inline bool isfitted(){return fitted;} + + inline int mixtures(){return nummix;} + + inline string get_type() { return mmtype;} + inline void set_type(string Arg) { mmtype = Arg;} + + inline string get_prefix() { return prefix;} + inline void set_prefix(string Arg) { prefix = Arg;} + + inline RowVector get_probmap() {return probmap;} + + inline float get_offset() {return offset;} + inline void set_offset(float Arg) {offset = Arg;} + + inline void flipres(int num){ + means = -means; + data = -data; + threshmaps = -threshmaps; + if(mmtype=="GGM"){ + float tmp; + tmp= means(2);means(2)=means(3);means(3)=tmp; + tmp=vars(2);vars(2)=vars(3);vars(3)=tmp; + tmp=props(2);props(2)=props(3);props(3)=tmp; + } + } + + inline void add_infstr(string what){ + threshinfo.push_back(what); + } + + inline string get_infstr(int num){ + if((threshinfo.size()<(unsigned int)(num-1))||(num<1)) + return string(""); + else + return threshinfo[num-1]; + } + + inline int size_infstr(){ + return threshinfo.size(); + } + + inline void clear_infstr(){ + threshinfo.clear(); + } + + inline void smooth_probs(float howmuch){ + volume4D<float> tempVol; + tempVol.setmatrix(probmap,Mask); + tempVol[0]= smooth(tempVol[0],howmuch); + probmap = tempVol.matrix(Mask); + } + + + + double datamean; + double datastdev; + + private: + // MelodicOptions &opts; + // Log &logger; //global log file + + //Log mainhtml; + + void gmmupdate(); + float gmmevidence(); + void gmmreducemm(); + void add_params(Matrix& mu, Matrix& sig, Matrix& pi, + float logLH, float MDL, float Evi, bool advance = false); + void get_params(int index, Matrix& mu, Matrix& sig, Matrix& pi, + float logLH, float MDL, float Evi); + + Matrix Params; + Matrix threshmaps; + + RowVector means; + RowVector vars; + RowVector props; + RowVector data; + RowVector probmap; + + volume<float> Mean; + volume<float> Mask; + + float epsilon; + float logprobY; + float MDL; + float Evi; + float offset; + + int nummix; + int numdata; + int cnumber; + + bool fitted; + bool fixdim; + + string prefix; + string mmtype; + string dirname; + + volumeinfo bginfo; + vector<string> threshinfo; + + }; +} + +#endif -- GitLab