/* first_utils.cc Brian Patenaude, Mark Jenkinson and Matthew Webster Copyright (C) 2006-2010 University of Oxford */ /* Part of FSL - FMRIB's Software Library http://www.fmrib.ox.ac.uk/fsl fsl@fmrib.ox.ac.uk Developed at FMRIB (Oxford Centre for Functional Magnetic Resonance Imaging of the Brain), Department of Clinical Neurology, Oxford University, Oxford, UK LICENCE FMRIB Software Library, Release 5.0 (c) 2012, The University of Oxford (the "Software") The Software remains the property of the University of Oxford ("the University"). The Software is distributed "AS IS" under this Licence solely for non-commercial use in the hope that it will be useful, but in order that the University as a charitable foundation protects its assets for the benefit of its educational and research purposes, the University makes clear that no condition is made or to be implied, nor is any warranty given or to be implied, as to the accuracy of the Software, or that it will be suitable for any particular purpose or for use under any specific conditions. Furthermore, the University disclaims all responsibility for the use which is made of the Software. It further disclaims any liability for the outcomes arising from using the Software. The Licensee agrees to indemnify the University and hold the University harmless from and against any and all claims, damages and liabilities asserted by third parties (including claims for negligence) which arise directly or indirectly from the use of the Software or the sale of any products based on the Software. No part of the Software may be reproduced, modified, transmitted or transferred in any form or by any means, electronic or mechanical, without the express permission of the University. The permission of the University is not required if the said reproduction, modification, transmission or transference is done without financial return, the conditions of this Licence are imposed upon the receiver of the product, and all original and amended source code is included in any transmitted product. You may be held legally responsible for any copyright infringement that is caused or encouraged by your failure to abide by these terms and conditions. You are not permitted under this Licence to use this Software commercially. Use for which any financial return is received shall be defined as commercial use, and includes (1) integration of all or part of the source code or the Software into a product for sale or license by or on behalf of Licensee to third parties or (2) use of the Software or any derivative of it for research with the final aim of developing software products for sale or license to a third party or (3) use of the Software or any derivative of it for research with the final aim of developing non-software products for sale or license to a third party, or (4) use of the Software to provide any service to an external organisation for which payment is received. If you are interested in using the Software commercially, please contact Isis Innovation Limited ("Isis"), the technology transfer company of the University, to negotiate a licence. Contact details are: innovation@isis.ox.ac.uk quoting reference DE/9564. */ #include #include #include "utils/options.h" #include "newimage/newimageall.h" #include "meshclass/meshclass.h" #include "shapeModel/shapeModel.h" #include "miscmaths/miscmaths.h" #include "fslvtkio/fslvtkio.h" using namespace std; using namespace NEWIMAGE; using namespace Utilities; using namespace mesh; using namespace SHAPE_MODEL_NAME; using namespace MISCMATHS; using namespace fslvtkio; string title="firt_utils University of Oxford (Brian Patenaude)"; string examples="first_utils [options] -i input -o output "; Option verbose(string("-v,--verbose"), false, string("output F-stats to standard out"), false, no_argument); Option help(string("-h,--help"), false, string("display this message"), false, no_argument); Option debug(string("--debug"), false, string("\tturn on debugging mode"), false, no_argument); Option overlap(string("--overlap"), false, string("Calculates Dice overlap."), false, no_argument); Option useScale(string("--useScale"), false, string("do stats"), false, no_argument); Option vertexAnalysis(string("--vertexAnalysis"), false, string("Perform vertex-wise stats from bvars."), false, no_argument); Option singleBoundaryCorr(string("--singleBoundaryCorr"), false, string("Correct boundary voxels of a single structure."), false, no_argument); Option usePCAfilter(string("--usePCAfilter"), false, string("Smooths the surface my truncating the mode parameters."), false, no_argument); Option usebvars(string("--usebvars"), false, string("Operate using the mode parameters output from FIRST."), false, no_argument); Option doMVGLM(string("--doMVGLM"), false, string("doMVGLM."), false, no_argument); Option useReconMNI(string("--useReconMNI"), false, string("Reconstruct meshes in MNI space."), false, no_argument); Option useReconNative(string("--useReconNative"), false, string("Reconstruct meshes in native space."), false, no_argument); Option useRigidAlign(string("--useRigidAlign"), false, string("Register meshes using 6 degree of freedom (7 if useScale is used)."), false, no_argument); Option useNorm(string("--useNorm"), false, string("Normalize volumes measurements."), false, no_argument); Option surfaceVAout(string("--surfaceout"), false, string("Output vertex analysis on the surface (old method)"), false, no_argument); Option reconMeshFromBvars(string("--reconMeshFromBvars"), false, string("Convert bvars to mesh."), false, no_argument); Option readBvars(string("--readBvars"), false, string("Read bvars from binary format"), false, no_argument); Option concatBvars(string("--concatBvars"), false, string("Concat bvars from binary format"), false, no_argument); Option meshToVol(string("--meshToVol"), false, string("Convert mesh to an image."), false, no_argument); Option centreOrigin(string("--centreOrigin"), false, string("Places origin of mesh at the centre of the image"), false, no_argument); Option saveVertices(string("--saveVertices"), string(""), string("filename for saving matrix of vertex coords: (all x, then all y, then all z) by Nsubjects"), false, requires_argument); Option inname(string("-i,--in"), string(""), string("filename of input image/mesh/bvars"), true, requires_argument); Option pathname(string("-a,--in"), string(""), string("Specifies extra path to image in .bvars file"), false, requires_argument); Option flirtmatsname(string("-f,--in"), string(""), string("Text file containing filenames of flirt matrices (filenames, not numbers)."), false, requires_argument); Option meshname(string("-m,--in"), string(""), string("Filename of input mesh"), false, requires_argument); Option normname(string("-g,--in"), string(""), string("Filename of normalization factors."), false, requires_argument); Option designname(string("-d,--in"), string(""), string("Filename of fsl design matrix"), false, requires_argument); Option refname(string("-r,--in"), string(""), string("Filename of reference image "), false, requires_argument); Option meshLabel(string("-l,--meshlabel"), 1, string("Specifies the label used to fill the mesh."), false, requires_argument); Option thresh(string("-p,--thresh"), 4, string("Threshhold for clean up."), false, requires_argument); Option numModes(string("-n,--numModes"), 0, string("Number of modes to retain per structure."), false, requires_argument); Option outname(string("-o,--out"), string(""), string("Output name"), true, requires_argument); int nonoptarg; //////////////////////////////////////////////////////////////////////////// //global variables int refXsize=182; int refYsize=218; int refZsize=182; float refXdim=1.0; float refYdim=1.0; float refZdim=1.0; void setShapeMesh(shapeModel * model1, const Mesh & m){ vector::iterator j=model1->smean.begin(); for (vector::const_iterator i = m._points.begin(); i!=m._points.end(); i++ , j+=3){ *j=(*i)->get_coord().X; *(j+1)=(*i)->get_coord().Y; *(j+2)=(*i)->get_coord().Z; } } void meshReg(Mesh & m, const string & flirtmatname){ //refsize is actually target image int numPoints=m.nvertices(); Matrix MeshPts(4,numPoints); Matrix NewMeshPts(4,numPoints); Matrix flirtmat(4,4); //read in flirt matrix, uses ascii ifstream fmat; fmat.open(flirtmatname.c_str()); float tmpfloat=0; for (int i=0; i<4;i++){ for (int j=0; j<4;j++){ fmat>>tmpfloat; flirtmat.element(i,j)=tmpfloat; // cout<::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ // cout<<"count "<get_coord().X; MeshPts.element(1,count)=(*i)->get_coord().Y; MeshPts.element(2,count)=(*i)->get_coord().Z; MeshPts.element(3,count)=1; count++; } // cout<<"mesh points loaded into matrix..."<::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ Pt newPt(NewMeshPts.element(0,count),NewMeshPts.element(1,count),NewMeshPts.element(2,count)); (*i)->_update_coord = newPt; count++; } m.update(); } void meshReg(Mesh & m, const vector< vector > & flirtmatv){ //refsize is actually target image int numPoints=m.nvertices(); Matrix MeshPts(4,numPoints); Matrix NewMeshPts(4,numPoints); Matrix flirtmat(4,4); //read in flirt matrix, uses ascii for (int i=0; i<4;i++){ for (int j=0; j<4;j++){ flirtmat.element(i,j)=flirtmatv.at(i).at(j); cout<::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ // cout<<"count "<get_coord().X; MeshPts.element(1,count)=(*i)->get_coord().Y; MeshPts.element(2,count)=(*i)->get_coord().Z; MeshPts.element(3,count)=1; count++; } // cout<<"mesh points loaded into matrix..."<::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ Pt newPt(NewMeshPts.element(0,count),NewMeshPts.element(1,count),NewMeshPts.element(2,count)); (*i)->_update_coord = newPt; count++; } m.update(); } inline ReturnMatrix unwrapMatrix(const Matrix & m) { ColumnVector munwrap(m.Nrows()*m.Ncols()); unsigned int count=0; for (int i =0; i vector vectorToVector( const Matrix & sm, const int & MaxModes){ vector vecM; if (sm.Nrows()==1){ for (int i=0;i< MaxModes ; i++){ vecM.push_back(static_cast(sm.element(0,i))); } }else{ for (int i=0;i< MaxModes ; i++){ vecM.push_back(static_cast(sm.element(i,0))); } } return vecM; } template vector vectorToVector( const Matrix & sm){ vector vecM; if (sm.Nrows()==1){ for (int i=0;i< sm.Ncols() ; i++){ vecM.push_back(static_cast(sm.element(0,i))); } }else{ for (int i=0;i< sm.Nrows() ; i++){ vecM.push_back(static_cast(sm.element(i,0))); } } return vecM; } template vector< vector > matrixToVector( const Matrix & sm, const int & MaxModes){ vector< vector > vecM; for (int j=0;j< MaxModes ; j++){ vector mode; for (int i=0;i< sm.Nrows() ; i++){ mode.push_back(sm.element(i,j)); } vecM.push_back(mode); } return vecM; } template vector< vector > matrixToVector( const Matrix & sm){ vector< vector > vecM; for (int j=0;j< sm.Ncols() ; j++) { vector mode; for (int i=0;i< sm.Nrows() ; i++) mode.push_back(static_cast(sm.element(i,j))); vecM.push_back(mode); } return vecM; } shapeModel* loadAndCreateShapeModel( const string & modelname) { if (verbose.value()) cout<<"read model"<(0)); if (verbose.value()) cout<<"done reading model"<getPointsAsMatrix().Nrows(); unsigned int M = static_cast(fmodel->getField("numSubjects").element(0,0)); int MaxModes=M; if (verbose.value()) cout<<"setting up shape/appearance model"< Smean; Matrix* Pts = new Matrix; *Pts=fmodel->getPointsAsMatrix(); if (verbose.value()) cout<<"The shape has "<element(i,0)); Smean.push_back(Pts->element(i,1)); Smean.push_back(Pts->element(i,2)); } Pts->ReleaseAndDelete(); //read polygon data vector< vector > polygons = matrixToVector(fmodel->getPolygons().t()); //process shape modes and conditional intensity mean modes Matrix SmodesM; Matrix ImodesM; SmodesM=unwrapMatrix(fmodel->getField("mode0")); ImodesM=unwrapMatrix(fmodel->getField("Imode0")); for (int i =1; i>mode; SmodesM=SmodesM | unwrapMatrix(fmodel->getField("mode"+mode)); ImodesM=ImodesM | unwrapMatrix(fmodel->getField("Imode"+mode)); } if (verbose.value()) cout< > Smodes = matrixToVector(SmodesM); vector< vector > Imodes = matrixToVector(ImodesM); ImodesM.Release(); SmodesM.Release(); //process rest of information, including intensity variance vector< vector > Iprec = matrixToVector(fmodel->getField("iCondPrec0").t()); vector Errs = vectorToVector(fmodel->getField("ErrPriors0")); vector se = vectorToVector(fmodel->getField("eigenValues"), MaxModes); vector ie = vectorToVector(fmodel->getField("iCondEigs0")); vector Imean = vectorToVector(unwrapMatrix(fmodel->getField("Imean"))); vector labels = vectorToVector(fmodel->getField("labels")); if (verbose.value()) cout<<"The model was constructed from "< & pts, const vector< vector > & polys ) { Mesh mesh; mesh._points.clear(); mesh._triangles.clear(); int i=0; for (vector::const_iterator p= pts.begin(); p!=pts.end(); p+=3,i++) { Mpoint * pt = new Mpoint(*p, *(p+1), *(p+2), i); mesh._points.push_back(pt); } for (vector< vector >::const_iterator p=polys.begin(); p!=polys.end(); p++) { Triangle * tr = new Triangle( mesh._points.at( p->at(0) ), mesh._points.at( p->at(1) ), mesh._points.at( p->at(2) )); mesh._triangles.push_back(tr); } return mesh; } //%%%%%%%%%%%%%%mesh fill void getBounds(Mesh m, int *bounds, float xdim, float ydim, float zdim){ float xmin=1000,xmax=-1000,ymin=1000,ymax=-1000,zmin=1000,zmax=-1000; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ float tempx=(*i)->get_coord().X; float tempy=(*i)->get_coord().Y; float tempz=(*i)->get_coord().Z; if (tempxxmax){ xmax=tempx; } if (tempyymax){ ymax=tempy; } if (tempzzmax){ zmax=tempz; } } *bounds=static_cast(floor(xmin/xdim)-1); *(bounds+1)=static_cast(ceil(xmax/xdim)+1); *(bounds+2)=static_cast(floor(ymin/ydim)-1); *(bounds+3)=static_cast(ceil(ymax/ydim)+1); *(bounds+4)=static_cast(floor(zmin/zdim)-1); *(bounds+5)=static_cast(ceil(zmax/zdim)+1); } void draw_segment(volume& image, const Pt& p1, const Pt& p2, int label) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); //in new version of bet2 double mininc = min(xdim,min(ydim,zdim)) * .5; Vec n = (p1 - p2); double d = n.norm(); n.normalize(); // double l = d*4; for (double i=0; i<=d; i+=mininc) { Pt p = p2 + i* n; image((int) floor((p.X)/xdim +.5),(int) floor((p.Y)/ydim +.5),(int) floor((p.Z)/zdim +.5)) = label; } } void draw_scalar_segment(volume& image, volume& nvol, const Pt& p1, const Pt& p2, float s1, float s2) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); //in new version of bet2 double mininc = min(xdim,min(ydim,zdim)) * .25; Vec n = (p1 - p2); double d = n.norm(); n.normalize(); // double l = d*4; for (double i=0; i<=d; i+=mininc) { Pt p = p2 + i* n; float interp_s = s2 + i/d*(s1-s2); image(MISCMATHS::round(p.X/xdim),MISCMATHS::round(p.Y/ydim),MISCMATHS::round(p.Z/zdim)) += interp_s; nvol(MISCMATHS::round(p.X/xdim),MISCMATHS::round(p.Y/ydim),MISCMATHS::round(p.Z/zdim)) += 1.0f; } } void set_scalars(Mesh& m, const ColumnVector& sc) { if (sc.Nrows()!=m.nvertices()) { cerr << "ERROR in set_scalars:: mismatch in number of vertices ("<::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ // loop over vertices (*i)->set_value(sc(count++)); } return; } volume draw_scalar_mesh(const volume& image, const Mesh &m, const ColumnVector& sc) { Mesh localMesh; localMesh = m; if (sc.Nrows()>0) set_scalars(localMesh,sc); // allow empty vector (zero size) to be passed in and values already in mesh to be used instead of scalars double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); double mininc = min(xdim,min(ydim,zdim)) * .25; volume res = image; res=0.0f; volume nvol = res; for (list::const_iterator i = localMesh._triangles.begin(); i!=localMesh._triangles.end(); i++) { Pt p1 = (*i)->get_vertice(1)->get_coord(); Pt p2 = (*i)->get_vertice(2)->get_coord(); Vec n = (*(*i)->get_vertice(0) - *(*i)->get_vertice(1)); double d = n.norm(); n.normalize(); float s0,s1,s2; s0=(*i)->get_vertice(0)->get_value(); s1=(*i)->get_vertice(1)->get_value(); s2=(*i)->get_vertice(2)->get_value(); for (double j=0; j<=d ; j+=mininc) { Pt p = p1 + (double)j* n; float s = s1 + j/d*(s0-s1); draw_scalar_segment(res, nvol, p, p2, s, s2); } } res=divide(res,nvol,nvol); return res; } volume draw_scalar_mesh(const volume& image, const Mesh &m) { ColumnVector dummy; return draw_scalar_mesh(image,m,dummy); } volume draw_mesh(const volume& image, const Mesh &m, int label) { double xdim = (double) image.xdim(); double ydim = (double) image.ydim(); double zdim = (double) image.zdim(); //in new version of bet2 double mininc = min(xdim,min(ydim,zdim)) * .5; volume res = image; for (list::const_iterator i = m._triangles.begin(); i!=m._triangles.end(); i++) { Vec n = (*(*i)->get_vertice(0) - *(*i)->get_vertice(1)); double d = n.norm(); n.normalize(); for (double j=0; j<=d ; j+=mininc) { Pt p = (*i)->get_vertice(1)->get_coord() + (double)j* n; draw_segment(res, p, (*i)->get_vertice(2)->get_coord(),label); } } return res; } volume make_mask_from_meshInOut(const volume & image, const Mesh& m, int label, int* bounds) { float xdim = (float) image.xdim(); float ydim = (float) image.ydim(); float zdim = (float) image.zdim(); volume mask; copyconvert(image,mask); mask = 0; mask = draw_mesh(mask, m,label+100); // THIS EXCLUDES THE ACTUAL MESH volume otl=mask; getBounds(m,bounds,xdim,ydim,zdim); vector current; current.clear(); Pt c(bounds[0]-2, bounds[2]-2, bounds[4]-2); mask.value(static_cast(c.X),static_cast(c.Y),static_cast(c.Z)) = label; current.push_back(c); int fillCount=0; while (!current.empty()) { Pt pc = current.back(); int x, y, z; x=(int) pc.X; y=(int) pc.Y; z=(int) pc.Z; current.pop_back(); fillCount++; if (bounds[0]<=x-1 && mask.value(x-1, y, z)==0) { mask.value(x-1, y, z) = label; current.push_back(Pt(x-1, y, z)); } if (bounds[2]<=y-1 && mask.value(x, y-1, z)==0) { mask.value(x, y-1, z) = label; current.push_back(Pt(x, y-1, z)); } if (bounds[4]<=z-1 && mask.value(x, y, z-1)==0) { mask.value(x, y, z-1) = label; current.push_back(Pt(x, y, z-1)); } if (bounds[1]>=x+1 && mask.value(x+1, y, z)==0){ mask.value(x+1, y, z) = label; current.push_back(Pt(x+1, y, z)); } if (bounds[3]>=y+1 && mask.value(x, y+1, z)==0){ mask.value(x, y+1, z) = label; current.push_back(Pt(x, y+1, z)); } if (bounds[5]>=z+1 && mask.value(x, y, z+1)==0){ mask.value(x, y, z+1) = label; current.push_back(Pt(x, y, z+1)); } } for (int i=bounds[0];i* vlabels){ for (unsigned int i=0;isize();i++){ if (vlabels->at(i)==label1){ return i; } } return -1; } bool findAddLabel(int label1,int label2,int* indseg, vector* vlabels, vector* vTP, vector* vFN, vector* vFP, vector* segImLabels,vector* minInterX,vector* maxInterX,vector* minInterY,vector* maxInterY,vector* minInterZ,vector* maxInterZ){ int ind2=-1;//ind1=-1, ind2=-1; int ind1=-1; //return 1 signifies intersection *indseg=-1; for (unsigned int i=0;isize();i++){ if ((segImLabels->at(i)==label1)&&(label1!=0)){ *indseg=i; i=segImLabels->size()+1; } } if ((*indseg==-1)&&(label1!=0)){ segImLabels->push_back(label1); minInterX->push_back(10000); maxInterX->push_back(0); minInterY->push_back(10000); maxInterY->push_back(0); minInterZ->push_back(10000); maxInterZ->push_back(0); *indseg=segImLabels->size()-1; } for (unsigned int i=0;isize();i++){ // cout<<"labels "<at(i)==label1)|(vlabels->at(i)==label2)){ if (label1==label2){ // cout<<"found ind1=ind2"<size()+1; }else{ if (label1==vlabels->at(i)){ ind1=i; }else{ ind2=i; } } } if(i==vlabels->size()-1){ // cout<<"do i enter?"<size(); vlabels->push_back(label1); vTP->push_back(0); vFN->push_back(0); vFP->push_back(0); } if (ind2==-1){ // cout<<"end and ind2=-1 "<size(); vlabels->push_back(label2); vTP->push_back(0); vFN->push_back(0); vFP->push_back(0); } } } } // cout<<"out of loop"<at(ind1)+=1; return true; }else{ vFP->at(ind1)+=1; vFN->at(ind2)+=1; return false; } //vCount->at(*ind1)+=1; } Matrix overlaps(const volume segIm, const volume gold){ int sizex= segIm.xsize(); int sizey=segIm.ysize(); int sizez=segIm.zsize(); bool inter; int indseg; //find union and intersection vector vlabels,vTP, vFN, vFP,segLabels; //these are used to speed up the distance calculation vector minInterX,maxInterX,minInterY,maxInterY,minInterZ,maxInterZ; vlabels.push_back(0); vTP.push_back(0); vFN.push_back(0); vFP.push_back(0); for (int k=0;kmaxInterX.at(indseg)){ maxInterX.at(indseg)=i; } if (j>maxInterY.at(indseg)){ maxInterY.at(indseg)=j; } if (k>maxInterZ.at(indseg)){ maxInterZ.at(indseg)=k; } // cout<<"leave min max update "<(segLabels.size()),9); for (unsigned int i=0; i(vTP.at(ind))/(vTP.at(ind)+vFP.at(ind)+vFN.at(ind)); simMeasures.element(i,5)=2.0*vTP.at(ind)/(2*vTP.at(ind)+vFP.at(ind)+vFN.at(ind)); simMeasures.element(i,6)=static_cast(vFN.at(ind))/(vFN.at(ind)+vTP.at(ind)); simMeasures.element(i,7)=static_cast(vFP.at(ind))/(vFN.at(ind)+vTP.at(ind)); simMeasures.element(i,8)=static_cast(vTP.at(ind))/(vFN.at(ind)+vTP.at(ind)); cout<<"Dice "< & vnames, vector& vnvars,string impath, vector< vector< vector > > & fmatv){ string stemp; string modelNames; int N;//number of subjects fmatv.clear(); ifstream fin; fin.open(fname.c_str()); //throw away first three lines getline(fin,stemp);//this is bvars file getline(fin,modelNames);//modelnames; fin>>stemp>>N; vnvars.clear(); //int NmaxBvars=0; //vector< vector > all_bvars; for (int i=0; i vbvars; fin>>stemp;//read in subject id vnames.push_back(impath+stemp); int nvars;//how many vars written for the subject fin>>nvars; vnvars.push_back(nvars); char blank; fin.read(reinterpret_cast(&blank),sizeof(char)); if (i==0){ bvars.ReSize(nvars,N); } vnvars.push_back(nvars); for (int j=0;j>ftemp; fin.read(reinterpret_cast(&ftemp),sizeof(float)); bvars.element(j,i)=ftemp; }else{ bvars.element(j,i)=0; } } // all_bvars.push_back(vbvars); vector< vector > mat; for (int k=0;k<4;k++) { vector row; for (int l=0;l<4;l++) { float ftemp; // fin>>ftemp; fin.read(reinterpret_cast(&ftemp),sizeof(float)); row.push_back(ftemp); } mat.push_back(row); } fmatv.push_back(mat); } return modelNames; } void write_bvars(string fname,string modelname,Matrix bvars, int numModes,vector vnames){ ofstream fout; fout.open(fname.c_str()); fout<<"this is a bvars file"< vdists, float min, float max){ int N=static_cast(vdists.size()); float bins=128; float binwidth=(max-min)/bins; vector bincounts; //initialize bincounts to zero for (int b=0;bmaxcount){ maxcount=bincounts.at(b); maxind=b; } } return (min+maxind*binwidth+binwidth/2.0); } float mode(vector vdists,int *maxcount){ // cout<<"calc mode"<(vdists.size()); *maxcount=0; float maxlowint=0; float bins=256; bins=128; float binwidth=(vdists.at(N-1)-0)/bins; int count=0; int bincount=1; float lowint=0; for (int i=0;i(*maxcount)){ *maxcount=count; maxlowint=lowint; } }else{ count=0; i--; bincount++; lowint=bincount*binwidth; } } return (maxlowint+binwidth/2.0); } float fullwidthhalfmax(vector vdists,float halfmaxval, float *halfmin,float *halfmax){ int N=static_cast(vdists.size()); int maxcount=0; float maxlowint=0; float bins=256; bins=128; float binwidth=(vdists.at(N-1)-0)/bins; int countprev=0; bool foundmin=false; int count=0; int bincount=1; float lowint=0; for (int i=0;i(maxcount)){ maxcount=count; maxlowint=lowint; } }else{ countprev=count; if ((count>halfmaxval)&&(!foundmin)){ *halfmin=lowint+binwidth/2.0; foundmin=true; } if ((count>halfmaxval)){ *halfmax=lowint+binwidth/2.0; } count=0; i--; bincount++; lowint=bincount*binwidth; } } return (maxlowint+binwidth/2.0); } float boundaryCorr(volume* mask, volume* ref, int label, float zthresh, int* bounds){ //returns volume //build intensity vector vector vgraylevels; vector ::iterator Iter; float dist=10000; for (int i=bounds[0];ivalue(i,j,k)==label){ dist=ref->value(i,j,k); if (vgraylevels.empty()){ vgraylevels.push_back(dist); }else if (dist>=vgraylevels.back()){ vgraylevels.push_back(dist); }else { for ( Iter = vgraylevels.begin( ) ; Iter !=vgraylevels.end( ) ; Iter++ ){ if (dist<*Iter){ vgraylevels.insert(Iter,dist); break; } } } } } } } int maxcount; //don't end up using the mode...re-calculate centre from fullwidth half-maximum mode(vgraylevels,&maxcount); //now find full width half maximum //float halfmaxval=maxcount/2.0; float halfmin,halfmax; fullwidthhalfmax(vgraylevels,maxcount/2.0,&halfmin, &halfmax); float mean=(halfmin+halfmax)/2; float sdev=abs(halfmax-halfmin)/2.35; //test for thalamus // volume zvol; // copyconvert(*mask, zvol); // zvol=0; float vol=0; float min=0, max=0; //calculates z-value for all lgive a nice place to initialize EM or could act directly on intensity and use range to initialize for (int i=bounds[0];ivalue(i,j,k)==(label+100 )){ z=(ref->value(i,j,k)-mean)/sdev; // zvol.value(i,j,k)=(z); if (zthresh>=0){ if (abs(z)>zthresh){ mask->value(i,j,k)=0; }else{ mask->value(i,j,k)=label; vol++; } } }else if (mask->value(i,j,k)==label){ vol++; z=(ref->value(i,j,k)-mean)/sdev; // zvol.value(i,j,k)=(z); if (z>max){ max=z; } if (z* mask, int* bounds){ //used to find label and set bounds int xmin=10000,ymin=10000,zmin=10000; int xmax=-1, ymax=-1, zmax=-1; int label=999; bool found=false; for (int i=bounds[0];ivalue(i,j,k)>0){ if (xmin>i){ xmin=i; } if (ymin>j){ ymin=j; } if (zmin>k){ zmin=k; } if (xmaxvalue(i,j,k)<100)&&(mask->value(i,j,k)!=0)&&(!found)){ label=mask->value(i,j,k); found=true; // break; } } // if (found){break;} } //if (found){break;} } bounds[0]=xmin-1; bounds[1]=xmax+1; bounds[2]=ymin-1; bounds[3]=ymax+1; bounds[4]=zmin-1; bounds[5]=zmax+1; return label; } //****************************END OF BOUNDARY CORRECTION FUNCTIONS************************************** //********************************GLM for stats******************************// ColumnVector GLM_fit(Matrix G, Matrix D, ColumnVector contrast){ //start for only well conditioned design matrices Matrix A=G.t()*G; Matrix Betas(D.Nrows(),D.Ncols()); Betas=A.i()*G.t()*D; Matrix Mres; Mres=D-G*(Betas); //calculate residual variance ColumnVector avgRes(D.Ncols()); for (int i=0; i X = design matrix (N_subj by N_evs) // D -> Y = data matrix (N_subj by 3) //Calculate estimated values Matrix Yhat=G*(G.t()*G).i()*G.t()*D; //calculate E covariance matrix Matrix E=D-Yhat; E=E.t()*E; // cout<<"hmm"< t1im; volume segim; int bounds[6]={0,0,0,0,0,0}; read_volume(t1im,refname.value()); read_volume(segim,inname.value()); //FIND LABEL AND BOUNDS FOR EACH IMAGE //need to reset lower bounds as well bounds[0]=0; bounds[2]=0; bounds[4]=0; bounds[1]=segim.xsize(); bounds[3]=segim.ysize(); bounds[5]=segim.zsize(); int label=findStructLabel(&segim, bounds); volume vz1; boundaryCorr(&segim, &t1im,label, thresh.value(), bounds); segim.setAuxFile("MGH-Subcortical"); // for automatic colormap save_volume(segim,outname.value()); } //*****************************LINEA TRANSFORM********************************************************// Matrix rigid_linear_xfm(Matrix Data,ColumnVector meanm, Mesh mesh, bool writeToFile){ //ColumnVector avgM(sub.Ncols()); //determine translations int Nsub=Data.Ncols(); int Npoints=Data.Nrows()/3; //***********CALCULATE CENTROIDS*************// //calculate centroid of mean mesh float Mxr=0,Myr=0,Mzr=0; for (int i=0;i vMx,vMy,vMz; for (int i=0;i vR; vector< float > vscale; for (int subject=0;subject::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ (*i)->_update_coord.X=DataNew.element(count,subject); (*i)->_update_coord.Y=DataNew.element(count+1,subject); (*i)->_update_coord.Z=DataNew.element(count+2,subject); count+=3; } m.update(); // string snum; // stringstream ssnum; // ssnum<>snum; // m.save(snum+"reg.vtk",3); } return DataNew; } Mesh setup_avMesh(const Mesh& m, const Matrix& MeshVerts) { // input m must have the right topology (i.e. triangles) and MeshVerts must contain the coordinates in the first column // with order of iterated points in m and the rows in MeshVerts corresponding (by a factor of 3 as X,Y,Z are stored sequentially for each point) Mesh avMesh; Matrix avVerts; avVerts=mean(MeshVerts,2); // form the average coordinate location across the whole group avMesh=m; int count=0; for (vector::iterator i = avMesh._points.begin(); i!=avMesh._points.end(); i++ ){ // loop over vertices Pt newpt; newpt.X = avVerts.element(count,0); newpt.Y = avVerts.element(count+1,0); newpt.Z = avVerts.element(count+2,0); (*i)->_update_coord = newpt; // clunky way of doing what should be: set_coord(const Pt &newpt) (*i)->update(); count+=3; } return avMesh; } Matrix calc_avNormals(Mesh& avMesh) { // TODO - would like this to be const but can't get it to compile like that! // TODO - i.e. Matrix calc_avNormals(Mesh& const avMesh) { // input m must have the right topology (i.e. triangles) and MeshVerts must contain the coordinates in the first column // with order of iterated points in m and the rows in MeshVerts corresponding (by a factor of 3 as X,Y,Z are stored sequentially for each point) Matrix avNormals(avMesh.nvertices()*3,1); int count=0; for (vector::iterator i = avMesh._points.begin(); i!=avMesh._points.end(); i++ ){ // loop over vertices Vec norm; norm=(*i)->local_normal(); avNormals.element(count,0) = norm.X; avNormals.element(count+1,0) = norm.Y; avNormals.element(count+2,0) = norm.Z; count+=3; } return avNormals; } Matrix recon_meshesMNI( shapeModel* model1, Matrix bvars, ColumnVector* meanm, Mesh * meshout,vector* vMeshes, Mesh& avMesh){ // note that meshout may be the same as avMesh (MJ:not yet verified) vMeshes->clear(); //want to return mean mesh in vector form meanm->ReSize(model1->smean.size()); { int count=0; int cumnum=0; for (int sh=0; sh<1;sh++) { Mesh m= convertToMesh(model1->smean, model1->cells);//model1->getTranslatedMesh(sh); *meshout=m; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ meanm->element(3*cumnum+count)=(*i)->get_coord().X; meanm->element(3*cumnum+count+1)=(*i)->get_coord().Y; meanm->element(3*cumnum+count+2)=(*i)->get_coord().Z; count+=3; } cumnum+=model1->smean.size(); } } //need number of subjects (to determine number of modes) //int M=model1->getNumberOfSubjects(); int Tpts=model1->smean.size()/3; Matrix MeshVerts(3*Tpts,bvars.Ncols()); Mesh m; //this is different than mnumber of subjects which were used to create model //int numSubs=bvars.Ncols(); //this loads all mesh point into a matrix to do stats on.... //cout<<"generate and load vertices into matrix "< vars; for (int i=0; igetDeformedGrid(vars),model1->cells); vMeshes->push_back(m); int count=0; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ // loop over vertices MeshVerts.element(3*cumnum+count,j)=(*i)->get_coord().X; MeshVerts.element(3*cumnum+count+1,j)=(*i)->get_coord().Y; MeshVerts.element(3*cumnum+count+2,j)=(*i)->get_coord().Z; count+=3; } cumnum+=model1->smean.size(); } } avMesh = setup_avMesh(m,MeshVerts); return MeshVerts; } Matrix recon_meshesNative( const string & modelname, const Matrix & bvars, ColumnVector & meanm, Mesh & meshout, const vector & subjectnames, const vector< vector< vector > > & flirtmats,vector & vMeshes, Mesh& avMesh){ vMeshes.clear(); //fslvtkIO* fin = new fslvtkIO(modelname,static_cast(0)); shapeModel* model1=loadAndCreateShapeModel(modelname); // shapeModel* model1= new shapeModel(); // model1->setImageParameters(refXsize,refYsize, refZsize,refXdim, refYdim, refZdim); // cout<<"load model "<load_bmv_binaryInfo(modelname,1); // model1->load_bmv_binary(modelname,1); //want to return mean mesh in vector form meanm.ReSize(model1->smean.size()); { int count=0; int cumnum=0; for (int sh=0; sh<1;sh++){ //difference between origin specification Mesh m=convertToMesh( model1->smean , model1->cells ); // m.save("targetMesh.vtk",3); //Mesh m=model1->getShapeMesh(sh); meshout=m; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ meanm.element(3*cumnum+count)=(*i)->get_coord().X; meanm.element(3*cumnum+count+1)=(*i)->get_coord().Y; meanm.element(3*cumnum+count+2)=(*i)->get_coord().Z; // cout<<"coord "<element(3*cumnum+count)<<" "<element(3*cumnum+count+1)<<" "<element(3*cumnum+count+2)<smean.size()/3; } } //need number of subjects (to determine number of modes) int Tpts=model1->smean.size()/3; Matrix MeshVerts(3*Tpts,bvars.Ncols()); //this is different than mnumber of subjects which were used to create model //this loads all mesh point into a matrix to do stats on.... // cout<<"generate and load vertices into matrix "< t1im; //for each subject vector vars; for (int i=0; igetDeformedGrid(vars),model1->cells); meshReg(m, flirtmats.at(j)); vMeshes.push_back(m); int count=0; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ){ MeshVerts.element(3*cumnum+count,j)=(*i)->get_coord().X; MeshVerts.element(3*cumnum+count+1,j)=(*i)->get_coord().Y; MeshVerts.element(3*cumnum+count+2,j)=(*i)->get_coord().Z; count+=3; } cumnum+=model1->smean.size()/3; } } avMesh = setup_avMesh(m,MeshVerts); return MeshVerts; } Matrix deMeanMatrix(Matrix M){ //demean rows Matrix Mnew(M.Nrows(),M.Ncols()); for (int i=0; i subjectnames; Matrix bvars; vector vN; Matrix target; //target is only used for glm //must include a design matrix with bvars to use glm //modelname is used to set a path vector< vector< vector > > vec_fmats; read_bvars(inname.value(),bvars,subjectnames, vN, pathname.value(),vec_fmats); target=read_ascii_matrix(designname.value()); if (target.Nrows()!=bvars.Ncols()) { try { target=read_vest(designname.value()); } catch (...) { cerr << "ERROR:: Design matrix incorrect (wrong size or cannot be read)" << endl; exit(EXIT_FAILURE); } if (target.Nrows()!=bvars.Ncols()) { cerr << "ERROR:: Design matrix incorrect (wrong size or cannot be read)" << endl; exit(EXIT_FAILURE); } } //can filter meshes if (usePCAfilter.value()){ //truncate number of modes to recon mesh (smoothing) bvars=bvars.SubMatrix(1,numModes.value(),1,bvars.Ncols()); } volume t1im; volume segim; vector vMeshes; Matrix MeshVerts;//this is used when placing t-stats on a mesh //need flirt matrices //load their names into a vector ifstream flirtmats; vector flirtmatnames; //**********done reading in bvars and models and flirt matrices ***************// //****************RECONSTRUCTION AND ALIGNMENT*********************/ //Choose the space in which to reconstruct the meshes Mesh modelMeanMesh; ColumnVector CVmodelMeanMesh; Mesh avMesh; if (useReconNative.value()){ flirtmats.open(flirtmatsname.value().c_str()); for (unsigned int i =0; i>stemp; flirtmatnames.push_back(stemp); ///inversion of flirtmatrix is handled in shape model function when a string is input } //Reconstruct in native space of the image (it recons the mni then applies flirt matrix) MeshVerts=recon_meshesNative( mname, bvars, CVmodelMeanMesh, modelMeanMesh,subjectnames, vec_fmats, vMeshes, avMesh); cout<<"done recon"< vnorm; if (useNorm.value()){ ifstream fnorm; fnorm.open(normname.value().c_str()); for (int subject=0;subject>temp; vnorm.push_back(temp); } } Matrix Volumes(target.Nrows(),1); //this is only used for GLM ofstream fvol_all; fvol_all.open((outname.value()+".vols").c_str()); for (int subject=0;subjectgetLabel(0),bounds); stringstream sstemp; string outnamess; sstemp<>outnamess; float voltemp; volume segimB; segimB=segim; voltemp=boundaryCorr(&segim, &t1im,model1->getLabel(0), thresh.value(),bounds); stringstream sstemp2; sstemp2<getLabel(0); string lbst; sstemp2>>lbst; segim.setAuxFile("MGH-Subcortical"); // for automatic colormap save_volume(segim,subjectnames.at(subject)+"FIRSTbcorr_lb"+lbst); fvol_all<>evnum; for (int i=0;i volscalar; int nverts=MeshVerts.Nrows()/3; if (!surfaceVAout.value()) { // do not output on the surface, instead do the new default of outputting a volume with the scalar normal dot product values (for use with randomise) volume refim; if (useReconMNI.value()) { read_volume(refim,string(getenv("FSLDIR")) + "/data/standard/MNI152_T1_1mm"); } else { read_volume(refim,string(getenv("FSLDIR")) + "/data/standard/MNI152_T1_1mm"); } volume maskvol(refim); maskvol=0.0f; volume4D volnormals; if (debug.value()) { volnormals.addvolume(maskvol); volnormals.addvolume(maskvol); volnormals.addvolume(maskvol); } Matrix avCoords; avCoords=mean(MeshVerts,2); // form the average coordinate location across the whole group for (int m=1; m<=MeshVerts.Nrows(); m+=3) { // vertex number (times 3) float xav=avCoords(m,1); float yav=avCoords(m+1,1); float zav=avCoords(m+2,1); // convert to voxel coordinates int xvav=MISCMATHS::round(xav/refim.xdim()), yvav=MISCMATHS::round(yav/refim.ydim()), zvav=MISCMATHS::round(zav/refim.zdim()); for (int n=1; n<=NumSubjects; n++) { // subject number int vnum=(m+2)/3; // careful to make this one for first vertex float dotprod=0.0; // convert to voxel coords (from FSL-style mm coords, which is what I assume everything is in internally - MJ) float xcoord=MeshVerts(m,n); float ycoord=MeshVerts(m+1,n); float zcoord=MeshVerts(m+2,n); // project coordinate difference onto normal // NB: normals are unit length here (based on local_normal() returning this in recon_* functions) dotprod += avNormals(m,1)*(xcoord-xav); dotprod += avNormals(m+1,1)*(ycoord-yav); dotprod += avNormals(m+2,1)*(zcoord-zav); ScalarVals(vnum,n)=dotprod; if (debug.value()) { volnormals(xvav,yvav,zvav,0)=avNormals(m,1); volnormals(xvav,yvav,zvav,1)=avNormals(m+1,1); volnormals(xvav,yvav,zvav,2)=avNormals(m+2,1); } } } for (int n=1; n<=NumSubjects; n++) { volscalar.addvolume(draw_scalar_mesh(refim,avMesh,ScalarVals.Column(n))); } save_volume4D(volscalar,outname.value()); maskvol=variancevol(volscalar); maskvol.binarise(1e-8); save_volume(maskvol,fslbasename(outname.value())+"_mask"); if (debug.value()) { save_volume4D(volnormals,fslbasename(outname.value())+"_normals"); } } // save vertex Matrix if requested (format is all x-coords, then all y-coords, then all z-coords in each column - one subject per row) if (saveVertices.set()) { Matrix ReshapedVerts(MeshVerts.Nrows(),MeshVerts.Ncols()); int newm=1; for (int m=1; m<=ReshapedVerts.Nrows(); m+=3) { // vertex number (times 3) for (int n=1; n<=ReshapedVerts.Ncols(); n++) { // subject number ReshapedVerts(newm,n)=MeshVerts(m,n); ReshapedVerts(newm+nverts,n)=MeshVerts(m+1,n); ReshapedVerts(newm+2*nverts,n)=MeshVerts(m+2,n); } newm++; } write_ascii_matrix(fslbasename(saveVertices.value())+"_mat.txt",ReshapedVerts); volume4D vertices(ReshapedVerts.Nrows()/3,3,1,ReshapedVerts.Ncols()); vertices.setmatrix(ReshapedVerts.t()); save_volume4D(vertices,saveVertices.value()); } if (!surfaceVAout.value()) { return; // finish here if not outputting things to the surface (with the MVGLM tests) } // Note: "target" is the design matrix (!) ColumnVector CVnorm(target.Nrows()); // if chosen can include a normalization EV (i.e. control for size) ...useful for vertex shape statistics if (useNorm.value()){ ifstream normIn; float normtemp; normIn.open(normname.value().c_str()); for (int subject=0;subject>normtemp; CVnorm.element(subject)=normtemp; } target=target | CVnorm ; } //****************END DEMEAN DESIGN MATRIX AND ADD ONE COLUMNS*********************/ Matrix contrast(target.Ncols()-1,target.Ncols()); int EVmin=1;//ignore mean column first EV to examine //int EVmax=1;//EV to include int EVmax=target.Ncols(); for (int EV=EVmin;EV>evnum; //update average mesh //these vector store tstats to plot on mesh vector meandifx; vector meandify; vector meandifz; Mesh m=vMeshes.at(0);//mesh.at(0) is used to determine topology/number of vertices int count=0; for (vector::iterator i = m._points.begin(); i!=m._points.end(); i++ ) { float meanx1=0,meany1=0,meanz1=0,meanx2=0,meany2=0, meanz2=0; // for (int i=0;i_update_coord = Pt(meanx1,meany1,meanz1); count+=3; } m.update(); setShapeMesh(model1,m); cout<<"set shape Mesh"< scalarsT; //this provides the option to do stats on the vertices //create F test contrast matrix (testing each EV separately) //contrast matrix is the identity matrix minus the EV'th row count=0; for (int j=0;jsetPoints(model1->smean); fout->setPolygons(model1->cells); fout->setScalars(scalarsT); Matrix Mmeandif(meandifx.size(),3); for (unsigned int mj=0; mjsetVectors(Mmeandif); // also save the DOFs Matrix dofvals(2,1); dofvals << dof1 << dof2; fout->addFieldData(dofvals,"FStatDOFs","float"); //save the mesg with vectors fout->save(outname.value()+evnum+".vtk");//,5,0); } } } void do_work_meshToVol(){ cout<<"mesh read0"< ref; volume segim; read_volume(ref,inname.value()); // shapeModel* mesh1 = new shapeModel; //mesh1->setImageParameters(ref.xsize(), ref.ysize(), ref.zsize(), ref.xdim(), ref.ydim(), ref.zdim()); // mesh1->load_vtk(meshname.value(),1); // cout<<"mesh read"<getTranslatedMesh(0); // }else{ // m1=mesh1->getShapeMesh(0); // } int bounds[6]={0,0,0,0,0,0}; int label=meshLabel.value(); segim=make_mask_from_meshInOut(ref,m1,label,bounds); segim.setAuxFile("MGH-Subcortical"); // for automatic colormap save_volume(segim,outname.value()); } void do_work_overlap(){ //this function is working directly on volumes volume gold; volume segim; read_volume(gold,refname.value()); read_volume(segim,inname.value()); overlaps(segim,gold); } void do_work_MVGLM() { // float F=MVGLM_fit(target, MeshVerts.SubMatrix(i+1,i+3,1,MeshVerts.Ncols()).t(),contrast); ifstream targ_in; targ_in.open(designname.value().c_str()); int Nevs=numModes.value(); int k=meshLabel.value(); float ftemp; int count=0; while (targ_in>>ftemp) { count++; } targ_in.close(); int N=count/Nevs ; Matrix target(N,Nevs); Matrix Y(N,k); Matrix contrast(1,Nevs); cout<<"There are "<>ftemp) { target.element(row,col)=ftemp; col++; if (col==Nevs) { col=0; row++; } } cout<<"target "<>ftemp) { Y.element(row,col)=ftemp; col++; if (col==k) { col=0; row++; } } cout<<"Y "<>ftemp) { contrast.element(0,col)=ftemp; col++; } cout<<"contrast "< subjectnames; Matrix bvars; vector vN; Matrix flirtmat(4,4); vector< vector< vector > > fmatv; read_bvars(inname.value(),bvars,subjectnames, vN, pathname.value(),fmatv); vector vars; for (int i=0; iregisterModel(fmatv.at(0)); cout<<"vars "<getDeformedGrid(vars),model1->cells); meshReg(m,fmatv.at(0)); m.save(outname.value(),3); } void do_work_readBvars(const string & filename) { string stemp,modelname,imagename; int Nsubs,Nbvars; ifstream fin; fin.open(filename.c_str()); getline(fin,stemp); fin>>modelname; fin>>stemp>>Nsubs; while (Nsubs!=0) { fin>>imagename>>Nbvars; char blank; fin.read(reinterpret_cast(&blank),sizeof(char)); float bvar; cout<<"BVARS"<(&bvar),sizeof(float)); cout<(&bvar),sizeof(float)); cout< > all_bvars; vector< vector > all_fmats; vector vimages; int count=0; while (flist>>fname) { count++; string stemp,modelname_temp; int Nsubs,Nbvars; ifstream fin; fin.open(fname.c_str()); getline(fin,stemp); fin>>modelname_temp; if (count==1) modelname=modelname_temp; if (strcmp(modelname.c_str(),modelname_temp.c_str())) { cerr<<"Bvars were generated with different models"<>stemp>>Nsubs; fin>>imagename>>Nbvars; vimages.push_back(imagename); char blank; fin.read(reinterpret_cast(&blank),sizeof(char)); float bvar; vector vbvars; for (int i=0;i(&bvar),sizeof(float)); vbvars.push_back(bvar); } all_bvars.push_back(vbvars); vector fmat; for (int i=1;i<=16;i++) { fin.read(reinterpret_cast(&bvar),sizeof(float)); fmat.push_back(bvar); if (verbose.value()){ cout< >::iterator i_bvars=all_bvars.begin(); vector< vector >::iterator i_fmat=all_fmats.begin(); for (vector::iterator i_f=vimages.begin();i_f!=vimages.end(); i_f++,i_bvars++,i_fmat++) { fout<<*i_f<<" "<size()<<" "; for (vector::iterator i_bvars2=i_bvars->begin();i_bvars2!=i_bvars->end(); i_bvars2++ ) fout.write(reinterpret_cast(&(*i_bvars2)),sizeof(*i_bvars2)); for (vector::iterator i_fmat2=i_fmat->begin(); i_fmat2!=i_fmat->end();i_fmat2++) fout.write(reinterpret_cast(&(*i_fmat2)),sizeof(*i_fmat2)); } } int main(int argc,char *argv[]) { Tracer tr("main"); OptionParser options(title, examples); try { // must include all wanted options here (the order determines how // the help message is printed) options.add(inname); options.add(normname); options.add(refname); options.add(pathname); options.add(flirtmatsname); options.add(useScale); options.add(overlap); options.add(meshname); options.add(useNorm); options.add(surfaceVAout); options.add(outname); options.add(thresh); options.add(meshLabel); options.add(usebvars); options.add(useReconMNI); options.add(vertexAnalysis); options.add(useReconNative); options.add(useRigidAlign); options.add(designname); options.add(reconMeshFromBvars); options.add(readBvars); options.add(meshToVol); options.add(centreOrigin); options.add(saveVertices); options.add(verbose); options.add(usePCAfilter); options.add(numModes); options.add(singleBoundaryCorr); options.add(doMVGLM); options.add(concatBvars); options.add(debug); options.add(help); nonoptarg = options.parse_command_line(argc, argv); // line below stops the program if the help was requested or // a compulsory option was not set if ( (help.value()) || (!options.check_compulsory_arguments(true)) ) { options.usage(); exit(EXIT_FAILURE); } // Call the local functions if (usebvars.value()){ do_work_bvars(); // }else if (imfrombvars.value()){ // do_work_bvarsToVols(); }else if (meshToVol.value()){ do_work_meshToVol(); }else if(singleBoundaryCorr.value()){ do_work_SingleClean(); }else if (overlap.value()){ do_work_overlap(); }else if (doMVGLM.value()){ do_work_MVGLM(); }else if (reconMeshFromBvars.value()) { do_work_reconMesh(); }else if (readBvars.value()) { do_work_readBvars(inname.value()); }else if (concatBvars.value()) { do_work_concatBvars(inname.value(), outname.value()); } } catch(X_OptionError& e) { options.usage(); cerr << endl << e.what() << endl; exit(EXIT_FAILURE); } catch(std::exception &e) { cerr << e.what() << endl; } return 0;// do_work(argc,argv); }