From 33445e6dad1a7881487034ab467d5b19249e0fa9 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Tue, 5 Oct 2021 16:26:26 +0100 Subject: [PATCH 1/2] Reformatting with clang-format --- src/DiscreteOpt/DiscreteCostFunction.h | 554 ++++--- src/DiscreteOpt/DiscreteGroupCostFunction.h | 78 +- src/DiscreteOpt/DiscreteGroupModel.h | 117 +- src/DiscreteOpt/DiscreteModel.h | 584 ++++--- src/DiscreteOpt/similarities.cc | 1385 +++++++++-------- src/DiscreteOpt/similarities.h | 634 ++++---- src/MSM/calculatevertexwisecorr.cc | 185 ++- src/MSM/estimate_curvature.cc | 212 ++- src/MSM/estimate_metric_distortion.cc | 165 +- src/MSM/estimate_strains.cc | 192 ++- src/MSM/intensity_normalise.cc | 151 +- .../minimise_anat-to-sphere_distortions.cc | 418 ++--- src/MSM/msm.cc | 175 ++- src/MSM/msmGOptions.h | 280 ++-- src/MSM/msmOptions.h | 364 +++-- src/MSM/msm_group.cc | 49 +- src/MSM/msm_makeicos.cc | 47 +- src/MSM/msm_metric_average.cc | 636 ++++---- src/MSM/msm_metric_sim.cc | 232 ++- src/MSM/msm_metricmath.cc | 701 +++++---- src/MSM/msm_surface_average.cc | 215 ++- src/MSM/msmapplywarp.cc | 359 ++--- src/MSM/msmresample.cc | 429 +++-- src/MSM/msmresamplemesh.cc | 164 +- src/MSM/msmresamplemetric.cc | 457 +++--- src/MSM/simulatediscreteregMR.cc | 465 +++--- src/MSM/surfconvert.cc | 118 +- src/MSMRegLib/ContinuosOpt.cc | 495 +++--- src/MSMRegLib/ContinuosOpt.h | 207 +-- src/MSMRegLib/Fusion.h | 183 +-- src/MSMRegLib/groupmeshreg.cc | 367 ++--- src/MSMRegLib/groupmeshreg.h | 69 +- src/MSMRegLib/meshmodify.cc | 918 ++++++----- src/MSMRegLib/meshmodify.h | 279 ++-- src/MSMRegLib/meshreg.cc | 971 ++++++------ src/MSMRegLib/meshreg.h | 114 +- 36 files changed, 6655 insertions(+), 6314 deletions(-) diff --git a/src/DiscreteOpt/DiscreteCostFunction.h b/src/DiscreteOpt/DiscreteCostFunction.h index ea795f1..d9aa536 100644 --- a/src/DiscreteOpt/DiscreteCostFunction.h +++ b/src/DiscreteOpt/DiscreteCostFunction.h @@ -5,21 +5,19 @@ Copyright (C) 2012 University of Oxford */ /* CCOPYRIGHT */ -#include #include "similarities.h" +#include -#include #include +#include -typedef map > myparam; -typedef pair > parameterPair; - +typedef map> myparam; +typedef pair> parameterPair; -namespace DISCRETEOPT{ +namespace DISCRETEOPT { - class DiscreteCostFunction - { - public: +class DiscreteCostFunction { +public: //typedef std::vector< std::vector > PairwiseMemory; //typedef std::vector< std::vector > TripletMemory; /** @@ -27,7 +25,6 @@ namespace DISCRETEOPT{ */ DiscreteCostFunction(); - /** * Destructor. */ @@ -76,27 +73,27 @@ namespace DISCRETEOPT{ /** * Computes the unary costs look-up table. */ - virtual void computeUnaryCosts(){}; + virtual void computeUnaryCosts() {}; /** * Computes the unary potential for a the given node */ - virtual double computeUnaryCost(int node, int label){ return 0; }; + virtual double computeUnaryCost(int node, int label) { return 0; }; /** * Computes the pairwise costs look-up table. */ - virtual void computePairwiseCosts(const int *pairs){}; + virtual void computePairwiseCosts(const int* pairs) {}; /** * Computes the pairwise potential for a the given pair and labels. */ - virtual double computePairwiseCost(int pair, int labelA, int labelB){ return 0; }; + virtual double computePairwiseCost(int pair, int labelA, int labelB) { return 0; }; /** * Initializes the pair weights with given weights. If no weights are provided, all are set to one. */ - virtual void initPairWeights(const double *weights = 0); + virtual void initPairWeights(const double* weights = 0); /** * Computes the triplet costs look-up table. @@ -113,7 +110,6 @@ namespace DISCRETEOPT{ */ ///virtual void initTripletWeights(const double *weights = 0); - /** * Computes the quartet costs look-up table. */ @@ -124,7 +120,6 @@ namespace DISCRETEOPT{ */ virtual double computeQuartetCost(int quartet, int labelA, int labelB, int labelC, int labelD) { return 0; } - /** * Evaluates the total cost for the zero labeling. */ @@ -133,27 +128,27 @@ namespace DISCRETEOPT{ /** * Evaluates the total cost for the given labeling. */ - virtual double evaluateTotalCostSum(const int *labeling, const int *pairs, const int *triplets = 0,const int *quartets = 0); + virtual double evaluateTotalCostSum(const int* labeling, const int* pairs, const int* triplets = 0, const int* quartets = 0); /** * Evaluates the sum of unary costs for a given labeling. */ - double evaluateUnaryCostSum(const int *labeling); + double evaluateUnaryCostSum(const int* labeling); /** * Evaluates the sum of pairwise costs for a given labeling. */ - double evaluatePairwiseCostSum(const int *labeling, const int *pairs); + double evaluatePairwiseCostSum(const int* labeling, const int* pairs); /** * Evaluates the sum of triplet costs for a given labeling. */ - double evaluateTripletCostSum(const int *labeling, const int *triplets); + double evaluateTripletCostSum(const int* labeling, const int* triplets); /** * Evaluates the sum of quartet costs for a given labeling. */ - double evaluateQuartetCostSum(const int *labeling, const int *quartets); + double evaluateQuartetCostSum(const int* labeling, const int* quartets); /** * Enables the memory for the pairwise potentials computation. @@ -165,11 +160,11 @@ namespace DISCRETEOPT{ */ // void enableTripletMemory(); - virtual void set_parameters(myparam & )=0; + virtual void set_parameters(myparam&) = 0; - virtual void report(){}; + virtual void report() {}; - protected: +protected: /** * Initializes the cost function. * \param numNodes Number of nodes. @@ -177,103 +172,112 @@ namespace DISCRETEOPT{ * \param numPairs Number of pairs. * \param numTriplets Number of triplets. */ - void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0,int numQuartets = 0); - - int m_num_nodes; ///< Number of nodes. - int m_num_labels; ///< Number of labels. - int m_num_pairs; ///< Number of pairs. - int m_num_triplets; ///< Number of triplets. - int m_num_quartets; ///< Number of quartets. + void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); + int m_num_nodes; ///< Number of nodes. + int m_num_labels; ///< Number of labels. + int m_num_pairs; ///< Number of pairs. + int m_num_triplets; ///< Number of triplets. + int m_num_quartets; ///< Number of quartets. - double *unarycosts; ///< Unary potentials look-up table. - double *paircosts; ///< Pairwise potentials look-up table. + double* unarycosts; ///< Unary potentials look-up table. + double* paircosts; ///< Pairwise potentials look-up table. // double *tripletcosts; ///< Triplet potentials look-up table. // double *quartetcosts; ///< Quartet potentials look-up table. ///(NOT USED!!) - double *pairweights; ///< Weightings for the pairwise potentials. + double* pairweights; ///< Weightings for the pairwise potentials. //double *tripletweights; ///< Weightings for the triplet potentials. // - int *_pairs; - int *_triplets; - int *_quartets; - int *labels; ///< Labeling array. + int* _pairs; + int* _triplets; + int* _quartets; + int* labels; ///< Labeling array. - float _reglambda; // scaling parameter for regulariser + float _reglambda; // scaling parameter for regulariser bool _debug; - bool _verbosity; + bool _verbosity; bool _concat; string _outdir; string _matlabpath; -//bool write; + //bool write; //PairwiseMemory m_paircosts_memory; ///< Pairwise potentials memory to avoid re-computations. //TripletMemory m_tripletcosts_memory; ///< Triplet potentials memory to avoid re-computations. //bool m_is_memory; ///< Indicates whether the pairwise potentials memory is enabled. //bool m_is_memory_triplets; ///< Indicates whether the triplet potentials memory is enabled. - }; +}; - /// should be able to implement affine spherical registration using discrete labels represent fixed rotations - class DummyCostFunction: public DiscreteCostFunction - { - public: - DummyCostFunction(){m_num_labels=2;}; +/// should be able to implement affine spherical registration using discrete labels represent fixed rotations +class DummyCostFunction : public DiscreteCostFunction { +public: + DummyCostFunction() { m_num_labels = 2; }; - void setUnaryCost(int node, double cost0, double cost1){ + void setUnaryCost(int node, double cost0, double cost1) + { - unaryenergies.insert(pair >(node, vector())); - unaryenergies[node].push_back(cost0); - unaryenergies[node].push_back(cost1); + unaryenergies.insert(pair>(node, vector())); + unaryenergies[node].push_back(cost0); + unaryenergies[node].push_back(cost1); } - void setPairwiseCost(int ind, double E00, double E01, double E10, double E11){ - pairenergies.insert(pair >(ind, vector())); - pairenergies[ind].push_back(E00); - pairenergies[ind].push_back(E01); - pairenergies[ind].push_back(E01); - pairenergies[ind].push_back(E11); + void setPairwiseCost(int ind, double E00, double E01, double E10, double E11) + { + pairenergies.insert(pair>(ind, vector())); + pairenergies[ind].push_back(E00); + pairenergies[ind].push_back(E01); + pairenergies[ind].push_back(E01); + pairenergies[ind].push_back(E11); } - double computePairwiseCost(int pair, int labelA, int labelB){ - double cost; - if(labelA==0 && labelB==0) - cost=pairenergies[pair][0]; - else if (labelA==0 && labelB==1) - cost=pairenergies[pair][1]; - else if (labelA==1 && labelB==0) - cost=pairenergies[pair][2]; - else - cost=pairenergies[pair][3]; - // cout << pair << " " << labelA << " " << labelB << " computePairwiseCost " << cost << endl; - return cost; + double computePairwiseCost(int pair, int labelA, int labelB) + { + double cost; + if (labelA == 0 && labelB == 0) + cost = pairenergies[pair][0]; + else if (labelA == 0 && labelB == 1) + cost = pairenergies[pair][1]; + else if (labelA == 1 && labelB == 0) + cost = pairenergies[pair][2]; + else + cost = pairenergies[pair][3]; + // cout << pair << " " << labelA << " " << labelB << " computePairwiseCost " << cost << endl; + return cost; } - void convertenergies(int numNodes,int numPairs, int numLabels){ - m_num_nodes=numNodes; m_num_labels=numLabels; m_num_pairs=numPairs; - if (unarycosts){ delete [] unarycosts; } - unarycosts = new double[numNodes*numLabels]; - for(int i=0;i > unaryenergies; /// maps of nodes xlabels x vals - map > pairenergies; - }; + void set_parameters(myparam&) {}; + +protected: + map> unaryenergies; /// maps of nodes xlabels x vals + map> pairenergies; +}; - class SRegDiscreteCostFunction: public DiscreteCostFunction - { +class SRegDiscreteCostFunction : public DiscreteCostFunction { - public: +public: // // Constructor. // @@ -281,85 +285,128 @@ namespace DISCRETEOPT{ ///////////////////// VARIABLE ASSIGNMENT ////////////////////////// // data input and reference mesh, plus low resolution control point grid - virtual void set_meshes(const NEWMESH::newmesh & target,const NEWMESH::newmesh & source, const NEWMESH::newmesh & GRID, int num=1){_TARGET=target; _SOURCE=source; _ORIG=source; _CPgrid=GRID; _oCPgrid=GRID;} - void set_meshes(const NEWMESH::newmesh & target,const NEWMESH::newmesh & source){_TARGET=target; _SOURCE=source;}; - - void set_anatomical(const NEWMESH::newmesh &targetS,const NEWMESH::newmesh &targetA,const NEWMESH::newmesh & sourceS,const NEWMESH::newmesh & sourceA){_TARGEThi=targetS; _aTARGET=targetA;_aICO=sourceS, _aSOURCE=sourceA;} - void set_anatomical_neighbourhood(const vector > & weights, const vector > neighbourhood){_ANATbaryweights=weights; NEARESTFACES=neighbourhood; } + virtual void set_meshes(const NEWMESH::newmesh& target, const NEWMESH::newmesh& source, const NEWMESH::newmesh& GRID, int num = 1) + { + _TARGET = target; + _SOURCE = source; + _ORIG = source; + _CPgrid = GRID; + _oCPgrid = GRID; + } + void set_meshes(const NEWMESH::newmesh& target, const NEWMESH::newmesh& source) + { + _TARGET = target; + _SOURCE = source; + }; + + void set_anatomical(const NEWMESH::newmesh& targetS, const NEWMESH::newmesh& targetA, const NEWMESH::newmesh& sourceS, const NEWMESH::newmesh& sourceA) + { + _TARGEThi = targetS; + _aTARGET = targetA; + _aICO = sourceS, _aSOURCE = sourceA; + } + void set_anatomical_neighbourhood(const vector>& weights, const vector> neighbourhood) + { + _ANATbaryweights = weights; + NEARESTFACES = neighbourhood; + } ///// holds data for source and target mesh, used for look up during similarity estimation newmesh project_anatomical(); - void set_featurespace(const boost::shared_ptr &features, bool _concatenate=false){FEAT=features; _concat=_concatenate;} + void set_featurespace(const boost::shared_ptr& features, bool _concatenate = false) + { + FEAT = features; + _concat = _concatenate; + } void initialize_regulariser(); - void set_initial_angles(const vector > angles){ + void set_initial_angles(const vector> angles) + { - double meanang=0; - for (size_t i = 0; i < angles.size(); i++) - { - for (size_t j = 0; j < angles[i].size(); j++) - { - meanang+=angles[i][j]; - } - } - _MEANANGLE=meanang/(3.0*angles.size()); + double meanang = 0; + for (size_t i = 0; i < angles.size(); i++) { + for (size_t j = 0; j < angles[i].size(); j++) { + meanang += angles[i][j]; + } + } + _MEANANGLE = meanang / (3.0 * angles.size()); } - virtual void set_matlab_path(string s){_matlabpath=s;} + virtual void set_matlab_path(string s) { _matlabpath = s; } /// - void set_dataaffintyweighting(const Matrix &HRWeight){_HIGHREScfweight=HRWeight;} + void set_dataaffintyweighting(const Matrix& HRWeight) { _HIGHREScfweight = HRWeight; } //// holds neighbourhood information - virtual void set_relations(const boost::shared_ptr &CONTROL,const boost::shared_ptr &TARG){ _controlrel=CONTROL; _targetrel=TARG; - _sourcerel=_controlrel->invert_relations(_CPgrid,_SOURCE); } + virtual void set_relations(const boost::shared_ptr& CONTROL, const boost::shared_ptr& TARG) + { + _controlrel = CONTROL; + _targetrel = TARG; + _sourcerel = _controlrel->invert_relations(_CPgrid, _SOURCE); + } - void set_parameters(myparam & ); + void set_parameters(myparam&); //MAXSEP is control grid vertex spacings - virtual void set_spacings(const ColumnVector &spacings, const double MAX, int num=0){MAXSEP=spacings;MVDmax=MAX;} + virtual void set_spacings(const ColumnVector& spacings, const double MAX, int num = 0) + { + MAXSEP = spacings; + MVDmax = MAX; + } - void debug(){_debug=true;} // for debuging + void debug() { _debug = true; } // for debuging /// label list changes between iterations for spherical optimisation (barycentres and vertices of regular sampling grid) - void set_labels(const vector labellist, const vector ROT=vector()){_labels=labellist; ROTATIONS= boost::shared_ptr >(new vector (ROT)); } // ROTATION MATRIX MAY ONLY BE REQUIRED FOR NON LINEAR FRAMEWORK + void set_labels(const vector labellist, const vector ROT = vector()) + { + _labels = labellist; + ROTATIONS = boost::shared_ptr>(new vector(ROT)); + } // ROTATION MATRIX MAY ONLY BE REQUIRED FOR NON LINEAR FRAMEWORK - inline void set_iter(int iter) {_iter=iter;} - virtual void reset_source(const NEWMESH::newmesh & source, int num=0){_SOURCE=source; } + inline void set_iter(int iter) { _iter = iter; } + virtual void reset_source(const NEWMESH::newmesh& source, int num = 0) { _SOURCE = source; } - void reset_anatomical(const string &, const int &); + void reset_anatomical(const string&, const int&); //void set_pairtrIDs(const vector &pair_trIDs){ _trIDs=pair_trIDs;} - virtual void reset_CPgrid(const NEWMESH::newmesh & grid, int num=0){_CPgrid=grid;} + virtual void reset_CPgrid(const NEWMESH::newmesh& grid, int num = 0) { _CPgrid = grid; } //////////////// GENERIC HELPER FUNCTIONS - bool within_controlpt_range(const int &CPindex, const int &sourceindex){ - double dist=0.0; - if(within_controlpt_range(CPindex,sourceindex,dist))return true; - else return false; - + bool within_controlpt_range(const int& CPindex, const int& sourceindex) + { + double dist = 0.0; + if (within_controlpt_range(CPindex, sourceindex, dist)) + return true; + else + return false; } - bool within_controlpt_range(const int &CPindex, const int &sourceindex, double & dist){ - Pt CP=_CPgrid.get_coord(CPindex); - dist= 2*RAD*asin((CP-_SOURCE.get_coord(sourceindex)).norm()/(2*RAD)); - if(dist<_controlptrange*MAXSEP(CPindex+1))return true; - else return false; - + bool within_controlpt_range(const int& CPindex, const int& sourceindex, double& dist) + { + Pt CP = _CPgrid.get_coord(CPindex); + dist = 2 * RAD * asin((CP - _SOURCE.get_coord(sourceindex)).norm() / (2 * RAD)); + if (dist < _controlptrange * MAXSEP(CPindex + 1)) + return true; + else + return false; } - virtual void initialize(int numNodes,int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); + virtual void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); - virtual void resample_target_data(const Pt &, const Pt &, const Pt &, const Pt &, const int &, const int &, const int &, int &){}; + virtual void resample_target_data(const Pt&, const Pt&, const Pt&, const Pt&, const int&, const int&, const int&, int&) {}; - virtual void resample_weights(){}; - virtual void get_source_data(){}; - virtual void reset_target_data(int){}; - virtual double triplet_likelihood(const int &,const int &,const int &,const int &,const Pt &,const Pt &,const Pt &){ return 0; }; + virtual void resample_weights() {}; + virtual void get_source_data() {}; + virtual void reset_target_data(int) {}; + virtual double triplet_likelihood(const int&, const int&, const int&, const int&, const Pt&, const Pt&, const Pt&) { return 0; }; - NEWMESH::newmesh get_SOURCE(){return _SOURCE;} - void report(){ if(_debug) cout << " sumlikelihood " << sumlikelihood << " sumregcost " << sumregcost < > _sourceinrange; - vector > NEARESTFACES; + vector> _sourceinrange; + vector> NEARESTFACES; //////////////////////// FEATURE SET ////////////////// boost::shared_ptr FEAT; /// holds data sparsesimkernel sim; // similarity object /////////////////// LABELLING PARAMETERS//////// vector _labels; - boost::shared_ptr > ROTATIONS; // rotates label set onto each control point + boost::shared_ptr> ROTATIONS; // rotates label set onto each control point double MVDmax; // max distance between CPs double anatMVD; @@ -415,23 +461,22 @@ namespace DISCRETEOPT{ int _simmeasure; int _RES; int _aRES; - int _rmode; + int _rmode; int _iter; int _threads; float _k_exp; - vector > _sourcedata; - vector > _targetdata; - vector > _weights; + vector> _sourcedata; + vector> _targetdata; + vector> _weights; - vector > _ANATbaryweights; + vector> _ANATbaryweights; resampler R; double MAXstrain; double strain95; - }; - +}; - /* +/* class AffineSRegDiscreteCostFunction: public SRegDiscreteCostFunction { public: @@ -454,11 +499,9 @@ namespace DISCRETEOPT{ }; */ - class NonLinearSRegDiscreteCostFunction: public SRegDiscreteCostFunction - { - - protected: +class NonLinearSRegDiscreteCostFunction : public SRegDiscreteCostFunction { +protected: ////////////// REGULARISER OPTIONS ///////////////////////// float _maxdist; float _expscaling; @@ -476,31 +519,31 @@ namespace DISCRETEOPT{ vector ROTATE2LABEL; vector _ORIGpositions; - public: +public: // // Constructor. // NonLinearSRegDiscreteCostFunction(); - virtual void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0,int numQuartets = 0); // quartets not used yet so no code for them below + virtual void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet so no code for them below - void set_parameters(myparam & ); + void set_parameters(myparam&); //// compute unary costs void computeUnaryCosts(); //// compute pairwise costs double computePairwiseCost(int pair, int labelA, int labelB); - void computePairwiseCosts(const int *pairs) ; + void computePairwiseCosts(const int* pairs); //compute triplet costs // void computeTripletCosts(); double computeTripletCost(int triplet, int labelA, int labelB, int labelC); - virtual double triplet_likelihood(const int &,const int &,const int &,const int &,const Pt &,const Pt &,const Pt &){ return 0;}; - /** + virtual double triplet_likelihood(const int&, const int&, const int&, const int&, const Pt&, const Pt&, const Pt&) { return 0; }; + /** * Computes the quartet costs look-up table. */ - // void computeQuartetCosts() {}; + // void computeQuartetCosts() {}; /** * Computes the quartet potential for a the given triplet and labels. @@ -508,153 +551,152 @@ namespace DISCRETEOPT{ double computeQuartetCost(int quartet, int labelA, int labelB, int labelC, int labelD) { return 0; } // for transforming anatomy - Triangle deform_anatomy(const int&,const int&,map & ,map &, map &); - + Triangle deform_anatomy(const int&, const int&, map&, map&, map&); void resample_weights(); - void get_target_data(const int &,const Matrix &); - - void get_target_data(const int&,const Pt&,const Pt&,const Pt&); + void get_target_data(const int&, const Matrix&); + void get_target_data(const int&, const Pt&, const Pt&, const Pt&); + virtual void get_data_index(const int& controlpoint, const int& sourcepoint, int& ind) {}; // data is held in 2D vectors in each case, but for univariate case data is controlpointsxfeatures and for multivariate its sourcepointsxfeatures. This function determines the correct index for rows +}; - virtual void get_data_index(const int & controlpoint, const int & sourcepoint, int & ind){}; // data is held in 2D vectors in each case, but for univariate case data is controlpointsxfeatures and for multivariate its sourcepointsxfeatures. This function determines the correct index for rows - }; - - class UnivariateNonLinearSRegDiscreteCostFunction: public NonLinearSRegDiscreteCostFunction - { - public: +class UnivariateNonLinearSRegDiscreteCostFunction : public NonLinearSRegDiscreteCostFunction { +public: // // Constructor. // - UnivariateNonLinearSRegDiscreteCostFunction(){}; - virtual void initialize(int numNodes, int numLabels, int numPairs,int numTriplets = 0, int numQuartets = 0); // quartets not used yet + UnivariateNonLinearSRegDiscreteCostFunction() {}; + virtual void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet virtual void get_source_data(); double computeUnaryCost(int node, int label); // void resample_source_data(const int &); - void reset_target_data(int node){ _targetdata[node-1].clear();} - virtual void resample_target_data(const Pt &, const Pt &, const Pt &, const Pt &, const int &, const int &, const int &, int &); - void get_data_index(const int & controlpoint, const int & sourcepoint, int &ind){ind=controlpoint;} - - }; + void reset_target_data(int node) { _targetdata[node - 1].clear(); } + virtual void resample_target_data(const Pt&, const Pt&, const Pt&, const Pt&, const int&, const int&, const int&, int&); + void get_data_index(const int& controlpoint, const int& sourcepoint, int& ind) { ind = controlpoint; } +}; - class MultivariateNonLinearSRegDiscreteCostFunction: public NonLinearSRegDiscreteCostFunction - { - public: +class MultivariateNonLinearSRegDiscreteCostFunction : public NonLinearSRegDiscreteCostFunction { +public: // // Constructor. // - MultivariateNonLinearSRegDiscreteCostFunction(){}; - virtual void initialize(int numNodes,int numLabels, int numPairs, int numTriplets = 0,int numQuartets = 0); // quartets not used yet + MultivariateNonLinearSRegDiscreteCostFunction() {}; + virtual void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet void get_source_data(); double computeUnaryCost(int node, int label); // void resample_source_data(const int & sourcept); - void reset_target_data(int node){ for(unsigned int i=0;i<_sourceinrange[node-1].size();i++) { _targetdata[_sourceinrange[node-1][i]-1].clear();}} /// *****NOT THREAD SAFE ******** - - virtual void resample_target_data(const Pt &, const Pt &, const Pt &, const Pt &, const int &, const int &, const int &, int &); - void get_data_index(const int & controlpoint, const int & sourcepoint, int & ind){if(sourcepoint > (int) _sourcedata.size()){cout << "vector index too high " << endl;exit(1);} - ind=sourcepoint;} - - }; + void reset_target_data(int node) + { + for (unsigned int i = 0; i < _sourceinrange[node - 1].size(); i++) { + _targetdata[_sourceinrange[node - 1][i] - 1].clear(); + } + } /// *****NOT THREAD SAFE ******** + + virtual void resample_target_data(const Pt&, const Pt&, const Pt&, const Pt&, const int&, const int&, const int&, int&); + void get_data_index(const int& controlpoint, const int& sourcepoint, int& ind) + { + if (sourcepoint > (int)_sourcedata.size()) { + cout << "vector index too high " << endl; + exit(1); + } + ind = sourcepoint; + } +}; - class alphaMINonLinearSRegDiscreteCostFunction: public MultivariateNonLinearSRegDiscreteCostFunction - { - public: +class alphaMINonLinearSRegDiscreteCostFunction : public MultivariateNonLinearSRegDiscreteCostFunction { +public: // // Constructor. // - alphaMINonLinearSRegDiscreteCostFunction(){}; + alphaMINonLinearSRegDiscreteCostFunction() {}; // void resample_source_data(const int & sourcept); +}; - }; - - class HOUnivariateNonLinearSRegDiscreteCostFunction: public UnivariateNonLinearSRegDiscreteCostFunction - { - public: +class HOUnivariateNonLinearSRegDiscreteCostFunction : public UnivariateNonLinearSRegDiscreteCostFunction { +public: // // Constructor. // - HOUnivariateNonLinearSRegDiscreteCostFunction(){}; - void initialize(int numNodes,int numLabels, int numPairs,int numTriplets = 0, int numQuartets = 0); // quartets not used yet + HOUnivariateNonLinearSRegDiscreteCostFunction() {}; + void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet void get_source_data(); - double computeUnaryCost(int node, int label){return 0;}; - - void set_relations(const boost::shared_ptr &CONTROL,const boost::shared_ptr &TARG){_controlrel=CONTROL; _targetrel=TARG; - _sourcerel=_controlrel->invert_relationsTR(_CPgrid,_SOURCE); } - double triplet_likelihood(const int &,const int &,const int &,const int &,const Pt &,const Pt &,const Pt &); + double computeUnaryCost(int node, int label) { return 0; }; - }; + void set_relations(const boost::shared_ptr& CONTROL, const boost::shared_ptr& TARG) + { + _controlrel = CONTROL; + _targetrel = TARG; + _sourcerel = _controlrel->invert_relationsTR(_CPgrid, _SOURCE); + } + double triplet_likelihood(const int&, const int&, const int&, const int&, const Pt&, const Pt&, const Pt&); +}; - class HOMultivariateNonLinearSRegDiscreteCostFunction: public MultivariateNonLinearSRegDiscreteCostFunction - { - public: +class HOMultivariateNonLinearSRegDiscreteCostFunction : public MultivariateNonLinearSRegDiscreteCostFunction { +public: // // Constructor. // - HOMultivariateNonLinearSRegDiscreteCostFunction(){}; - void initialize(int numNodes,int numLabels, int numPairs,int numTriplets = 0, int numQuartets = 0); // quartets not used yet + HOMultivariateNonLinearSRegDiscreteCostFunction() {}; + void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet void get_source_data(); - double computeUnaryCost(int node, int label){return 0;}; - - void set_relations(const boost::shared_ptr &CONTROL,const boost::shared_ptr &TARG){_controlrel=CONTROL; _targetrel=TARG; - _sourcerel=_controlrel->invert_relationsTR(_CPgrid,_SOURCE); } - - double triplet_likelihood(const int &,const int &,const int &,const int &,const Pt &,const Pt &,const Pt &); - }; - + double computeUnaryCost(int node, int label) { return 0; }; + void set_relations(const boost::shared_ptr& CONTROL, const boost::shared_ptr& TARG) + { + _controlrel = CONTROL; + _targetrel = TARG; + _sourcerel = _controlrel->invert_relationsTR(_CPgrid, _SOURCE); + } - class RegularisationDiscreteCostFunction: public SRegDiscreteCostFunction - { - protected: + double triplet_likelihood(const int&, const int&, const int&, const int&, const Pt&, const Pt&, const Pt&); +}; - //////////////////////// MESHES ////////////////////// +class RegularisationDiscreteCostFunction : public SRegDiscreteCostFunction { +protected: + //////////////////////// MESHES ////////////////////// // NEWMESH::newmesh _SPHERE; // SOURCE MESH - float _rexp; - - public: - // - // Constructor. - // - RegularisationDiscreteCostFunction(double shear, double bulk, double exp); - - - void initialize(int numNodes,int numLabels, int numPairs,int numTriplets = 0, int numQuartets = 0); // quartets not used yet - //void reset_CPgrid(const NEWMESH::newmesh & grid, int num=0){_SPHERE=grid;} - double computeTripletRegularisation(int triplet, int labelA, int labelB, int labelC); - - }; - - class MetricDistortionDiscreteCostFunction: public RegularisationDiscreteCostFunction - { - - protected: - bool isinitialised; - - public: - // - // Constructor. - // - MetricDistortionDiscreteCostFunction(double shear, double bulk, double exp):RegularisationDiscreteCostFunction(shear, bulk, exp){isinitialised=false;} - + float _rexp; - double computeTripletCost(int triplet, int labelA, int labelB, int labelC){ - if (isinitialised==false) - throw DISCRETEOPTHOCRException("MetricDistortionDiscreteCostFunction::You must supply meshes."); - return computeTripletRegularisation(triplet,labelA, labelB,labelC); +public: + // + // Constructor. + // + RegularisationDiscreteCostFunction(double shear, double bulk, double exp); - } + void initialize(int numNodes, int numLabels, int numPairs, int numTriplets = 0, int numQuartets = 0); // quartets not used yet + //void reset_CPgrid(const NEWMESH::newmesh & grid, int num=0){_SPHERE=grid;} + double computeTripletRegularisation(int triplet, int labelA, int labelB, int labelC); }; +class MetricDistortionDiscreteCostFunction : public RegularisationDiscreteCostFunction { +protected: + bool isinitialised; +public: + // + // Constructor. + // + MetricDistortionDiscreteCostFunction(double shear, double bulk, double exp) + : RegularisationDiscreteCostFunction(shear, bulk, exp) + { + isinitialised = false; + } + double computeTripletCost(int triplet, int labelA, int labelB, int labelC) + { + if (isinitialised == false) + throw DISCRETEOPTHOCRException("MetricDistortionDiscreteCostFunction::You must supply meshes."); + return computeTripletRegularisation(triplet, labelA, labelB, labelC); + } +}; } diff --git a/src/DiscreteOpt/DiscreteGroupCostFunction.h b/src/DiscreteOpt/DiscreteGroupCostFunction.h index 393df7b..2de0f25 100644 --- a/src/DiscreteOpt/DiscreteGroupCostFunction.h +++ b/src/DiscreteOpt/DiscreteGroupCostFunction.h @@ -5,24 +5,22 @@ Copyright (C) 2014 University of Oxford */ /* CCOPYRIGHT */ -#include #include "DiscreteCostFunction.h" +#include //#include -#include #include +#include //#include "tbb/tick_count.h" //using namespace tbb; -typedef map > myparam; -typedef pair > parameterPair; +typedef map> myparam; +typedef pair> parameterPair; +namespace DISCRETEOPTHOCR { -namespace DISCRETEOPTHOCR{ +class GroupDiscreteCostFunction : public SRegDiscreteCostFunction { - class GroupDiscreteCostFunction: public SRegDiscreteCostFunction - { - - public: +public: // // Constructor. // @@ -30,27 +28,29 @@ namespace DISCRETEOPTHOCR{ // ~GroupDiscreteCostFunction(); //// SET UP ////////////////// - void set_parameters(myparam & ); + void set_parameters(myparam&); /// neighbouhood info - void set_relations(const boost::shared_ptr &CONTROL,const boost::shared_ptr &TARG); + void set_relations(const boost::shared_ptr& CONTROL, const boost::shared_ptr& TARG); void get_spacings(); - void set_meshes(const NEWMESH::newmesh & target,const NEWMESH::newmesh & source, const NEWMESH::newmesh & GRID, int num=1){_TEMPLATE=target; - - _ORIG=source; - num_subjects=num; - VERTICES_PER_SUBJ=GRID.nvertices(); - TRIPLETS_PER_SUBJ=GRID.ntriangles(); - MVD_LR=Calculate_MVD(GRID); - cout << " costfunction set meshes " << num << endl; - for (int i=0;i &); - map resample_onto_template(const int &,const int &,const Pt &, const vector &); - - protected: + void resampler_worker_function(const int&, const int&, const vector&); + map resample_onto_template(const int&, const int&, const Pt&, const vector&); +protected: //////////////////////// MESHES ////////////////////// vector _DATAMESHES; // TARGET MESH vector _CONTROLMESHES; // TARGET MESH newmesh _TEMPLATE; /////////////////////// NEIGHBOURHOOD INFO //////////////////// - vector > _CONTROLRELATIONS; // hold control grid neighbours of each source vertex - vector > _TEMPLATERELATIONS; // hold target grid neighbours of each source vertex - vector > TEMPLATEPTS; + vector> _CONTROLRELATIONS; // hold control grid neighbours of each source vertex + vector> _TEMPLATERELATIONS; // hold target grid neighbours of each source vertex + vector> TEMPLATEPTS; vector SPACINGS; //////////////////////DATA////////////////// - vector RESAMPLEDDATA; - vector > PATCHDATA; + vector RESAMPLEDDATA; + vector> PATCHDATA; //double **L1data; //Engine *eng; /// matlab engine @@ -104,8 +102,6 @@ namespace DISCRETEOPTHOCR{ bool _quadcost; bool _setpairs; - - }; - +}; } diff --git a/src/DiscreteOpt/DiscreteGroupModel.h b/src/DiscreteOpt/DiscreteGroupModel.h index f8460fd..67d4087 100644 --- a/src/DiscreteOpt/DiscreteGroupModel.h +++ b/src/DiscreteOpt/DiscreteGroupModel.h @@ -12,71 +12,83 @@ #include "DiscreteModel.h" #include - +namespace DISCRETEOPTHOCR { -namespace DISCRETEOPTHOCR{ - - - - class GroupDiscreteModel: public SRegDiscreteModel - { - protected: +class GroupDiscreteModel : public SRegDiscreteModel { +protected: vector m_DATAMESHES; // TARGET MESH vector m_CONTROLMESHES; // TARGET MESH - - NEWMESH::newmesh m_TEMPLATE; /// template data grid + + NEWMESH::newmesh m_TEMPLATE; /// template data grid NEWMESH::newmesh m_TEMPLATE_LR; /// template control grid /////////////////////// NEIGHBOURHOOD INFO //////////////////// - boost::shared_ptr m_TEMPLATE_LR_ALL_RELATIONS; /// hold neighbourhood between control grids and to LR target - vector > > BETWEEN_SUBJECT_PAIRS; - vector subjects; - + boost::shared_ptr m_TEMPLATE_LR_ALL_RELATIONS; /// hold neighbourhood between control grids and to LR target + vector>> BETWEEN_SUBJECT_PAIRS; + vector subjects; + int m_num_subjects; int control_grid_size; - public: + +public: /** * Constructor. */ - GroupDiscreteModel(){}; - ~GroupDiscreteModel(){}; - - GroupDiscreteModel(myparam & P){ - m_CPres=2; m_SGres=4; m_simmeasure=2; m_multivariate=false; m_verbosity=false; m_outdir="";m_debug=false; - set_parameters(P); - cout << " create cf group 1 " << endl; - costfct=boost::shared_ptr(new GroupDiscreteCostFunction()); - m_inputrel=boost::shared_ptr(new RELATIONS()); - m_cp_neighbourhood=boost::shared_ptr(new RELATIONS ()); - costfct->set_parameters(P); - + GroupDiscreteModel() {}; + ~GroupDiscreteModel() {}; + + GroupDiscreteModel(myparam& P) + { + m_CPres = 2; + m_SGres = 4; + m_simmeasure = 2; + m_multivariate = false; + m_verbosity = false; + m_outdir = ""; + m_debug = false; + set_parameters(P); + cout << " create cf group 1 " << endl; + costfct = boost::shared_ptr(new GroupDiscreteCostFunction()); + m_inputrel = boost::shared_ptr(new RELATIONS()); + m_cp_neighbourhood = boost::shared_ptr(new RELATIONS()); + costfct->set_parameters(P); }; - void set_meshspace(const NEWMESH::newmesh & target,const NEWMESH::newmesh & source, const int num=1){ m_TEMPLATE=target; - m_DATAMESHES.clear(); - m_num_subjects=num; - for (int i=0;ireset_source(source,num);} - else{throw DISCRETEOPTHOCRException("Discrete Model:: You cannot reset the source mesh withou initialising the discrete costfunction");} + void reset_meshspace(const NEWMESH::newmesh& source, int num = 0) + { + char filename[1000]; + cout << " reset meshspace" << endl; + m_DATAMESHES[num] = source; + //sprintf(filename,"SOURCE_set_up_it%d_res%d_num%d.surf.gii",m_iter, m_CPres,num); m_DATAMESHES[num].save(filename); + if (costfct.get()) { + costfct->reset_source(source, num); + } else { + throw DISCRETEOPTHOCRException("Discrete Model:: You cannot reset the source mesh withou initialising the discrete costfunction"); + } } - - void reset_CPgrid(const NEWMESH::newmesh & grid, int num=0){ - m_CONTROLMESHES[num]=grid; + + void reset_CPgrid(const NEWMESH::newmesh& grid, int num = 0) + { + m_CONTROLMESHES[num] = grid; } - - void warp_CPgrid(NEWMESH::newmesh & START, NEWMESH::newmesh & END, int num=0){ barycentric_mesh_interpolation(m_CONTROLMESHES[num],START,END); unfold(m_CONTROLMESHES[num]); } + void warp_CPgrid(NEWMESH::newmesh& START, NEWMESH::newmesh& END, int num = 0) + { + barycentric_mesh_interpolation(m_CONTROLMESHES[num], START, END); + unfold(m_CONTROLMESHES[num]); + } - void applyLabeling(){applyLabeling(labeling);} ; - void applyLabeling(int *discreteLabeling); + void applyLabeling() { applyLabeling(labeling); }; + void applyLabeling(int* discreteLabeling); void initialize_quartets(); void initialize_pairs(); @@ -85,20 +97,17 @@ namespace DISCRETEOPTHOCR{ void estimate_triplets(); void estimate_quartets(); void estimate_combinations(int, int*); - - void Initialize(const newmesh &); - void Initialize(){}; - void get_rotations(vector &); + void Initialize(const newmesh&); + void Initialize() {}; + void get_rotations(vector&); void setupCostFunction(); //// functions for keeping track of between mesh relationships void get_between_subject_pairs(); void resample_to_template(); - NEWMESH::newmesh get_CPgrid(int num=0){return m_CONTROLMESHES[num];} - - }; - + NEWMESH::newmesh get_CPgrid(int num = 0) { return m_CONTROLMESHES[num]; } +}; } diff --git a/src/DiscreteOpt/DiscreteModel.h b/src/DiscreteOpt/DiscreteModel.h index 4499870..e79ad17 100644 --- a/src/DiscreteOpt/DiscreteModel.h +++ b/src/DiscreteOpt/DiscreteModel.h @@ -8,46 +8,73 @@ #include "DiscreteCostFunction.h" #include +namespace DISCRETEOPT { -namespace DISCRETEOPT{ - - void sort_nodeids(int *, int ); - - class DiscreteModel - { - public: +void sort_nodeids(int*, int); +class DiscreteModel { +public: /** * Constructor. */ - DiscreteModel() - : m_num_nodes(0), m_num_labels(0), m_num_pairs(0), m_num_triplets(0), m_num_quartets(0), m_lambda(0.0), labeling(0), pairs(0), triplets(0), quartets(0) - { - _numthreads=1; - } + DiscreteModel() + : m_num_nodes(0) + , m_num_labels(0) + , m_num_pairs(0) + , m_num_triplets(0) + , m_num_quartets(0) + , m_lambda(0.0) + , labeling(0) + , pairs(0) + , triplets(0) + , quartets(0) + { + _numthreads = 1; + } /** * Constructor. */ - DiscreteModel(myparam P) - : m_num_nodes(0), m_num_labels(0), m_num_pairs(0), m_num_triplets(0), m_num_quartets(0), m_lambda(0.0), labeling(0), pairs(0), triplets(0), quartets(0) - { - _numthreads=1; - } + DiscreteModel(myparam P) + : m_num_nodes(0) + , m_num_labels(0) + , m_num_pairs(0) + , m_num_triplets(0) + , m_num_quartets(0) + , m_lambda(0.0) + , labeling(0) + , pairs(0) + , triplets(0) + , quartets(0) + { + _numthreads = 1; + } //====================================================================================================================// /** * Destructor. */ virtual ~DiscreteModel() - { - if(labeling) { delete[] labeling; labeling = 0; } - if(pairs) { delete[] pairs; pairs = 0; } - if(triplets) { delete[] triplets; triplets = 0; } - if(quartets) { delete[] quartets; quartets= 0; } - - // if(costfct) { delete costfct; costfct = 0; } - } + { + if (labeling) { + delete[] labeling; + labeling = 0; + } + if (pairs) { + delete[] pairs; + pairs = 0; + } + if (triplets) { + delete[] triplets; + triplets = 0; + } + if (quartets) { + delete[] quartets; + quartets = 0; + } + + // if(costfct) { delete costfct; costfct = 0; } + } /** * Sets the weighting between unary and pairwise costs. @@ -59,7 +86,6 @@ namespace DISCRETEOPT{ */ int getNumNodes() const { return m_num_nodes; } - /** * Returns the number of labels. */ @@ -114,28 +140,28 @@ namespace DISCRETEOPT{ /** * Returns the cost function. */ - virtual boost::shared_ptr getCostFunction() =0;// this class is pure virtual + virtual boost::shared_ptr getCostFunction() = 0; // this class is pure virtual //virtual void InitializeUnaryCost(int)=0; /** * Invokes the unary costs look-up table computation. */ - virtual void computeUnaryCosts(){}; + virtual void computeUnaryCosts() {}; /** * Invokes the unary potential for a the given node */ - virtual double computeUnaryCost(int node, int label){ return 0; }; + virtual double computeUnaryCost(int node, int label) { return 0; }; /** * Invokes the pairwise costs look-up table computation. */ - virtual void computePairwiseCosts(){}; + virtual void computePairwiseCosts() {}; /** * Invokes the pairwise potential for a the given pair and labels. */ - virtual double computePairwiseCost(int pair, int labelA, int labelB){ return 0;}; + virtual double computePairwiseCost(int pair, int labelA, int labelB) { return 0; }; /** * Invokes the triplet costs look-up table computation. @@ -150,12 +176,12 @@ namespace DISCRETEOPT{ /** * Invokes the pair weights initialization. */ - virtual void initPairWeights(const double *pairweights = 0){}; + virtual void initPairWeights(const double* pairweights = 0) {}; /** * Invokes the triplet weights initialization. */ - virtual void initTripletWeights(const double *tripletweights = 0){}; + virtual void initTripletWeights(const double* tripletweights = 0) {}; /** * Invokes the quartet costs look-up table. @@ -180,32 +206,32 @@ namespace DISCRETEOPT{ /** * Evaluates the total cost for the zero labeling. */ - virtual double evaluateTotalCostSumZeroLabeling(){return 0;}; + virtual double evaluateTotalCostSumZeroLabeling() { return 0; }; /** * Evaluates the total cost w.r.t to the current labeling. */ - virtual double evaluateTotalCostSum(){return 0;}; + virtual double evaluateTotalCostSum() { return 0; }; /** * Evaluates the unary cost sum w.r.t to the current labeling. */ - virtual double evaluateUnaryCostSum(){return 0;}; + virtual double evaluateUnaryCostSum() { return 0; }; /** * Evaluates the pairwise cost sum w.r.t to the current labeling. */ - virtual double evaluatePairwiseCostSum(){return 0;}; + virtual double evaluatePairwiseCostSum() { return 0; }; /** * Evaluates the triplet cost sum w.r.t to the current labeling. */ - virtual double evaluateTripletCostSum(){return 0;}; + virtual double evaluateTripletCostSum() { return 0; }; /** * Evaluates the quartet cost sum w.r.t to the current labeling. */ - virtual double evaluateQuartetCostSum(){return 0;}; + virtual double evaluateQuartetCostSum() { return 0; }; /** * Computes the uncertainties. @@ -215,15 +241,15 @@ namespace DISCRETEOPT{ /** * Applies the current labeling to the model configuration. */ - virtual void applyLabeling(){}; + virtual void applyLabeling() {}; /** * Applies the given labeling to the model configuration. */ - virtual void applyLabeling(int *discreteLabeling){}; - virtual void applytestLabeling(int *discreteLabeling,int lab){}; + virtual void applyLabeling(int* discreteLabeling) {}; + virtual void applytestLabeling(int* discreteLabeling, int lab) {}; /// gets label for particular node - virtual int GetLabel(int node)=0; + virtual int GetLabel(int node) = 0; /** * Frees memory which is not needed any more after optimization. @@ -234,20 +260,18 @@ namespace DISCRETEOPT{ * Prints the labeling. */ - virtual void report(){}; - - int getNumthreads(){return _numthreads;} + virtual void report() {}; + int getNumthreads() { return _numthreads; } void printLabeling(); // virtual void Initialize()=0; - virtual void Initialize(const newmesh &){}; - virtual void Initialize(){}; - virtual void setupCostFunction(){}; - virtual void set_parameters(myparam PAR){}; - protected: - + virtual void Initialize(const newmesh&) {}; + virtual void Initialize() {}; + virtual void setupCostFunction() {}; + virtual void set_parameters(myparam PAR) {}; +protected: /** * Deletes the cost function. */ @@ -258,152 +282,199 @@ namespace DISCRETEOPT{ */ void initLabeling(); - int m_num_nodes; ///< Number of model nodes (e.g. grid nodes, variables, etc). - int m_num_labels; ///< Number of labels. - int m_num_pairs; ///< Number of node pairs. - int m_num_triplets; ///< Number of node triplets. - int m_num_quartets; ///< Number of node quartets (currently none). - + int m_num_nodes; ///< Number of model nodes (e.g. grid nodes, variables, etc). + int m_num_labels; ///< Number of labels. + int m_num_pairs; ///< Number of node pairs. + int m_num_triplets; ///< Number of node triplets. + int m_num_quartets; ///< Number of node quartets (currently none). - float m_lambda; ///< Weighting between unary and pairwise costs. + float m_lambda; ///< Weighting between unary and pairwise costs. - int *labeling; ///< Labeling array. - int* pairs; ///< Node pairs array. - int *triplets; ///< Node triplets array. - int *quartets; ///< Node triplets array. + int* labeling; ///< Labeling array. + int* pairs; ///< Node pairs array. + int* triplets; ///< Node triplets array. + int* quartets; ///< Node triplets array. int _numthreads; string m_outdir; bool m_verbosity; + ///< Cost function. +}; - ///< Cost function. - }; - - class DiscreteModelDummy:public DiscreteModel - { +class DiscreteModelDummy : public DiscreteModel { - public: - DiscreteModelDummy(){ - costfct=boost::shared_ptr(new DummyCostFunction()); - //costfct->initialize(m_num_nodes,m_num_labels,m_num_pairs,m_num_triplets); - pairIDs.clear(); - m_num_pairs=0; m_num_nodes=0; m_num_labels=2; +public: + DiscreteModelDummy() + { + costfct = boost::shared_ptr(new DummyCostFunction()); + //costfct->initialize(m_num_nodes,m_num_labels,m_num_pairs,m_num_triplets); + pairIDs.clear(); + m_num_pairs = 0; + m_num_nodes = 0; + m_num_labels = 2; } //// create dummy costfunction to be used with fummy model (will just save output of conversion) - boost::shared_ptr getCostFunction() { boost::shared_ptr dcostfct=costfct; return dcostfct; } + boost::shared_ptr getCostFunction() + { + boost::shared_ptr dcostfct = costfct; + return dcostfct; + } ///// ELC conversion functions ////////// - void AddNode(int num){ //cout << " addnode " << num << endl; - m_num_nodes=num; }; + void AddNode(int num) + { //cout << " addnode " << num << endl; + m_num_nodes = num; + }; // Adds unary term Ei(x_i) to the energy function with cost values Ei(0)=E0, Ei(1)=E1. - void AddUnaryTerm(int node, double E0, double E1){ - // cout << node << "set UnaryCost " << E0 << " " << E1 << "m_num_nodes " << m_num_nodes << endl; - costfct->setUnaryCost(node,E0, E1);}; + void AddUnaryTerm(int node, double E0, double E1) + { + // cout << node << "set UnaryCost " << E0 << " " << E1 << "m_num_nodes " << m_num_nodes << endl; + costfct->setUnaryCost(node, E0, E1); + }; /// adds pairwise term for binary costs with label combinations 00,01,10,11 - void AddPairwiseTerm(int node1, int node2, double E00, double E01, double E10, double E11){ - pairIDs.insert(pair >(m_num_pairs, vector())); - pairIDs[m_num_pairs].push_back(node1); - pairIDs[m_num_pairs].push_back(node2); - // cout << node1 << " " << node2 << " add pair " << E00<< " " << E01 << " " << E10 << " " << E11 << " m_num_pairs " << m_num_pairs << endl; - costfct->setPairwiseCost(m_num_pairs,E00,E01,E10,E11); - m_num_pairs++; + void AddPairwiseTerm(int node1, int node2, double E00, double E01, double E10, double E11) + { + pairIDs.insert(pair>(m_num_pairs, vector())); + pairIDs[m_num_pairs].push_back(node1); + pairIDs[m_num_pairs].push_back(node2); + // cout << node1 << " " << node2 << " add pair " << E00<< " " << E01 << " " << E10 << " " << E11 << " m_num_pairs " << m_num_pairs << endl; + costfct->setPairwiseCost(m_num_pairs, E00, E01, E10, E11); + m_num_pairs++; } //// FastPD conversion functions - void initialise(){ - initLabeling(); - costfct->convertenergies(m_num_nodes,m_num_pairs,2); - pairs = new int [m_num_pairs*2]; - int pair=0; - for(int i=0;iconvertenergies(m_num_nodes, m_num_pairs, 2); + pairs = new int[m_num_pairs * 2]; + int pair = 0; + for (int i = 0; i < m_num_pairs; i++) { + pairs[2 * pair] = pairIDs[i][0]; + pairs[2 * pair + 1] = pairIDs[i][1]; + pair++; + } } - void reset(){ - pairIDs.clear(); - m_num_pairs=0; m_num_nodes=0; m_num_labels=2; - costfct->reset(); + void reset() + { + pairIDs.clear(); + m_num_pairs = 0; + m_num_nodes = 0; + m_num_labels = 2; + costfct->reset(); } /// write - int GetLabel(int node){ return labeling[node];} + int GetLabel(int node) { return labeling[node]; } - protected: - map > pairIDs; +protected: + map> pairIDs; boost::shared_ptr costfct; - }; +}; - class SRegDiscreteModel: public DiscreteModel - { +class SRegDiscreteModel : public DiscreteModel { - public: +public: /** * Constructor. */ - SRegDiscreteModel(){ - m_CPres=2; m_SGres=4; m_simmeasure=2; m_multivariate=false; m_verbosity=false; m_outdir=""; m_debug=false; m_regoption=2; - _pairwise=false; _estquartet=false; m_triclique=false; - m_inputrel=boost::shared_ptr(new RELATIONS()); - m_cp_neighbourhood=boost::shared_ptr(new RELATIONS ()); + SRegDiscreteModel() + { + m_CPres = 2; + m_SGres = 4; + m_simmeasure = 2; + m_multivariate = false; + m_verbosity = false; + m_outdir = ""; + m_debug = false; + m_regoption = 2; + _pairwise = false; + _estquartet = false; + m_triclique = false; + m_inputrel = boost::shared_ptr(new RELATIONS()); + m_cp_neighbourhood = boost::shared_ptr(new RELATIONS()); }; /** * Constructor. */ - SRegDiscreteModel(myparam& PAR){ - m_CPres=2; m_SGres=4; m_simmeasure=2; m_multivariate=false; m_verbosity=false; m_outdir="";m_debug=false; m_regoption=2; - _pairwise=false; _estquartet=false; m_triclique=false; - set_parameters(PAR); - initialize_cost_function(m_multivariate,m_simmeasure,PAR); - m_inputrel=boost::shared_ptr(new RELATIONS()); - m_cp_neighbourhood=boost::shared_ptr(new RELATIONS ()); - + SRegDiscreteModel(myparam& PAR) + { + m_CPres = 2; + m_SGres = 4; + m_simmeasure = 2; + m_multivariate = false; + m_verbosity = false; + m_outdir = ""; + m_debug = false; + m_regoption = 2; + _pairwise = false; + _estquartet = false; + m_triclique = false; + set_parameters(PAR); + initialize_cost_function(m_multivariate, m_simmeasure, PAR); + m_inputrel = boost::shared_ptr(new RELATIONS()); + m_cp_neighbourhood = boost::shared_ptr(new RELATIONS()); } /** * Destructor. */ - ~SRegDiscreteModel(){}; + ~SRegDiscreteModel() {}; /** * Returns the cost function. */ - boost::shared_ptr getCostFunction() { boost::shared_ptr dcostfct=costfct; return dcostfct; }// upcast + boost::shared_ptr getCostFunction() + { + boost::shared_ptr dcostfct = costfct; + return dcostfct; + } // upcast //void InitializeUnaryCost(int label){ if(costfct) costfct->InitializeUnaryCost(label); }; /** * Invokes the unary costs look-up table computation. */ - void computeUnaryCosts(){ if(costfct) costfct->computeUnaryCosts(); } + void computeUnaryCosts() + { + if (costfct) + costfct->computeUnaryCosts(); + } /** * Invokes the unary potential for a the given node */ - double computeUnaryCost(int node, int label) {return (costfct) ? costfct->computeUnaryCost(node,label): 0.0f; } + double computeUnaryCost(int node, int label) { return (costfct) ? costfct->computeUnaryCost(node, label) : 0.0f; } /** * Invokes the pairwise costs look-up table computation. */ - void computePairwiseCosts() { if(costfct) costfct->computePairwiseCosts(pairs); } + void computePairwiseCosts() + { + if (costfct) + costfct->computePairwiseCosts(pairs); + } - double computePairwiseCost(int pair, int labelA, int labelB){return (costfct) ? costfct->computePairwiseCost(pair,labelA,labelB): 0.0f; } + double computePairwiseCost(int pair, int labelA, int labelB) { return (costfct) ? costfct->computePairwiseCost(pair, labelA, labelB) : 0.0f; } /** * Invokes the pair weights initialization. */ - void initPairWeights(const double *pairweights = 0) { if(costfct) costfct->initPairWeights(pairweights); } + void initPairWeights(const double* pairweights = 0) + { + if (costfct) + costfct->initPairWeights(pairweights); + } - /** + /** * Invokes the pairwise costs look-up table computation. */ // void computeTripletCosts() { if(costfct) costfct->computeTripletCosts(); } - double computeTripletCost(int triplet, int labelA, int labelB, int labelC){return (costfct) ?costfct->computeTripletCost(triplet,labelA,labelB,labelC): 0.0f; } + double computeTripletCost(int triplet, int labelA, int labelB, int labelC) { return (costfct) ? costfct->computeTripletCost(triplet, labelA, labelB, labelC) : 0.0f; } /** * Computes the quartet costs look-up table. @@ -413,106 +484,175 @@ namespace DISCRETEOPT{ /** * Computes the quartet potential for a the given triplet and labels. */ - double computeQuartetCost(int quartet, int labelA, int labelB, int labelC, int labelD) { return (costfct) ? costfct->computeQuartetCost(quartet,labelA,labelB,labelC,labelD): 0.0f;} + double computeQuartetCost(int quartet, int labelA, int labelB, int labelC, int labelD) { return (costfct) ? costfct->computeQuartetCost(quartet, labelA, labelB, labelC, labelD) : 0.0f; } /** * Invokes the pair weights initialization. */ // void initTripletWeights(const double *tripletweights = 0) { if(costfct) costfct->initTripletWeights(tripletweights); } - /** * Evaluates the total cost for the zero labeling. */ - double evaluateTotalCostSumZeroLabeling(){ return (costfct) ? costfct->evaluateTotalCostSumZeroLabeling() : 0.0f; } + double evaluateTotalCostSumZeroLabeling() { return (costfct) ? costfct->evaluateTotalCostSumZeroLabeling() : 0.0f; } /** * Evaluates the total cost w.r.t to the current labeling. */ - double evaluateTotalCostSum(){ return (costfct) ? costfct->evaluateTotalCostSum(labeling,pairs,triplets,quartets) : 0.0f; } + double evaluateTotalCostSum() { return (costfct) ? costfct->evaluateTotalCostSum(labeling, pairs, triplets, quartets) : 0.0f; } /** * Evaluates the unary cost sum w.r.t to the current labeling. */ - double evaluateUnaryCostSum(){ if(costfct) return costfct->evaluateUnaryCostSum(labeling); else return 0.0f; } + double evaluateUnaryCostSum() + { + if (costfct) + return costfct->evaluateUnaryCostSum(labeling); + else + return 0.0f; + } /** * Evaluates the pairwise cost sum w.r.t to the current labeling. */ - double evaluatePairwiseCostSum(){ if(costfct) return costfct->evaluatePairwiseCostSum(labeling,pairs); else return 0.0f; } - + double evaluatePairwiseCostSum() + { + if (costfct) + return costfct->evaluatePairwiseCostSum(labeling, pairs); + else + return 0.0f; + } /** * Evaluates the triplet cost sum w.r.t to the current labeling. */ - double evaluateTripletCostSum() { if(costfct) return costfct->evaluateTripletCostSum(labeling,triplets); else return 0.0f; } + double evaluateTripletCostSum() + { + if (costfct) + return costfct->evaluateTripletCostSum(labeling, triplets); + else + return 0.0f; + } /** * Evaluates the quartet cost sum w.r.t to the current labeling. */ - double evaluateQuartetCostSum() { if(costfct) return costfct->evaluateQuartetCostSum(labeling,triplets); else return 0.0f; } + double evaluateQuartetCostSum() + { + if (costfct) + return costfct->evaluateQuartetCostSum(labeling, triplets); + else + return 0.0f; + } virtual void set_parameters(myparam PAR); /* INITIALIZE MODEL */ - virtual void set_meshspace(const NEWMESH::newmesh & target,const NEWMESH::newmesh & source, const int num=1){ -m_TARGET=target; m_SOURCE=source; } - + virtual void set_meshspace(const NEWMESH::newmesh& target, const NEWMESH::newmesh& source, const int num = 1) + { + m_TARGET = target; + m_SOURCE = source; + } // void set_anatomical_meshspace(const boost::shared_ptr &ref_sphere, const boost::shared_ptr &ref_anat,const NEWMESH::newmesh & source_anat){ if(costfct.get()){ costfct->set_anatomical(ref_sphere, ref_anat,source_anat);}} - void set_anatomical_meshspace(const NEWMESH::newmesh &ref_sphere, const NEWMESH::newmesh &ref_anat,const NEWMESH::newmesh & source_sphere, const NEWMESH::newmesh & source_anat){ if(costfct.get()){ costfct->set_anatomical(ref_sphere, ref_anat,source_sphere,source_anat);}} + void set_anatomical_meshspace(const NEWMESH::newmesh& ref_sphere, const NEWMESH::newmesh& ref_anat, const NEWMESH::newmesh& source_sphere, const NEWMESH::newmesh& source_anat) + { + if (costfct.get()) { + costfct->set_anatomical(ref_sphere, ref_anat, source_sphere, source_anat); + } + } - void set_anatomical_neighbourhood(const vector > & weights, const vector > neighbourhood){ if(costfct.get()){ costfct->set_anatomical_neighbourhood(weights,neighbourhood);}} + void set_anatomical_neighbourhood(const vector>& weights, const vector> neighbourhood) + { + if (costfct.get()) { + costfct->set_anatomical_neighbourhood(weights, neighbourhood); + } + } - void set_featurespace(const boost::shared_ptr &FEATURES, bool _concatenate=false){ - if(FEATURES->get_dim()>1) m_multivariate=true; - if(costfct.get()){ costfct->set_featurespace(FEATURES,_concatenate); } - else {throw DISCRETEOPTHOCRException("Discrete Model:: You have not initialised the discrete costfunction before setting the featurespace");} + void set_featurespace(const boost::shared_ptr& FEATURES, bool _concatenate = false) + { + if (FEATURES->get_dim() > 1) + m_multivariate = true; + if (costfct.get()) { + costfct->set_featurespace(FEATURES, _concatenate); + } else { + throw DISCRETEOPTHOCRException("Discrete Model:: You have not initialised the discrete costfunction before setting the featurespace"); + } } - void set_L1path(string s){if(costfct.get()){ costfct->set_matlab_path(s); }} + void set_L1path(string s) + { + if (costfct.get()) { + costfct->set_matlab_path(s); + } + } //// costfunction weighting combines source and reference weightings at beginning of optimisation iteration - //will not be 100% accurate but will remove any sensitivity of the label choices to weighting - void setupCostFunctionWeighting(const Matrix & Weight){costfct->set_dataaffintyweighting(Weight);}; + void setupCostFunctionWeighting(const Matrix& Weight) { costfct->set_dataaffintyweighting(Weight); }; /// source needs to be reset after every iteration of discrete optimisation - virtual void reset_meshspace(const NEWMESH::newmesh & source, int num=0){ + virtual void reset_meshspace(const NEWMESH::newmesh& source, int num = 0) + { - m_SOURCE=source; - if(costfct.get()){costfct->reset_source(source);} - else{throw DISCRETEOPTHOCRException("Discrete Model:: You cannot reset the source mesh withou initialising the discrete costfunction");} + m_SOURCE = source; + if (costfct.get()) { + costfct->reset_source(source); + } else { + throw DISCRETEOPTHOCRException("Discrete Model:: You cannot reset the source mesh withou initialising the discrete costfunction"); + } } - virtual void reset_CPgrid(const NEWMESH::newmesh & grid, int num=0){ - m_CPgrid=grid; + virtual void reset_CPgrid(const NEWMESH::newmesh& grid, int num = 0) + { + m_CPgrid = grid; } - virtual void warp_CPgrid(NEWMESH::newmesh & START, NEWMESH::newmesh & END, int num=0){ barycentric_mesh_interpolation(m_CPgrid,START,END); unfold(m_CPgrid);} + virtual void warp_CPgrid(NEWMESH::newmesh& START, NEWMESH::newmesh& END, int num = 0) + { + barycentric_mesh_interpolation(m_CPgrid, START, END); + unfold(m_CPgrid); + } - void initialize_cost_function(const bool &MV, const int & sim, myparam &P); + void initialize_cost_function(const bool& MV, const int& sim, myparam& P); void Initialize_sampling_grid(); - void label_sampling_grid(const int &, const double &, NEWMESH::newmesh &); + void label_sampling_grid(const int&, const double&, NEWMESH::newmesh&); vector rescale_sampling_grid(); - virtual void Initialize(const newmesh &); - - virtual void set_debug(){m_debug=true; costfct->debug();} // for debuging + virtual void Initialize(const newmesh&); - boost::shared_ptr get_cp_neighbourhood(){return m_cp_neighbourhood;}; + virtual void set_debug() + { + m_debug = true; + costfct->debug(); + } // for debuging - NEWMESH::newmesh get_SOURCE(){ if(costfct.get()) return costfct->get_SOURCE(); else{ cout << " no costfunction return inital source mesh " << endl;return m_SOURCE; } } + boost::shared_ptr get_cp_neighbourhood() { return m_cp_neighbourhood; }; - NEWMESH::newmesh get_TARGET(){return m_TARGET;} - virtual NEWMESH::newmesh get_CPgrid(int num=0){return m_CPgrid;} + NEWMESH::newmesh get_SOURCE() + { + if (costfct.get()) + return costfct->get_SOURCE(); + else { + cout << " no costfunction return inital source mesh " << endl; + return m_SOURCE; + } + } - void report(){ if(costfct.get()){ costfct->report();}} - int GetLabel(int node){return labeling[node];} + NEWMESH::newmesh get_TARGET() { return m_TARGET; } + virtual NEWMESH::newmesh get_CPgrid(int num = 0) { return m_CPgrid; } - protected: + void report() + { + if (costfct.get()) { + costfct->report(); + } + } + int GetLabel(int node) { return labeling[node]; } +protected: NEWMESH::newmesh m_TARGET; // TARGET MESH NEWMESH::newmesh m_SOURCE; // SOURCE MESH NEWMESH::newmesh m_CPgrid; ///// CONTROL POINT GRID @@ -520,11 +660,11 @@ m_TARGET=target; m_SOURCE=source; } boost::shared_ptr m_cp_neighbourhood; // hold control grid neighbours of each source vertex boost::shared_ptr m_inputrel; // hold target grid neighbours of each source vertex - boost::shared_ptr m_samplerel; // hold target grid neighbours of each source vertex + boost::shared_ptr m_samplerel; // hold target grid neighbours of each source vertex - int m_CPres;//control grid resolution - int m_SGres;// sampling grid resolution - int m_iter;// iteration of the discrete optimisation + int m_CPres; //control grid resolution + int m_SGres; // sampling grid resolution + int m_iter; // iteration of the discrete optimisation int m_centroid; /// used for selecting which sampling grid vertex will form the center of the sampling grid int m_simmeasure; // sim measure i.e. correlation int m_regoption; // sim measure i.e. correlation @@ -542,87 +682,81 @@ m_TARGET=target; m_SOURCE=source; } Pt centre; // vector > pair_trIDs; - vector m_samples; // samples based on vertices of sampling grid + vector m_samples; // samples based on vertices of sampling grid vector m_barycentres; // samples based on barycentres of sampling grid vector m_labels; // labels iterates between samples and barycnetres and is the label set used within cosfct vector m_ROT; // rotates sampling grid to each control point - boost::shared_ptr costfct; // costfunction object - }; + boost::shared_ptr costfct; // costfunction object +}; - class AffineSRegDiscreteModel: public SRegDiscreteModel - { +class AffineSRegDiscreteModel : public SRegDiscreteModel { - public: +public: /** * Constructor. */ - AffineSRegDiscreteModel(){}; - AffineSRegDiscreteModel(myparam & P):SRegDiscreteModel(P){}; - void setupCostFunction() ; - }; - - class NonLinearSRegDiscreteModel: public SRegDiscreteModel - { - protected: + AffineSRegDiscreteModel() {}; + AffineSRegDiscreteModel(myparam& P) + : SRegDiscreteModel(P) {}; + void setupCostFunction(); +}; - public: +class NonLinearSRegDiscreteModel : public SRegDiscreteModel { +protected: +public: /** * Constructor. */ - NonLinearSRegDiscreteModel(){}; - NonLinearSRegDiscreteModel(myparam & P):SRegDiscreteModel(P){ set_parameters(P); }; - + NonLinearSRegDiscreteModel() {}; + NonLinearSRegDiscreteModel(myparam& P) + : SRegDiscreteModel(P) + { + set_parameters(P); + }; - void applyLabeling(){applyLabeling(labeling);} ; - void applyLabeling(int *discreteLabeling); - // void applytestLabeling(int *discreteLabeling,int lab); + void applyLabeling() { applyLabeling(labeling); }; + void applyLabeling(int* discreteLabeling); + // void applytestLabeling(int *discreteLabeling,int lab); void estimate_pairs(); void estimate_triplets(); - void Initialize(const newmesh &); - void Initialize(){}; + void Initialize(const newmesh&); + void Initialize() {}; - void get_rotations(vector &); + void get_rotations(vector&); void setupCostFunction(); +}; - }; - - class RegularisationDiscreteModel: public NonLinearSRegDiscreteModel - { - protected: - - - public: - /** +class RegularisationDiscreteModel : public NonLinearSRegDiscreteModel { +protected: +public: + /** * Constructor. */ - //RegularisationDiscreteModel(int SAMP, double shear, double bulk, double exp){ m_SGres=SAMP; costfct=boost::shared_ptr(new RegularisationDiscreteCostFunction(shear,bulk, exp)); m_num_pairs=0;}; - RegularisationDiscreteModel(int SAMP, double shear, double bulk, double exp){ m_SGres=SAMP; costfct=boost::shared_ptr (new RegularisationDiscreteCostFunction(shear,bulk, exp)); m_num_pairs=0;}; - void Initialize(const newmesh &); - void Initialize(){}; - void setupCostFunction(); - - - + //RegularisationDiscreteModel(int SAMP, double shear, double bulk, double exp){ m_SGres=SAMP; costfct=boost::shared_ptr(new RegularisationDiscreteCostFunction(shear,bulk, exp)); m_num_pairs=0;}; + RegularisationDiscreteModel(int SAMP, double shear, double bulk, double exp) + { + m_SGres = SAMP; + costfct = boost::shared_ptr(new RegularisationDiscreteCostFunction(shear, bulk, exp)); + m_num_pairs = 0; }; + void Initialize(const newmesh&); + void Initialize() {}; + void setupCostFunction(); +}; - class MetricDistortionDiscreteModel: public RegularisationDiscreteModel - { - protected: - - - public: +class MetricDistortionDiscreteModel : public RegularisationDiscreteModel { +protected: +public: /** * Constructor. */ - MetricDistortionDiscreteModel(int SAMP, double shear, double bulk, double exp):RegularisationDiscreteModel(SAMP, shear, bulk, exp){ }; - }; - - - + MetricDistortionDiscreteModel(int SAMP, double shear, double bulk, double exp) + : RegularisationDiscreteModel(SAMP, shear, bulk, exp) {}; +}; } diff --git a/src/DiscreteOpt/similarities.cc b/src/DiscreteOpt/similarities.cc index 2e70614..e307f95 100644 --- a/src/DiscreteOpt/similarities.cc +++ b/src/DiscreteOpt/similarities.cc @@ -7,767 +7,808 @@ /* CCOPYRIGHT */ #include "similarities.h" /// HISTOGRAM 2D FUNCTIONS -namespace DISCRETEOPT{ +namespace DISCRETEOPT { histogram2D::~histogram2D() { - m_nbinsx=0; - m_nbinsy=0; - m_min_x = 0; - m_min_y = 0; - m_max_x = 0; - m_max_y = 0; - m_width_x = 0; - m_width_y = 0; - - _nsamps=0; + m_nbinsx = 0; + m_nbinsy = 0; + m_min_x = 0; + m_min_y = 0; + m_max_x = 0; + m_max_y = 0; + m_width_x = 0; + m_width_y = 0; + + _nsamps = 0; } void histogram2D::Initialize(int nbinsx, int nbinsy, double maxx, double maxy, double minx, double miny) { - - m_nbinsx = nbinsx; - m_nbinsy = nbinsy; - m_min_x = minx; - m_min_y = miny; - m_max_x = maxx; - m_max_y = maxy; - m_width_x = (m_max_x - m_min_x) / (double)m_nbinsx; - m_width_y = (m_max_y - m_min_y) / (double)m_nbinsy; - - Matrix newmat(m_nbinsx, m_nbinsy); - - _bins=newmat; - _weights=newmat; - _bins=0; - _nsamps=0; - _weights=0; + + m_nbinsx = nbinsx; + m_nbinsy = nbinsy; + m_min_x = minx; + m_min_y = miny; + m_max_x = maxx; + m_max_y = maxy; + m_width_x = (m_max_x - m_min_x) / (double)m_nbinsx; + m_width_y = (m_max_y - m_min_y) / (double)m_nbinsy; + + Matrix newmat(m_nbinsx, m_nbinsy); + + _bins = newmat; + _weights = newmat; + _bins = 0; + _nsamps = 0; + _weights = 0; } void histogram2D::Zero() { - int i,j; + int i, j; - for (j = 1; j <= m_nbinsy; j++) { - for (i = 1; i <= m_nbinsx; i++) { - _bins(i,j) = 0; + for (j = 1; j <= m_nbinsy; j++) { + for (i = 1; i <= m_nbinsx; i++) { + _bins(i, j) = 0; + } } - } - _nsamps=0; + _nsamps = 0; } - void histogram2D::AddSample(double x, double y) { - int i, j; - - - if (x < m_min_x) return; - if (x > m_max_x) return; - if (y < m_min_y) return; - if (y > m_max_y) return; - - i = (int) MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5*m_width_x) / (m_max_x - m_min_x)); - j = (int) MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5*m_width_y) / (m_max_y - m_min_y)); - - if (i < 1) i = 1; - if (j < 1) j = 1; - if (i > m_nbinsx) i = m_nbinsx; - if (j > m_nbinsy) j = m_nbinsy ; - - - _bins(i,j) += 1; - _weights(i,j)=1; - _nsamps += 1; - - + int i, j; + + if (x < m_min_x) + return; + if (x > m_max_x) + return; + if (y < m_min_y) + return; + if (y > m_max_y) + return; + + i = (int)MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5 * m_width_x) / (m_max_x - m_min_x)); + j = (int)MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5 * m_width_y) / (m_max_y - m_min_y)); + + if (i < 1) + i = 1; + if (j < 1) + j = 1; + if (i > m_nbinsx) + i = m_nbinsx; + if (j > m_nbinsy) + j = m_nbinsy; + + _bins(i, j) += 1; + _weights(i, j) = 1; + _nsamps += 1; } void histogram2D::AddSample(double weight, double x, double y) { - int i, j; - - if (x < m_min_x) return; - if (x > m_max_x) return; - if (y < m_min_y) return; - if (y > m_max_y) return; - - i = (int) MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5*m_width_x) / (m_max_x - m_min_x)); - j = (int) MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5*m_width_y) / (m_max_y - m_min_y)); - - if (i < 1) i = 1; - if (j < 1) j = 1; - if (i > m_nbinsx) i = m_nbinsx; - if (j > m_nbinsy) j = m_nbinsy ; - - _bins(i,j) += 1; - _weights(i,j)=1;// set as one for the time being until we can find correct formula weight; - _nsamps += 1; - - + int i, j; + + if (x < m_min_x) + return; + if (x > m_max_x) + return; + if (y < m_min_y) + return; + if (y > m_max_y) + return; + + i = (int)MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5 * m_width_x) / (m_max_x - m_min_x)); + j = (int)MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5 * m_width_y) / (m_max_y - m_min_y)); + + if (i < 1) + i = 1; + if (j < 1) + j = 1; + if (i > m_nbinsx) + i = m_nbinsx; + if (j > m_nbinsy) + j = m_nbinsy; + + _bins(i, j) += 1; + _weights(i, j) = 1; // set as one for the time being until we can find correct formula weight; + _nsamps += 1; } void histogram2D::DeleteSample(double x, double y) { - int i, j; - - - if (x < m_min_x) return; - if (x > m_max_x) return; - if (y < m_min_y) return; - if (y > m_max_y) return; - - i = (int) MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5*m_width_x) / (m_max_x - m_min_x)); - j = (int) MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5*m_width_y) / (m_max_y - m_min_y)); - - if (i < 0) i = 1; - if (j < 0) j = 1; - if (i > m_nbinsx) i = m_nbinsx; - if (j > m_nbinsy) j = m_nbinsy; - - _bins(i,j) -= 1; - _nsamps -= 1; - + int i, j; + + if (x < m_min_x) + return; + if (x > m_max_x) + return; + if (y < m_min_y) + return; + if (y > m_max_y) + return; + + i = (int)MISCMATHS::round(m_nbinsx * (x - m_min_x - 0.5 * m_width_x) / (m_max_x - m_min_x)); + j = (int)MISCMATHS::round(m_nbinsy * (y - m_min_y - 0.5 * m_width_y) / (m_max_y - m_min_y)); + + if (i < 0) + i = 1; + if (j < 0) + j = 1; + if (i > m_nbinsx) + i = m_nbinsx; + if (j > m_nbinsy) + j = m_nbinsy; + + _bins(i, j) -= 1; + _nsamps -= 1; } -double histogram2D::MarginalEntropyX(){ - int i,j; - ColumnVector M(m_nbinsx); - double E=0; - - M=0; +double histogram2D::MarginalEntropyX() +{ + int i, j; + ColumnVector M(m_nbinsx); + double E = 0; + M = 0; - for (i=1;i<=m_nbinsx;i++){ - for(j=1;j<=m_nbinsy;j++){ - M(i)=M(i)+_bins(i,j)/(double)_nsamps; - } + for (i = 1; i <= m_nbinsx; i++) { + for (j = 1; j <= m_nbinsy; j++) { + M(i) = M(i) + _bins(i, j) / (double)_nsamps; + } + } - } + for (i = 1; i <= m_nbinsx; i++) { + if (M(i) > 0) + E -= M(i) * log(M(i)); + } - for (i=1;i<=m_nbinsx;i++){ - if(M(i)>0) - E-=M(i)*log(M(i)); - } - - return E; + return E; } -double histogram2D::MarginalEntropyY(){ - int i,j; - ColumnVector M(m_nbinsy); - double E=0; +double histogram2D::MarginalEntropyY() +{ + int i, j; + ColumnVector M(m_nbinsy); + double E = 0; - M=0; + M = 0; - for (j=1;j<=m_nbinsy;j++){ - for(i=1;i<=m_nbinsx;i++){ - M(j)=M(j)+_bins(i,j)/(double)_nsamps; - + for (j = 1; j <= m_nbinsy; j++) { + for (i = 1; i <= m_nbinsx; i++) { + M(j) = M(j) + _bins(i, j) / (double)_nsamps; + } } - } - for (i=1;i<=m_nbinsx;i++){ - if(M(i)>0) - E-=M(i)*log(M(i)); - } - return E; + for (i = 1; i <= m_nbinsx; i++) { + if (M(i) > 0) + E -= M(i) * log(M(i)); + } + return E; } -double histogram2D::JointEntropy(){ - int i,j; - double E=0; - Matrix JP(m_nbinsx,m_nbinsy); +double histogram2D::JointEntropy() +{ + int i, j; + double E = 0; + Matrix JP(m_nbinsx, m_nbinsy); - for (i=1;i<=m_nbinsy;i++){ - for(j=1;j<=m_nbinsx;j++){ - JP(i,j)=_bins(i,j)/(double)_nsamps; + for (i = 1; i <= m_nbinsy; i++) { + for (j = 1; j <= m_nbinsx; j++) { + JP(i, j) = _bins(i, j) / (double)_nsamps; + } } - } - - for (i=1;i<=m_nbinsy;i++){ - for(j=1;j<=m_nbinsx;j++){ - if(JP(i,j)>0) - E-=_weights(i,j)*JP(i,j)*log(JP(i,j)); - + for (i = 1; i <= m_nbinsy; i++) { + for (j = 1; j <= m_nbinsx; j++) { + if (JP(i, j) > 0) + E -= _weights(i, j) * JP(i, j) * log(JP(i, j)); + } } - } - - return E; + + return E; } +double histogram2D::normalisedmutualinformation() +{ + if (this->JointEntropy() > 1e-5) + return (this->MarginalEntropyX() + this->MarginalEntropyY()) / this->JointEntropy(); + else + return 0; +} +void simkernel::set_input(string path_to_input) +{ // assume matrix is full?? + m_A = boost::shared_ptr(new FullBFMatrix(path_to_input)); +} - double histogram2D::normalisedmutualinformation(){ - if(this->JointEntropy() >1e-5 )return (this->MarginalEntropyX()+this->MarginalEntropyY())/this->JointEntropy(); - else return 0; - } +void simkernel::set_reference(string path_to_ref) +{ + m_B = boost::shared_ptr(new FullBFMatrix(path_to_ref)); +} - +void simkernel::Initialize(int simval) +{ - void simkernel::set_input(string path_to_input){ // assume matrix is full?? + _sim = simval; - m_A =boost::shared_ptr (new FullBFMatrix (path_to_input)); - - } - - void simkernel::set_reference(string path_to_ref){ - m_B =boost::shared_ptr (new FullBFMatrix (path_to_ref)); - } - - void simkernel::Initialize(int simval){ - - _sim=simval; - - if(m_A==NULL){ throw DISCRETEOPTHOCRException("SIMILARITIES:: Connectivity matrices have not been initliased");} - - if(_sim==1|| _sim==2){ - - _rmeanA=meanvector(*m_A); - if(m_A->Nrows()==1) _meanA=_rmeanA(1); - if(m_B!=NULL) - _rmeanB=meanvector(*m_B); - else - _rmeanB=_rmeanA; - - if(m_B->Nrows()==1) _meanB=_rmeanB(1); + if (m_A == NULL) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: Connectivity matrices have not been initliased"); } - - - /// for NMI initialise histogram - if(_sim==3){ - calc_range(m_A,maxx,minx); - if(m_B==NULL){ - miny=minx; - maxy=maxx; - } - else - calc_range(m_B,maxy,miny); - - if(m_A->Nrows()<256) - hist.Initialize(m_A->Nrows()-1,m_A->Nrows()-1,maxx,maxy,minx,miny); - else{ - hist.Initialize(256,256,maxx,maxy,minx,miny); - } - } - - } - - ///// for the case where we are working on vector data and we have no knowledge of the full data m_A (currently used in discrete opt) - void simkernel::Initialize(int simval,const vector &inputdata, const vector &refdata,const vector &weights){ - - _sim=simval; - _initialised=true; - if(_sim==3){ - - calc_range(inputdata,maxx,minx); - calc_range(refdata,maxy,miny); - if(inputdata.size()<256) - hist.Initialize(inputdata.size()-1,inputdata.size()-1,maxx,maxy,minx,miny); - else{ - hist.Initialize(256,256,maxx,maxy,minx,miny); - } - + + if (_sim == 1 || _sim == 2) { + + _rmeanA = meanvector(*m_A); + if (m_A->Nrows() == 1) + _meanA = _rmeanA(1); + if (m_B != NULL) + _rmeanB = meanvector(*m_B); + else + _rmeanB = _rmeanA; + + if (m_B->Nrows() == 1) + _meanB = _rmeanB(1); } - else{ - _meanA=0;_meanB=0; - double sum=0; - for(unsigned int i=0;i0){ - _meanA/=sum; - _meanB/=sum; - } - if(_meanA!=_meanA) cout << _meanA << " mean A nan " << sum << endl; - if(_meanB!=_meanB) cout << _meanB << " mean B nan " << sum << endl; + + /// for NMI initialise histogram + if (_sim == 3) { + calc_range(m_A, maxx, minx); + if (m_B == NULL) { + miny = minx; + maxy = maxx; + } else + calc_range(m_B, maxy, miny); + + if (m_A->Nrows() < 256) + hist.Initialize(m_A->Nrows() - 1, m_A->Nrows() - 1, maxx, maxy, minx, miny); + else { + hist.Initialize(256, 256, maxx, maxy, minx, miny); + } } - +} - } +///// for the case where we are working on vector data and we have no knowledge of the full data m_A (currently used in discrete opt) +void simkernel::Initialize(int simval, const vector& inputdata, const vector& refdata, const vector& weights) +{ - RowVector simkernel::meanvector(const BFMatrix &fdt_matrix) - { + _sim = simval; + _initialised = true; + if (_sim == 3) { + + calc_range(inputdata, maxx, minx); + calc_range(refdata, maxy, miny); + if (inputdata.size() < 256) + hist.Initialize(inputdata.size() - 1, inputdata.size() - 1, maxx, maxy, minx, miny); + else { + hist.Initialize(256, 256, maxx, maxy, minx, miny); + } + + } else { + _meanA = 0; + _meanB = 0; + double sum = 0; + for (unsigned int i = 0; i < inputdata.size(); i++) { + double varwght = 0; + if (weights.size() == inputdata.size()) + varwght = weights[i]; + else + varwght = 1; + + _meanA += varwght * inputdata[i]; + _meanB += varwght * refdata[i]; + sum += varwght; + if (_meanA != _meanA) + cout << i << "weights.size " << weights.size() << " weights[i] " << weights[i] << " weight " << varwght << " inputdata[i] " << inputdata[i] << endl; + if (_meanB != _meanB) + cout << i << "weights.size " << weights.size() << " weights[i] " << weights[i] << " weight " << varwght << " refdata[i] " << refdata[i] << endl; + } + if (sum > 0) { + _meanA /= sum; + _meanB /= sum; + } + if (_meanA != _meanA) + cout << _meanA << " mean A nan " << sum << endl; + if (_meanB != _meanB) + cout << _meanB << " mean B nan " << sum << endl; + } +} + +RowVector simkernel::meanvector(const BFMatrix& fdt_matrix) +{ RowVector mean(fdt_matrix.Ncols()); - mean=0; - - if(fdt_matrix.Nrows()==1){ - double sum=0; - for (unsigned int i=0; i < fdt_matrix.Ncols(); i++){ - sum=sum+fdt_matrix.Peek(1,i+1); - } - for (unsigned int i=0; i < fdt_matrix.Ncols(); i++) - mean(i+1)=sum/fdt_matrix.Ncols(); - } - else{ - for (unsigned int i=0; i < fdt_matrix.Ncols(); i++){ - double sum=0; - - for (unsigned int j=0; j < fdt_matrix.Nrows(); j++){ - sum=sum+fdt_matrix.Peek(j+1,i+1); - - } - mean(i+1)=sum/fdt_matrix.Nrows(); - - } + mean = 0; + + if (fdt_matrix.Nrows() == 1) { + double sum = 0; + for (unsigned int i = 0; i < fdt_matrix.Ncols(); i++) { + sum = sum + fdt_matrix.Peek(1, i + 1); + } + for (unsigned int i = 0; i < fdt_matrix.Ncols(); i++) + mean(i + 1) = sum / fdt_matrix.Ncols(); + } else { + for (unsigned int i = 0; i < fdt_matrix.Ncols(); i++) { + double sum = 0; + + for (unsigned int j = 0; j < fdt_matrix.Nrows(); j++) { + sum = sum + fdt_matrix.Peek(j + 1, i + 1); + } + mean(i + 1) = sum / fdt_matrix.Nrows(); + } } - + return mean; - } +} - +void simkernel::calc_range(boost::shared_ptr mat, double& max, double& min) +{ - void simkernel::calc_range(boost::shared_ptr mat, double &max, double &min){ + for (unsigned int i = 1; i <= mat->Nrows(); i++) { + for (unsigned int j = 1; j <= mat->Ncols(); j++) { + if (mat->Peek(i, j) > max) + max = mat->Peek(i, j); + if (mat->Peek(i, j) < min) + min = mat->Peek(i, j); + } + } +} +void simkernel::calc_range(const vector& mat, double& max, double& min) +{ - for (unsigned int i=1; i <= mat->Nrows(); i++){ - for (unsigned int j=1; j <= mat->Ncols(); j++){ - if( mat->Peek(i,j)>max) - max=mat->Peek(i,j); - if(mat->Peek(i,j)< min) - min=mat->Peek(i,j); - } + max = 0; + min = 1e7; + for (unsigned int i = 0; i < mat.size(); i++) { + if (mat[i] > max) + max = mat[i]; + if (mat[i] < min) + min = mat[i]; } - } +} - void simkernel::calc_range(const vector &mat, double &max, double &min){ +double simkernel::corr(int i, int j) +{ - max=0; min=1e7; - for (unsigned int i=0; i < mat.size(); i++){ - if( mat[i]>max) - max=mat[i]; - if(mat[i]< min) - min=mat[i]; - } - - } + int num = 0, numB = 0; + ; + double prod, varA, varB; + prod = 0; + varA = 0; + varB = 0; - + if (m_B.get() == 0) + m_B = m_A; - double simkernel::corr(int i,int j){ - - int num=0,numB=0;; - double prod,varA,varB; - prod=0; varA=0; varB=0; + if (_rmeanA.Ncols() == 0) { + _rmeanA = meanvector(*m_A); + if (_rmeanB.Ncols() == 0) { + if (m_B == NULL) + _rmeanB = _rmeanA; + else + _rmeanB = meanvector(*m_B); + } + } + boost::shared_ptr> ptr = boost::dynamic_pointer_cast>(m_A); - if(m_B.get()==0) m_B=m_A; - + double Bzerooffset = (0.0 - _rmeanB(j)); // result for all zero values of sparse mat + double Azerooffset = (0.0 - _rmeanA(i)); - if(_rmeanA.Ncols()==0){ - _rmeanA=meanvector(*m_A); - if(_rmeanB.Ncols()==0) { - if(m_B==NULL) - _rmeanB=_rmeanA; - else - _rmeanB=meanvector(*m_B); - } + for (BFMatrixColumnIterator it = m_A->begin(i); it != m_A->end(i); it++) { + prod += (*it - _rmeanA(i)) * (m_B->Peek(it.Row(), j) - _rmeanB(j)); + varA += (*it - _rmeanA(i)) * (*it - _rmeanA(i)); + varB += (m_B->Peek(it.Row(), j) - _rmeanB(j)) * (m_B->Peek(it.Row(), j) - _rmeanB(j)); + num++; } - boost::shared_ptr > ptr =boost::dynamic_pointer_cast >(m_A); - double Bzerooffset=(0.0 - _rmeanB(j)); // result for all zero values of sparse mat - double Azerooffset=(0.0 - _rmeanA(i)); - - for (BFMatrixColumnIterator it=m_A->begin(i);it!=m_A->end(i);it++){ - prod +=(*it-_rmeanA(i))*(m_B->Peek(it.Row(),j)-_rmeanB(j)); - varA+=(*it-_rmeanA(i))*(*it-_rmeanA(i)); - varB+=(m_B->Peek(it.Row(),j)-_rmeanB(j))*(m_B->Peek(it.Row(),j)-_rmeanB(j)); - num++; - } + if (ptr) { //if sparse run all for all rows where A had zero values + varA += (m_A->Nrows() - num) * Azerooffset * Azerooffset; /// for rows where A has no values - if(ptr){ //if sparse run all for all rows where A had zero values + for (BFMatrixColumnIterator it = m_B->begin(j); it != m_B->end(j); it++) { + if (m_A->Peek(it.Row(), i) == 0) { + prod += Azerooffset * (*it - _rmeanB(j)); + num++; + varB += (*it - _rmeanB(j)) * (*it - _rmeanB(j)); + } + numB++; + } - varA+=(m_A->Nrows()-num)*Azerooffset*Azerooffset; /// for rows where A has no values + varB += (m_A->Nrows() - numB) * Bzerooffset * Bzerooffset; /// for rows where B has no values + prod += (2 * m_A->Nrows() - num) * Azerooffset * Bzerooffset; /// for rows where A&B have no values + } - for (BFMatrixColumnIterator it=m_B->begin(j);it!=m_B->end(j);it++){ - if(m_A->Peek(it.Row(),i)==0){ - prod +=Azerooffset*(*it-_rmeanB(j)); - num++; - varB+=(*it-_rmeanB(j))*(*it-_rmeanB(j)); - } - numB++; - } - - - varB+=(m_A->Nrows()-numB)*Bzerooffset*Bzerooffset; /// for rows where B has no values - prod+=(2*m_A->Nrows()-num)*Azerooffset*Bzerooffset; /// for rows where A&B have no values - } + if (varA == 0.0 || varB == 0.0) + return 0.0; + else + return prod / (sqrt(varA) * sqrt(varB)); +} - if (varA == 0.0 || varB == 0.0) return 0.0; else - return prod/(sqrt(varA)*sqrt(varB)); - - } +double simkernel::SSD(int i, int j) +{ + double prod = 0; + if (m_B.get() == 0) + m_B = m_A; - double simkernel::SSD(int i, int j){ - - double prod=0; - if(m_B.get()==0) m_B=m_A; - - boost::shared_ptr > ptr =boost::dynamic_pointer_cast >(m_A); + boost::shared_ptr> ptr = boost::dynamic_pointer_cast>(m_A); - for (BFMatrixColumnIterator it=m_A->begin(i);it!=m_A->end(i);it++) - prod +=(*it-m_B->Peek(it.Row(),j))*(*it-m_B->Peek(it.Row(),j)); - - if(ptr){ - - for (BFMatrixColumnIterator it=m_B->begin(j);it!=m_B->end(j);it++){ - if(m_A->Peek(it.Row(),i)==0) - prod +=(*it)*(*it); - } - + for (BFMatrixColumnIterator it = m_A->begin(i); it != m_A->end(i); it++) + prod += (*it - m_B->Peek(it.Row(), j)) * (*it - m_B->Peek(it.Row(), j)); + + if (ptr) { + + for (BFMatrixColumnIterator it = m_B->begin(j); it != m_B->end(j); it++) { + if (m_A->Peek(it.Row(), i) == 0) + prod += (*it) * (*it); + } } - - return sqrt(prod)/m_A->Nrows(); - } - - - /* NMI derived similarity kernel*/ - double simkernel::NMI(int i, int j){ - - if(m_A->Nrows()<256) - hist.ReSize(m_A->Nrows()-1,m_A->Nrows()-1); + + return sqrt(prod) / m_A->Nrows(); +} + +/* NMI derived similarity kernel*/ +double simkernel::NMI(int i, int j) +{ + + if (m_A->Nrows() < 256) + hist.ReSize(m_A->Nrows() - 1, m_A->Nrows() - 1); else - hist.ReSize(256,256); - - - if(m_B.get()==0) m_B=m_A; - - for (unsigned int s=1;s<=m_A->Nrows();s++){ - - hist.AddSample(m_A->Peek(s,i),m_B->Peek(s,j)); - - } - - return hist.normalisedmutualinformation(); - } - - //// for vectors - weight function is optional - - double simkernel::corr(const vector &A,const vector &B,const vector &weights){ - - double prod,varA,varB; - double sum=0; - prod=0; varA=0; varB=0; - - if(A.size()!=B.size()){cout << A.size() << " " << B.size() << " " << weights.size() << endl; throw DISCRETEOPTHOCRException("SIMILARITIES:: correlation, data dimensions do not match");} - Initialize(2,A,B,weights); + hist.ReSize(256, 256); - for (unsigned int s=0;sNrows(); s++) { + + hist.AddSample(m_A->Peek(s, i), m_B->Peek(s, j)); + } + + return hist.normalisedmutualinformation(); +} + +//// for vectors - weight function is optional - sum+=varwght; - if(sum!=sum) cout << " varwght " << varwght << endl; - if(prod!=prod) cout <& A, const vector& B, const vector& weights) +{ + double prod, varA, varB; + double sum = 0; + prod = 0; + varA = 0; + varB = 0; + + if (A.size() != B.size()) { + cout << A.size() << " " << B.size() << " " << weights.size() << endl; + throw DISCRETEOPTHOCRException("SIMILARITIES:: correlation, data dimensions do not match"); } + Initialize(2, A, B, weights); + + for (unsigned int s = 0; s < A.size(); s++) { + double varwght = 0; + if (weights.size() == A.size()) { + varwght = weights[s]; + } //cout << s << " varwght " << varwght << endl;} + else + varwght = 1; - if(sum>0){ - prod/=sum; - varA/=sum; - varB/=sum; + prod = prod + varwght * (A[s] - _meanA) * (B[s] - _meanB); + + varA = varA + varwght * (A[s] - _meanA) * (A[s] - _meanA); + varB = varB + varwght * (B[s] - _meanB) * (B[s] - _meanB); + + sum += varwght; + if (sum != sum) + cout << " varwght " << varwght << endl; + if (prod != prod) + cout << s << " prod " << prod << " A[s] " << A[s] << " " << B[s] << "_meanA " << _meanA << " _meanB " << _meanB << endl; + if (varA != varA) + cout << s << " varA " << varA << " A[s] " << A[s] << " " << B[s] << "_meanA " << _meanA << " _meanB " << _meanB << endl; + if (varB != varB) + cout << s << " varB " << varB << " A[s] " << A[s] << " " << B[s] << "_meanA " << _meanA << " _meanB " << _meanB << endl; } - - if (varA == 0.0 || varB == 0.0) return 0.0; - else{ - if (prod!=0 && ((prod/(sqrt(varA)*sqrt(varB))) != (prod/(sqrt(varA)*sqrt(varB))))) - cout << prod << " sqrt(varA) " << sqrt(varA) << " sqrt(varB) " << sqrt(varB) << endl; - return prod/(sqrt(varA)*sqrt(varB)); + if (sum > 0) { + prod /= sum; + varA /= sum; + varB /= sum; } - - } - double simkernel::corr(const map &A,const map &B){ - - double prod,varA,varB,val; - double MAPA_MEAN=0,MAPB_MEAN=0; - int ind=0; - prod=0; varA=0; varB=0; - + if (varA == 0.0 || varB == 0.0) + return 0.0; + else { + if (prod != 0 && ((prod / (sqrt(varA) * sqrt(varB))) != (prod / (sqrt(varA) * sqrt(varB))))) + cout << prod << " sqrt(varA) " << sqrt(varA) << " sqrt(varB) " << sqrt(varB) << endl; + return prod / (sqrt(varA) * sqrt(varB)); + } +} + +double simkernel::corr(const map& A, const map& B) +{ + + double prod, varA, varB, val; + double MAPA_MEAN = 0, MAPB_MEAN = 0; + int ind = 0; + prod = 0; + varA = 0; + varB = 0; + /// estimate mean - for (map::const_iterator iter = A.begin(); iter != A.end(); ++iter){ - if(B.find(iter->first) != B.end()){ - MAPA_MEAN+=iter->second; - MAPB_MEAN+=B.find(iter->first)->second; - ind++; - } + for (map::const_iterator iter = A.begin(); iter != A.end(); ++iter) { + if (B.find(iter->first) != B.end()) { + MAPA_MEAN += iter->second; + MAPB_MEAN += B.find(iter->first)->second; + ind++; + } } - if(ind==0){ cout << " ind==0 << A.size() " << A.size() << " " << B.size() << endl; val=MAXSIM; } - else{ - - MAPA_MEAN/=ind; - MAPB_MEAN/=ind; - - for (map::const_iterator iter = A.begin(); iter != A.end(); ++iter){ - if(B.find(iter->first) != B.end()){ - //if(iter->second!=iter->second) cout << " iter->second!=iter->second " << iter->second << endl; - //if(B.find(iter->first)->second!=B.find(iter->first)->second) cout << " iB.find(iter->first)->second!=B.find(iter->first)->second " << B.find(iter->first)->second << endl; - - prod = prod+(iter->second - MAPA_MEAN)*(B.find(iter->first)->second - MAPB_MEAN); - - varA = varA+(iter->second - MAPA_MEAN)*(iter->second - MAPA_MEAN); - varB = varB+(B.find(iter->first)->second - MAPB_MEAN)*(B.find(iter->first)->second - MAPB_MEAN); - - //if(varA!=varA) cout << " varA " << varA << " MAPA_MEAN " << MAPA_MEAN << " iter->second " << iter->second << " ind " << ind << endl; - //if(varB!=varB) cout << " varB " << varA << " MAPB_MEAN " << MAPB_MEAN <<" B.find(iter->first)->second " << B.find(iter->first)->second << " ind " << ind << endl; - - } - - } + if (ind == 0) { + cout << " ind==0 << A.size() " << A.size() << " " << B.size() << endl; + val = MAXSIM; + } else { - - prod/=ind; - varA/=ind; - varB/=ind; - + MAPA_MEAN /= ind; + MAPB_MEAN /= ind; - if (varA == 0.0 || varB == 0.0) val=0.0; - else {val=prod/(sqrt(varA)*sqrt(varB)); + for (map::const_iterator iter = A.begin(); iter != A.end(); ++iter) { + if (B.find(iter->first) != B.end()) { + //if(iter->second!=iter->second) cout << " iter->second!=iter->second " << iter->second << endl; + //if(B.find(iter->first)->second!=B.find(iter->first)->second) cout << " iB.find(iter->first)->second!=B.find(iter->first)->second " << B.find(iter->first)->second << endl; - val=1-(1+val)/2; - } - if(val!=val) cout << "prod " << prod << " varA " << varA << " varB " << varB <<" ind " << ind << endl; + prod = prod + (iter->second - MAPA_MEAN) * (B.find(iter->first)->second - MAPB_MEAN); - } + varA = varA + (iter->second - MAPA_MEAN) * (iter->second - MAPA_MEAN); + varB = varB + (B.find(iter->first)->second - MAPB_MEAN) * (B.find(iter->first)->second - MAPB_MEAN); + + //if(varA!=varA) cout << " varA " << varA << " MAPA_MEAN " << MAPA_MEAN << " iter->second " << iter->second << " ind " << ind << endl; + //if(varB!=varB) cout << " varB " << varA << " MAPB_MEAN " << MAPB_MEAN <<" B.find(iter->first)->second " << B.find(iter->first)->second << " ind " << ind << endl; + } + } - if(val!=val) cout << " 2 prod " << prod << " varA " << varA << " varB " << varB <<" ind " << ind << endl; + prod /= ind; + varA /= ind; + varB /= ind; + if (varA == 0.0 || varB == 0.0) + val = 0.0; + else { + val = prod / (sqrt(varA) * sqrt(varB)); + + val = 1 - (1 + val) / 2; + } + if (val != val) + cout << "prod " << prod << " varA " << varA << " varB " << varB << " ind " << ind << endl; + } + + if (val != val) + cout << " 2 prod " << prod << " varA " << varA << " varB " << varB << " ind " << ind << endl; return val; - } - - // used for calculating componentwise 'correlation' - double simkernel::corrdebug(const int &i, Matrix &COMP, const vector &A,const vector &B,const vector &weights){ - - double prod,varA,varB; - double sum=0; - prod=0; varA=0; varB=0; - - if(A.size()!=B.size()){cout << A.size() << " " << B.size() << " " << weights.size() << endl; throw DISCRETEOPTHOCRException("SIMILARITIES:: correlation, data dimensions do not match");} - Initialize(2,A,B,weights); +} - - for (unsigned int s=0;s& A, const vector& B, const vector& weights) +{ - COMP(s+1,i+1)=varwght*(A[s] - _meanA)*(B[s] - _meanB); + double prod, varA, varB; + double sum = 0; + prod = 0; + varA = 0; + varB = 0; - prod = prod+COMP(s+1,i+1); - + if (A.size() != B.size()) { + cout << A.size() << " " << B.size() << " " << weights.size() << endl; + throw DISCRETEOPTHOCRException("SIMILARITIES:: correlation, data dimensions do not match"); + } + Initialize(2, A, B, weights); - varA = varA+varwght*(A[s] - _meanA)*(A[s] - _meanA); - varB = varB+varwght*(B[s] - _meanB)*(B[s] - _meanB); - - sum+=varwght; - - } + for (unsigned int s = 0; s < A.size(); s++) { + double varwght = 0; + if (weights.size() == A.size()) + varwght = weights[s]; + else + varwght = 1; + + COMP(s + 1, i + 1) = varwght * (A[s] - _meanA) * (B[s] - _meanB); + + prod = prod + COMP(s + 1, i + 1); + + varA = varA + varwght * (A[s] - _meanA) * (A[s] - _meanA); + varB = varB + varwght * (B[s] - _meanB) * (B[s] - _meanB); - if(sum>0){ - prod/=sum; - varA/=sum; - varB/=sum; + sum += varwght; } - - for (unsigned int s=0;s 0) { + prod /= sum; + varA /= sum; + varB /= sum; } - - if (varA == 0.0 || varB == 0.0) return 0.0; else - return prod/(sqrt(varA)*sqrt(varB)); - - } - - double simkernel::SSD(const vector &A,const vector &B,const vector &weights){ - - double prod=0,sum=0; - if(A.size()!=B.size()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: SSD data dimensions do not match");} - Initialize(3,A,B,weights); + for (unsigned int s = 0; s < A.size(); s++) { + COMP(s + 1, i + 1) /= (sum * sqrt(varA) * sqrt(varB)); + } - for (unsigned int s=0;s0) prod=prod/sum; + if (varA == 0.0 || varB == 0.0) + return 0.0; + else + return prod / (sqrt(varA) * sqrt(varB)); +} + +double simkernel::SSD(const vector& A, const vector& B, const vector& weights) +{ + + double prod = 0, sum = 0; + + if (A.size() != B.size()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: SSD data dimensions do not match"); + } + Initialize(3, A, B, weights); + + for (unsigned int s = 0; s < A.size(); s++) { + double varwght = 0; + if (weights.size() == A.size()) + varwght = weights[s]; + else + varwght = 1; + prod = prod + varwght * (A[s] - B[s]) * (A[s] - B[s]); + sum += varwght; + } + if (sum > 0) + prod = prod / sum; return prod; - } +} + +double simkernel::nSSD(const vector& A, const vector& B, const vector& weights) +{ /// normalized by variance - was hoped this would make SSD better for discrete opt but doesn't seem to be the case + + double prod = 0, sum = 0; + double varA = 0.0, varB = 0.0; + if (A.size() != B.size()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: SSD data dimensions do not match"); + } - - double simkernel::nSSD(const vector &A,const vector &B,const vector &weights){ /// normalized by variance - was hoped this would make SSD better for discrete opt but doesn't seem to be the case - - double prod=0,sum=0; - double varA=0.0,varB=0.0; - if(A.size()!=B.size()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: SSD data dimensions do not match");} - // only perform calculations for non zero values - for (unsigned int s=0;s0){ - prod/=sum; - varA/=sum; - varB/=sum; + if (sum > 0) { + prod /= sum; + varA /= sum; + varB /= sum; } - if((sqrt(varA)*sqrt(varB))>0) prod=prod/(sqrt(varA)*sqrt(varB)); + if ((sqrt(varA) * sqrt(varB)) > 0) + prod = prod / (sqrt(varA) * sqrt(varB)); return prod; - } - - +} - double simkernel::NMI(const vector &A,const vector &B,const vector &weights){ +double simkernel::NMI(const vector& A, const vector& B, const vector& weights) +{ double val; - if(A.size()!=B.size()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: NMI data dimensions do not match");} + if (A.size() != B.size()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: NMI data dimensions do not match"); + } - Initialize(4,A,B,weights); + Initialize(4, A, B, weights); - if(A.size()<256) - hist.ReSize(A.size()-1,A.size()-1); + if (A.size() < 256) + hist.ReSize(A.size() - 1, A.size() - 1); else - hist.ReSize(256,256); - - for (unsigned int s=0;s &input,const vector &reference,const vector &weights){ - - double val=0.0; - - switch (_sim){ + +double simkernel::get_sim_for_min(const vector& input, const vector& reference, const vector& weights) +{ + + double val = 0.0; + + switch (_sim) { case 1: - val=SSD(input,reference,weights); + val = SSD(input, reference, weights); case 2: - val=corr(input,reference,weights); - val=1-(1+val)/2; // scale between 0 and 1 - break; + val = corr(input, reference, weights); + val = 1 - (1 + val) / 2; // scale between 0 and 1 + break; case 3: - val=NMI(input,reference); - break; + val = NMI(input, reference); + break; } - return val; - } +} - - double simkernel::get_sim_for_mindebug(const int & i, Matrix &COMP, const vector &input,const vector &reference,const vector &weights){ - - double val=0.0; - - switch (_sim){ +double simkernel::get_sim_for_mindebug(const int& i, Matrix& COMP, const vector& input, const vector& reference, const vector& weights) +{ + + double val = 0.0; + + switch (_sim) { case 1: - val=SSD(input,reference,weights); - break; + val = SSD(input, reference, weights); + break; case 2: - val=corrdebug(i,COMP,input,reference,weights); - val=1-(1+val)/2;// scale between 0 and 1 - break; + val = corrdebug(i, COMP, input, reference, weights); + val = 1 - (1 + val) / 2; // scale between 0 and 1 + break; case 3: - val=NMI(input,reference); - break; + val = NMI(input, reference); + break; } - return val; - } - -/////ALPHA ENTROPY **NOT CURRENTLY AVAILABLE **** +} +/////ALPHA ENTROPY **NOT CURRENTLY AVAILABLE **** /* vector simkernel::alpha_entropy(vector > &M, vector &weights, int &kNN, const double & eps,vector > & neighbours) { @@ -837,100 +878,84 @@ double histogram2D::JointEntropy(){ } */ /////// -void fullsimkernel::calculate_sim_column(int ind){ +void fullsimkernel::calculate_sim_column(int ind) +{ - - int cols; - - if(m_B==NULL) - cols= m_A->Ncols(); - else - cols= m_B->Ncols(); - - - for (int j=1; j <= cols; j++){ - switch (_sim){ - case 1: - (*mp)(j,ind)=-SSD(ind,j); - break; - case 2: - (*mp)(j,ind)=corr(ind,j); - break; - case 3: - (*mp)(j,ind)=NMI(ind,j); - break; - - } - } -} - -void fullsimkernel::calculate_full_sim_kernel(){ - int cols; - - - /// Determine whether calulating self similarity (therefore m_B=m_A) - if(m_B==NULL) - cols= m_A->Ncols(); + + if (m_B == NULL) + cols = m_A->Ncols(); else - cols= m_B->Ncols(); - - - for (unsigned int i=1; i <= m_A->Ncols(); i++){ - for (int j=1; j <= cols; j++){ - switch (_sim){ - case 1: - (*mp)(j,i)=-SSD(i,j); - break; - case 2: - (*mp)(j,i)=corr(i,j); - break; - case 3: - (*mp)(j,i)=NMI(i,j); - break; - - } - } + cols = m_B->Ncols(); + + for (int j = 1; j <= cols; j++) { + switch (_sim) { + case 1: + (*mp)(j, ind) = -SSD(ind, j); + break; + case 2: + (*mp)(j, ind) = corr(ind, j); + break; + case 3: + (*mp)(j, ind) = NMI(ind, j); + break; + } } - } - void fullsimkernel::calculate_NN_sim_kernel(){ - - - - - for (unsigned int i=1; i <= m_A->Ncols(); i++){ - switch (_sim){ - case 1: - (*mp)(i,i)=SSD(i,i); - break; - case 2: - (*mp)(i,i)=corr(i,i); - break; - case 3: - (*mp)(i,i)=NMI(i,i); - break; - - } - +void fullsimkernel::calculate_full_sim_kernel() +{ + + int cols; + + /// Determine whether calulating self similarity (therefore m_B=m_A) + if (m_B == NULL) + cols = m_A->Ncols(); + else + cols = m_B->Ncols(); + + for (unsigned int i = 1; i <= m_A->Ncols(); i++) { + for (int j = 1; j <= cols; j++) { + switch (_sim) { + case 1: + (*mp)(j, i) = -SSD(i, j); + break; + case 2: + (*mp)(j, i) = corr(i, j); + break; + case 3: + (*mp)(j, i) = NMI(i, j); + break; + } + } } - } +void fullsimkernel::calculate_NN_sim_kernel() +{ + for (unsigned int i = 1; i <= m_A->Ncols(); i++) { + switch (_sim) { + case 1: + (*mp)(i, i) = SSD(i, i); + break; + case 2: + (*mp)(i, i) = corr(i, i); + break; + case 3: + (*mp)(i, i) = NMI(i, i); + break; + } + } +} void fullsimkernel::Print(const std::string fname) const { - if (!fname.length()) cout << endl << *mp << endl; - else write_ascii_matrix(fname,*mp); + if (!fname.length()) + cout << endl + << *mp << endl; + else + write_ascii_matrix(fname, *mp); } - - - - - } - - diff --git a/src/DiscreteOpt/similarities.h b/src/DiscreteOpt/similarities.h index 109521f..3ca471d 100644 --- a/src/DiscreteOpt/similarities.h +++ b/src/DiscreteOpt/similarities.h @@ -6,16 +6,14 @@ /* CCOPYRIGHT */ /* class for calculating similarity between rows of connectivity matrices */ -/* SIM KERNEL IS COLUMN ORIENTATED TO BE CONSISTENT WITH SPARSE MAT COLUMN COMPRESSION - MESH REG ASSUMES EACH VERTEX IS REPRESENTED BY A COLUMN *//// - +/* SIM KERNEL IS COLUMN ORIENTATED TO BE CONSISTENT WITH SPARSE MAT COLUMN COMPRESSION - MESH REG ASSUMES EACH VERTEX IS REPRESENTED BY A COLUMN */ /// #if !defined(similarities_h) #define similarities_h +#include "newmesh/featurespace.h" #include #include -#include "newmesh/featurespace.h" - #define MAXREAL 1e6 #define MAXSIM 1e6 @@ -25,94 +23,94 @@ using namespace std; using namespace NEWMAT; using namespace MISCMATHS; - /* histogram class- used for information theoretic similarity measures */ /* 1d histogram class exists in miscmaths - */ -namespace DISCRETEOPT{ -class histogram2D{ - - - int m_nbinsx; - int m_nbinsy; - int _nsamps; - double m_min_x; - double m_min_y; - double m_max_x; - double m_max_y; - double m_width_x; - double m_width_y; - Matrix _bins; - Matrix _weights; - - public: - +namespace DISCRETEOPT { +class histogram2D { + + int m_nbinsx; + int m_nbinsy; + int _nsamps; + double m_min_x; + double m_min_y; + double m_max_x; + double m_max_y; + double m_width_x; + double m_width_y; + Matrix _bins; + Matrix _weights; + +public: //Constructor - histogram2D(){}; - - // Destructor - ~histogram2D(); - inline double operator()(int i, int j){return _bins(i,j);}; + histogram2D() {}; - void Initialize(int, int, double, double, double, double); - - /// this can be used to remove bin matrix if memory overheads are a consideration (i.e. when using a large number of separate histograms as in Costfunction.cc) - void Reset(){_bins.ReSize(0,0);_nsamps=0;}; - void Zero(); - void ReSize(int m, int n){_bins.ReSize(m,n);_bins=0;_nsamps=0;}; - - // add count for sample x,y - void AddSample(double, double); - void AddSample(double,double, double); // for weighted NMI + // Destructor + ~histogram2D(); + inline double operator()(int i, int j) { return _bins(i, j); }; - // delete count for sample x,y - void DeleteSample(double, double); + void Initialize(int, int, double, double, double, double); - /// Entropy calculations - double MarginalEntropyX(); - double MarginalEntropyY(); - double JointEntropy(); + /// this can be used to remove bin matrix if memory overheads are a consideration (i.e. when using a large number of separate histograms as in Costfunction.cc) + void Reset() + { + _bins.ReSize(0, 0); + _nsamps = 0; + }; + void Zero(); + void ReSize(int m, int n) + { + _bins.ReSize(m, n); + _bins = 0; + _nsamps = 0; + }; - // Normalised mutual Information - double normalisedmutualinformation(); + // add count for sample x,y + void AddSample(double, double); + void AddSample(double, double, double); // for weighted NMI + // delete count for sample x,y + void DeleteSample(double, double); - }; + /// Entropy calculations + double MarginalEntropyX(); + double MarginalEntropyY(); + double JointEntropy(); + // Normalised mutual Information + double normalisedmutualinformation(); +}; +class DISCRETEOPTHOCRException : public std::exception { - class DISCRETEOPTHOCRException : public std::exception{ - - public: +public: const char* errmesg; - + DISCRETEOPTHOCRException(const char* msg) - { - errmesg=msg; - } - + { + errmesg = msg; + } + virtual const char* what() const throw() { - std::cout< m_A; - boost::shared_ptr m_B; - + boost::shared_ptr m_A; + boost::shared_ptr m_B; + RowVector _rmeanA; //ROW-WISE MEAN RowVector _rmeanB; - + double _meanA; double _meanB; int _sim; @@ -121,306 +119,352 @@ class histogram2D{ double maxy; double minx; double miny; - + histogram2D hist; /// for NMI - boost::shared_ptr _rel; /// remembers nearest neighbours of each input mesh vertex + boost::shared_ptr _rel; /// remembers nearest neighbours of each input mesh vertex bool _issparse; // true if BFMATRIX is sparse; bool _initialised; - public: +public: //Constructors - options for sparse and regular matrices - - simkernel(){ maxx=0;maxy=0;minx=MAXREAL;miny=MAXREAL; _sim=1; _thr=0.0; _issparse=false;_initialised=false;}; - simkernel(unsigned int m, unsigned int n) { maxx=0;maxy=0;minx=MAXREAL;miny=MAXREAL;_sim=1; _thr=0.0;_issparse=false;_initialised=false;}; - + + simkernel() + { + maxx = 0; + maxy = 0; + minx = MAXREAL; + miny = MAXREAL; + _sim = 1; + _thr = 0.0; + _issparse = false; + _initialised = false; + }; + simkernel(unsigned int m, unsigned int n) + { + maxx = 0; + maxy = 0; + minx = MAXREAL; + miny = MAXREAL; + _sim = 1; + _thr = 0.0; + _issparse = false; + _initialised = false; + }; + // Destructor - virtual ~simkernel(){ } ; - + virtual ~simkernel() {}; + // Access as NEWMAT::Matrix virtual NEWMAT::ReturnMatrix AsMatrix() const = 0; - + // Basic properties virtual unsigned int Nrows() const = 0; virtual unsigned int Ncols() const = 0; - + virtual void Clear() = 0; virtual void Resize(unsigned int m, unsigned int n) = 0; // Print matrix (for debugging) - virtual void Print(const std::string fname=std::string("")) const = 0; - + virtual void Print(const std::string fname = std::string("")) const = 0; + // Accessing - inline double operator()(unsigned int r, unsigned int c) const {return(Peek(r,c));} - + inline double operator()(unsigned int r, unsigned int c) const { return (Peek(r, c)); } + virtual double Peek(unsigned int r, unsigned int c) const = 0; - + // Assigning virtual void Set(unsigned int x, unsigned int y, double val) = 0; - void set_simval(const int & val){_sim=val;} - inline void Set_thr(double T){_thr=T;}; + void set_simval(const int& val) { _sim = val; } + inline void Set_thr(double T) { _thr = T; }; //// INITIALIZE ///////////////////////// - - void set_input(BFMatrix &in ){ FullBFMatrix *pin = dynamic_cast(&in); if(pin) m_A = boost::shared_ptr(new FullBFMatrix (*pin)); else { SparseBFMatrix *psdin = dynamic_cast *>(&in); m_A = boost::shared_ptr(new SparseBFMatrix (*psdin)); _issparse=true;}}; - - void set_reference(BFMatrix &ref){ FullBFMatrix *pref = dynamic_cast(&ref); if(pref) m_B = boost::shared_ptr(new FullBFMatrix (*pref)); else { SparseBFMatrix *psdref = dynamic_cast *>(&ref); m_B = boost::shared_ptr(new SparseBFMatrix (*psdref));_issparse=true;}}; - - void set_input(boost::shared_ptr in ){ m_A = in;}; /// for use with featurespace class - featurespace creates the data and initialises the pointer - - void set_reference(boost::shared_ptr ref){ m_B =ref;};// for use with featurespace class - featurespace creates the data and initialises the pointer + + void set_input(BFMatrix& in) + { + FullBFMatrix* pin = dynamic_cast(&in); + if (pin) + m_A = boost::shared_ptr(new FullBFMatrix(*pin)); + else { + SparseBFMatrix* psdin = dynamic_cast*>(&in); + m_A = boost::shared_ptr(new SparseBFMatrix(*psdin)); + _issparse = true; + } + }; + + void set_reference(BFMatrix& ref) + { + FullBFMatrix* pref = dynamic_cast(&ref); + if (pref) + m_B = boost::shared_ptr(new FullBFMatrix(*pref)); + else { + SparseBFMatrix* psdref = dynamic_cast*>(&ref); + m_B = boost::shared_ptr(new SparseBFMatrix(*psdref)); + _issparse = true; + } + }; + + void set_input(boost::shared_ptr in) { m_A = in; }; /// for use with featurespace class - featurespace creates the data and initialises the pointer + + void set_reference(boost::shared_ptr ref) { m_B = ref; }; // for use with featurespace class - featurespace creates the data and initialises the pointer void set_input(string); - + void set_reference(string); - - void set_relations(boost::shared_ptr R) {_rel= R;}; - inline void release_data(){m_A.reset(); m_B.reset();}; + void set_relations(boost::shared_ptr R) { _rel = R; }; + + inline void release_data() + { + m_A.reset(); + m_B.reset(); + }; void Initialize(int); - void reset_histogram(){hist.Reset();}; // for minimising memory overheads - void zero_histogram(){hist.Zero();}; - void resize_histogram(int m,int n){hist.ReSize(m,n);}; - + void reset_histogram() { hist.Reset(); }; // for minimising memory overheads + void zero_histogram() { hist.Zero(); }; + void resize_histogram(int m, int n) { hist.ReSize(m, n); }; + //////// SIMILARITY MEASURES ///////////// - RowVector meanvector(const BFMatrix &); // for correlation measure - - void calc_range(boost::shared_ptr ,double&, double&); // for histogram based measures - void calc_range(const vector &, double &, double &); - - /// pearsons correlation + RowVector meanvector(const BFMatrix&); // for correlation measure + + void calc_range(boost::shared_ptr, double&, double&); // for histogram based measures + void calc_range(const vector&, double&, double&); + + /// pearsons correlation double corr(int, int); // sum of square differences double SSD(int, int); - + /// normalised mutual information double NMI(int, int); - + ////////////// FOR VECTOR FORMAT ///////////////// - void Initialize(int,const vector &, const vector &,const vector & weights= vector()); // weighted version + void Initialize(int, const vector&, const vector&, const vector& weights = vector()); // weighted version - double corr(const vector &, const vector &, const vector & weights= vector()); - double corr(const map &,const map &); + double corr(const vector&, const vector&, const vector& weights = vector()); + double corr(const map&, const map&); - double corrdebug(const int &i, Matrix &, const vector &, const vector &, const vector & weights= vector()); + double corrdebug(const int& i, Matrix&, const vector&, const vector&, const vector& weights = vector()); - double SSD(const vector &,const vector &,const vector & weights= vector()); + double SSD(const vector&, const vector&, const vector& weights = vector()); - double nSSD(const vector &,const vector &,const vector & weights= vector() ); + double nSSD(const vector&, const vector&, const vector& weights = vector()); - double NMI(const vector &, const vector &, const vector & weights= vector()); - + double NMI(const vector&, const vector&, const vector& weights = vector()); - vector alpha_entropy(vector > &, vector &, int &, const double &,vector > &); - + vector alpha_entropy(vector>&, vector&, int&, const double&, vector>&); /// calculate similiarity using similarity function chosen during initialisation i.e. SSD, corr etc - double get_sim_for_min(const vector &,const vector &,const vector& weights= vector()); - double get_sim_for_mindebug(const int &i, Matrix &, const vector &,const vector &,const vector& weights= vector()); - + double get_sim_for_min(const vector&, const vector&, const vector& weights = vector()); + double get_sim_for_mindebug(const int& i, Matrix&, const vector&, const vector&, const vector& weights = vector()); + double get_sim(int, int); - double get_sim_for_min(int , int ); - + double get_sim_for_min(int, int); + ///////////////////////////////////////////// - virtual void calculate_sim_column(int) =0; /// one input vertex at a time - - virtual void calculate_full_sim_kernel() =0; - virtual void calculate_NN_sim_kernel()=0; - - }; - - - ///// full and sparse simkernel are not currently used for discrete optimisation - template - class sparsesimkernel: public simkernel - { - - private: - boost::shared_ptr > mp; - - public: - - // Constructors, destructor and assignment - copied from bfmatrix simpler way? - sparsesimkernel() - : mp(boost::shared_ptr >(new MISCMATHS::SpMat())) {}; - sparsesimkernel(unsigned int m, unsigned int n) - : mp(boost::shared_ptr >(new MISCMATHS::SpMat(m,n))){}; - sparsesimkernel(unsigned int m, unsigned int n, const unsigned int *irp, const unsigned int *jcp, const double *sp) - : mp(boost::shared_ptr >(new MISCMATHS::SpMat(m,n,irp,jcp,sp))){}; - sparsesimkernel(const MISCMATHS::SpMat& M) - : mp(boost::shared_ptr >(new MISCMATHS::SpMat(M))){}; - sparsesimkernel(const NEWMAT::Matrix& M) - : mp(boost::shared_ptr >(new MISCMATHS::SpMat(M))) {}; + virtual void calculate_sim_column(int) = 0; /// one input vertex at a time + + virtual void calculate_full_sim_kernel() = 0; + virtual void calculate_NN_sim_kernel() = 0; +}; + +///// full and sparse simkernel are not currently used for discrete optimisation +template +class sparsesimkernel : public simkernel { + +private: + boost::shared_ptr> mp; + +public: + // Constructors, destructor and assignment - copied from bfmatrix simpler way? + sparsesimkernel() + : mp(boost::shared_ptr>(new MISCMATHS::SpMat())) {}; + sparsesimkernel(unsigned int m, unsigned int n) + : mp(boost::shared_ptr>(new MISCMATHS::SpMat(m, n))) {}; + sparsesimkernel(unsigned int m, unsigned int n, const unsigned int* irp, const unsigned int* jcp, const double* sp) + : mp(boost::shared_ptr>(new MISCMATHS::SpMat(m, n, irp, jcp, sp))) {}; + sparsesimkernel(const MISCMATHS::SpMat& M) + : mp(boost::shared_ptr>(new MISCMATHS::SpMat(M))) {}; + sparsesimkernel(const NEWMAT::Matrix& M) + : mp(boost::shared_ptr>(new MISCMATHS::SpMat(M))) {}; virtual ~sparsesimkernel() {}; - virtual const sparsesimkernel& operator=(const sparsesimkernel& M) { - mp = boost::shared_ptr >(new MISCMATHS::SpMat(*(M.mp))); return(*this); + virtual const sparsesimkernel& operator=(const sparsesimkernel& M) + { + mp = boost::shared_ptr>(new MISCMATHS::SpMat(*(M.mp))); + return (*this); }; // Access as NEWMAT::Matrix - virtual NEWMAT::ReturnMatrix AsMatrix() const {NEWMAT::Matrix ret; ret = mp->AsNEWMAT(); ret.Release(); return(ret);}; - + virtual NEWMAT::ReturnMatrix AsMatrix() const + { + NEWMAT::Matrix ret; + ret = mp->AsNEWMAT(); + ret.Release(); + return (ret); + }; + // Basic properties - virtual unsigned int Nrows() const {return(mp->Nrows());}; - virtual unsigned int Ncols() const {return(mp->Ncols());}; - - virtual void Clear() {mp = boost::shared_ptr >(new MISCMATHS::SpMat());} - virtual void Resize(unsigned int m, unsigned int n) {mp = boost::shared_ptr >(new MISCMATHS::SpMat(m,n));} - + virtual unsigned int Nrows() const { return (mp->Nrows()); }; + virtual unsigned int Ncols() const { return (mp->Ncols()); }; + + virtual void Clear() { mp = boost::shared_ptr>(new MISCMATHS::SpMat()); } + virtual void Resize(unsigned int m, unsigned int n) { mp = boost::shared_ptr>(new MISCMATHS::SpMat(m, n)); } + // Accessing values - virtual double Peek(unsigned int r, unsigned int c) const {return(mp->Peek(r,c));} + virtual double Peek(unsigned int r, unsigned int c) const { return (mp->Peek(r, c)); } // Setting and inserting values - virtual void Set(unsigned int x, unsigned int y, double val) {mp->Set(x,y,val);} + virtual void Set(unsigned int x, unsigned int y, double val) { mp->Set(x, y, val); } // Print matrix (for debugging) - virtual void Print(const std::string fname=std::string("")) const {mp->Print(fname);}; + virtual void Print(const std::string fname = std::string("")) const { mp->Print(fname); }; // connectivity matrices will require transposing due to column compressed sparse mat format - taking path rather than object to save duplication of memory. - virtual void calculate_sim_column(int); - - virtual void calculate_full_sim_kernel() ; + + virtual void calculate_full_sim_kernel(); void calculate_NN_sim_kernel(); - }; +}; + +class fullsimkernel : public simkernel { +private: + boost::shared_ptr mp; - class fullsimkernel : public simkernel - { - private: - boost::shared_ptr mp; - public: +public: // Constructors, destructor and assignment - fullsimkernel() {mp = boost::shared_ptr(new NEWMAT::Matrix());}; - fullsimkernel(unsigned int m, unsigned int n) {mp = boost::shared_ptr(new NEWMAT::Matrix(m,n));}; - fullsimkernel(const MISCMATHS::SpMat& M) {mp = boost::shared_ptr(new NEWMAT::Matrix(M.AsNEWMAT()));}; - fullsimkernel(const NEWMAT::Matrix& M) {mp = boost::shared_ptr(new NEWMAT::Matrix(M));}; + fullsimkernel() { mp = boost::shared_ptr(new NEWMAT::Matrix()); }; + fullsimkernel(unsigned int m, unsigned int n) { mp = boost::shared_ptr(new NEWMAT::Matrix(m, n)); }; + fullsimkernel(const MISCMATHS::SpMat& M) { mp = boost::shared_ptr(new NEWMAT::Matrix(M.AsNEWMAT())); }; + fullsimkernel(const NEWMAT::Matrix& M) { mp = boost::shared_ptr(new NEWMAT::Matrix(M)); }; virtual ~fullsimkernel() {}; - virtual const fullsimkernel& operator=(const fullsimkernel& M) { - mp = boost::shared_ptr(new NEWMAT::Matrix(*(M.mp))); return(*this); + virtual const fullsimkernel& operator=(const fullsimkernel& M) + { + mp = boost::shared_ptr(new NEWMAT::Matrix(*(M.mp))); + return (*this); }; - virtual NEWMAT::ReturnMatrix AsMatrix() const {NEWMAT::Matrix ret; ret = *mp; ret.Release(); return(ret);}; - virtual const NEWMAT::Matrix& ReadAsMatrix() const {return(*mp);} ; + virtual NEWMAT::ReturnMatrix AsMatrix() const + { + NEWMAT::Matrix ret; + ret = *mp; + ret.Release(); + return (ret); + }; + virtual const NEWMAT::Matrix& ReadAsMatrix() const { return (*mp); }; // Basic properties - virtual unsigned int Nrows() const {return(mp->Nrows());}; - virtual unsigned int Ncols() const {return(mp->Ncols());}; - virtual void Clear() {mp->ReSize(0,0);} - virtual void Resize(unsigned int m, unsigned int n) {mp->ReSize(m,n);}; - + virtual unsigned int Nrows() const { return (mp->Nrows()); }; + virtual unsigned int Ncols() const { return (mp->Ncols()); }; + virtual void Clear() { mp->ReSize(0, 0); } + virtual void Resize(unsigned int m, unsigned int n) { mp->ReSize(m, n); }; + // Print matrix (for debugging) - virtual void Print(const std::string fname=std::string("")) const; - + virtual void Print(const std::string fname = std::string("")) const; + // Accessing values - virtual double Peek(unsigned int r, unsigned int c) const {return((*mp)(r,c));}; - - // Setting and inserting values. - virtual void Set(unsigned int x, unsigned int y, double val) {(*mp)(x,y)=val;} - + virtual double Peek(unsigned int r, unsigned int c) const { return ((*mp)(r, c)); }; + + // Setting and inserting values. + virtual void Set(unsigned int x, unsigned int y, double val) { (*mp)(x, y) = val; } + // functions for calculating full similarity kernel for whichever sim measure - virtual void calculate_sim_column(int); - - virtual void calculate_full_sim_kernel() ; + virtual void calculate_sim_column(int); + + virtual void calculate_full_sim_kernel(); void calculate_NN_sim_kernel(); - }; - +}; - template - void sparsesimkernel::calculate_sim_column(int ind){ +template +void sparsesimkernel::calculate_sim_column(int ind) +{ RowVector A, B; - - if(!_rel.get()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix");} - - - - for (int j=1; j <= _rel->Nrows(ind); j++){ - if((*_rel)(j,ind)){ - switch (_sim){ - case 1: - mp->Set((int)(*_rel)(j,ind),ind,-SSD(ind,(int)(*_rel)(j,ind))); - - break; - case 2: - mp->Set((int)(*_rel)(j,ind),ind,corr(ind,(int)(*_rel)(j,ind))); - break; - case 3: - mp->Set((int)(*_rel)(j,ind),ind,NMI(ind,(int)(*_rel)(j,ind))); - break; - } - - } + + if (!_rel.get()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix"); } - - } - - template - void sparsesimkernel::calculate_NN_sim_kernel(){ - - - if(!_rel.get()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix");} - - - if((unsigned int) _rel->Ncols() != (unsigned int) m_A->Ncols()){ - throw DISCRETEOPTHOCRException("SIMILARITIES::connectivity matrix and mesh have incompatible dimensions ");} - - - for (unsigned int i=1; i <= m_A->Ncols(); i++){ - - if((*_rel)(1,i)){ - switch (_sim){ - case 1: - mp->Set((int)(*_rel)(1,i),i,SSD(i,(int) (*_rel)(1,i))); - break; - case 2: - mp->Set((int)(*_rel)(1,i),i,corr(i,(int) (*_rel)(1,i))); - break; - case 3: - mp->Set((int)(*_rel)(1,i),i,NMI(i,(int) (*_rel)(1,i))); - break; - } - } + + for (int j = 1; j <= _rel->Nrows(ind); j++) { + if ((*_rel)(j, ind)) { + switch (_sim) { + case 1: + mp->Set((int)(*_rel)(j, ind), ind, -SSD(ind, (int)(*_rel)(j, ind))); + + break; + case 2: + mp->Set((int)(*_rel)(j, ind), ind, corr(ind, (int)(*_rel)(j, ind))); + break; + case 3: + mp->Set((int)(*_rel)(j, ind), ind, NMI(ind, (int)(*_rel)(j, ind))); + break; + } + } } - } - - - - - -template -void sparsesimkernel::calculate_full_sim_kernel(){ - - - if(!_rel.get()){ throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix");} - - - if((unsigned int) _rel->Ncols() != (unsigned int) m_A->Ncols()){ - throw DISCRETEOPTHOCRException("SIMILARITIES::connectivity matrix and mesh have incompatible dimensions ");} - - - - for (unsigned int i=1; i <= m_A->Ncols(); i++){ - - for (int j=1; j <= _rel->Nrows(i); j++){ - if((*_rel)(j,i)){ - - switch (_sim){ - case 1: - mp->Set((int)(*_rel)(j,i),i,SSD(i,(int) (*_rel)(j,i))); - break; - case 2: - mp->Set((int)(*_rel)(j,i),i,corr(i,(int) (*_rel)(j,i))); - break; - case 3: - mp->Set((int)(*_rel)(j,i),i,NMI(i,(int) (*_rel)(j,i))); - break; - } - } +} + +template +void sparsesimkernel::calculate_NN_sim_kernel() +{ + + if (!_rel.get()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix"); } - } - - - } + + if ((unsigned int)_rel->Ncols() != (unsigned int)m_A->Ncols()) { + throw DISCRETEOPTHOCRException("SIMILARITIES::connectivity matrix and mesh have incompatible dimensions "); + } + + for (unsigned int i = 1; i <= m_A->Ncols(); i++) { + + if ((*_rel)(1, i)) { + switch (_sim) { + case 1: + mp->Set((int)(*_rel)(1, i), i, SSD(i, (int)(*_rel)(1, i))); + break; + case 2: + mp->Set((int)(*_rel)(1, i), i, corr(i, (int)(*_rel)(1, i))); + break; + case 3: + mp->Set((int)(*_rel)(1, i), i, NMI(i, (int)(*_rel)(1, i))); + break; + } + } + } +} + +template +void sparsesimkernel::calculate_full_sim_kernel() +{ + + if (!_rel.get()) { + throw DISCRETEOPTHOCRException("SIMILARITIES:: calculate_sim_column must set RELATIONS matrix"); + } + + if ((unsigned int)_rel->Ncols() != (unsigned int)m_A->Ncols()) { + throw DISCRETEOPTHOCRException("SIMILARITIES::connectivity matrix and mesh have incompatible dimensions "); + } + + for (unsigned int i = 1; i <= m_A->Ncols(); i++) { + + for (int j = 1; j <= _rel->Nrows(i); j++) { + if ((*_rel)(j, i)) { + + switch (_sim) { + case 1: + mp->Set((int)(*_rel)(j, i), i, SSD(i, (int)(*_rel)(j, i))); + break; + case 2: + mp->Set((int)(*_rel)(j, i), i, corr(i, (int)(*_rel)(j, i))); + break; + case 3: + mp->Set((int)(*_rel)(j, i), i, NMI(i, (int)(*_rel)(j, i))); + break; + } + } + } + } +} } #endif diff --git a/src/MSM/calculatevertexwisecorr.cc b/src/MSM/calculatevertexwisecorr.cc index 944728b..2efdb88 100644 --- a/src/MSM/calculatevertexwisecorr.cc +++ b/src/MSM/calculatevertexwisecorr.cc @@ -5,10 +5,10 @@ Copyright (C) 2012 University of Oxford */ /* CCOPYRIGHT */ -#include -#include -#include "newmesh/meshfns.h" #include "MeshReg/meshreg.h" +#include "newmesh/meshfns.h" +#include +#include using namespace std; using namespace MISCMATHS; @@ -17,101 +17,100 @@ using namespace MESHREG; void Usage() { - cout << "calculatevertexwisecorr " << endl; - cout << "Input are func files assumes surfaces have been resampled to same mesh " << endl; - cout << " options: " << endl; - cout << "-compare X compare correlation to this file " << endl; + cout << "calculatevertexwisecorr " << endl; + cout << "Input are func files assumes surfaces have been resampled to same mesh " << endl; + cout << " options: " << endl; + cout << "-compare X compare correlation to this file " << endl; } -int main( int argc, char **argv ) +int main(int argc, char** argv) { - newmesh SURFACE1, SURFACE2, OUTSURF,COMP; - vector data1,data2; - string outputname; - sparsesimkernel sim; - double correlation,sum=0.0; - bool _compare=false; - int ok=0; - - if(argc < 3){ - - Usage(); - exit(0); - } - - SURFACE1.load(argv[1],false,false); - argc--; - argv++; - SURFACE2.load(argv[1],false,false); - argc--; - argv++; - outputname=argv[1]; - argc--; - argv++; - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-compare") == 0)){ - argc--; - argv++; - _compare=true; - COMP.load(argv[1],false,true); - argc--; - argv++; - ok = 1; + newmesh SURFACE1, SURFACE2, OUTSURF, COMP; + vector data1, data2; + string outputname; + sparsesimkernel sim; + double correlation, sum = 0.0; + bool _compare = false; + int ok = 0; + + if (argc < 3) { + + Usage(); + exit(0); } - } - OUTSURF=SURFACE1; - - OUTSURF.clear_data(); - ColumnVector allcorr(SURFACE1.npvalues()); - - if(SURFACE1.npvalues()!=SURFACE2.npvalues() || SURFACE1.get_dimension()!=SURFACE2.get_dimension()) { cout << " surfaces have different number of vertices, or features abort! " << endl; exit(1);} - - if(SURFACE1.get_dimension()==1){ - for (int i=0;i 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-compare") == 0)) { + argc--; + argv++; + _compare = true; + COMP.load(argv[1], false, true); + argc--; + argv++; + ok = 1; + } } - OUTSURF.save(outputname+"DIFF.func.gii"); + OUTSURF = SURFACE1; + + OUTSURF.clear_data(); + ColumnVector allcorr(SURFACE1.npvalues()); - } + if (SURFACE1.npvalues() != SURFACE2.npvalues() || SURFACE1.get_dimension() != SURFACE2.get_dimension()) { + cout << " surfaces have different number of vertices, or features abort! " << endl; + exit(1); + } + if (SURFACE1.get_dimension() == 1) { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + data1.push_back(SURFACE1.get_pvalue(i)); + data2.push_back(SURFACE2.get_pvalue(i)); + } + correlation = sim.corr(data1, data2); + cout << " mean=" << correlation << endl; + } else { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + data1.clear(); + data2.clear(); + + for (int j = 0; j < SURFACE1.get_dimension(); j++) { + data1.push_back(SURFACE1.get_pvalue(i, j)); + data2.push_back(SURFACE2.get_pvalue(i, j)); + } + correlation = sim.corr(data1, data2); + allcorr(i + 1) = correlation; + + sum += correlation; + } + + OUTSURF.set_pvalues(allcorr); + double mean, var = 0.0; + mean = sum / SURFACE1.npvalues(); + for (int i = 0; i < SURFACE1.npvalues(); i++) + var += (OUTSURF.get_pvalue(i) - mean) * (OUTSURF.get_pvalue(i) - mean); + + var /= SURFACE1.npvalues(); + + cout << " mean=" << mean << endl; + cout << " var=" << var << endl; + + OUTSURF.save(outputname + ".func.gii"); + } + if (_compare) { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + double diff = OUTSURF.get_pvalue(i) - COMP.get_pvalue(i); + OUTSURF.set_pvalue(i, diff); + } + OUTSURF.save(outputname + "DIFF.func.gii"); + } } diff --git a/src/MSM/estimate_curvature.cc b/src/MSM/estimate_curvature.cc index fca314b..336e76f 100644 --- a/src/MSM/estimate_curvature.cc +++ b/src/MSM/estimate_curvature.cc @@ -7,17 +7,16 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include -#include -#include -#include -#include -#include +#include "newimage/newimageall.h" #include "newmat.h" #include "newmatio.h" #include "utils/options.h" -#include "newimage/newimageall.h" - +#include +#include +#include +#include +#include +#include #include "MeshReg/meshreg.h" @@ -29,112 +28,109 @@ using namespace MESHREG; void Usage() { - cout << "estimate_curvature <-option> " << endl; - cout << " estimates mean curvature by fiting a least-squares quadratic patch to the local neighborhood of a vertex f(x,y) = ax^2 + by^2 + cxy + dx + ey + f (inspired by patchcuvature.m the matlab function " << endl; - cout << " options: " << endl; - cout << " -fit-radius default 2 " << endl; - cout << " " << endl; + cout << "estimate_curvature <-option> " << endl; + cout << " estimates mean curvature by fiting a least-squares quadratic patch to the local neighborhood of a vertex f(x,y) = ax^2 + by^2 + cxy + dx + ey + f (inspired by patchcuvature.m the matlab function " << endl; + cout << " options: " << endl; + cout << " -fit-radius default 2 " << endl; + cout << " " << endl; } +int main(int argc, char** argv) +{ + + newmesh ORIG, SPHERE; + string outdir; + double fit_radius = 2, smoothval = 2.0; + boost::shared_ptr REL; + bool _calcrel = false, _smooth = false; + bool _outputrho = false; + int ok; + + if (argc < 3) { -int main(int argc, char **argv){ - - - newmesh ORIG,SPHERE; - string outdir; - double fit_radius=2, smoothval=2.0; - boost::shared_ptr REL; - bool _calcrel=false,_smooth=false; - bool _outputrho=false; - int ok; - - if(argc < 3){ - - Usage(); - exit(0); - } - - - ORIG.load(argv[1]); - argc--; - argv++; - outdir=argv[1]; - argc--; - argv++; - - - while (argc > 1) { - ok = 0; - - if((ok == 0) && (strcmp(argv[1], "-fit-radius") == 0)){ - argc--; - argv++; - fit_radius=atof(argv[1]); - argc--; - argv++; - ok=1; + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-sphere") == 0)){ - argc--; - argv++; - SPHERE.load(argv[1]); - _calcrel=true; - argc--; - argv++; - ok=1; + + ORIG.load(argv[1]); + argc--; + argv++; + outdir = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + + if ((ok == 0) && (strcmp(argv[1], "-fit-radius") == 0)) { + argc--; + argv++; + fit_radius = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-sphere") == 0)) { + argc--; + argv++; + SPHERE.load(argv[1]); + _calcrel = true; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-smooth") == 0)) { + argc--; + argv++; + _smooth = true; + smoothval = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-rho") == 0)) { + argc--; + argv++; + _outputrho = true; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } + } + + if (_calcrel) { + REL = boost::shared_ptr(new RELATIONS(SPHERE, SPHERE, 3 * asin(fit_radius / RAD))); + REL->update_RELATIONS(SPHERE); } - else if((ok == 0) && (strcmp(argv[1], "-smooth") == 0)){ - argc--; - argv++; - _smooth=true; - smoothval=atof(argv[1]); - argc--; - argv++; - ok=1; + cout << " estimate curvature " << endl; + mean_curvature(fit_radius, ORIG, REL); + + if (_smooth) { + if (!_calcrel) { + cout << " need sphere for smoothing currently " << endl; + exit(1); + } + resampler R; + boost::shared_ptr scalardata; + boost::shared_ptr EXCL; + scalardata = boost::shared_ptr(new FullBFMatrix(1, SPHERE.nvertices())); + R.set_method("GAUSSIAN"); + + for (int i = 0; i < ORIG.nvertices(); i++) + scalardata->Set(1, i + 1, ORIG.get_pvalue(i)); + + R.resampledata(SPHERE, SPHERE, EXCL, scalardata, smoothval, REL); + + for (int i = 0; i < ORIG.nvertices(); i++) + ORIG.set_pvalue(i, scalardata->Peek(1, i + 1)); } - else if((ok == 0) && (strcmp(argv[1], "-rho") == 0)){ - argc--; - argv++; - _outputrho=true; - ok=1; - } else{cout << " option doesn't exist " << endl; exit(1);} - } - - if(_calcrel){ - REL=boost::shared_ptr(new RELATIONS (SPHERE,SPHERE,3*asin(fit_radius/RAD))); - REL->update_RELATIONS(SPHERE); - } - cout << " estimate curvature " << endl; - mean_curvature(fit_radius,ORIG,REL); - - if(_smooth){ - if(!_calcrel) {cout << " need sphere for smoothing currently " << endl; exit(1);} - resampler R; - boost::shared_ptr scalardata; - boost::shared_ptr EXCL; - scalardata =boost::shared_ptr (new FullBFMatrix (1,SPHERE.nvertices())); - R.set_method("GAUSSIAN"); - - for (int i=0;iSet(1,i+1,ORIG.get_pvalue(i)); - - R.resampledata(SPHERE,SPHERE,EXCL,scalardata,smoothval,REL) ; - - for (int i=0;iPeek(1,i+1)); - - } - char filename[1000]; - sprintf(filename,"%s-meancurvature.func",outdir.c_str()); - ORIG.save(filename); - if(_outputrho){ - - for (int i=0;i -#include -#include -#include -#include -#include +#include "newimage/newimageall.h" #include "newmat.h" #include "newmatio.h" #include "utils/options.h" -#include "newimage/newimageall.h" - +#include +#include +#include +#include +#include +#include #include "MeshReg/meshreg.h" @@ -29,82 +28,84 @@ using namespace MESHREG; void Usage() { - cout << "estimate_metric_distortion < output> <-option> " << endl; - cout << " Compares triangle areas before and after registration - can be used to assess strength of regularisation" << endl; - cout << " options: " << endl; - cout << " -target project result onto a target image (requires argument)" << endl; - cout << " -abs take absolute value " << endl; - + cout << "estimate_metric_distortion < output> <-option> " << endl; + cout << " Compares triangle areas before and after registration - can be used to assess strength of regularisation" << endl; + cout << " options: " << endl; + cout << " -target project result onto a target image (requires argument)" << endl; + cout << " -abs take absolute value " << endl; } +int main(int argc, char** argv) +{ + + newmesh ORIG, TRANSFORMED, TARG, DISTMAP; + resampler R; + string outdir; + boost::shared_ptr EXCL; + int ok; + bool _targ = false, _abs = false; + if (argc < 4) { -int main(int argc, char **argv){ - - - newmesh ORIG, TRANSFORMED,TARG,DISTMAP; - resampler R; - string outdir; - boost::shared_ptr EXCL; - int ok; - bool _targ=false,_abs=false; - if(argc < 4){ - - Usage(); - exit(0); - } - - - ORIG.load(argv[1]); - argc--; - argv++; - TRANSFORMED.load(argv[1]); - argc--; - argv++; - outdir=argv[1]; - argc--; - argv++; - - TARG=TRANSFORMED; - - while (argc > 1) { - ok = 0; - - if((ok == 0) && (strcmp(argv[1], "-target") == 0)){ - argc--; - argv++; - _targ=true; - TARG.load(argv[1]); - argc--; - argv++; - ok = 1; - }if((ok == 0) && (strcmp(argv[1], "-abs") == 0)){ - argc--; - argv++; - _abs=true; - ok = 1; + Usage(); + exit(0); + } + + ORIG.load(argv[1]); + argc--; + argv++; + TRANSFORMED.load(argv[1]); + argc--; + argv++; + outdir = argv[1]; + argc--; + argv++; + + TARG = TRANSFORMED; + + while (argc > 1) { + ok = 0; + + if ((ok == 0) && (strcmp(argv[1], "-target") == 0)) { + argc--; + argv++; + _targ = true; + TARG.load(argv[1]); + argc--; + argv++; + ok = 1; + } + if ((ok == 0) && (strcmp(argv[1], "-abs") == 0)) { + argc--; + argv++; + _abs = true; + ok = 1; + } + + else { + cout << " option doesn't exist " << endl; + exit(1); + } + } + + DISTMAP = TRANSFORMED; + ColumnVector distortion = getarealdistortion(ORIG, TRANSFORMED); + double meandist = 0; + double val = 0; + for (int i = 0; i < DISTMAP.nvertices(); i++) { + if (_abs == true) + val = abs(distortion(i + 1)); + else + val = distortion(i + 1); + DISTMAP.set_pvalue(i, val); + meandist += val; + } + meandist /= DISTMAP.nvertices(); + cout << " mean=" << meandist << endl; + DISTMAP.save(outdir + "distortion.func"); + + if (_targ) { + double MVD = Calculate_MVD(TRANSFORMED); + R.resample_scalar(DISTMAP, TARG, asin(MVD / (2 * RAD)), EXCL); + DISTMAP.save(outdir + "distortion_on_target.func"); } - - else{cout << " option doesn't exist " << endl; exit(1);} - } - - - - DISTMAP=TRANSFORMED; - ColumnVector distortion=getarealdistortion(ORIG,TRANSFORMED); - double meandist=0; - double val=0; - for(int i=0;i -#include -#include -#include -#include -#include +#include "newimage/newimageall.h" #include "newmat.h" #include "newmatio.h" #include "utils/options.h" -#include "newimage/newimageall.h" - +#include +#include +#include +#include +#include +#include #include "MeshReg/meshreg.h" @@ -29,107 +28,106 @@ using namespace MESHREG; void Usage() { - cout << "estimate_strains <-option> " << endl; - cout << " estimates principal strains tangent to surface" << endl; - cout << " options: " << endl; - cout << " -fit-radius default 2 " << endl; - cout << " -sphere X.surf.gii supply input sphere for approximate neighbourhood searching (will speed up calculation) " << endl; - cout <<"-bulk bulk modulus (default 10) " << endl; - cout << "-shear shear modulus (default 10) " << endl; - - cout << " " << endl; + cout << "estimate_strains <-option> " << endl; + cout << " estimates principal strains tangent to surface" << endl; + cout << " options: " << endl; + cout << " -fit-radius default 2 " << endl; + cout << " -sphere X.surf.gii supply input sphere for approximate neighbourhood searching (will speed up calculation) " << endl; + cout << "-bulk bulk modulus (default 10) " << endl; + cout << "-shear shear modulus (default 10) " << endl; + + cout << " " << endl; } +int main(int argc, char** argv) +{ -int main(int argc, char **argv){ - - clock_t start = clock(); - - newmesh ORIG, TRANSFORMED, STRAINS,SPHERE; - boost::shared_ptr VECS; VECS= boost::shared_ptr (new Matrix); - string outdir; - double fit_radius=0; - double MU=0.1,KAPPA=10; - boost::shared_ptr REL; - boost::shared_ptr SPHERETMP; - int ok; - bool _targ=false,_calcrel=false; - if(argc < 4){ - - Usage(); - exit(0); - } + clock_t start = clock(); + + newmesh ORIG, TRANSFORMED, STRAINS, SPHERE; + boost::shared_ptr VECS; + VECS = boost::shared_ptr(new Matrix); + string outdir; + double fit_radius = 0; + double MU = 0.1, KAPPA = 10; + boost::shared_ptr REL; + boost::shared_ptr SPHERETMP; + int ok; + bool _targ = false, _calcrel = false; + if (argc < 4) { + + Usage(); + exit(0); + } - - ORIG.load(argv[1]); - argc--; - argv++; - TRANSFORMED.load(argv[1]); - argc--; - argv++; - outdir=argv[1]; - argc--; - argv++; - - - while (argc > 1) { - ok = 0; - - if((ok == 0) && (strcmp(argv[1], "-fit-radius") == 0)){ - argc--; - argv++; - fit_radius=atof(argv[1]); - argc--; - argv++; - ok=1; + ORIG.load(argv[1]); + argc--; + argv++; + TRANSFORMED.load(argv[1]); + argc--; + argv++; + outdir = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + + if ((ok == 0) && (strcmp(argv[1], "-fit-radius") == 0)) { + argc--; + argv++; + fit_radius = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-sphere") == 0)) { + argc--; + argv++; + SPHERE.load(argv[1]); + _calcrel = true; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-bulk") == 0)) { + argc--; + argv++; + KAPPA = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-shear") == 0)) { + argc--; + argv++; + MU = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "-sphere") == 0)){ - argc--; - argv++; - SPHERE.load(argv[1]); - _calcrel=true; - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-bulk") == 0)){ - argc--; - argv++; - KAPPA=atof(argv[1]); - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-shear") == 0)){ - argc--; - argv++; - MU=atof(argv[1]); - argc--; - argv++; - ok=1; - } else{cout << " option doesn't exist " << endl; exit(1);} - } - /* if(_calcrel){ + /* if(_calcrel){ REL=boost::shared_ptr(new RELATIONS (SPHERE,SPHERE,3*asin(fit_radius/RAD))); REL->update_RELATIONS(SPHERE); } */ - cout << " calculate strains " << MU << " " << KAPPA << endl; - ORIG.estimate_normals(); TRANSFORMED.estimate_normals(); - if(SPHERE.nvertices()==ORIG.nvertices()) { - SPHERETMP=boost::shared_ptr(new newmesh (SPHERE)); - } - - if(fit_radius>0) - STRAINS=calculate_strains(fit_radius,ORIG,TRANSFORMED,VECS,REL); - else - STRAINS=calculate_triangular_strains(ORIG,TRANSFORMED,MU,KAPPA); + cout << " calculate strains " << MU << " " << KAPPA << endl; + ORIG.estimate_normals(); + TRANSFORMED.estimate_normals(); + if (SPHERE.nvertices() == ORIG.nvertices()) { + SPHERETMP = boost::shared_ptr(new newmesh(SPHERE)); + } + + if (fit_radius > 0) + STRAINS = calculate_strains(fit_radius, ORIG, TRANSFORMED, VECS, REL); + else + STRAINS = calculate_triangular_strains(ORIG, TRANSFORMED, MU, KAPPA); - - STRAINS.save(outdir+"strains.func"); + STRAINS.save(outdir + "strains.func"); - /* ofstream strain1,strain2; + /* ofstream strain1,strain2; strain1.open(outdir+"U1"); strain2.open(outdir+"U2"); diff --git a/src/MSM/intensity_normalise.cc b/src/MSM/intensity_normalise.cc index 74fa523..a3893c2 100644 --- a/src/MSM/intensity_normalise.cc +++ b/src/MSM/intensity_normalise.cc @@ -7,17 +7,16 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include -#include -#include -#include -#include -#include +#include "newimage/newimageall.h" #include "newmat.h" #include "newmatio.h" #include "utils/options.h" -#include "newimage/newimageall.h" - +#include +#include +#include +#include +#include +#include #include "MeshReg/meshreg.h" @@ -29,80 +28,78 @@ using namespace MESHREG; void Usage() { - cout << "intensity_normalise <-option> " << endl; - cout << "-option " << endl; - cout << " -exclin exclude zeros for input mesh" << endl; - cout << " -exclref exclude zeros for reference mesh" << endl; + cout << "intensity_normalise <-option> " << endl; + cout << "-option " << endl; + cout << " -exclin exclude zeros for input mesh" << endl; + cout << " -exclref exclude zeros for reference mesh" << endl; - cout << " " << endl; + cout << " " << endl; } +int main(int argc, char** argv) +{ + + boost::shared_ptr DATAIN; // holds generic BFMATRIX data which can be sparse or full matrices + boost::shared_ptr DATAREF; + boost::shared_ptr EXCL_IN, EXCL_REF; + int ok = 0; + newmesh ORIG, TARGET; + bool _exclude_in = false, _exclude_ref = false, _scale = false; + string output; + + if (argc < 5) { -int main(int argc, char **argv){ - - boost::shared_ptr DATAIN; // holds generic BFMATRIX data which can be sparse or full matrices - boost::shared_ptr DATAREF; - boost::shared_ptr EXCL_IN, EXCL_REF; -int ok=0; - newmesh ORIG, TARGET; - bool _exclude_in=false, _exclude_ref=false, _scale=false; - string output; - - if(argc < 5){ - - Usage(); - exit(0); - } - - - ORIG.load(argv[1]); - argc--; - argv++; - TARGET.load(argv[1]); - argc--; - argv++; - set_data(argv[1],DATAIN,ORIG); - argc--; - argv++; - set_data(argv[1],DATAREF,TARGET); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-exclin") == 0)){ - argc--; - argv++; - _exclude_in=true; - ok = 1; + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-exclref") == 0)){ - argc--; - argv++; - _exclude_ref=true; - ok = 1; + + ORIG.load(argv[1]); + argc--; + argv++; + TARGET.load(argv[1]); + argc--; + argv++; + set_data(argv[1], DATAIN, ORIG); + argc--; + argv++; + set_data(argv[1], DATAREF, TARGET); + argc--; + argv++; + output = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-exclin") == 0)) { + argc--; + argv++; + _exclude_in = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-exclref") == 0)) { + argc--; + argv++; + _exclude_ref = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-scale") == 0)) { + argc--; + argv++; + _scale = true; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "-scale") == 0)){ - argc--; - argv++; - _scale=true; - ok = 1; + + if (_exclude_in) { + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(ORIG, DATAIN->AsMatrix(), 0, 0))); } - else{cout << " option doesn't exist " << endl; exit(1);} - } - - if(_exclude_in){ - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(ORIG,DATAIN->AsMatrix(),0,0))); - } - if(_exclude_ref){ - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(TARGET,DATAREF->AsMatrix(),0,0))); - } - - multivariate_histogram_normalization(*DATAIN,*DATAREF,EXCL_IN,EXCL_REF,_scale); - ORIG.set_pvalues(DATAIN->AsMatrix()); - ORIG.save(output); - + if (_exclude_ref) { + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(TARGET, DATAREF->AsMatrix(), 0, 0))); + } + + multivariate_histogram_normalization(*DATAIN, *DATAREF, EXCL_IN, EXCL_REF, _scale); + ORIG.set_pvalues(DATAIN->AsMatrix()); + ORIG.save(output); } diff --git a/src/MSM/minimise_anat-to-sphere_distortions.cc b/src/MSM/minimise_anat-to-sphere_distortions.cc index 499ab46..60cfed5 100644 --- a/src/MSM/minimise_anat-to-sphere_distortions.cc +++ b/src/MSM/minimise_anat-to-sphere_distortions.cc @@ -7,12 +7,11 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include -#include -#include -#include #include +#include +#include #include +#include #include #include "MeshReg/meshreg.h" @@ -25,217 +24,218 @@ using namespace MESHREG; void Usage() { - cout << "minimise_anat-to-sphere_distortion < output> <-option> " << endl; - cout << " Relaxes sphere vertex locations to minimise distorions" << endl; - cout << "options" << endl; - cout << "-levels " << endl; - cout << "-resolutions_per_level (argument is a comma separated list) " << endl; - cout << "-iters (argument is a comma separated list, needs to have as many items as resolutions) " << endl; - cout << "-setexp " << endl; - cout << "-bulk bulk modulus parameter (default 10)" << endl; - cout << "-shear shear modulus parameter (default 0.1)" << endl; + cout << "minimise_anat-to-sphere_distortion < output> <-option> " << endl; + cout << " Relaxes sphere vertex locations to minimise distorions" << endl; + cout << "options" << endl; + cout << "-levels " << endl; + cout << "-resolutions_per_level (argument is a comma separated list) " << endl; + cout << "-iters (argument is a comma separated list, needs to have as many items as resolutions) " << endl; + cout << "-setexp " << endl; + cout << "-bulk bulk modulus parameter (default 10)" << endl; + cout << "-shear shear modulus parameter (default 0.1)" << endl; +} +vector read_stringstream(string params) +{ + vector list; + int i; + std::stringstream ss(params); + while (ss >> i) { + list.push_back(i); + + if (ss.peek() == ',') + ss.ignore(); + } + return list; } +int main(int argc, char** argv) +{ + + newmesh ANAT, SPHERE; + newmesh ANATres, SPHEREres, ico; + newmesh controlgrid, transformed_controlgrid; + double energy = 0, newenergy = 0; + double mu = 0.1, kappa = 10, rexp = 1.0; + + boost::shared_ptr MODEL; -vector read_stringstream(string params){ - vector list; - int i; - std::stringstream ss(params); - while (ss >> i) - { - list.push_back(i); + string outdir; + int ok, resolutionlevels = 1, iter; + string iters; + string resolutions; + double area_anat, area_sphere, maxnorm = 0; + std::vector anat_res(1, 5), iters_res(1, 5); + bool _debug = true; - if (ss.peek() == ',') - ss.ignore(); + if (argc < 4) { + + Usage(); + exit(0); } - return list; -} -int main(int argc, char **argv){ - - - newmesh ANAT, SPHERE; - newmesh ANATres, SPHEREres,ico; - newmesh controlgrid, transformed_controlgrid; - double energy=0,newenergy=0; - double mu=0.1,kappa=10,rexp=1.0; - - boost::shared_ptr MODEL; - - string outdir; - int ok,resolutionlevels=1,iter; - string iters; - string resolutions; - double area_anat,area_sphere,maxnorm=0; - std::vector anat_res(1,5),iters_res(1,5); - bool _debug=true; - - if(argc < 4){ - - Usage(); - exit(0); - } - - - ANAT.load(argv[1]); - argc--; - argv++; - SPHERE.load(argv[1]); - argc--; - argv++; - outdir=argv[1]; - argc--; - argv++; - - - while (argc > 1) { - ok = 0; - cout << argv[1] << endl; - - if((ok == 0) && (strcmp(argv[1], "-levels") == 0)){ - argc--; - argv++; - resolutionlevels=atoi(argv[1]); - cout << " levels " << resolutionlevels << endl; - - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-iters") == 0)){ - argc--; - argv++; - iters=argv[1]; - iters_res=read_stringstream(iters); - cout << " iterations " << iters_res[0] << endl; - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-setexp") == 0)){ - argc--; - argv++; - rexp=atof(argv[1]); - cout << " exp " << rexp << endl; - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-bulk") == 0)){ - argc--; - argv++; - kappa=atof(argv[1]); - cout << " kappa " << kappa << endl; - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-shear") == 0)){ - argc--; - argv++; - mu=atof(argv[1]); - cout << " mu " << mu << endl; - argc--; - argv++; - ok=1; - } - else if((ok == 0) && (strcmp(argv[1], "-resolutions_per_level") == 0)){ - argc--; - argv++; - resolutions=argv[1]; - anat_res=read_stringstream(resolutions); - argc--; - argv++; - ok=1; - } - else{cout << " option doesn't exist " << endl; exit(1);} - } - - - - char filename[1000]; - newmesh STRAINS,SPHEREnew; - double totstrains=0,tristrain=0; - Reduction HOCR_mode=HOCR; - true_rescale(SPHERE,RAD); - SPHEREnew=SPHERE; - SPHEREnew=calculate_triangular_strains(ANAT,SPHEREnew,mu,kappa); - sprintf(filename,"%sSTRAINShiINIT.func",outdir.c_str()); - - SPHEREnew.save(filename); - for(int it=0;it(new MetricDistortionDiscreteModel(anat_res[it]+2,mu,kappa,rexp)); - MODEL->reset_meshspace(ANATres); - cout << it << " init strains " << totstrains<< endl; - - MODEL->Initialize(SPHEREres); - if(it>0){ MODEL->warp_CPgrid(controlgrid,transformed_controlgrid) ; SPHEREres=MODEL->get_CPgrid(); } - - if(_debug) MODEL->set_debug(); - iter=0; - while(iter < iters_res[it]){ - cout << " iter " << iter << " iters_res[it] " << endl; - MODEL->setupCostFunction(); - int *Labels=MODEL->getLabeling(); - newenergy=Fusion::optimize(MODEL,HOCR_mode,_debug); - - MODEL->applyLabeling(); - if(iter>0 && iter%2==0 && newenergy>=energy) { cout << iter << "energy" << energy << " newenergy " << newenergy << " level has converged" << (iter-1) %2 << endl; break;} - for (int i = 0; i get_CPgrid(); - // unfold(transformed_controlgrid); --- is unfold going to be necessary??? - //MODEL->reset_CPgrid(transformed_controlgrid); - //transformed_controlgrid.save(filename); - - totstrains=0; - for(int i=0;iget_CPgrid(); - controlgrid=ico; - - } - sprintf(filename,"%sSPHERE.LR.surf",outdir.c_str()); - transformed_controlgrid.save(filename); - transformed_controlgrid=calculate_triangular_strains(ANATres,transformed_controlgrid,mu,kappa); - sprintf(filename,"%sSTRAINS.LR.func",outdir.c_str()); - transformed_controlgrid.save(filename); - barycentric_mesh_interpolation(SPHEREnew,controlgrid,transformed_controlgrid); - sprintf(filename,"%sSPHERE.surf",outdir.c_str()); - SPHEREnew.save(filename); - SPHEREnew=calculate_triangular_strains(ANAT,SPHEREnew,mu,kappa); - sprintf(filename,"%sSTRAINShi.func",outdir.c_str()); - - SPHEREnew.save(filename); - SPHEREnew=SPHERE; + ANAT.load(argv[1]); + argc--; + argv++; + SPHERE.load(argv[1]); + argc--; + argv++; + outdir = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + cout << argv[1] << endl; + + if ((ok == 0) && (strcmp(argv[1], "-levels") == 0)) { + argc--; + argv++; + resolutionlevels = atoi(argv[1]); + cout << " levels " << resolutionlevels << endl; + + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-iters") == 0)) { + argc--; + argv++; + iters = argv[1]; + iters_res = read_stringstream(iters); + cout << " iterations " << iters_res[0] << endl; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-setexp") == 0)) { + argc--; + argv++; + rexp = atof(argv[1]); + cout << " exp " << rexp << endl; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-bulk") == 0)) { + argc--; + argv++; + kappa = atof(argv[1]); + cout << " kappa " << kappa << endl; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-shear") == 0)) { + argc--; + argv++; + mu = atof(argv[1]); + cout << " mu " << mu << endl; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-resolutions_per_level") == 0)) { + argc--; + argv++; + resolutions = argv[1]; + anat_res = read_stringstream(resolutions); + argc--; + argv++; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } + } + char filename[1000]; + newmesh STRAINS, SPHEREnew; + double totstrains = 0, tristrain = 0; + Reduction HOCR_mode = HOCR; + true_rescale(SPHERE, RAD); + SPHEREnew = SPHERE; + SPHEREnew = calculate_triangular_strains(ANAT, SPHEREnew, mu, kappa); + sprintf(filename, "%sSTRAINShiINIT.func", outdir.c_str()); + + SPHEREnew.save(filename); + for (int it = 0; it < resolutionlevels; it++) { + cout << " Initialising level " << it + 1 << " " << anat_res[it] << endl; + + ico.make_mesh_from_icosa(anat_res[it]); + true_rescale(ico, RAD); + SPHEREres = ico; + ANATres = mesh_resample(ANAT, SPHERE, SPHEREres); + STRAINS = ANATres; + + if (it == (resolutionlevels - 1)) { + sprintf(filename, "%sSPHEREINIT.LR.surf", outdir.c_str()); + SPHEREres.save(filename); + sprintf(filename, "%sANAT.LR.surf", outdir.c_str()); + ANATres.save(filename); + } + + totstrains = 0; + for (int i = 0; i < STRAINS.ntriangles(); i++) { + tristrain = calculate_triangular_strain(i, ANATres, SPHEREres, mu, kappa); + totstrains += tristrain; + //cout << i << " STRAINS.get_pvalue(i) " << tristrain <(new MetricDistortionDiscreteModel(anat_res[it] + 2, mu, kappa, rexp)); + MODEL->reset_meshspace(ANATres); + cout << it << " init strains " << totstrains << endl; + + MODEL->Initialize(SPHEREres); + if (it > 0) { + MODEL->warp_CPgrid(controlgrid, transformed_controlgrid); + SPHEREres = MODEL->get_CPgrid(); + } + + if (_debug) + MODEL->set_debug(); + iter = 0; + while (iter < iters_res[it]) { + cout << " iter " << iter << " iters_res[it] " << endl; + MODEL->setupCostFunction(); + int* Labels = MODEL->getLabeling(); + newenergy = Fusion::optimize(MODEL, HOCR_mode, _debug); + + MODEL->applyLabeling(); + if (iter > 0 && iter % 2 == 0 && newenergy >= energy) { + cout << iter << "energy" << energy << " newenergy " << newenergy << " level has converged" << (iter - 1) % 2 << endl; + break; + } + for (int i = 0; i < SPHEREres.nvertices(); i++) { + cout << i << " _iter " << iter << " label " << Labels[i] << endl; + } + //sprintf(filename,"SPHEREres-%d-iter-%d.surf",it,iter); + transformed_controlgrid = MODEL->get_CPgrid(); + // unfold(transformed_controlgrid); --- is unfold going to be necessary??? + //MODEL->reset_CPgrid(transformed_controlgrid); + //transformed_controlgrid.save(filename); + + totstrains = 0; + for (int i = 0; i < STRAINS.ntriangles(); i++) { + tristrain = calculate_triangular_strain(i, ANATres, transformed_controlgrid, mu, kappa); + totstrains += tristrain; + // cout << i << " STRAINS.get_pvalue(i) " << tristrain <get_CPgrid(); + controlgrid = ico; + } + sprintf(filename, "%sSPHERE.LR.surf", outdir.c_str()); + transformed_controlgrid.save(filename); + transformed_controlgrid = calculate_triangular_strains(ANATres, transformed_controlgrid, mu, kappa); + sprintf(filename, "%sSTRAINS.LR.func", outdir.c_str()); + transformed_controlgrid.save(filename); + barycentric_mesh_interpolation(SPHEREnew, controlgrid, transformed_controlgrid); + sprintf(filename, "%sSPHERE.surf", outdir.c_str()); + SPHEREnew.save(filename); + SPHEREnew = calculate_triangular_strains(ANAT, SPHEREnew, mu, kappa); + sprintf(filename, "%sSTRAINShi.func", outdir.c_str()); + + SPHEREnew.save(filename); + SPHEREnew = SPHERE; } diff --git a/src/MSM/msm.cc b/src/MSM/msm.cc index ef3294d..ffa3067 100644 --- a/src/MSM/msm.cc +++ b/src/MSM/msm.cc @@ -8,8 +8,6 @@ #include "MeshReg/meshreg.h" #include "msmOptions.h" - - #include "newran.h" #include @@ -20,83 +18,98 @@ using namespace MESHREG; msmOptions* msmOptions::gopt = NULL; - - -int main(int argc, char *argv[]) { - - msmOptions& opts = msmOptions::getInstance(); - Log& logger = LogSingleton::getInstance(); - string CMpathin; - - opts.parse_command_line(argc,argv,logger); - //opts.parse_command_line(argc,argv); - MeshReg MR; - - //// INITIALISE VARIABLES //////////////////// - if(opts.printoptions.value()){ MR.print_config_options(); return 0; } - // if(opts.version.value()){ cout << " MSM_XS version 0.0" << endl; return 0; } - if(opts.verbose.value()) MR.set_verbosity(opts.verbose.value()); - if(opts.debug.value()) MR.set_debug(opts.debug.value()); - - MR.set_input(opts.inputmesh.value()); - if(opts.referencemesh.value()=="") MR.set_reference(opts.inputmesh.value()); - else MR.set_reference(opts.referencemesh.value()); - - ////// add anatomical meshes for stress and strain //////////// - if(opts.inputanatmesh.value()!=""){ - if(opts.referenceanatmesh.value()=="") { cout << " Error: must supply both anatomical meshes or none "<< endl; exit(1);} - MR.set_anatomical(opts.inputanatmesh.value(),opts.referenceanatmesh.value()); - } - - MR.set_outdir(opts.outbase.value()); - MR.set_output_format(opts.outformat.value()); - - - if(opts.transformed_sphere.set()) MR.set_transformed(opts.transformed_sphere.value()); - if(opts.cfweight_in.set()) MR.set_input_cfweighting(opts.cfweight_in.value()); - if(opts.cfweight_ref.set()) MR.set_reference_cfweighting(opts.cfweight_ref.value()); - - if(opts.in_register.set()){ - //// if data is supplied at a different resolution to the input or transformed mesh it is necessary to resample i.e. HCP 32K to native - //// the in_register sphere HAS to be the sphere on which the data is supplied and the input or transformed mesh MUST be in alignment with it. - newmesh in_register, target; - resampler R; R.set_method("ADAP_BARY"); - boost::shared_ptr DATA; - char filename[1000]; - if(opts.transformed_sphere.set()) target.load(opts.transformed_sphere.value()); - else target.load(opts.inputmesh.value()); - - in_register.load(opts.in_register.value()); - set_data(opts.CMmatrixin.value(),DATA,in_register); - R.resampledata(in_register,target,DATA,0.1); - sprintf(filename,"%sinput_in_register.func.gii",opts.outbase.value().c_str()); - target.set_pvalues(DATA->AsMatrix()); - target.save(filename); - CMpathin=filename; - - }else CMpathin=opts.CMmatrixin.value(); - - MR.set_CMpathin(CMpathin); - MR.set_CMpathref(opts.CMmatrixref.value()); - - - MR.run_multiresolutions(opts.multiresolutionlevels.value(),opts.smoothoutput.value(),opts.parameters.value()); - - if(opts.in_register.set()){ - /// if data is supplied at a lower mesh resolution, then resample final warp accordingly. This is typically a HCP formating issue - newmesh ORIG, FINAL, in_register; - char filename[1000]; - - if(opts.transformed_sphere.set()) ORIG.load(opts.transformed_sphere.value()); - else ORIG.load(opts.inputmesh.value()); - - in_register.load(opts.in_register.value()); - sprintf(filename,"%ssphere.reg%s",opts.outbase.value().c_str(),MR.get_surf_format().c_str()); - - FINAL.load(filename); - barycentric_mesh_interpolation(in_register,ORIG,FINAL); - sprintf(filename,"%ssphere.in_register.reg.%s",opts.outbase.value().c_str(),MR.get_surf_format().c_str()); - in_register.save(filename); - - } +int main(int argc, char* argv[]) +{ + + msmOptions& opts = msmOptions::getInstance(); + Log& logger = LogSingleton::getInstance(); + string CMpathin; + + opts.parse_command_line(argc, argv, logger); + //opts.parse_command_line(argc,argv); + MeshReg MR; + + //// INITIALISE VARIABLES //////////////////// + if (opts.printoptions.value()) { + MR.print_config_options(); + return 0; + } + // if(opts.version.value()){ cout << " MSM_XS version 0.0" << endl; return 0; } + if (opts.verbose.value()) + MR.set_verbosity(opts.verbose.value()); + if (opts.debug.value()) + MR.set_debug(opts.debug.value()); + + MR.set_input(opts.inputmesh.value()); + if (opts.referencemesh.value() == "") + MR.set_reference(opts.inputmesh.value()); + else + MR.set_reference(opts.referencemesh.value()); + + ////// add anatomical meshes for stress and strain //////////// + if (opts.inputanatmesh.value() != "") { + if (opts.referenceanatmesh.value() == "") { + cout << " Error: must supply both anatomical meshes or none " << endl; + exit(1); + } + MR.set_anatomical(opts.inputanatmesh.value(), opts.referenceanatmesh.value()); + } + + MR.set_outdir(opts.outbase.value()); + MR.set_output_format(opts.outformat.value()); + + if (opts.transformed_sphere.set()) + MR.set_transformed(opts.transformed_sphere.value()); + if (opts.cfweight_in.set()) + MR.set_input_cfweighting(opts.cfweight_in.value()); + if (opts.cfweight_ref.set()) + MR.set_reference_cfweighting(opts.cfweight_ref.value()); + + if (opts.in_register.set()) { + //// if data is supplied at a different resolution to the input or transformed mesh it is necessary to resample i.e. HCP 32K to native + //// the in_register sphere HAS to be the sphere on which the data is supplied and the input or transformed mesh MUST be in alignment with it. + newmesh in_register, target; + resampler R; + R.set_method("ADAP_BARY"); + boost::shared_ptr DATA; + char filename[1000]; + if (opts.transformed_sphere.set()) + target.load(opts.transformed_sphere.value()); + else + target.load(opts.inputmesh.value()); + + in_register.load(opts.in_register.value()); + set_data(opts.CMmatrixin.value(), DATA, in_register); + R.resampledata(in_register, target, DATA, 0.1); + sprintf(filename, "%sinput_in_register.func.gii", opts.outbase.value().c_str()); + target.set_pvalues(DATA->AsMatrix()); + target.save(filename); + CMpathin = filename; + + } else + CMpathin = opts.CMmatrixin.value(); + + MR.set_CMpathin(CMpathin); + MR.set_CMpathref(opts.CMmatrixref.value()); + + MR.run_multiresolutions(opts.multiresolutionlevels.value(), opts.smoothoutput.value(), opts.parameters.value()); + + if (opts.in_register.set()) { + /// if data is supplied at a lower mesh resolution, then resample final warp accordingly. This is typically a HCP formating issue + newmesh ORIG, FINAL, in_register; + char filename[1000]; + + if (opts.transformed_sphere.set()) + ORIG.load(opts.transformed_sphere.value()); + else + ORIG.load(opts.inputmesh.value()); + + in_register.load(opts.in_register.value()); + sprintf(filename, "%ssphere.reg%s", opts.outbase.value().c_str(), MR.get_surf_format().c_str()); + + FINAL.load(filename); + barycentric_mesh_interpolation(in_register, ORIG, FINAL); + sprintf(filename, "%ssphere.in_register.reg.%s", opts.outbase.value().c_str(), MR.get_surf_format().c_str()); + in_register.save(filename); + } } diff --git a/src/MSM/msmGOptions.h b/src/MSM/msmGOptions.h index 5d7c72c..b3ec70a 100644 --- a/src/MSM/msmGOptions.h +++ b/src/MSM/msmGOptions.h @@ -11,13 +11,13 @@ #if !defined(msmGOptions_h) #define msmGOptions_h -#include -#include +#include "utils/log.h" +#include "utils/options.h" #include -#include +#include #include -#include "utils/options.h" -#include "utils/log.h" +#include +#include using namespace Utilities; using namespace NEWMESH; @@ -25,146 +25,142 @@ using namespace NEWMESH; class msmGOptions { public: - static msmGOptions& getInstance(); - ~msmGOptions() { delete gopt; } - - - Option help; - Option verbose; - Option printoptions; - Option version; - Option debug; - - Option meshes; - Option templatemesh; - Option data; - - Option outbase; - Option parameters; /// slowly replace most of these with the parameter file?? - // Option L1matlabpath; - - Option multiresolutionlevels; - Option smoothoutput; - - bool parse_command_line(int argc, char** argv,Log& logger); - - vector return_datarange(NEWMESH::newmesh); - private: - msmGOptions(); - const msmGOptions& operator=(msmGOptions&); - msmGOptions(msmGOptions&); - - OptionParser options; - - static msmGOptions* gopt; - + static msmGOptions& getInstance(); + ~msmGOptions() { delete gopt; } + + Option help; + Option verbose; + Option printoptions; + Option version; + Option debug; + + Option meshes; + Option templatemesh; + Option data; + + Option outbase; + Option parameters; /// slowly replace most of these with the parameter file?? + // Option L1matlabpath; + + Option multiresolutionlevels; + Option smoothoutput; + + bool parse_command_line(int argc, char** argv, Log& logger); + + vector return_datarange(NEWMESH::newmesh); + +private: + msmGOptions(); + const msmGOptions& operator=(msmGOptions&); + msmGOptions(msmGOptions&); + + OptionParser options; + + static msmGOptions* gopt; }; - inline msmGOptions& msmGOptions::getInstance(){ - - if(gopt == NULL) - gopt = new msmGOptions(); - - return *gopt; - } - -inline msmGOptions::msmGOptions() : - help(string("-h,--help"), false, - string("display this message"), - false, no_argument), - verbose(string("-v,--verbose"), false, - string("switch on diagnostic messages"), - false, no_argument), - printoptions(string("-p,--printoptions"), false, - string("print configuration file options"), - false, no_argument), - version(string("--version"), false, - string("report version informations"), - false, no_argument), - debug(string("--debug"), false, - string("run debugging or optimising options"), - false, no_argument), - meshes(string("--meshes"), string(""), - string("list of paths to input meshes (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), - true , requires_argument), - templatemesh(string("--template"), string(""), - string("templates sphere for resampling (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), - true , requires_argument), - data(string("--data"), string(""), - string("list of paths to the data"), - false , requires_argument), - outbase(string("-o,--out"), string(""), - string("output basename"), - true, requires_argument), - parameters(string("--conf"), string(""), - string("\tconfiguration file "), - false, requires_argument), - // L1matlabpath(string("--L1path"), string(""), - // string("\tPath to L1min matlab code"), - // false, requires_argument), - multiresolutionlevels(string("--levels"),0, - string("number of resolution levels (default = number of resolution levels specified by --opt in config file)"), - false, requires_argument), - smoothoutput(string("--smoothout"), 0, - string("smooth tranformed output with this sigma (default=0)"), - false, requires_argument), - - options("msm", "msm [options]\n") +inline msmGOptions& msmGOptions::getInstance() { - try { - - options.add(help); - options.add(verbose); - options.add(printoptions); - options.add(version); - options.add(debug); + + if (gopt == NULL) + gopt = new msmGOptions(); + + return *gopt; +} + +inline msmGOptions::msmGOptions() + : help(string("-h,--help"), false, + string("display this message"), + false, no_argument) + , verbose(string("-v,--verbose"), false, + string("switch on diagnostic messages"), + false, no_argument) + , printoptions(string("-p,--printoptions"), false, + string("print configuration file options"), + false, no_argument) + , version(string("--version"), false, + string("report version informations"), + false, no_argument) + , debug(string("--debug"), false, + string("run debugging or optimising options"), + false, no_argument) + , meshes(string("--meshes"), string(""), + string("list of paths to input meshes (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), + true, requires_argument) + , templatemesh(string("--template"), string(""), + string("templates sphere for resampling (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), + true, requires_argument) + , data(string("--data"), string(""), + string("list of paths to the data"), + false, requires_argument) + , outbase(string("-o,--out"), string(""), + string("output basename"), + true, requires_argument) + , parameters(string("--conf"), string(""), + string("\tconfiguration file "), + false, requires_argument) + , + // L1matlabpath(string("--L1path"), string(""), + // string("\tPath to L1min matlab code"), + // false, requires_argument), + multiresolutionlevels(string("--levels"), 0, + string("number of resolution levels (default = number of resolution levels specified by --opt in config file)"), + false, requires_argument) + , smoothoutput(string("--smoothout"), 0, + string("smooth tranformed output with this sigma (default=0)"), + false, requires_argument) + , + + options("msm", "msm [options]\n") +{ + try { + + options.add(help); + options.add(verbose); + options.add(printoptions); + options.add(version); + options.add(debug); options.add(meshes); options.add(templatemesh); options.add(data); - options.add(outbase); - options.add(parameters); - // options.add(L1matlabpath); - options.add(multiresolutionlevels); - options.add(smoothoutput); - } - catch(X_OptionError& e) { - options.usage(); - cerr << endl << e.what() << endl; - } - catch(std::exception &e) { - cerr << e.what() << endl; - } - - - -} - -inline bool msmGOptions::parse_command_line(int argc, char** argv,Log& logger){ - - - for(int a = options.parse_command_line(argc, argv); a < argc; a++) ; - if(!(printoptions.value() || version.value()) ){ - if(help.value() || ! options.check_compulsory_arguments()) - { - options.usage(); - //throw NEWMAT::Exception("Not all of the compulsory arguments have been provided"); - exit(2); - } - - logger.makeDir(outbase.value()+"logdir","MSM.log"); - - - - // do again so that options are logged - for(int a = 0; a < argc; a++) - logger.str() << argv[a] << " "; - - logger.str() << endl << "---------------------------------------------" << endl << endl; - } - return true; + options.add(outbase); + options.add(parameters); + // options.add(L1matlabpath); + options.add(multiresolutionlevels); + options.add(smoothoutput); + } catch (X_OptionError& e) { + options.usage(); + cerr << endl + << e.what() << endl; + } catch (std::exception& e) { + cerr << e.what() << endl; + } } +inline bool msmGOptions::parse_command_line(int argc, char** argv, Log& logger) +{ + for (int a = options.parse_command_line(argc, argv); a < argc; a++) + ; + if (!(printoptions.value() || version.value())) { + if (help.value() || !options.check_compulsory_arguments()) { + options.usage(); + //throw NEWMAT::Exception("Not all of the compulsory arguments have been provided"); + exit(2); + } + + logger.makeDir(outbase.value() + "logdir", "MSM.log"); + + // do again so that options are logged + for (int a = 0; a < argc; a++) + logger.str() << argv[a] << " "; + + logger.str() << endl + << "---------------------------------------------" << endl + << endl; + } + return true; +} /* inline vector msmOptions::return_datarange(NEWMESH::newmesh in){ */ @@ -172,7 +168,7 @@ inline bool msmGOptions::parse_command_line(int argc, char** argv,Log& logger){ /* int range2; */ /* int i; */ /* int indexval=index.value(); */ - + /* if(range.value()<1E-7){ */ /* range2=in.nvertices(); */ /* cout << " range2 " << range2 << endl;; */ @@ -188,12 +184,11 @@ inline bool msmGOptions::parse_command_line(int argc, char** argv,Log& logger){ /* // cout << " range " << range << " patch " < >::const_iterator i=in.vbegin();i!=in.vend();i++){ */ /* // cout << " here 1 " << (*i)->get_value() << endl; */ /* if(in.get_pvalue((*i)->get_no()) > 0){ */ - + /* V.push_back((*i)->get_no()+1); /// labels indexing runs from 1 !!! */ /* ind++; */ /* /// note this was in error before inasmuch as if I was using a patch I would count indexes from 0 but the datarange assumed indexing was running from 1 */ @@ -231,4 +226,3 @@ inline bool msmGOptions::parse_command_line(int argc, char** argv,Log& logger){ /* } */ #endif - diff --git a/src/MSM/msmOptions.h b/src/MSM/msmOptions.h index 218a908..3cdd8f0 100644 --- a/src/MSM/msmOptions.h +++ b/src/MSM/msmOptions.h @@ -11,13 +11,13 @@ #if !defined(msmOptions_h) #define msmOptions_h -#include -#include +#include "utils/log.h" +#include "utils/options.h" #include -#include +#include #include -#include "utils/options.h" -#include "utils/log.h" +#include +#include using namespace Utilities; using namespace NEWMESH; @@ -25,189 +25,183 @@ using namespace NEWMESH; class msmOptions { public: - static msmOptions& getInstance(); - ~msmOptions() { delete gopt; } - - - Option help; - Option verbose; - Option printoptions; - // Option version; - Option debug; - - - Option inputmesh; - Option referencemesh; - Option inputanatmesh; - Option referenceanatmesh; - - - Option CMmatrixin; - Option CMmatrixref; - - - Option transformed_sphere; - Option in_register; - - Option cfweight_in; - Option cfweight_ref; - - - Option outbase; - Option outformat; - Option parameters; /// slowly replace most of these with the parameter file?? - - Option multiresolutionlevels; - Option smoothoutput; - - bool parse_command_line(int argc, char** argv,Log& logger); - - vector return_datarange(NEWMESH::newmesh); - private: - msmOptions(); - const msmOptions& operator=(msmOptions&); - msmOptions(msmOptions&); - - OptionParser options; - - static msmOptions* gopt; - + static msmOptions& getInstance(); + ~msmOptions() { delete gopt; } + + Option help; + Option verbose; + Option printoptions; + // Option version; + Option debug; + + Option inputmesh; + Option referencemesh; + Option inputanatmesh; + Option referenceanatmesh; + + Option CMmatrixin; + Option CMmatrixref; + + Option transformed_sphere; + Option in_register; + + Option cfweight_in; + Option cfweight_ref; + + Option outbase; + Option outformat; + Option parameters; /// slowly replace most of these with the parameter file?? + + Option multiresolutionlevels; + Option smoothoutput; + + bool parse_command_line(int argc, char** argv, Log& logger); + + vector return_datarange(NEWMESH::newmesh); + +private: + msmOptions(); + const msmOptions& operator=(msmOptions&); + msmOptions(msmOptions&); + + OptionParser options; + + static msmOptions* gopt; }; - inline msmOptions& msmOptions::getInstance(){ - - if(gopt == NULL) - gopt = new msmOptions(); - - return *gopt; - } - -inline msmOptions::msmOptions() : - help(string("-h,--help"), false, - string("display this message"), - false, no_argument), - verbose(string("-v,--verbose"), false, - string("switch on diagnostic messages"), - false, no_argument), - printoptions(string("-p,--printoptions"), false, - string("print configuration file options"), - false, no_argument), - // version(string("--version"), false, - // string("report version informations"), - // false, no_argument), - debug(string("--debug"), false, - string("run debugging or optimising options"), - false, no_argument,false), - inputmesh(string("--inmesh"), string(""), - string("input mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), - true , requires_argument), - referencemesh(string("--refmesh"), string(""), - string("reference mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere. If not included algorithm assumes reference mesh is equivalent input"), - false , requires_argument), - inputanatmesh(string("--inanat"), string(""), - string("input anatomical mesh (available formats: VTK, ASCII, GIFTI). For Example, white, pial, midthickness (must either supply both input and reference anatomical surfaces or none)"), - false , requires_argument,false), - referenceanatmesh(string("--refanat"), string(""), - string("reference mesh (available formats: VTK, ASCII, GIFTI). For Example, white, pial, midthickness (must either supply both input and reference anatomical surfaces or none)"), - false , requires_argument,false), - - CMmatrixin(string("--indata"), string(""), - string("scalar or multivariate data for input - can be ASCII (.asc,.dpv,.txt) or GIFTI (.func.gii or .shape.gii) "), - false, requires_argument), - CMmatrixref(string("--refdata"), string(""), - string("scalar or multivariate data for reference - can be ASCII (.asc,.dpv,.txt) or GIFTI (.func.gii or .shape.gii) "), - false, requires_argument), - - transformed_sphere(string("--trans"), string(""), - string("\t Transformed source mesh (output of a previous registration). Use this to initiliase the current registration."), - false , requires_argument), - in_register(string("--in_register"), string(""), - string("\t Input mesh at data resolution. Used to resample data onto input mesh if data is supplied at a different resolution. Note this mesh HAS to be in alignment with either the input_mesh of (if supplied) the transformed source mesh. Use with supreme caution."), - false , requires_argument), - cfweight_in(string("--inweight"), string(""), - string("cost function weighting for input - weights data in these vertices when calculating similarity (ASCII or GIFTI). Can be multivariate provided dimension equals that of data "), - false , requires_argument), - cfweight_ref(string("--refweight"), string(""), - string("cost function weighting for reference - weights data in these vertices when calculating similarity (ASCII or GIFTI). Can be multivariate provided dimension equals that of data"), - false , requires_argument), - outbase(string("-o,--out"), string(""), - string("output basename"), - true, requires_argument), - outformat(string("-f,--format"), string("GIFTI"), - string("format of output files, can be: GIFTI, VTK, ASCII or ASCII_MAT (for full details of output file formats see MSM wiki)"), - false, requires_argument), - parameters(string("--conf"), string(""), - string("\tconfiguration file "), - false, requires_argument), - multiresolutionlevels(string("--levels"),0, - string("number of resolution levels (default = number of resolution levels specified by --opt in config file)"), - false, requires_argument), - smoothoutput(string("--smoothout"), 0, - string("smooth tranformed output with this sigma (default=0)"), - false, requires_argument), - - options("msm", "msm [options]\n") +inline msmOptions& msmOptions::getInstance() { - try { - - options.add(help); - options.add(verbose); - options.add(printoptions); - options.add(debug); + + if (gopt == NULL) + gopt = new msmOptions(); + + return *gopt; +} + +inline msmOptions::msmOptions() + : help(string("-h,--help"), false, + string("display this message"), + false, no_argument) + , verbose(string("-v,--verbose"), false, + string("switch on diagnostic messages"), + false, no_argument) + , printoptions(string("-p,--printoptions"), false, + string("print configuration file options"), + false, no_argument) + , + // version(string("--version"), false, + // string("report version informations"), + // false, no_argument), + debug(string("--debug"), false, + string("run debugging or optimising options"), + false, no_argument, false) + , inputmesh(string("--inmesh"), string(""), + string("input mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere"), + true, requires_argument) + , referencemesh(string("--refmesh"), string(""), + string("reference mesh (available formats: VTK, ASCII, GIFTI). Needs to be a sphere. If not included algorithm assumes reference mesh is equivalent input"), + false, requires_argument) + , inputanatmesh(string("--inanat"), string(""), + string("input anatomical mesh (available formats: VTK, ASCII, GIFTI). For Example, white, pial, midthickness (must either supply both input and reference anatomical surfaces or none)"), + false, requires_argument, false) + , referenceanatmesh(string("--refanat"), string(""), + string("reference mesh (available formats: VTK, ASCII, GIFTI). For Example, white, pial, midthickness (must either supply both input and reference anatomical surfaces or none)"), + false, requires_argument, false) + , + + CMmatrixin(string("--indata"), string(""), + string("scalar or multivariate data for input - can be ASCII (.asc,.dpv,.txt) or GIFTI (.func.gii or .shape.gii) "), + false, requires_argument) + , CMmatrixref(string("--refdata"), string(""), + string("scalar or multivariate data for reference - can be ASCII (.asc,.dpv,.txt) or GIFTI (.func.gii or .shape.gii) "), + false, requires_argument) + , + + transformed_sphere(string("--trans"), string(""), + string("\t Transformed source mesh (output of a previous registration). Use this to initiliase the current registration."), + false, requires_argument) + , in_register(string("--in_register"), string(""), + string("\t Input mesh at data resolution. Used to resample data onto input mesh if data is supplied at a different resolution. Note this mesh HAS to be in alignment with either the input_mesh of (if supplied) the transformed source mesh. Use with supreme caution."), + false, requires_argument) + , cfweight_in(string("--inweight"), string(""), + string("cost function weighting for input - weights data in these vertices when calculating similarity (ASCII or GIFTI). Can be multivariate provided dimension equals that of data "), + false, requires_argument) + , cfweight_ref(string("--refweight"), string(""), + string("cost function weighting for reference - weights data in these vertices when calculating similarity (ASCII or GIFTI). Can be multivariate provided dimension equals that of data"), + false, requires_argument) + , outbase(string("-o,--out"), string(""), + string("output basename"), + true, requires_argument) + , outformat(string("-f,--format"), string("GIFTI"), + string("format of output files, can be: GIFTI, VTK, ASCII or ASCII_MAT (for full details of output file formats see MSM wiki)"), + false, requires_argument) + , parameters(string("--conf"), string(""), + string("\tconfiguration file "), + false, requires_argument) + , multiresolutionlevels(string("--levels"), 0, + string("number of resolution levels (default = number of resolution levels specified by --opt in config file)"), + false, requires_argument) + , smoothoutput(string("--smoothout"), 0, + string("smooth tranformed output with this sigma (default=0)"), + false, requires_argument) + , + + options("msm", "msm [options]\n") +{ + try { + + options.add(help); + options.add(verbose); + options.add(printoptions); + options.add(debug); options.add(inputmesh); options.add(referencemesh); - options.add(inputanatmesh); + options.add(inputanatmesh); options.add(referenceanatmesh); - options.add(CMmatrixin); - options.add(CMmatrixref); - options.add(transformed_sphere); - options.add(in_register); - options.add(cfweight_in); - options.add(cfweight_ref); - options.add(outbase); - options.add(outformat); - options.add(parameters); - options.add(multiresolutionlevels); - options.add(smoothoutput); - } - catch(X_OptionError& e) { - options.usage(); - cerr << endl << e.what() << endl; - } - catch(std::exception &e) { - cerr << e.what() << endl; - } - - - -} - -inline bool msmOptions::parse_command_line(int argc, char** argv,Log& logger){ - - - for(int a = options.parse_command_line(argc, argv); a < argc; a++) ; - if(!(printoptions.value()) ){ - if(help.value() || ! options.check_compulsory_arguments()) - { - options.usage(); - //throw NEWMAT::Exception("Not all of the compulsory arguments have been provided"); - exit(2); - } - - logger.makeDir(outbase.value()+"logdir","MSM.log"); - - - - // do again so that options are logged - for(int a = 0; a < argc; a++) - logger.str() << argv[a] << " "; - - logger.str() << endl << "---------------------------------------------" << endl << endl; - } - return true; + options.add(CMmatrixin); + options.add(CMmatrixref); + options.add(transformed_sphere); + options.add(in_register); + options.add(cfweight_in); + options.add(cfweight_ref); + options.add(outbase); + options.add(outformat); + options.add(parameters); + options.add(multiresolutionlevels); + options.add(smoothoutput); + } catch (X_OptionError& e) { + options.usage(); + cerr << endl + << e.what() << endl; + } catch (std::exception& e) { + cerr << e.what() << endl; + } } +inline bool msmOptions::parse_command_line(int argc, char** argv, Log& logger) +{ + for (int a = options.parse_command_line(argc, argv); a < argc; a++) + ; + if (!(printoptions.value())) { + if (help.value() || !options.check_compulsory_arguments()) { + options.usage(); + //throw NEWMAT::Exception("Not all of the compulsory arguments have been provided"); + exit(2); + } + + logger.makeDir(outbase.value() + "logdir", "MSM.log"); + + // do again so that options are logged + for (int a = 0; a < argc; a++) + logger.str() << argv[a] << " "; + + logger.str() << endl + << "---------------------------------------------" << endl + << endl; + } + return true; +} /* inline vector msmOptions::return_datarange(NEWMESH::newmesh in){ */ @@ -215,7 +209,7 @@ inline bool msmOptions::parse_command_line(int argc, char** argv,Log& logger){ /* int range2; */ /* int i; */ /* int indexval=index.value(); */ - + /* if(range.value()<1E-7){ */ /* range2=in.nvertices(); */ /* cout << " range2 " << range2 << endl;; */ @@ -231,12 +225,11 @@ inline bool msmOptions::parse_command_line(int argc, char** argv,Log& logger){ /* // cout << " range " << range << " patch " < >::const_iterator i=in.vbegin();i!=in.vend();i++){ */ /* // cout << " here 1 " << (*i)->get_value() << endl; */ /* if(in.get_pvalue((*i)->get_no()) > 0){ */ - + /* V.push_back((*i)->get_no()+1); /// labels indexing runs from 1 !!! */ /* ind++; */ /* /// note this was in error before inasmuch as if I was using a patch I would count indexes from 0 but the datarange assumed indexing was running from 1 */ @@ -274,4 +267,3 @@ inline bool msmOptions::parse_command_line(int argc, char** argv,Log& logger){ /* } */ #endif - diff --git a/src/MSM/msm_group.cc b/src/MSM/msm_group.cc index be065a7..760194e 100644 --- a/src/MSM/msm_group.cc +++ b/src/MSM/msm_group.cc @@ -12,7 +12,6 @@ //#include "HOCR/QPBO.h" - #include "newran.h" #include @@ -23,32 +22,38 @@ using namespace MESHREG; msmGOptions* msmGOptions::gopt = NULL; +int main(int argc, char* argv[]) +{ - -int main(int argc, char *argv[]) { - - msmGOptions& opts = msmGOptions::getInstance(); - Log& logger = LogSingleton::getInstance(); - string CMpathin; + msmGOptions& opts = msmGOptions::getInstance(); + Log& logger = LogSingleton::getInstance(); + string CMpathin; - opts.parse_command_line(argc,argv,logger); - //opts.parse_command_line(argc,argv); - GroupMeshReg MR; + opts.parse_command_line(argc, argv, logger); + //opts.parse_command_line(argc,argv); + GroupMeshReg MR; - //// INITIALISE VARIABLES //////////////////// - if(opts.printoptions.value()){ MR.print_config_options(); return 0; } - if(opts.version.value()){ cout << " MSM_XS version 0.0" << endl; return 0; } - if(opts.verbose.value()) MR.set_verbosity(opts.verbose.value()); - if(opts.debug.value()) MR.set_debug(opts.debug.value()); + //// INITIALISE VARIABLES //////////////////// + if (opts.printoptions.value()) { + MR.print_config_options(); + return 0; + } + if (opts.version.value()) { + cout << " MSM_XS version 0.0" << endl; + return 0; + } + if (opts.verbose.value()) + MR.set_verbosity(opts.verbose.value()); + if (opts.debug.value()) + MR.set_debug(opts.debug.value()); - MR.set_inputs(opts.meshes.value()); - MR.set_template(opts.templatemesh.value()); - MR.set_data_list(opts.data.value()); + MR.set_inputs(opts.meshes.value()); + MR.set_template(opts.templatemesh.value()); + MR.set_data_list(opts.data.value()); - MR.set_outdir(opts.outbase.value()); + MR.set_outdir(opts.outbase.value()); - // MR.set_matlab(opts.L1matlabpath.value()); + // MR.set_matlab(opts.L1matlabpath.value()); - MR.run_multiresolutions(opts.multiresolutionlevels.value(),opts.smoothoutput.value(),opts.parameters.value()); - + MR.run_multiresolutions(opts.multiresolutionlevels.value(), opts.smoothoutput.value(), opts.parameters.value()); } diff --git a/src/MSM/msm_makeicos.cc b/src/MSM/msm_makeicos.cc index 6107392..8c7150f 100644 --- a/src/MSM/msm_makeicos.cc +++ b/src/MSM/msm_makeicos.cc @@ -7,43 +7,38 @@ /* CCOPYRIGHT */ #include "newmat.h" #include "newmesh/meshfns.h" -#include /* clock_t, clock, CLOCKS_PER_SEC */ - - +#include /* clock_t, clock, CLOCKS_PER_SEC */ using namespace NEWMAT; using namespace NEWMESH; void Usage() -{ cout << " msm_makeicos " << endl; - +{ + cout << " msm_makeicos " << endl; } +int main(int argc, char** argv) +{ -int main(int argc, char **argv){ - + newmesh ico; + int res; + char filename[1000], out[1000]; - newmesh ico; - int res; - char filename[1000],out[1000]; + if (argc < 2) { - if(argc < 2){ + Usage(); + exit(0); + } - Usage(); - exit(0); - } + res = atoi(argv[1]); + argc--; + argv++; - - - res=atoi(argv[1]); - argc--; - argv++; - - - ico.make_mesh_from_icosa(res); true_rescale(ico,RAD); - sprintf(out," icosphere res: %d #vertices: %d ", res, ico.nvertices()); - cout << out << endl; + ico.make_mesh_from_icosa(res); + true_rescale(ico, RAD); + sprintf(out, " icosphere res: %d #vertices: %d ", res, ico.nvertices()); + cout << out << endl; - sprintf(filename,"ico-%d.surf.gii",res); - ico.save(filename); + sprintf(filename, "ico-%d.surf.gii", res); + ico.save(filename); } diff --git a/src/MSM/msm_metric_average.cc b/src/MSM/msm_metric_average.cc index 33d1641..70e7df8 100644 --- a/src/MSM/msm_metric_average.cc +++ b/src/MSM/msm_metric_average.cc @@ -1,15 +1,14 @@ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include -#include -#include -#include +#include "MeshReg/meshreg.h" +#include "newmesh/meshfns.h" +#include "utils/options.h" #include +#include +#include #include -#include "utils/options.h" -#include "newmesh/meshfns.h" -#include "MeshReg/meshreg.h" - +#include +#include using namespace std; using namespace MISCMATHS; @@ -18,330 +17,339 @@ using namespace MESHREG; void Usage() { - cout << "msm_metric_average <-options> " << endl; - cout << "options: " << endl; - cout << "-target " << endl; - cout << "-abs " << endl; - cout << "-weighted distances" << endl; - cout << "-sigma " << endl; - cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; - + cout << "msm_metric_average <-options> " << endl; + cout << "options: " << endl; + cout << "-target " << endl; + cout << "-abs " << endl; + cout << "-weighted distances" << endl; + cout << "-sigma " << endl; + cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; } +int main(int argc, char** argv) +{ + + boost::shared_ptr EXCL_ref; + SpMat* DATA = new SpMat(); + int ok; + int _avdim = 0; + double newval; + float _sigma; -int main(int argc, char **argv){ - - - boost::shared_ptr EXCL_ref; - SpMat *DATA =new SpMat(); - int ok; - int _avdim=0; - double newval; - float _sigma; - - NEWMESH::newmesh totalcounts; - - NEWMESH::newmesh IN, TARG, HISTTARG,AVERAGE,VARIANCE,Zscore; - - string output,excl_in,excl_ref; - vector distances; - - vector INlist,INsurflist; - vector INPUTS; - bool _isdatamatrix=false; - string subtype; - bool _exclude=false,_excludenorm=false,_normalize=false; - bool _abs=false,_weighted=false; - ColumnVector exclusion; - - if(argc < 2){ - - Usage(); - exit(0); - } - - INlist=read_ascii_list(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - newval=0.0; - excl_in="";excl_ref=""; - EXCL_ref=boost::shared_ptr(new NEWMESH::newmesh ()) ; - - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-target") == 0)){ - argc--; - argv++; - _isdatamatrix=1; - cout << " normalize " << argv[1] << endl; - TARG.load(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-inputsurfaces") == 0)){ - argc--; - argv++; - INsurflist=read_ascii_list(argv[1]); - if(INsurflist.size()!=INlist.size()){ cout << " surf list is not the same length as data list" << endl; exit(1); } - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-excl_in") == 0)){ - argc--; - argv++; - _exclude=1; - excl_in=argv[1]; - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-excl_ref") == 0)){ - argc--; - argv++; - _exclude=1; - excl_ref=argv[1]; - EXCL_ref->load(excl_ref,false,false); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-abs") == 0)){ - argc--; - argv++; - _abs=1; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-averagedim") == 0)){ - argc--; - argv++; - _avdim=atoi(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-weighted") == 0)){ - argc--; - argv++; - _weighted=true; - distances=read_ascii_list(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-sigma") == 0)){ - argc--; - argv++; - _sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; + NEWMESH::newmesh totalcounts; + + NEWMESH::newmesh IN, TARG, HISTTARG, AVERAGE, VARIANCE, Zscore; + + string output, excl_in, excl_ref; + vector distances; + + vector INlist, INsurflist; + vector INPUTS; + bool _isdatamatrix = false; + string subtype; + bool _exclude = false, _excludenorm = false, _normalize = false; + bool _abs = false, _weighted = false; + ColumnVector exclusion; + + if (argc < 2) { + + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-normalize") == 0)){ - argc--; - argv++; - _normalize=true; - HISTTARG.load_gifti(argv[1],false,false); - argc--; - argv++; - ok = 1; + + INlist = read_ascii_list(argv[1]); + argc--; + argv++; + output = argv[1]; + argc--; + argv++; + newval = 0.0; + excl_in = ""; + excl_ref = ""; + EXCL_ref = boost::shared_ptr(new NEWMESH::newmesh()); + + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-target") == 0)) { + argc--; + argv++; + _isdatamatrix = 1; + cout << " normalize " << argv[1] << endl; + TARG.load(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-inputsurfaces") == 0)) { + argc--; + argv++; + INsurflist = read_ascii_list(argv[1]); + if (INsurflist.size() != INlist.size()) { + cout << " surf list is not the same length as data list" << endl; + exit(1); + } + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl_in") == 0)) { + argc--; + argv++; + _exclude = 1; + excl_in = argv[1]; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl_ref") == 0)) { + argc--; + argv++; + _exclude = 1; + excl_ref = argv[1]; + EXCL_ref->load(excl_ref, false, false); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-abs") == 0)) { + argc--; + argv++; + _abs = 1; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-averagedim") == 0)) { + argc--; + argv++; + _avdim = atoi(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-weighted") == 0)) { + argc--; + argv++; + _weighted = true; + distances = read_ascii_list(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-sigma") == 0)) { + argc--; + argv++; + _sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-normalize") == 0)) { + argc--; + argv++; + _normalize = true; + HISTTARG.load_gifti(argv[1], false, false); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl") == 0)) { + argc--; + argv++; + _excludenorm = true; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "-excl") == 0)){ - argc--; - argv++; - _excludenorm=true; - ok = 1; + if (!_isdatamatrix) + TARG.load(INlist[0]); + if (excl_ref == "") { + *EXCL_ref = TARG; + + for (int i = 0; i < EXCL_ref->nvertices(); i++) { + EXCL_ref->set_pvalue(i, 1); + } } - else{cout << " option doesn't exist " << endl; exit(1);} - } - if(!_isdatamatrix)TARG.load(INlist[0]); - if(excl_ref==""){ - *EXCL_ref=TARG; - - for (int i=0;invertices();i++){ - EXCL_ref->set_pvalue(i,1); + + exclusion.ReSize(TARG.nvertices()); + exclusion = 1; + + /////////////// INITIALIZE ////////////////////// + int dim, vert; + subtype = INlist[0].substr(INlist[0].size() - 8, 4); + if (_isdatamatrix) { /// set average either to dimensions of target mesh or, assuming all data have been resampled already to the size of first input mesh + AVERAGE = TARG; + vert = TARG.nvertices(); + if (INsurflist.size() == 0) + IN = AVERAGE; + } else { + AVERAGE.load(INlist[0]); + vert = AVERAGE.nvertices(); } - } - - exclusion.ReSize(TARG.nvertices()); exclusion=1; - - /////////////// INITIALIZE ////////////////////// - int dim,vert; - subtype = INlist[0].substr(INlist[0].size()-8, 4); - if(_isdatamatrix){ /// set average either to dimensions of target mesh or, assuming all data have been resampled already to the size of first input mesh - AVERAGE=TARG; - vert=TARG.nvertices(); - if(INsurflist.size()==0) IN=AVERAGE; - } - else{ - AVERAGE.load(INlist[0]); - vert=AVERAGE.nvertices(); - } - - if(subtype=="func" || subtype=="hape" ){ // define dimension of data - IN.load(INlist[0],false,false); - dim=IN.get_dimension(); - }else { - DATA=new SpMat(INlist[0]); - if(DATA->Ncols()>DATA->Nrows()) dim=DATA->Nrows(); - else dim=DATA->Ncols(); - } - - - /// initialise average and variances to zero - Matrix tmpData(dim,vert); tmpData=0; - AVERAGE.set_pvalues(tmpData); - VARIANCE=AVERAGE; - Zscore=AVERAGE; - totalcounts=AVERAGE; - - int atlasdim=AVERAGE.get_dimension(); - double sumweighted=0; - vector weight(INlist.size(),1); - ///////////////////////////////////////////////////// - for (unsigned int i=0;i(INlist[i]); - IN.set_pvalues(DATA->AsNEWMAT()); - }else - IN.load(INlist[i]); - - if(IN.nvertices()!=TARG.nvertices() && TARG.nvertices()>0){ - //// resample data onto target - resampler R; R.set_method("ADAP_BARY"); - Matrix tmpDATA=IN.get_pvalues(); - R.resampledata(IN,TARG,tmpDATA,1); - IN=TARG; - IN.set_pvalues(tmpDATA); + + if (subtype == "func" || subtype == "hape") { // define dimension of data + IN.load(INlist[0], false, false); + dim = IN.get_dimension(); + } else { + DATA = new SpMat(INlist[0]); + if (DATA->Ncols() > DATA->Nrows()) + dim = DATA->Nrows(); + else + dim = DATA->Ncols(); } - //// options to intensity normalise - if(_normalize) { - Matrix DATAREF=HISTTARG.get_pvalues(); - Matrix DATAIN=IN.get_pvalues(); - boost::shared_ptr BFIN,BFREF; - boost::shared_ptr EXCL_IN, EXCL_REF; - BFIN = boost::shared_ptr(new FullBFMatrix (DATAIN)); - BFREF=boost::shared_ptr (new FullBFMatrix (DATAREF)); // - - if(_excludenorm){ - cout << " TARG.nvertices() " << TARG.nvertices() << " DATAREF.Ncols() " << DATAREF.Ncols() << endl; - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG,DATAIN,0,0))); - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG,DATAREF,0,0))); - - } - - multivariate_histogram_normalization(*BFIN,*BFREF,EXCL_IN,EXCL_REF,false); - //IN.set_pvalues(BFIN->AsMatrix()); - //char filename[1000]; - //sprintf(filename,"IN_norm-%d.func",i); - //IN.save(filename); - - - } - - INPUTS.push_back(IN); - boost::shared_ptr EXCL; - int dim=IN.get_dimension(); - if(dim!=atlasdim){cout << i << " dim " << dim << " atlasdim " << endl; throw MeshReg_error("Feature dimensions do not agree");} - - if(_weighted){ - if(_sigma==0){ cout << "must set sigma for weighted" <nvertices() " << EXCL_ref->nvertices() << endl; - for (int j=0;jget_pvalue(j) && abs(IN.get_pvalue(j,d)) > EPSILON){ - if(_abs) newval=AVERAGE.get_pvalue(j,d)+weight[i]*abs(IN.get_pvalue(j,d)); - else newval=AVERAGE.get_pvalue(j,d)+weight[i]*IN.get_pvalue(j,d); - totalcounts.set_pvalue(j,totalcounts.get_pvalue(j,d)+weight[i]*1,d); - AVERAGE.set_pvalue(j,newval,d); - }else{ - if(_exclude) - exclusion(j+1)=0; - } - - } - + /// initialise average and variances to zero + Matrix tmpData(dim, vert); + tmpData = 0; + AVERAGE.set_pvalues(tmpData); + VARIANCE = AVERAGE; + Zscore = AVERAGE; + totalcounts = AVERAGE; + + int atlasdim = AVERAGE.get_dimension(); + double sumweighted = 0; + vector weight(INlist.size(), 1); + ///////////////////////////////////////////////////// + for (unsigned int i = 0; i < INlist.size(); i++) { + cout << i << " " << INlist[i] << endl; + if (subtype == "func" || subtype == "hape") { + if (INsurflist.size() == INlist.size()) + IN.load(INsurflist[i]); + IN.load(INlist[i], false, false); + } else if (_isdatamatrix) { + DATA = new SpMat(INlist[i]); + IN.set_pvalues(DATA->AsNEWMAT()); + } else + IN.load(INlist[i]); + + if (IN.nvertices() != TARG.nvertices() && TARG.nvertices() > 0) { + //// resample data onto target + resampler R; + R.set_method("ADAP_BARY"); + Matrix tmpDATA = IN.get_pvalues(); + R.resampledata(IN, TARG, tmpDATA, 1); + IN = TARG; + IN.set_pvalues(tmpDATA); + } + + //// options to intensity normalise + if (_normalize) { + Matrix DATAREF = HISTTARG.get_pvalues(); + Matrix DATAIN = IN.get_pvalues(); + boost::shared_ptr BFIN, BFREF; + boost::shared_ptr EXCL_IN, EXCL_REF; + BFIN = boost::shared_ptr(new FullBFMatrix(DATAIN)); + BFREF = boost::shared_ptr(new FullBFMatrix(DATAREF)); // + + if (_excludenorm) { + cout << " TARG.nvertices() " << TARG.nvertices() << " DATAREF.Ncols() " << DATAREF.Ncols() << endl; + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG, DATAIN, 0, 0))); + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG, DATAREF, 0, 0))); + } + + multivariate_histogram_normalization(*BFIN, *BFREF, EXCL_IN, EXCL_REF, false); + //IN.set_pvalues(BFIN->AsMatrix()); + //char filename[1000]; + //sprintf(filename,"IN_norm-%d.func",i); + //IN.save(filename); + } + + INPUTS.push_back(IN); + boost::shared_ptr EXCL; + int dim = IN.get_dimension(); + if (dim != atlasdim) { + cout << i << " dim " << dim << " atlasdim " << endl; + throw MeshReg_error("Feature dimensions do not agree"); + } + + if (_weighted) { + if (_sigma == 0) { + cout << "must set sigma for weighted" << endl; + exit(1); + } + weight[i] = exp(-0.5 * ((atof(distances[i].c_str())) / _sigma) * ((atof(distances[i].c_str())) / _sigma)); + // sumweighted+=weight[i]; + cout << "distance " << distances[i] << " weight " << weight[i] << endl; + } //else{ sumweighted=1;} + cout << i << " weight " << weight[i] << endl; + // cout << " add to total ... " << IN.nvertices() << endl; + for (int d = 0; d < atlasdim; d++) { + cout << d << " atlasdim " << atlasdim << " dim " << dim << "EXCL_ref->nvertices() " << EXCL_ref->nvertices() << endl; + for (int j = 0; j < AVERAGE.nvertices(); j++) { + if (EXCL_ref->get_pvalue(j) && abs(IN.get_pvalue(j, d)) > EPSILON) { + if (_abs) + newval = AVERAGE.get_pvalue(j, d) + weight[i] * abs(IN.get_pvalue(j, d)); + else + newval = AVERAGE.get_pvalue(j, d) + weight[i] * IN.get_pvalue(j, d); + totalcounts.set_pvalue(j, totalcounts.get_pvalue(j, d) + weight[i] * 1, d); + AVERAGE.set_pvalue(j, newval, d); + } else { + if (_exclude) + exclusion(j + 1) = 0; + } + } + } + // cout <<" here "<< endl; } - // cout <<" here "<< endl; - } - - double sumav=0; - - for(int d=0;dget_pvalue(j) && exclusion(j+1)){ - if(_abs) newval=weight[i]*(abs(INPUTS[i].get_pvalue(j,d))-AVERAGE.get_pvalue(j,d)); - else newval=weight[i]*(INPUTS[i].get_pvalue(j,d)-AVERAGE.get_pvalue(j,d)); - newval=VARIANCE.get_pvalue(j,d)+newval*newval; - VARIANCE.set_pvalue(j,newval,d); - } - } + for (unsigned int i = 0; i < INlist.size(); i++) { + + for (int d = 0; d < atlasdim; d++) { + for (int j = 0; j < AVERAGE.nvertices(); j++) { + if (EXCL_ref->get_pvalue(j) && exclusion(j + 1)) { + if (_abs) + newval = weight[i] * (abs(INPUTS[i].get_pvalue(j, d)) - AVERAGE.get_pvalue(j, d)); + else + newval = weight[i] * (INPUTS[i].get_pvalue(j, d) - AVERAGE.get_pvalue(j, d)); + newval = VARIANCE.get_pvalue(j, d) + newval * newval; + VARIANCE.set_pvalue(j, newval, d); + } + } + } } - } - double meanvar=0; - for(int d=0;dget_pvalue(i) && totalcounts.get_pvalue(i,d) > 0 && exclusion(i+1)){ - newval=sqrt(VARIANCE.get_pvalue(i,d)/(totalcounts.get_pvalue(i,d))); - VARIANCE.set_pvalue(i,newval,d); - if(_avdim==-1 || _avdim==d) meanvar+=newval; - //cout << i << " newval " << newval << " VARIANCE.get_pvalue(d,i) " << VARIANCE.get_pvalue(d,i) << " AVERAGE.get_pvalue(d,i) " << AVERAGE.get_pvalue(d,i) << " totalcounts.get_pvalue(d,i) " << totalcounts.get_pvalue(d,i) << " meanvar " << meanvar << endl; - - } - else VARIANCE.set_pvalue(i,0,d); + double meanvar = 0; + for (int d = 0; d < atlasdim; d++) { + for (int i = 0; i < VARIANCE.nvertices(); i++) { + if (EXCL_ref->get_pvalue(i) && totalcounts.get_pvalue(i, d) > 0 && exclusion(i + 1)) { + newval = sqrt(VARIANCE.get_pvalue(i, d) / (totalcounts.get_pvalue(i, d))); + VARIANCE.set_pvalue(i, newval, d); + if (_avdim == -1 || _avdim == d) + meanvar += newval; + //cout << i << " newval " << newval << " VARIANCE.get_pvalue(d,i) " << VARIANCE.get_pvalue(d,i) << " AVERAGE.get_pvalue(d,i) " << AVERAGE.get_pvalue(d,i) << " totalcounts.get_pvalue(d,i) " << totalcounts.get_pvalue(d,i) << " meanvar " << meanvar << endl; + + } else + VARIANCE.set_pvalue(i, 0, d); + } } - } - for(int d=0;d0 && exclusion(i+1)) - newval=(abs(AVERAGE.get_pvalue(i,d)))/VARIANCE.get_pvalue(i,d); - else - newval=0; + for (int d = 0; d < atlasdim; d++) { + for (int i = 0; i < VARIANCE.nvertices(); i++) { + if (VARIANCE.get_pvalue(i, d) > 0 && exclusion(i + 1)) + newval = (abs(AVERAGE.get_pvalue(i, d))) / VARIANCE.get_pvalue(i, d); + else + newval = 0; - Zscore.set_pvalue(i,newval,d); + Zscore.set_pvalue(i, newval, d); + } } - } -int totdim; - if(_avdim==-1) totdim=atlasdim; - else totdim=1; - cout << " meanval " << sumav/(VARIANCE.nvertices()*totdim) << endl; + int totdim; + if (_avdim == -1) + totdim = atlasdim; + else + totdim = 1; + cout << " meanval " << sumav / (VARIANCE.nvertices() * totdim) << endl; - cout << " meanvar " << meanvar/(VARIANCE.nvertices()*totdim) << endl; + cout << " meanvar " << meanvar / (VARIANCE.nvertices() * totdim) << endl; - AVERAGE.save(output+"AVERAGE.func"); - VARIANCE.save(output+"STD.func"); - Zscore.save(output+"ZSCORE.func"); - delete DATA; + AVERAGE.save(output + "AVERAGE.func"); + VARIANCE.save(output + "STD.func"); + Zscore.save(output + "ZSCORE.func"); + delete DATA; } diff --git a/src/MSM/msm_metric_sim.cc b/src/MSM/msm_metric_sim.cc index 5414b1e..21bac83 100644 --- a/src/MSM/msm_metric_sim.cc +++ b/src/MSM/msm_metric_sim.cc @@ -1,7 +1,7 @@ -#include -#include -#include "newmesh/meshfns.h" #include "MeshReg/meshreg.h" +#include "newmesh/meshfns.h" +#include +#include using namespace std; using namespace MISCMATHS; @@ -10,126 +10,124 @@ using namespace MESHREG; void Usage() { - cout << "msm_metric_sim " << endl; - cout << "Input are func files assumes surfaces have been resampled to same mesh " << endl; - cout << " options: " << endl; - cout << "-compare X compare correlation to this file " << endl; + cout << "msm_metric_sim " << endl; + cout << "Input are func files assumes surfaces have been resampled to same mesh " << endl; + cout << " options: " << endl; + cout << "-compare X compare correlation to this file " << endl; } -int main( int argc, char **argv ) +int main(int argc, char** argv) { - newmesh SURFACE1, SURFACE2, OUTSURF,COMP; - vector data1,data2; - string outputname; - sparsesimkernel sim; - double correlation,sum=0.0; - bool _compare=false; - bool _exclude=false; - int ok=0; - - if(argc < 3){ - - Usage(); - exit(0); - } - - SURFACE1.load(argv[1],false,false); - argc--; - argv++; - SURFACE2.load(argv[1],false,false); - argc--; - argv++; - outputname=argv[1]; - argc--; - argv++; - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-compare") == 0)){ - argc--; - argv++; - _compare=true; - COMP.load(argv[1],false,true); - argc--; - argv++; - ok = 1; + newmesh SURFACE1, SURFACE2, OUTSURF, COMP; + vector data1, data2; + string outputname; + sparsesimkernel sim; + double correlation, sum = 0.0; + bool _compare = false; + bool _exclude = false; + int ok = 0; + + if (argc < 3) { + + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-excl") == 0)){ - argc--; - argv++; - _exclude=true; - ok = 1; + + SURFACE1.load(argv[1], false, false); + argc--; + argv++; + SURFACE2.load(argv[1], false, false); + argc--; + argv++; + outputname = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-compare") == 0)) { + argc--; + argv++; + _compare = true; + COMP.load(argv[1], false, true); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl") == 0)) { + argc--; + argv++; + _exclude = true; + ok = 1; + } } - } - if(SURFACE1.npvalues()!=SURFACE2.npvalues() || SURFACE1.get_dimension()!=SURFACE2.get_dimension()) { cout << " surfaces have different number of vertices, or features abort! " << endl; exit(1);} - - boost::shared_ptr EXCL_IN, EXCL_REF; - if(_exclude){ - Matrix DATAIN,DATAREF; - DATAIN=SURFACE1.get_pvalues(); - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SURFACE1,DATAIN,0,0))); - DATAREF=SURFACE2.get_pvalues(); - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SURFACE1,DATAREF,0,0))); - }else{ - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(SURFACE1)); - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(SURFACE2)); - for(int i=0;iset_pvalue(i,1); - EXCL_REF->set_pvalue(i,1); - } - } - - OUTSURF=SURFACE1; - - OUTSURF.clear_data(); - ColumnVector allcorr(SURFACE1.npvalues()); - - - if(SURFACE1.get_dimension()==1){ - for (int i=0;iget_pvalue(i)>0 && EXCL_REF->get_pvalue(i) > 0){ - data1.push_back(SURFACE1.get_pvalue(i)); - data2.push_back(SURFACE2.get_pvalue(i)); - } - } - correlation=sim.corr(data1,data2); - cout << " mean=" << correlation << endl; - } - else{ - for (int i=0;i EXCL_IN, EXCL_REF; + if (_exclude) { + Matrix DATAIN, DATAREF; + DATAIN = SURFACE1.get_pvalues(); + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SURFACE1, DATAIN, 0, 0))); + DATAREF = SURFACE2.get_pvalues(); + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SURFACE1, DATAREF, 0, 0))); + } else { + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(SURFACE1)); + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(SURFACE2)); + for (int i = 0; i < SURFACE1.npvalues(); i++) { + EXCL_IN->set_pvalue(i, 1); + EXCL_REF->set_pvalue(i, 1); + } + } + OUTSURF = SURFACE1; + + OUTSURF.clear_data(); + ColumnVector allcorr(SURFACE1.npvalues()); + + if (SURFACE1.get_dimension() == 1) { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + if (EXCL_IN->get_pvalue(i) > 0 && EXCL_REF->get_pvalue(i) > 0) { + data1.push_back(SURFACE1.get_pvalue(i)); + data2.push_back(SURFACE2.get_pvalue(i)); + } + } + correlation = sim.corr(data1, data2); + cout << " mean=" << correlation << endl; + } else { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + data1.clear(); + data2.clear(); + + for (int j = 0; j < SURFACE1.get_dimension(); j++) { + data1.push_back(SURFACE1.get_pvalue(i, j)); + data2.push_back(SURFACE2.get_pvalue(i, j)); + } + correlation = sim.corr(data1, data2); + allcorr(i + 1) = correlation; + + sum += correlation; + } + + OUTSURF.set_pvalues(allcorr); + double mean, var = 0.0; + mean = sum / SURFACE1.npvalues(); + for (int i = 0; i < SURFACE1.npvalues(); i++) + var += (OUTSURF.get_pvalue(i) - mean) * (OUTSURF.get_pvalue(i) - mean); + + var /= SURFACE1.npvalues(); + + cout << " mean=" << mean << endl; + cout << " var=" << var << endl; + + OUTSURF.save(outputname + ".func.gii"); + } + if (_compare) { + for (int i = 0; i < SURFACE1.npvalues(); i++) { + double diff = OUTSURF.get_pvalue(i) - COMP.get_pvalue(i); + OUTSURF.set_pvalue(i, diff); + } + OUTSURF.save(outputname + "DIFF.func.gii"); + } } diff --git a/src/MSM/msm_metricmath.cc b/src/MSM/msm_metricmath.cc index e44581d..224f3c2 100644 --- a/src/MSM/msm_metricmath.cc +++ b/src/MSM/msm_metricmath.cc @@ -7,398 +7,391 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include -#include -#include -#include +#include "MeshReg/meshreg.h" +#include "newmesh/meshfns.h" +#include "utils/options.h" #include -#include +#include +#include #include -#include "utils/options.h" -#include "newmesh/meshfns.h" -#include "MeshReg/meshreg.h" - +#include +#include +#include using namespace std; using namespace MISCMATHS; using namespace NEWMESH; using namespace MESHREG; -enum sValue { evND, - ev1, - ev2, - ev3, - ev4, - ev5, - ev6, - evfin }; +enum sValue { evND, + ev1, + ev2, + ev3, + ev4, + ev5, + ev6, + evfin }; - // Map to associate the strings with the enum values +// Map to associate the strings with the enum values static std::map s_mapValues; - -void set_method(const string &M){ + +void set_method(const string& M) +{ s_mapValues["-mean"] = ev1; s_mapValues["-variance"] = ev2; s_mapValues["-sum"] = ev3; s_mapValues["-max"] = ev4; - s_mapValues["-min"] = ev5; - s_mapValues["-rank"] = ev6; - s_mapValues["-percentile"] = evfin; + s_mapValues["-min"] = ev5; + s_mapValues["-rank"] = ev6; + s_mapValues["-percentile"] = evfin; +} - } - void Usage() { - cout << "msm_metricmath -operations -options " << endl; - cout << "options: " << endl; - cout << "-exclude lthr upthr use exclusion mesh for cut defined using upper (uthr) and lower (lthr) thresholds" << endl; - cout << "-vertex-wise estimate statistics across columns (not implemented yet)" << endl; - cout << " -exclusionmask use another input file to define exclusion " << endl; - cout << " -abs estimate absolute average " << endl; - - cout << "operations are one or more of: " << endl; - cout << "-mean " << endl; - cout << "-variance " << endl; - cout << "-sum " << endl; - cout << "-max " << endl; - cout << "-min " << endl; - cout << "-percentile X " << endl; + cout << "msm_metricmath -operations -options " << endl; + cout << "options: " << endl; + cout << "-exclude lthr upthr use exclusion mesh for cut defined using upper (uthr) and lower (lthr) thresholds" << endl; + cout << "-vertex-wise estimate statistics across columns (not implemented yet)" << endl; + cout << " -exclusionmask use another input file to define exclusion " << endl; + cout << " -abs estimate absolute average " << endl; + + cout << "operations are one or more of: " << endl; + cout << "-mean " << endl; + cout << "-variance " << endl; + cout << "-sum " << endl; + cout << "-max " << endl; + cout << "-min " << endl; + cout << "-percentile X " << endl; } +vector estimate_average(vector perc, bool makeabs, newmesh& IN, boost::shared_ptr EXCL) +{ -vector estimate_average(vector perc, bool makeabs,newmesh &IN, boost::shared_ptr EXCL){ - - vector average(IN.get_dimension(),0); - vector totalcounts(IN.get_dimension(),0.0); - cout << " EXCL.get() " << EXCL.get() << endl; - - for (int d=0;dget_pvalue(i,d)) " << (!EXCL.get() || EXCL->get_pvalue(i,d)) << " IN.get_pvalue(i,d)) " << IN.get_pvalue(i,d) << " (abs(IN.get_pvalue(i,d)) > EPSILON) " << (abs(IN.get_pvalue(i,d)) > EPSILON) << endl; - if((!EXCL.get() || EXCL->get_pvalue(i)) && (abs(IN.get_pvalue(i,d)) > EPSILON) && (abs(IN.get_pvalue(i,d)) < perc[d])){ - //EXCL->set_pvalue(i,10); - if(makeabs) average[d]+= abs(IN.get_pvalue(i,d)); - else average[d]+= IN.get_pvalue(i,d); - totalcounts[d]+=1; - } - } - average[d]/=totalcounts[d]; - if(abs(average[d]) < 0.001) average[d]=0; - cout << "average of dimension " << d << " is " << average[d] <save("EXCL2.func.gii"); - return average; + vector average(IN.get_dimension(), 0); + vector totalcounts(IN.get_dimension(), 0.0); + cout << " EXCL.get() " << EXCL.get() << endl; + + for (int d = 0; d < IN.get_dimension(); d++) { + for (int i = 0; i < IN.npvalues(); i++) { + //cout << i << " (!EXCL.get() | EXCL->get_pvalue(i,d)) " << (!EXCL.get() || EXCL->get_pvalue(i,d)) << " IN.get_pvalue(i,d)) " << IN.get_pvalue(i,d) << " (abs(IN.get_pvalue(i,d)) > EPSILON) " << (abs(IN.get_pvalue(i,d)) > EPSILON) << endl; + if ((!EXCL.get() || EXCL->get_pvalue(i)) && (abs(IN.get_pvalue(i, d)) > EPSILON) && (abs(IN.get_pvalue(i, d)) < perc[d])) { + //EXCL->set_pvalue(i,10); + if (makeabs) + average[d] += abs(IN.get_pvalue(i, d)); + else + average[d] += IN.get_pvalue(i, d); + totalcounts[d] += 1; + } + } + average[d] /= totalcounts[d]; + if (abs(average[d]) < 0.001) + average[d] = 0; + cout << "average of dimension " << d << " is " << average[d] << endl; + // if(abs(average[d]) < 0.001) average[d]=0; + } + // EXCL->save("EXCL2.func.gii"); + return average; } -void estimate_pca(newmesh &IN){ - - - Matrix DATA=IN.get_pvalues(); - DiagonalMatrix eigenvals; - double sumvar=0; - SVD(DATA,eigenvals); - - vector vals(eigenvals.Nrows(),0); - - double tolerance = Max(DATA.Nrows(),DATA.Ncols()) * eigenvals.Maximum() * 1e-16; - - int therank=0; - - for(int i=0; itolerance) - therank++; - - } - - for(int i=0; isave("EXCL2.func.gii"); +void estimate_pca(newmesh& IN) +{ + + Matrix DATA = IN.get_pvalues(); + DiagonalMatrix eigenvals; + double sumvar = 0; + SVD(DATA, eigenvals); + + vector vals(eigenvals.Nrows(), 0); + + double tolerance = Max(DATA.Nrows(), DATA.Ncols()) * eigenvals.Maximum() * 1e-16; + + int therank = 0; + + for (int i = 0; i < eigenvals.Nrows(); i++) { + sumvar += eigenvals(i + 1); + cout << "eigval " << i << " is " << eigenvals(i + 1) << endl; + if (eigenvals(i + 1) > tolerance) + therank++; + } + + for (int i = 0; i < eigenvals.Nrows(); i++) + cout << " percentage variance " << i << " is " << eigenvals(i + 1) / sumvar << endl; + cout << " rank " << therank << endl; + // EXCL->save("EXCL2.func.gii"); } -void estimate_variance(bool makeabs,newmesh &IN, boost::shared_ptr EXCL, vector average = vector()){ - - vector thresh(IN.get_dimension(),1); - if(average.size()!=IN.get_dimension()) average=estimate_average(thresh,makeabs,IN,EXCL); - vector variance(IN.get_dimension(),0); - vector totalcounts(IN.get_dimension(),0.0); - - for (int d=0;dget_pvalue(i)) && (abs(IN.get_pvalue(i,d)) > EPSILON)){ - if(makeabs) variance[d]+=( abs(IN.get_pvalue(i,d))-average[d])*(abs(IN.get_pvalue(i,d))-average[d]); - else variance[d]+=( IN.get_pvalue(i,d)-average[d])*( IN.get_pvalue(i,d)-average[d]); - totalcounts[d]+=1; - } - } - cout << "variance of dimension " << d << " is " << variance[d]/totalcounts[d] << " average " << average[d] << endl; - - } - - +void estimate_variance(bool makeabs, newmesh& IN, boost::shared_ptr EXCL, vector average = vector()) +{ + + vector thresh(IN.get_dimension(), 1); + if (average.size() != IN.get_dimension()) + average = estimate_average(thresh, makeabs, IN, EXCL); + vector variance(IN.get_dimension(), 0); + vector totalcounts(IN.get_dimension(), 0.0); + + for (int d = 0; d < IN.get_dimension(); d++) { + for (int i = 0; i < IN.npvalues(); i++) { + if ((!EXCL.get() || EXCL->get_pvalue(i)) && (abs(IN.get_pvalue(i, d)) > EPSILON)) { + if (makeabs) + variance[d] += (abs(IN.get_pvalue(i, d)) - average[d]) * (abs(IN.get_pvalue(i, d)) - average[d]); + else + variance[d] += (IN.get_pvalue(i, d) - average[d]) * (IN.get_pvalue(i, d) - average[d]); + totalcounts[d] += 1; + } + } + cout << "variance of dimension " << d << " is " << variance[d] / totalcounts[d] << " average " << average[d] << endl; + } } +void estimate_sum(bool makeabs, newmesh& IN, boost::shared_ptr EXCL) +{ -void estimate_sum(bool makeabs, newmesh &IN, boost::shared_ptr EXCL){ - - - vector sum(IN.get_dimension(),0); - - for (int d=0;dget_pvalue(i)) && abs(IN.get_pvalue(i,d)) > EPSILON){ - if( makeabs) sum[d]+= abs(IN.get_pvalue(i,d)); - else sum[d]+= IN.get_pvalue(i,d); - - } - } - cout << "sum of dimension " << d << " is " << sum[d] << endl; - - } - - + vector sum(IN.get_dimension(), 0); + + for (int d = 0; d < IN.get_dimension(); d++) { + for (int i = 0; i < IN.npvalues(); i++) { + if ((!EXCL.get() || EXCL->get_pvalue(i)) && abs(IN.get_pvalue(i, d)) > EPSILON) { + if (makeabs) + sum[d] += abs(IN.get_pvalue(i, d)); + else + sum[d] += IN.get_pvalue(i, d); + } + } + cout << "sum of dimension " << d << " is " << sum[d] << endl; + } } -void estimate_max(bool makeabs,newmesh &IN, boost::shared_ptr EXCL){ - - - - vector max(IN.get_dimension(),0); - double val; - for (int d=0;dget_pvalue(i)) && abs(IN.get_pvalue(i,d)) > EPSILON){ - if( makeabs) val=abs(IN.get_pvalue(i,d)); - else val=IN.get_pvalue(i,d); - if(val > max[d]) - max[d]=val; - } - } - cout << "max of dimension " << d << " is " << max[d] < EXCL) +{ + + vector max(IN.get_dimension(), 0); + double val; + for (int d = 0; d < IN.get_dimension(); d++) { + for (int i = 0; i < IN.npvalues(); i++) { + if ((!EXCL.get() || EXCL->get_pvalue(i)) && abs(IN.get_pvalue(i, d)) > EPSILON) { + if (makeabs) + val = abs(IN.get_pvalue(i, d)); + else + val = IN.get_pvalue(i, d); + if (val > max[d]) + max[d] = val; + } + } + cout << "max of dimension " << d << " is " << max[d] << endl; + } } -vector estimate_min(bool makeabs, newmesh &IN, boost::shared_ptr EXCL){ - - - - vector min(IN.get_dimension(),std::numeric_limits::max()); - double val; - for (int d=0;dget_pvalue(i)) && abs(IN.get_pvalue(i,d)) > EPSILON){ - if( makeabs) val=abs(IN.get_pvalue(i,d)); - else val=IN.get_pvalue(i,d); - if(val < min[d]) - min[d]=val; - } - } - cout << "min of dimension " << d << " is " << min[d] < estimate_min(bool makeabs, newmesh& IN, boost::shared_ptr EXCL) +{ + + vector min(IN.get_dimension(), std::numeric_limits::max()); + double val; + for (int d = 0; d < IN.get_dimension(); d++) { + for (int i = 0; i < IN.npvalues(); i++) { + if ((!EXCL.get() || EXCL->get_pvalue(i)) && abs(IN.get_pvalue(i, d)) > EPSILON) { + if (makeabs) + val = abs(IN.get_pvalue(i, d)); + else + val = IN.get_pvalue(i, d); + if (val < min[d]) + min[d] = val; + } + } + cout << "min of dimension " << d << " is " << min[d] << endl; + } + + return min; } -vector estimate_percentile(float perc, int bins, bool makeabs, newmesh &IN, boost::shared_ptr EXCL){ - - ColumnVector DATA(IN.npvalues()); - - vector percentile(IN.get_dimension(),0); - cout << " makeabs" << makeabs << endl; - double val; - for (int d=0;d estimate_percentile(float perc, int bins, bool makeabs, newmesh& IN, boost::shared_ptr EXCL) +{ + + ColumnVector DATA(IN.npvalues()); + + vector percentile(IN.get_dimension(), 0); + cout << " makeabs" << makeabs << endl; + double val; + for (int d = 0; d < IN.get_dimension(); d++) { + DATA = 0; + for (int i = 0; i < IN.npvalues(); i++) { + + if (makeabs) + DATA(i + 1) = abs(IN.get_pvalue(i, d)); + else + DATA(i + 1) = IN.get_pvalue(i, d); + //if(DATA(i+1)<0) cout << i << " DATA " << DATA(i+1) << endl; + } + Histogram hist = build_histogram(DATA, EXCL, bins); + // hist.generateCDF(); + // ColumnVector CDF=hist.getCDF(); + percentile[d] = hist.getPercentile(perc); + cout << "percentile " << perc << "of dimension " << d << " is " << percentile[d] << endl; + } + + return percentile; } -int main(int argc, char **argv){ - - - boost::shared_ptr EXCL; - vector thresh; - NEWMESH::newmesh IN,exclusionmask; - int ok,_bins=256; - bool _exclude=false,_vertexwise=false; - bool _abs=false; - boost::shared_ptr DATA; - string output; - vector operations; - double uthr=1,lthr=0; - char filename[1000]; - float _perc; - float limit=0.99999; - if(argc < 2){ - - Usage(); - exit(0); - } - - cout << argv[1] << endl; - set_data(argv[1],DATA,IN); - argc--; - argv++; - - - cout << " here " << endl; -//operations - if(strcmp(argv[1], "-operations")==0) { +int main(int argc, char** argv) +{ + + boost::shared_ptr EXCL; + vector thresh; + NEWMESH::newmesh IN, exclusionmask; + int ok, _bins = 256; + bool _exclude = false, _vertexwise = false; + bool _abs = false; + boost::shared_ptr DATA; + string output; + vector operations; + double uthr = 1, lthr = 0; + char filename[1000]; + float _perc; + float limit = 0.99999; + if (argc < 2) { + + Usage(); + exit(0); + } + + cout << argv[1] << endl; + set_data(argv[1], DATA, IN); argc--; argv++; - while(argc > 1 && strcmp(argv[1], "-options") != 0){ - operations.push_back(argv[1]); - if(strcmp(argv[1], "-percentile")== 0){ - cout << " 1 " << argv[1] << endl; - argc--; - argv++; - cout << argv[1] << endl; - _perc=atof(argv[1]); - argc--; - argv++; - _bins=atoi(argv[1]); - argc--; - argv++; - }else{ - argc--; - argv++; - } - } - } - - //options - while (argc > 1){ - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-options") == 0)){ - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-vertex-wise") == 0)){ - argc--; - argv++; - _vertexwise=true; - ok = 1; - cout << " not implemented yet " < 1 && strcmp(argv[1], "-options") != 0) { + operations.push_back(argv[1]); + if (strcmp(argv[1], "-percentile") == 0) { + cout << " 1 " << argv[1] << endl; + argc--; + argv++; + cout << argv[1] << endl; + _perc = atof(argv[1]); + argc--; + argv++; + _bins = atoi(argv[1]); + argc--; + argv++; + } else { + argc--; + argv++; + } + } } - else if((ok == 0) && (strcmp(argv[1], "-exclusionmask") == 0)){ - argc--; - argv++; - set_data(argv[1],DATA,exclusionmask); - cout << exclusionmask.npvalues() << " " << argv[1] << endl; - _exclude=true; - argc--; - argv++; - ok = 1; + + //options + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-options") == 0)) { + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-vertex-wise") == 0)) { + argc--; + argv++; + _vertexwise = true; + ok = 1; + cout << " not implemented yet " << endl; + exit(1); + } else if ((ok == 0) && (strcmp(argv[1], "-exclude") == 0)) { + argc--; + argv++; + _exclude = true; + lthr = atof(argv[1]); + argc--; + argv++; + uthr = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-exclusionmask") == 0)) { + argc--; + argv++; + set_data(argv[1], DATA, exclusionmask); + cout << exclusionmask.npvalues() << " " << argv[1] << endl; + _exclude = true; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-abs") == 0)) { + argc--; + argv++; + cout << " abs " << endl; + _abs = true; + + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-limit") == 0)) { + argc--; + argv++; + cout << " abs " << endl; + limit = atof(argv[1]); + argc--; + argv++; + + ok = 1; + } + + else { + cout << argv[1] << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "-abs") == 0)){ - argc--; - argv++; - cout << " abs " << endl; - _abs=true; - - ok = 1; + + if (_exclude) { + if (exclusionmask.npvalues() > 0) { + EXCL = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(exclusionmask, exclusionmask.get_pvalues(), lthr, uthr))); + cout << exclusionmask.npvalues() << endl; + + EXCL->save("exclusion.func"); + exclusionmask.save("exclusion1.func"); + for (int i = 0; i < EXCL->npvalues(); i++) { + if (EXCL->get_pvalue(i) == 0) + EXCL->set_pvalue(i, 1); + else + EXCL->set_pvalue(i, 0); + } + } else + EXCL = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(IN, IN.get_pvalues(), lthr, uthr))); } - else if((ok == 0) && (strcmp(argv[1], "-limit") == 0)){ - argc--; - argv++; - cout << " abs " << endl; - limit=atof(argv[1]); - argc--; - argv++; - - ok = 1; - } - - else{cout << argv[1] << " option doesn't exist " << endl; exit(1);} - } - - if(_exclude){ - if(exclusionmask.npvalues()>0){ - EXCL= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(exclusionmask,exclusionmask.get_pvalues(),lthr,uthr))); - cout << exclusionmask.npvalues() << endl; - - EXCL->save("exclusion.func"); exclusionmask.save("exclusion1.func"); - for (int i=0;inpvalues();i++){ - if(EXCL->get_pvalue(i)==0) EXCL->set_pvalue(i,1); - else EXCL->set_pvalue(i,0); - - } + + cout << " limit " << limit << endl; + thresh = estimate_percentile(limit, 100, true, IN, EXCL); + + // EXCL->save("EXCL.func"); + vector av; + //////////////////////////// + for (unsigned int op = 0; op < operations.size(); op++) { + set_method(operations[op]); + + switch (s_mapValues[operations[op]]) { + case ev1: + av = estimate_average(thresh, _abs, IN, EXCL); + break; + case ev2: + estimate_variance(_abs, IN, EXCL, av); + break; + case ev3: + estimate_sum(_abs, IN, EXCL); + break; + case ev4: + estimate_max(_abs, IN, EXCL); + break; + case ev5: + estimate_min(_abs, IN, EXCL); + break; + case ev6: + estimate_pca(IN); + break; + case evfin: + estimate_percentile(_perc, _bins, _abs, IN, EXCL); + break; + default: + cout << "'" << operations[op] + << "' is an invalid string or not yet implemented " << endl; + break; + } } - else - EXCL= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(IN,IN.get_pvalues(),lthr,uthr))); - } - - cout << " limit " << limit << endl; - thresh=estimate_percentile(limit,100, true,IN,EXCL); - - - // EXCL->save("EXCL.func"); - vector av; - //////////////////////////// - for (unsigned int op=0;op -#include -#include -#include +#include "MeshReg/meshreg.h" +#include "newmesh/meshfns.h" +#include "utils/options.h" #include +#include +#include #include -#include "utils/options.h" -#include "newmesh/meshfns.h" -#include "MeshReg/meshreg.h" - +#include +#include using namespace std; using namespace MISCMATHS; @@ -25,112 +24,112 @@ using namespace MESHREG; void Usage() { - cout << "msm_surface_average <-options> " << endl; - cout << "options: " << endl; - cout << "-weighted X supply a list of distances from the mean" << endl; - cout << "-sigma X sigma values " << endl; + cout << "msm_surface_average <-options> " << endl; + cout << "options: " << endl; + cout << "-weighted X supply a list of distances from the mean" << endl; + cout << "-sigma X sigma values " << endl; } +int main(int argc, char** argv) +{ + + NEWMESH::newmesh IN, AVERAGE; -int main(int argc, char **argv){ - - - NEWMESH::newmesh IN, AVERAGE; - - string output; - vector INlist,distances; - bool _weighted=false; - double _sigma; - double weight; - double sumweighted=0; - int ok=0; - - - if(argc < 2){ - - Usage(); - exit(0); - } - - INlist=read_ascii_list(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - - - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-weighted") == 0)){ - argc--; - argv++; - _weighted=true; - distances=read_ascii_list(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-sigma") == 0)){ - argc--; - argv++; - _sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; + string output; + vector INlist, distances; + bool _weighted = false; + double _sigma; + double weight; + double sumweighted = 0; + int ok = 0; + + if (argc < 2) { + + Usage(); + exit(0); } - else{cout << argv[1] << " option doesn't exist " << endl; exit(1);} - } - - AVERAGE.load(INlist[0]); - - for(int i=0;i 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-weighted") == 0)) { + argc--; + argv++; + _weighted = true; + distances = read_ascii_list(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-sigma") == 0)) { + argc--; + argv++; + _sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else { + cout << argv[1] << " option doesn't exist " << endl; + exit(1); + } } - } + AVERAGE.load(INlist[0]); + + for (int i = 0; i < AVERAGE.nvertices(); i++) { + Pt p; + AVERAGE.set_coord(i, p); + } + double mean = 0; + //for (unsigned int i=0;i /* clock_t, clock, CLOCKS_PER_SEC */ - - +#include /* clock_t, clock, CLOCKS_PER_SEC */ using namespace NEWMAT; using namespace NEWMESH; void Usage() -{ cout << " msmapplywarp -options " << endl; - cout << " Projects the to-be-transformed mesh though a transformation defined by an original mesh and its deformed counterpart" << endl; - cout << " It is optional to supply the undeformed (original) mesh, but if no original mesh is supplied the algorithm will assume that the warp is prescribed by an icospheric template" << endl; - cout << " -options " << endl; - cout << " -original X.surf.gii " << endl; - cout << " -deformed DEFORMED.surf.gii (MUST be supplied in order to warp data)" << endl; - cout << " -anat TARGET_SPHERE.surf.gii TARGET_ANAT.surf (2 inputs!). This will effectively project the INPUT anatomical mesh through the spherical warp." << endl; - cout << " -nospherical don't save spherical warp " << endl; - cout << " -affine (estimate affine transformation between input (-original) and deformed (-deformed) meshes and apply this to the to-be-transformed-mesh " << endl; - cout << " -readaffine X; where X is an affine transformation matrix " << endl; - cout << " -writeaffine write out affine transformation matrix" << endl; - - +{ + cout << " msmapplywarp -options " << endl; + cout << " Projects the to-be-transformed mesh though a transformation defined by an original mesh and its deformed counterpart" << endl; + cout << " It is optional to supply the undeformed (original) mesh, but if no original mesh is supplied the algorithm will assume that the warp is prescribed by an icospheric template" << endl; + cout << " -options " << endl; + cout << " -original X.surf.gii " << endl; + cout << " -deformed DEFORMED.surf.gii (MUST be supplied in order to warp data)" << endl; + cout << " -anat TARGET_SPHERE.surf.gii TARGET_ANAT.surf (2 inputs!). This will effectively project the INPUT anatomical mesh through the spherical warp." << endl; + cout << " -nospherical don't save spherical warp " << endl; + cout << " -affine (estimate affine transformation between input (-original) and deformed (-deformed) meshes and apply this to the to-be-transformed-mesh " << endl; + cout << " -readaffine X; where X is an affine transformation matrix " << endl; + cout << " -writeaffine write out affine transformation matrix" << endl; } -void get_areas(newmesh &M){ - double val; - ColumnVector meanarea(M.nvertices()); meanarea=0; - - for ( vector::const_iterator i=M.tbegin() ; i!=M.tend(); i++){ - NEWMESH::Pt v1 = (*i).get_vertex_coord(0), v2 = (*i).get_vertex_coord(1), v3 = (*i).get_vertex_coord(2); - - val=computeArea(v1, v2, v3); - meanarea((*i).get_vertex_no(0)+1)+=(1/3)*val; - meanarea((*i).get_vertex_no(1)+1)+=(1/3)*val; - meanarea((*i).get_vertex_no(2)+1)+=(1/3)*val; - - } - for (int i=0;i::const_iterator i = M.tbegin(); i != M.tend(); i++) { + NEWMESH::Pt v1 = (*i).get_vertex_coord(0), v2 = (*i).get_vertex_coord(1), v3 = (*i).get_vertex_coord(2); -} -int main(int argc, char **argv){ - - - newmesh to_be_deformed,to_be_deformed2, initial,final; - newmesh TARGETSPHERE, TARGETANAT; - newmesh ANAT_TRANS; - Matrix _affinemat; - string output; - - boost::shared_ptr _rel; - bool _isregular=true, _projectanat=false; - bool _deformed=false, _areas=false; - bool _affine=false, _supplyaffine=false, _writeaffine=false; - char filename[1000]; - int ok; - - if(argc < 3){ - - Usage(); - exit(0); - } - - - to_be_deformed.load(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - recentre(to_be_deformed); - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-original") == 0)){ - argc--; - argv++; - initial.load(argv[1]); - recentre(initial); - _isregular=false; - argc--; - argv++; - ok = 1; + val = computeArea(v1, v2, v3); + meanarea((*i).get_vertex_no(0) + 1) += (1 / 3) * val; + meanarea((*i).get_vertex_no(1) + 1) += (1 / 3) * val; + meanarea((*i).get_vertex_no(2) + 1) += (1 / 3) * val; } - else if((ok == 0) && (strcmp(argv[1], "-deformed") == 0)){ - argc--; - argv++; - final.load(argv[1]); - recentre(final); - _deformed=true; - argc--; - argv++; - ok = 1; + for (int i = 0; i < M.nvertices(); i++) { + M.set_pvalue(i, meanarea(i + 1)); } - else if((ok == 0) && (strcmp(argv[1], "-anat") == 0)){ - argc--; - argv++; - TARGETSPHERE.load(argv[1]); - recentre(TARGETSPHERE); - argc--; - argv++; - TARGETANAT.load(argv[1]); - argc--; - argv++; - _projectanat=true; - - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-affine") == 0)){ - argc--; - argv++; - _affine=true; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-outputareas") == 0)){ - argc--; - argv++; - _areas=true; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-readaffine") == 0)){ - argc--; - argv++; - _supplyaffine=true; - _affinemat=read_ascii_matrix(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-writeaffine") == 0)){ - argc--; - argv++; - _writeaffine=true; - ok = 1; +} +int main(int argc, char** argv) +{ + + newmesh to_be_deformed, to_be_deformed2, initial, final; + newmesh TARGETSPHERE, TARGETANAT; + newmesh ANAT_TRANS; + Matrix _affinemat; + string output; + + boost::shared_ptr _rel; + bool _isregular = true, _projectanat = false; + bool _deformed = false, _areas = false; + bool _affine = false, _supplyaffine = false, _writeaffine = false; + char filename[1000]; + int ok; + + if (argc < 3) { + + Usage(); + exit(0); } - else{ cout < 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-original") == 0)) { + argc--; + argv++; + initial.load(argv[1]); + recentre(initial); + _isregular = false; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-deformed") == 0)) { + argc--; + argv++; + final.load(argv[1]); + recentre(final); + _deformed = true; + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-anat") == 0)) { + argc--; + argv++; + TARGETSPHERE.load(argv[1]); + recentre(TARGETSPHERE); + argc--; + argv++; + TARGETANAT.load(argv[1]); + argc--; + argv++; + _projectanat = true; + + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-affine") == 0)) { + argc--; + argv++; + _affine = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-outputareas") == 0)) { + argc--; + argv++; + _areas = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-readaffine") == 0)) { + argc--; + argv++; + _supplyaffine = true; + _affinemat = read_ascii_matrix(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-writeaffine") == 0)) { + argc--; + argv++; + _writeaffine = true; + ok = 1; + } else { + cout << argv[1] << "option npot present " << endl; + exit(1); + } } - } - else{ - - if(_supplyaffine){ - cout << _affinemat << endl; - affine_transform(to_be_deformed,_affinemat); - - }else{ - newmesh ICO; - - if(_isregular){ - int ico=final.get_ico_resolution(); - - - ICO.make_mesh_from_icosa(ico); true_rescale(ICO,RAD); - - - }else ICO=initial; - - if(_affine){ - cout << " affine transformation" << endl; - Matrix affinetrans=affine_transform(to_be_deformed,ICO,final); - if(_writeaffine){ - sprintf(filename,"%s_affinewarp.txt",output.c_str()); - write_ascii_matrix(filename,affinetrans); - } - } - else - barycentric_mesh_interpolation(to_be_deformed,ICO,final); - - - if(_projectanat){ - ANAT_TRANS=projectmesh(to_be_deformed,TARGETSPHERE,TARGETANAT); - sprintf(filename,"%s_projectedwarp.surf.gii",output.c_str()); - ANAT_TRANS.save(filename); - - if(_areas){ - get_areas(ANAT_TRANS); - - - sprintf(filename,"%s_projectedwarp_areas.func.gii",output.c_str()); - ANAT_TRANS.save(filename); - - } - + if (!_deformed && !_supplyaffine) { + if (!_projectanat) { + cout << _supplyaffine << "Cannot resample without a target and anatomical mesh. Please supply a target and anatomical mesh (-anat option) for resampling or a deformed mesh (-deformed option) for warping" << endl; + exit(1); + } + ANAT_TRANS = projectmesh(to_be_deformed, TARGETSPHERE, TARGETANAT); + sprintf(filename, "%s_anatresampled.surf.gii", output.c_str()); + ANAT_TRANS.save(filename); + if (_areas) { + get_areas(ANAT_TRANS); + + sprintf(filename, "%s_anatresampled_areas.func.gii", output.c_str()); + ANAT_TRANS.save(filename); + } + + } else { + + if (_supplyaffine) { + cout << _affinemat << endl; + affine_transform(to_be_deformed, _affinemat); + + } else { + newmesh ICO; + + if (_isregular) { + int ico = final.get_ico_resolution(); + + ICO.make_mesh_from_icosa(ico); + true_rescale(ICO, RAD); + + } else + ICO = initial; + + if (_affine) { + cout << " affine transformation" << endl; + Matrix affinetrans = affine_transform(to_be_deformed, ICO, final); + if (_writeaffine) { + sprintf(filename, "%s_affinewarp.txt", output.c_str()); + write_ascii_matrix(filename, affinetrans); + } + } else + barycentric_mesh_interpolation(to_be_deformed, ICO, final); + + if (_projectanat) { + ANAT_TRANS = projectmesh(to_be_deformed, TARGETSPHERE, TARGETANAT); + sprintf(filename, "%s_projectedwarp.surf.gii", output.c_str()); + ANAT_TRANS.save(filename); + + if (_areas) { + get_areas(ANAT_TRANS); + + sprintf(filename, "%s_projectedwarp_areas.func.gii", output.c_str()); + ANAT_TRANS.save(filename); + } + } + } + sprintf(filename, "%s_warp.surf.gii", output.c_str()); + to_be_deformed.save(filename); } - - } - sprintf(filename,"%s_warp.surf.gii",output.c_str()); - to_be_deformed.save(filename); - } } diff --git a/src/MSM/msmresample.cc b/src/MSM/msmresample.cc index 8dec339..5555e86 100644 --- a/src/MSM/msmresample.cc +++ b/src/MSM/msmresample.cc @@ -7,252 +7,231 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include "newmesh/newmesh.h" #include "MeshReg/meshreg.h" #include "miscmaths/SpMat.h" +#include "newmesh/newmesh.h" using namespace MESHREG; void Usage() { - cout << "msmresample <-option> " << endl; - cout << "-option " << endl; - cout << " -project - project final result back down onto surface (requires argument) " << endl; - cout << " -labels - load labels file for input (inc. .func. and .shape, requires argument)" << endl; - cout << " -datamat - multivariate data matrix (requires argument)" << endl; - cout << " -barycentric use barycentric interpolation" << endl; - cout << " -adap_bary use adaptive barycentric interpolation" << endl; - cout << " -linear - linear interpolation kernel with kernel size X (requires argument)" << endl; - cout << " -gaussian - gaussian interpolation kernel with std deviation X (requires argument) " << endl; - cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; - cout << " -excl exclude the area of the cut form contributing to the resampling" << endl; - cout << " -arealdist estimate areal distortion" << endl; + cout << "msmresample <-option> " << endl; + cout << "-option " << endl; + cout << " -project - project final result back down onto surface (requires argument) " << endl; + cout << " -labels - load labels file for input (inc. .func. and .shape, requires argument)" << endl; + cout << " -datamat - multivariate data matrix (requires argument)" << endl; + cout << " -barycentric use barycentric interpolation" << endl; + cout << " -adap_bary use adaptive barycentric interpolation" << endl; + cout << " -linear - linear interpolation kernel with kernel size X (requires argument)" << endl; + cout << " -gaussian - gaussian interpolation kernel with std deviation X (requires argument) " << endl; + cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; + cout << " -excl exclude the area of the cut form contributing to the resampling" << endl; + cout << " -arealdist estimate areal distortion" << endl; } +int main(int argc, char** argv) +{ -int main(int argc, char **argv){ - - Matrix M; - int ok,getwm; - bool barycentric,adap_barycentric,_normalize; - resampler resample; - //MeshReg MR; // only used for read list -> move to resample? - NEWMESH::newmesh in,SPH,REG,ICO,wm,HISTTARG; - bool _outputlabel,_transform,_project,_exclude; - bool _save_rel,_datamatrix, _datamatsp; - string output; - double thr; - double sigma,rad; - boost::shared_ptr _rel; - string rel_out; - boost::shared_ptr datamat; - bool labels=false; - // BFMatrix *datamat; - - - if(argc < 3){ - - Usage(); - exit(0); - } - - - in.load(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - - recentre(in); - - getwm=0; thr=0.0; sigma=1.0;rad=100.0; - _transform=false;_project=false;_outputlabel=false; - _datamatrix=false; _save_rel=false; _datamatsp=false; - _exclude=false; resample.set_method("NN"); - barycentric=false; adap_barycentric=false; _normalize=false; - - - while (argc > 1) { - ok = 0; - cout << argv[1] << endl; - - if((ok == 0) && (strcmp(argv[1], "-project") == 0)){ - argc--; - argv++; - _project=true; - SPH.load(argv[1]); - recentre(SPH); - argc--; - argv++; - ok = 1; - }else if((ok == 0) && (strcmp(argv[1], "-labels") == 0)){ - argc--; - argv++; - labels=true; - - in.load(argv[1],false,false); - Matrix M=in.get_pvalues(); - datamat = boost::shared_ptr(new FullBFMatrix (M)); - - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-datamat") == 0)){ - argc--; - argv++; - _datamatrix=true; - Matrix M=read_ascii_matrix(argv[1]); - datamat = boost::shared_ptr(new FullBFMatrix (M)); - in.set_pvalues(M); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-datamatsp") == 0)){ - argc--; - argv++; - _datamatsp=true; - SpMat M(argv[1]); - cout << " after load sparsemat " << endl; - datamat = boost::shared_ptr(new SparseBFMatrix (M)); - in.set_pvalues(datamat->AsMatrix()); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-normalize") == 0)){ - argc--; - argv++; - _normalize=true; - HISTTARG.load(argv[1],false,false); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-wmmesh") == 0)){ - argc--; - argv++; - getwm=1; - wm.load(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-excl") == 0)){ - argc--; - argv++; - _exclude=true; - ok = 1; + Matrix M; + int ok, getwm; + bool barycentric, adap_barycentric, _normalize; + resampler resample; + //MeshReg MR; // only used for read list -> move to resample? + NEWMESH::newmesh in, SPH, REG, ICO, wm, HISTTARG; + bool _outputlabel, _transform, _project, _exclude; + bool _save_rel, _datamatrix, _datamatsp; + string output; + double thr; + double sigma, rad; + boost::shared_ptr _rel; + string rel_out; + boost::shared_ptr datamat; + bool labels = false; + // BFMatrix *datamat; + + if (argc < 3) { + + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-barycentric") == 0)){ - argc--; - argv++; - barycentric=true; - resample.set_method("BARYCENTRIC"); - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-adap_bary") == 0)){ - argc--; - argv++; - adap_barycentric=true; - resample.set_method("ADAP_BARY"); - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-linear") == 0)){ - argc--; - argv++; - resample.set_method("LINEAR"); - sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-gaussian") == 0)){ - argc--; - argv++; - resample.set_method("GAUSSIAN"); - sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; - } - else{cout << " option doesn't exist " << endl; exit(1);} - - } - - - - boost::shared_ptr EXCL_IN, EXCL_REF; - Matrix DATAIN; - if(_exclude){ - DATAIN=in.get_pvalues(); - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(in,DATAIN,0,0))); - } - - if(_normalize) { - Matrix DATAREF; - boost::shared_ptr BFIN,BFREF; - DATAREF=HISTTARG.get_pvalues(); - if(!datamat.get()){ - Matrix M=in.get_pvalues(); - datamat = boost::shared_ptr(new FullBFMatrix (M)); + in.load(argv[1]); + argc--; + argv++; + output = argv[1]; + argc--; + argv++; + + recentre(in); + + getwm = 0; + thr = 0.0; + sigma = 1.0; + rad = 100.0; + _transform = false; + _project = false; + _outputlabel = false; + _datamatrix = false; + _save_rel = false; + _datamatsp = false; + _exclude = false; + resample.set_method("NN"); + barycentric = false; + adap_barycentric = false; + _normalize = false; + + while (argc > 1) { + ok = 0; + cout << argv[1] << endl; + + if ((ok == 0) && (strcmp(argv[1], "-project") == 0)) { + argc--; + argv++; + _project = true; + SPH.load(argv[1]); + recentre(SPH); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-labels") == 0)) { + argc--; + argv++; + labels = true; + + in.load(argv[1], false, false); + Matrix M = in.get_pvalues(); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-datamat") == 0)) { + argc--; + argv++; + _datamatrix = true; + Matrix M = read_ascii_matrix(argv[1]); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + in.set_pvalues(M); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-datamatsp") == 0)) { + argc--; + argv++; + _datamatsp = true; + SpMat M(argv[1]); + cout << " after load sparsemat " << endl; + datamat = boost::shared_ptr(new SparseBFMatrix(M)); + in.set_pvalues(datamat->AsMatrix()); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-normalize") == 0)) { + argc--; + argv++; + _normalize = true; + HISTTARG.load(argv[1], false, false); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-wmmesh") == 0)) { + argc--; + argv++; + getwm = 1; + wm.load(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl") == 0)) { + argc--; + argv++; + _exclude = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-barycentric") == 0)) { + argc--; + argv++; + barycentric = true; + resample.set_method("BARYCENTRIC"); + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-adap_bary") == 0)) { + argc--; + argv++; + adap_barycentric = true; + resample.set_method("ADAP_BARY"); + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-linear") == 0)) { + argc--; + argv++; + resample.set_method("LINEAR"); + sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-gaussian") == 0)) { + argc--; + argv++; + resample.set_method("GAUSSIAN"); + sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } + } + boost::shared_ptr EXCL_IN, EXCL_REF; + Matrix DATAIN; + if (_exclude) { + DATAIN = in.get_pvalues(); + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(in, DATAIN, 0, 0))); } - if(_exclude){ - cout << SPH.nvertices() << " " << DATAREF.Ncols() << endl; - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG,DATAREF,0,0))); - + if (_normalize) { + Matrix DATAREF; + boost::shared_ptr BFIN, BFREF; + DATAREF = HISTTARG.get_pvalues(); + if (!datamat.get()) { + Matrix M = in.get_pvalues(); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + } + + if (_exclude) { + cout << SPH.nvertices() << " " << DATAREF.Ncols() << endl; + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(HISTTARG, DATAREF, 0, 0))); + } + + BFREF = boost::shared_ptr(new FullBFMatrix(DATAREF)); // + multivariate_histogram_normalization(*datamat, *BFREF, EXCL_IN, EXCL_REF, false); + in.set_pvalues(datamat->AsMatrix()); } - - BFREF=boost::shared_ptr (new FullBFMatrix (DATAREF)); // - multivariate_histogram_normalization(*datamat,*BFREF,EXCL_IN,EXCL_REF,false); - in.set_pvalues(datamat->AsMatrix()); - } + if (_project) { + for (int i = 0; i < SPH.nvertices(); i++) + SPH.set_pvalue(i, 0); - + if (datamat.get()) { + resample.resampledata(in, SPH, EXCL_IN, datamat, sigma); - if(_project){ - for (int i=0;iAsMatrix()); - SPH.save(output+".func"); - }else{ - datamat->Print(output); - - } - - + if (labels) { + SPH.set_pvalues(datamat->AsMatrix()); + SPH.save(output + ".func"); + } else { + datamat->Print(output); + } - if(getwm){ - - for (int i = 0; i < SPH.nvertices(); i++) - wm.set_pvalue(i,SPH.get_pvalue(i)); - - } + if (getwm) { - + for (int i = 0; i < SPH.nvertices(); i++) + wm.set_pvalue(i, SPH.get_pvalue(i)); + } - if(getwm) - wm.save(output +"targetmesh"); - - } - + if (getwm) + wm.save(output + "targetmesh"); + } } diff --git a/src/MSM/msmresamplemesh.cc b/src/MSM/msmresamplemesh.cc index c99b146..fed36d2 100644 --- a/src/MSM/msmresamplemesh.cc +++ b/src/MSM/msmresamplemesh.cc @@ -7,80 +7,79 @@ /* CCOPYRIGHT */ #include "newmat.h" #include "newmesh/meshfns.h" -#include /* clock_t, clock, CLOCKS_PER_SEC */ - - +#include /* clock_t, clock, CLOCKS_PER_SEC */ using namespace NEWMAT; using namespace NEWMESH; void Usage() -{ cout << " msmresamplemesh -options " << endl; - cout << " -data X supply data for resampling " << endl; - cout << " -adap resample adaptively " << endl; - +{ + cout << " msmresamplemesh -options " << endl; + cout << " -data X supply data for resampling " << endl; + cout << " -adap resample adaptively " << endl; } +int main(int argc, char** argv) +{ + + newmesh in_anat, in_sphere, ico; + newmesh ANAT_res; + string output; + double res; + char filename[1000]; + resampler R; + R.set_method("ADAP_BARY"); + int ok; + bool _resampledata = false; + bool _adap = false; + if (argc < 3) { + + Usage(); + exit(0); + } -int main(int argc, char **argv){ - - - newmesh in_anat,in_sphere,ico; - newmesh ANAT_res; - string output; - double res; - char filename[1000]; - resampler R; R.set_method("ADAP_BARY"); - int ok; - bool _resampledata=false; - bool _adap=false; - if(argc < 3){ - - Usage(); - exit(0); - } - - - in_anat.load(argv[1]); - argc--; - argv++; - in_sphere.load(argv[1]); - argc--; - argv++; - res=atoi(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "-data") == 0)){ - argc--; - argv++; - _resampledata=true; - in_sphere.load(argv[1],false,false); - argc--; - argv++; - ok = 1; + in_anat.load(argv[1]); + argc--; + argv++; + in_sphere.load(argv[1]); + argc--; + argv++; + res = atoi(argv[1]); + argc--; + argv++; + output = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "-data") == 0)) { + argc--; + argv++; + _resampledata = true; + in_sphere.load(argv[1], false, false); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-adap") == 0)) { + argc--; + argv++; + _adap = true; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "-adap") == 0)){ - argc--; - argv++; - _adap=true; - ok = 1; - }else{cout << " option doesn't exist " << endl; exit(1);} - } - cout << " Make ico " << endl; - ico.make_mesh_from_icosa(res); true_rescale(ico,RAD); - - - Matrix TRANSLATE=recentre(in_sphere); - true_rescale(in_sphere,RAD); - //recentre anat /// - Pt mean; - /* if(TRANSLATE.NormFrobenius() > EPSILON){ + cout << " Make ico " << endl; + ico.make_mesh_from_icosa(res); + true_rescale(ico, RAD); + + Matrix TRANSLATE = recentre(in_sphere); + true_rescale(in_sphere, RAD); + //recentre anat /// + Pt mean; + /* if(TRANSLATE.NormFrobenius() > EPSILON){ // ColumnVector P_in(4); @@ -112,22 +111,21 @@ int main(int argc, char **argv){ } */ - ANAT_res=mesh_resample(in_anat,in_sphere,ico,_adap); - sprintf(filename,"%s-anat.surf",output.c_str()); - mean*=0; - for (int i=0;i< ANAT_res.nvertices();i++) - mean+=ANAT_res.get_coord(i); - - mean/=ANAT_res.nvertices(); - cout << "anat res mean" << mean.X << " mean.Y " << mean.Y << " mean.Z " << mean.Z << endl; - ANAT_res.save(filename); - sprintf(filename,"%s-regular_sphere.surf",output.c_str()); - ico.save(filename); - - if(_resampledata){ - R.resample_scalar(in_sphere,ico,1); - sprintf(filename,"%s-resampled_data.func",output.c_str()); - in_sphere.save(filename); - - } + ANAT_res = mesh_resample(in_anat, in_sphere, ico, _adap); + sprintf(filename, "%s-anat.surf", output.c_str()); + mean *= 0; + for (int i = 0; i < ANAT_res.nvertices(); i++) + mean += ANAT_res.get_coord(i); + + mean /= ANAT_res.nvertices(); + cout << "anat res mean" << mean.X << " mean.Y " << mean.Y << " mean.Z " << mean.Z << endl; + ANAT_res.save(filename); + sprintf(filename, "%s-regular_sphere.surf", output.c_str()); + ico.save(filename); + + if (_resampledata) { + R.resample_scalar(in_sphere, ico, 1); + sprintf(filename, "%s-resampled_data.func", output.c_str()); + in_sphere.save(filename); + } } diff --git a/src/MSM/msmresamplemetric.cc b/src/MSM/msmresamplemetric.cc index 995e4e9..de6b453 100644 --- a/src/MSM/msmresamplemetric.cc +++ b/src/MSM/msmresamplemetric.cc @@ -7,266 +7,249 @@ /* CCOPYRIGHT */ /* this program is designed to downsample freesurfer label files to be used in combination with the SPH6.vtk or other downsampled meshes*/ -#include "newmesh/newmesh.h" #include "MeshReg/meshreg.h" #include "miscmaths/SpMat.h" +#include "newmesh/newmesh.h" using namespace MESHREG; void Usage() { - cout << "msmresamplemetric <-option> " << endl; - cout << "-option " << endl; - cout << " -project - project final result back down onto surface (requires argument) " << endl; - cout << " -labels - load labels file for input (inc. .func. and .shape, requires argument)" << endl; - cout << " -datamat - multivariate data matrix (requires argument)" << endl; - cout << " -barycentric use barycentric interpolation" << endl; - cout << " -adap_bary use adaptive barycentric interpolation" << endl; - cout << " -linear - linear interpolation kernel with kernel size X (requires argument)" << endl; - cout << " -gaussian - gaussian interpolation kernel with std deviation X (requires argument) " << endl; - cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; - cout << " -excl exclude the area of the cut form contributing to the resampling" << endl; - cout << " -arealdist estimate areal distortion" << endl; + cout << "msmresamplemetric <-option> " << endl; + cout << "-option " << endl; + cout << " -project - project final result back down onto surface (requires argument) " << endl; + cout << " -labels - load labels file for input (inc. .func. and .shape, requires argument)" << endl; + cout << " -datamat - multivariate data matrix (requires argument)" << endl; + cout << " -barycentric use barycentric interpolation" << endl; + cout << " -adap_bary use adaptive barycentric interpolation" << endl; + cout << " -linear - linear interpolation kernel with kernel size X (requires argument)" << endl; + cout << " -gaussian - gaussian interpolation kernel with std deviation X (requires argument) " << endl; + cout << " -normalize - normlalize intensity range to target (requires argument)" << endl; + cout << " -excl exclude the area of the cut form contributing to the resampling" << endl; + cout << " -arealdist estimate areal distortion" << endl; } +int main(int argc, char** argv) +{ -int main(int argc, char **argv){ - - Matrix M; - int ok,getwm; - bool barycentric,adap_barycentric,_normalize; - resampler resample; - //MeshReg MR; // only used for read list -> move to resample? - NEWMESH::newmesh in,SPH,REG,ICO,wm,HISTTARG; - bool _outputlabel,_transform,_project,_exclude; - bool _save_rel,_datamatrix,getdist, _datamatsp; - string output; - double thr; - double sigma,rad; - boost::shared_ptr _rel; - string rel_out; - boost::shared_ptr datamat; - bool labels=false; - // BFMatrix *datamat; - - - if(argc < 3){ - - Usage(); - exit(0); - } - - - in.load(argv[1]); - argc--; - argv++; - output=argv[1]; - argc--; - argv++; - - recentre(in); - - getwm=0; thr=0.0; sigma=1.0;rad=100.0; - _transform=false;_project=false;_outputlabel=false; - _datamatrix=false; _save_rel=false; _datamatsp=false; - _exclude=false; resample.set_method("NN"); - barycentric=false; adap_barycentric=false; _normalize=false; - - // cout << " here 2 " << endl; - while (argc > 1) { - ok = 0; - cout << argv[1] << endl; - - if((ok == 0) && (strcmp(argv[1], "-project") == 0)){ - argc--; - argv++; - _project=true; - SPH.load(argv[1]); - cout << " recentre target " << endl; - recentre(SPH); - argc--; - argv++; - ok = 1; - }else if((ok == 0) && (strcmp(argv[1], "-labels") == 0)){ - argc--; - argv++; - labels=true; - cout << " labels " << argv[1] << endl; - in.load(argv[1],false,false); - Matrix M=in.get_pvalues(); - datamat = boost::shared_ptr(new FullBFMatrix (M)); - - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-datamat") == 0)){ - argc--; - argv++; - _datamatrix=true; - Matrix M=read_ascii_matrix(argv[1]); - datamat = boost::shared_ptr(new FullBFMatrix (M)); - in.set_pvalues(M); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-datamatsp") == 0)){ - argc--; - argv++; - _datamatsp=true; - cout << " load sparsemat " << endl; - SpMat M(argv[1]); - // tmp=new SpMat (argv[1]); - cout << " after load sparsemat " << endl; - datamat = boost::shared_ptr(new SparseBFMatrix (M)); - in.set_pvalues(datamat->AsMatrix()); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-normalize") == 0)){ - argc--; - argv++; - _normalize=true; - cout <<" normalize " << endl; - HISTTARG.load_gifti(argv[1],false,false); - argc--; - argv++; - ok = 1; + Matrix M; + int ok, getwm; + bool barycentric, adap_barycentric, _normalize; + resampler resample; + //MeshReg MR; // only used for read list -> move to resample? + NEWMESH::newmesh in, SPH, REG, ICO, wm, HISTTARG; + bool _outputlabel, _transform, _project, _exclude; + bool _save_rel, _datamatrix, getdist, _datamatsp; + string output; + double thr; + double sigma, rad; + boost::shared_ptr _rel; + string rel_out; + boost::shared_ptr datamat; + bool labels = false; + // BFMatrix *datamat; + + if (argc < 3) { + + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "-wmmesh") == 0)){ - argc--; - argv++; - getwm=1; - wm.load(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-excl") == 0)){ - argc--; - argv++; - _exclude=true; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-barycentric") == 0)){ - argc--; - argv++; - barycentric=true; - resample.set_method("BARYCENTRIC"); - cout << " METHOD IS BARCENTRIC " << endl; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-adap_bary") == 0)){ - argc--; - argv++; - adap_barycentric=true; - resample.set_method("ADAP_BARY"); - cout << " METHOD IS ADAPTIVE BARCENTRIC " << endl; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-linear") == 0)){ - argc--; - argv++; - resample.set_method("LINEAR"); - sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; - } - else if((ok == 0) && (strcmp(argv[1], "-gaussian") == 0)){ - argc--; - argv++; - resample.set_method("GAUSSIAN"); - sigma=atof(argv[1]); - argc--; - argv++; - ok = 1; - } - else{cout << " option doesn't exist " << endl; exit(1);} - - } + in.load(argv[1]); + argc--; + argv++; + output = argv[1]; + argc--; + argv++; + + recentre(in); + + getwm = 0; + thr = 0.0; + sigma = 1.0; + rad = 100.0; + _transform = false; + _project = false; + _outputlabel = false; + _datamatrix = false; + _save_rel = false; + _datamatsp = false; + _exclude = false; + resample.set_method("NN"); + barycentric = false; + adap_barycentric = false; + _normalize = false; + + // cout << " here 2 " << endl; + while (argc > 1) { + ok = 0; + cout << argv[1] << endl; + + if ((ok == 0) && (strcmp(argv[1], "-project") == 0)) { + argc--; + argv++; + _project = true; + SPH.load(argv[1]); + cout << " recentre target " << endl; + recentre(SPH); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-labels") == 0)) { + argc--; + argv++; + labels = true; + cout << " labels " << argv[1] << endl; + in.load(argv[1], false, false); + Matrix M = in.get_pvalues(); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-datamat") == 0)) { + argc--; + argv++; + _datamatrix = true; + Matrix M = read_ascii_matrix(argv[1]); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + in.set_pvalues(M); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-datamatsp") == 0)) { + argc--; + argv++; + _datamatsp = true; + cout << " load sparsemat " << endl; + SpMat M(argv[1]); + // tmp=new SpMat (argv[1]); + cout << " after load sparsemat " << endl; + datamat = boost::shared_ptr(new SparseBFMatrix(M)); + in.set_pvalues(datamat->AsMatrix()); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-normalize") == 0)) { + argc--; + argv++; + _normalize = true; + cout << " normalize " << endl; + HISTTARG.load_gifti(argv[1], false, false); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-wmmesh") == 0)) { + argc--; + argv++; + getwm = 1; + wm.load(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-excl") == 0)) { + argc--; + argv++; + _exclude = true; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-barycentric") == 0)) { + argc--; + argv++; + barycentric = true; + resample.set_method("BARYCENTRIC"); + cout << " METHOD IS BARCENTRIC " << endl; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-adap_bary") == 0)) { + argc--; + argv++; + adap_barycentric = true; + resample.set_method("ADAP_BARY"); + cout << " METHOD IS ADAPTIVE BARCENTRIC " << endl; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-linear") == 0)) { + argc--; + argv++; + resample.set_method("LINEAR"); + sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "-gaussian") == 0)) { + argc--; + argv++; + resample.set_method("GAUSSIAN"); + sigma = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else { + cout << " option doesn't exist " << endl; + exit(1); + } + } - - double meannorm=0; - double varnorm=0; - - boost::shared_ptr EXCL_IN, EXCL_REF; - Matrix DATAIN; - if(_exclude){ - DATAIN=in.get_pvalues(); - EXCL_IN= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(in,DATAIN,0,0))); - // EXCL_IN->save("IN_EXCL.func"); - //DATAIN->Print("DATAIN"); - - } - - if(_normalize) { - Matrix DATAREF; - boost::shared_ptr BFIN,BFREF; - DATAREF=HISTTARG.get_pvalues(); - if(!datamat.get()){ - Matrix M=in.get_pvalues(); - datamat = boost::shared_ptr(new FullBFMatrix (M)); + double meannorm = 0; + double varnorm = 0; + boost::shared_ptr EXCL_IN, EXCL_REF; + Matrix DATAIN; + if (_exclude) { + DATAIN = in.get_pvalues(); + EXCL_IN = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(in, DATAIN, 0, 0))); + // EXCL_IN->save("IN_EXCL.func"); + //DATAIN->Print("DATAIN"); } - if(_exclude){ - cout << "exclude " << endl; - EXCL_REF= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SPH,DATAREF,0,0))); - // EXCL_REF->save("REF_EXCL.func"); + if (_normalize) { + Matrix DATAREF; + boost::shared_ptr BFIN, BFREF; + DATAREF = HISTTARG.get_pvalues(); + if (!datamat.get()) { + Matrix M = in.get_pvalues(); + datamat = boost::shared_ptr(new FullBFMatrix(M)); + } + + if (_exclude) { + cout << "exclude " << endl; + EXCL_REF = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(SPH, DATAREF, 0, 0))); + // EXCL_REF->save("REF_EXCL.func"); + } + + BFREF = boost::shared_ptr(new FullBFMatrix(DATAREF)); // + multivariate_histogram_normalization(*datamat, *BFREF, EXCL_IN, EXCL_REF, false); + in.set_pvalues(datamat->AsMatrix()); } - - BFREF=boost::shared_ptr (new FullBFMatrix (DATAREF)); // - multivariate_histogram_normalization(*datamat,*BFREF,EXCL_IN,EXCL_REF,false); - in.set_pvalues(datamat->AsMatrix()); - } + bool _scalar = false; - + if (_project) { + for (int i = 0; i < SPH.nvertices(); i++) + SPH.set_pvalue(i, 0); + if (datamat.get()) { + resample.resampledata(in, SPH, EXCL_IN, datamat, sigma); + //SPH.set_pvalues(datamat->AsMatrix()); - bool _scalar=false; + } else { + resample.resample_scalar(in, SPH, sigma, EXCL_IN); + //resample.downsample(in,SPH,sigma,EXCL); + } - if(_project){ - for (int i=0;iAsMatrix()); - - } - else{ - resample.resample_scalar(in,SPH,sigma,EXCL_IN); - //resample.downsample(in,SPH,sigma,EXCL); - } - + if (labels) { + SPH.set_pvalues(datamat->AsMatrix()); + SPH.save(output + ".func"); + } else { + datamat->Print(output); + } - if(labels){ - SPH.set_pvalues(datamat->AsMatrix()); - SPH.save(output+".func"); - }else{ - datamat->Print(output); - - } - - + if (getwm) { - if(getwm){ - - for (int i = 0; i < SPH.nvertices(); i++) - wm.set_pvalue(i,SPH.get_pvalue(i)); - - } + for (int i = 0; i < SPH.nvertices(); i++) + wm.set_pvalue(i, SPH.get_pvalue(i)); + } - - - if(getwm) - wm.save(output +"targetmesh"); - - } - //delete datamatsp; + if (getwm) + wm.save(output + "targetmesh"); + } + //delete datamatsp; } diff --git a/src/MSM/simulatediscreteregMR.cc b/src/MSM/simulatediscreteregMR.cc index 89eb7dc..d710bac 100644 --- a/src/MSM/simulatediscreteregMR.cc +++ b/src/MSM/simulatediscreteregMR.cc @@ -7,8 +7,8 @@ /* CCOPYRIGHT */ #include "MeshReg/meshreg.h" -#include #include +#include using namespace std; using namespace NEWMAT; @@ -18,258 +18,259 @@ using namespace NEWMESH; #define sigma 1 -Pt get_square(NEWMESH::newmesh& IN){ - cout << " get sqaure " << endl; - double theta,phi,mindist=RAD; - NEWMESH::Pt ci,origin,closest; - SpMat data(1,IN.nvertices()); - double disttoorigin; - resampler R; - NEWMESH::newmesh tmpmesh=IN; - R.set_method("GAUSSIAN"); - origin.X=RAD*sin(0.5*3.14)*cos(0); - origin.Y=RAD*sin(0.5*3.14)*sin(0); - origin.Z=RAD*cos(0.5*3.14); - - for (int i=0;i data(1, IN.nvertices()); + double disttoorigin; + resampler R; + NEWMESH::newmesh tmpmesh = IN; + R.set_method("GAUSSIAN"); + origin.X = RAD * sin(0.5 * 3.14) * cos(0); + origin.Y = RAD * sin(0.5 * 3.14) * sin(0); + origin.Z = RAD * cos(0.5 * 3.14); + + for (int i = 0; i < IN.nvertices(); i++) { + ci = IN.get_coord(i); + phi = atan2(ci.Y, ci.X); + theta = acos(ci.Z / RAD); + disttoorigin = (ci - origin).norm(); + if (disttoorigin < mindist) { + mindist = disttoorigin; + closest = ci; + } + if (theta >= 0.3 * 3.14 && theta <= 0.7 * 3.14) { + if (phi >= -0.2 * 3.14 && phi < 0.2 * 3.14) { + IN.set_pvalue(i, 10); + } + } } - if(theta>=0.3*3.14 && theta<=0.7*3.14){ - if(phi>=-0.2*3.14 && phi< 0.2*3.14) { - IN.set_pvalue(i,10); - } + + R.resample_scalar(IN, tmpmesh, sigma); + cout << " here " << endl; + for (int i = 0; i < IN.nvertices(); i++) { + if (IN.get_pvalue(i) > 1) + data.Set(1, i + 1, IN.get_pvalue(i)); + else + IN.set_pvalue(i, 0); } - } - - R.resample_scalar(IN,tmpmesh,sigma); - cout << " here " << endl; - for (int i=0;i1) - data.Set(1,i+1,IN.get_pvalue(i)); - else - IN.set_pvalue(i,0); - } - data.Print("CMfile_reference"); - return closest; + data.Print("CMfile_reference"); + return closest; } -void get_circle(NEWMESH::newmesh& IN, Pt p){ - cout << " get circle " << endl; - double val,dist; - NEWMESH::Pt ci; - SpMat data(1,IN.nvertices()); - NEWMESH::newmesh tmpmesh=IN; - resampler R; - R.set_method("GAUSSIAN"); - for (int i=0;i10){ - - IN.set_pvalue(i,10); +void get_circle(NEWMESH::newmesh& IN, Pt p) +{ + cout << " get circle " << endl; + double val, dist; + NEWMESH::Pt ci; + SpMat data(1, IN.nvertices()); + NEWMESH::newmesh tmpmesh = IN; + resampler R; + R.set_method("GAUSSIAN"); + for (int i = 0; i < IN.nvertices(); i++) { + ci = IN.get_coord(i); + dist = (ci - p).norm(); + val = std::ceil(100 * exp(-(dist * dist) / (2 * (sigma) * (sigma)))); + if (val > 10) { + + IN.set_pvalue(i, 10); + } } - } - - R.resample_scalar(IN,tmpmesh,0.1*sigma); - for (int i=0;i1) - data.Set(1,i+1,IN.get_pvalue(i)); - else - IN.set_pvalue(i,0); - } - - data.Print("CMfile_input"); -} -void check_sim(NEWMESH::newmesh &IN){ - cout << " in check sim " << IN.nvertices() << endl; - ///// creat a check patten by dividing theta range into 3 and phi range into 6 - Matrix DATA(1,IN.nvertices()); DATA=0; - Matrix checksize(3,2); - checksize(1,1)=5; checksize(1,2)=15; - checksize(2,1)=7; checksize(2,2)=21; - checksize(3,1)=3; checksize(3,2)=9; - - for (int row=1;row<=1;row++){ - Grid checks; - - checks.Initialize(IN,checksize(row,1),checksize(row,2)); - - vector > cells=checks.return_cell2mesh(); - // vector val; - int val=1; - - for(unsigned int i=0;i 1) + data.Set(1, i + 1, IN.get_pvalue(i)); + else + IN.set_pvalue(i, 0); } - } - // newmesh ICO; - //ICO.load("/Users/emmar/MRIDATA/Phase2/Scalar/NATIVE/SURF/100307.L.myelin.native.surf.gii"); - - //Matrix DATA2=ICO.get_pvalues(); - //resampler R; - //R.set_method("GAUSSIAN"); - //R.resampledata(ICO,IN,DATA2,sigma); - //cout << IN.nvertices() << " DATA2.Ncols() " << DATA2.Ncols() << " DATA.Ncols() " << DATA.Ncols() << " DATA2.Nrows() " << DATA2.Nrows() << " DATA.Nrows() " << DATA.Nrows() << endl; - //for (int i=1;i> cells = checks.return_cell2mesh(); + // vector val; + int val = 1; + + for (unsigned int i = 0; i < cells.size(); i++) { + //cout << i << " cells[i].size() " << cells[i].size() << endl; + for (unsigned int j = 0; j < cells[i].size(); j++) { + //cout < tmp(1,IN.nvertices()),tmp2(1,REF.nvertices()); - // - cout << "REF.mvertices() " << REF.nvertices() << endl; - - tmpM=IN; - //Pt centre=get_square(REF); - //cout << " centre.X " << centre.X << " centre.Y " << centre.Y << " centre.Z " << centre.Z << endl; - //get_circle(IN,centre); - - check_sim(IN); - - REF=IN; - - - cout << " init " << IN.nvertices() << " ref.nvertices() " < tmp(1, IN.nvertices()), tmp2(1, REF.nvertices()); + // + cout << "REF.mvertices() " << REF.nvertices() << endl; + + tmpM = IN; + //Pt centre=get_square(REF); + //cout << " centre.X " << centre.X << " centre.Y " << centre.Y << " centre.Z " << centre.Z << endl; + //get_circle(IN,centre); + + check_sim(IN); + + REF = IN; + + cout << " init " << IN.nvertices() << " ref.nvertices() " << REF.nvertices() << endl; + ICO.load("/Users/emmar/MRIDATA/BadSubjects/205725/MNINonLinear/Native/205725.L.sphere.native.surf.gii"); + REG.load("/Users/emmar/MRIDATA/BadSubjects/205725/MNINonLinear/Native/205725.L.sphere.reg.native.surf.gii"); + // REG.load("/Users/emmar/MRIDATA/Myelindatanew/CP10051_v3/CP10051_v3.L.MyelinMap_on_sphere.reg.reg_LR.native.asc"); + double MVDinput = Calculate_MVD(IN); + //cout << MVDinput << " sigma " << 2*asin(MVDinput/(2*RAD))<< endl; + + tmpM = REF; + cout << "before upsample " << endl; + barycentric_mesh_interpolation(tmpM, ICO, REG); + //upsample_transform_RBF(tmpM,ICO,REG,4*asin(ang*MVDinput/(2*RAD))); + cout << "after upsample " << endl; + resampler R; + R.set_method("NN"); + Matrix DATA = IN.get_pvalues(); + R.resampledata(tmpM, IN, DATA, sigma); + // R.resample_scalar(REF,tmpM,_sigma); + + REF.set_pvalues(DATA); + REF.save("REFchecks2.func"); + cout << "REF.mvertices() " << REF.nvertices() << endl; } -NEWMESH::newmesh create_conf_weighting(newmesh M){ +NEWMESH::newmesh create_conf_weighting(newmesh M) +{ + + newmesh conf = M; + Matrix DATA = M.get_pvalues(); - newmesh conf=M; - Matrix DATA= M.get_pvalues(); - - for (int i=1;i<=M.nvertices();i++) - DATA(1,i)=1; - - // for (int i=1;i<=M.nvertices();i++){ - // if(DATA(2,i)>1.27) DATA(1,i)=1; - // else DATA(1,i)=0; - //} + for (int i = 1; i <= M.nvertices(); i++) + DATA(1, i) = 1; - conf.set_pvalues(DATA); - conf.save("conf_weighting.func.gii"); + // for (int i=1;i<=M.nvertices();i++){ + // if(DATA(2,i)>1.27) DATA(1,i)=1; + // else DATA(1,i)=0; + //} - return conf; -} + conf.set_pvalues(DATA); + conf.save("conf_weighting.func.gii"); -void smooth(NEWMESH::newmesh &M, const double & _sigma){ + return conf; +} - resampler R; - NEWMESH::newmesh target=M; +void smooth(NEWMESH::newmesh& M, const double& _sigma) +{ - R.set_method("GAUSSIAN"); - R.resample_scalar(M,target,_sigma); + resampler R; + NEWMESH::newmesh target = M; + R.set_method("GAUSSIAN"); + R.resample_scalar(M, target, _sigma); } -int main( int argc, char **argv ) +int main(int argc, char** argv) { - NEWMESH::newmesh conf,INPUT,INPUTorig,REF; - resampler resample; - char filename[1000]; - int maxiters=10; - vector _iters; - vector _sigma; - vector ang; - vector _datares; - MeshReg MR; - ofstream out; - int levels=3; - - out.open("simconf"); - out << "--simval=1,2,2,2" << endl; - out << "--it=50,3,3,3" << endl; - out << "--CPgrid=0,2,3,4" << endl; - out << "--datagrid=5,5,5,6" << endl; - out << " --lambda=0,0.005,0.003,0.002 " << endl; - out << " --sigma_in=5,3,2,1 " << endl; - out << " --aKNN=20,20,20,20 " << endl; - out << " --opt=AFFINE,DISCRETE,DISCRETE,DISCRETE " << endl; - //out << " --HO " << endl; - - out.close(); - - _datares.push_back(6); - _sigma.push_back(0); - ang.push_back(1.2); - - initialize_data(INPUT,REF, _datares[0], ang[0],_sigma[0]); - conf=create_conf_weighting(REF); - - INPUT.save("CMfile_input.func"); - INPUT.save("CMfile_input.surf"); - REF.save("CMfile_reference.func"); - - //// INITIALISE VARIABLES //////////////////// - - MR.set_verbosity(true); - - MR.set_input("CMfile_input.surf.gii"); - MR.set_reference("CMfile_input.surf.gii"); - MR.set_outdir("./"); - - MR.set_CMpathin("CMfile_input.func.gii"); - MR.set_CMpathref("CMfile_reference.func.gii"); - - // MR.set_reference_cfweighting("conf_weighting.func.gii"); - // MR.resample(true); - MR.run_multiresolutions(levels,sigma,"simconf"); - - - + NEWMESH::newmesh conf, INPUT, INPUTorig, REF; + resampler resample; + char filename[1000]; + int maxiters = 10; + vector _iters; + vector _sigma; + vector ang; + vector _datares; + MeshReg MR; + ofstream out; + int levels = 3; + + out.open("simconf"); + out << "--simval=1,2,2,2" << endl; + out << "--it=50,3,3,3" << endl; + out << "--CPgrid=0,2,3,4" << endl; + out << "--datagrid=5,5,5,6" << endl; + out << " --lambda=0,0.005,0.003,0.002 " << endl; + out << " --sigma_in=5,3,2,1 " << endl; + out << " --aKNN=20,20,20,20 " << endl; + out << " --opt=AFFINE,DISCRETE,DISCRETE,DISCRETE " << endl; + //out << " --HO " << endl; + + out.close(); + + _datares.push_back(6); + _sigma.push_back(0); + ang.push_back(1.2); + + initialize_data(INPUT, REF, _datares[0], ang[0], _sigma[0]); + conf = create_conf_weighting(REF); + + INPUT.save("CMfile_input.func"); + INPUT.save("CMfile_input.surf"); + REF.save("CMfile_reference.func"); + + //// INITIALISE VARIABLES //////////////////// + + MR.set_verbosity(true); + + MR.set_input("CMfile_input.surf.gii"); + MR.set_reference("CMfile_input.surf.gii"); + MR.set_outdir("./"); + + MR.set_CMpathin("CMfile_input.func.gii"); + MR.set_CMpathref("CMfile_reference.func.gii"); + + // MR.set_reference_cfweighting("conf_weighting.func.gii"); + // MR.resample(true); + MR.run_multiresolutions(levels, sigma, "simconf"); } - - - /////// nxt need potentials - - - +/////// nxt need potentials diff --git a/src/MSM/surfconvert.cc b/src/MSM/surfconvert.cc index e96cea0..6232266 100644 --- a/src/MSM/surfconvert.cc +++ b/src/MSM/surfconvert.cc @@ -5,11 +5,10 @@ Copyright (C) 2012 University of Oxford */ /* CCOPYRIGHT */ -#include -#include -#include "newmesh/meshfns.h" #include "MeshReg/meshreg.h" - +#include "newmesh/meshfns.h" +#include +#include using namespace std; using namespace MISCMATHS; @@ -18,68 +17,69 @@ using namespace MESHREG; void Usage() { - cout << "surfconvert < surfaces> " << endl; - cout << "options: " << endl; - cout << "--data add data (requires argument) " << endl; - cout << "--rescale (requires argument) " << endl; - + cout << "surfconvert < surfaces> " << endl; + cout << "options: " << endl; + cout << "--data add data (requires argument) " << endl; + cout << "--rescale (requires argument) " << endl; } -int main( int argc, char **argv ) +int main(int argc, char** argv) { - newmesh SURFACE; - int ok=0; - double rescale=1.0; - string outname; - - if(argc < 2){ + newmesh SURFACE; + int ok = 0; + double rescale = 1.0; + string outname; - Usage(); - exit(0); - } + if (argc < 2) { - cout << "argv[1" << argv[1] << endl; - SURFACE.load(argv[1]); - argc--; - argv++; - cout << "argv[1" << argv[1] << endl; - outname=argv[1]; - argc--; - argv++; - - while (argc > 1) { - ok = 0; - if((ok == 0) && (strcmp(argv[1], "--data") == 0)){ - argc--; - argv++; - SURFACE.load(argv[1],false,true); - argc--; - argv++; - ok = 1; + Usage(); + exit(0); } - else if((ok == 0) && (strcmp(argv[1], "--centre") == 0)){ - argc--; - argv++; - recentre(SURFACE); - - ok = 1; + + cout << "argv[1" << argv[1] << endl; + SURFACE.load(argv[1]); + argc--; + argv++; + cout << "argv[1" << argv[1] << endl; + outname = argv[1]; + argc--; + argv++; + + while (argc > 1) { + ok = 0; + if ((ok == 0) && (strcmp(argv[1], "--data") == 0)) { + argc--; + argv++; + SURFACE.load(argv[1], false, true); + argc--; + argv++; + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "--centre") == 0)) { + argc--; + argv++; + recentre(SURFACE); + + ok = 1; + } else if ((ok == 0) && (strcmp(argv[1], "--rescale") == 0)) { + argc--; + argv++; + rescale = atof(argv[1]); + argc--; + argv++; + ok = 1; + } else { + cout << argv[1] << " option doesn't exist " << endl; + exit(1); + } } - else if((ok == 0) && (strcmp(argv[1], "--rescale") == 0)){ - argc--; - argv++; - rescale=atof(argv[1]); - argc--; - argv++; - ok = 1; - } else{ cout << argv[1] << " option doesn't exist " << endl; exit(1);} - } - if(rescale>1.0){ - for(int i=0;i 1.0) { + for (int i = 0; i < SURFACE.nvertices(); i++) { + Pt p = SURFACE.get_coord(i); + p.normalize(); + p = p * rescale; + SURFACE.set_coord(i, p); + } } - } - SURFACE.save(outname); + SURFACE.save(outname); } diff --git a/src/MSMRegLib/ContinuosOpt.cc b/src/MSMRegLib/ContinuosOpt.cc index 06b3a4d..b2141ce 100644 --- a/src/MSMRegLib/ContinuosOpt.cc +++ b/src/MSMRegLib/ContinuosOpt.cc @@ -9,294 +9,301 @@ #include "ContinuosOpt.h" namespace MESHREG { - - void MeshCF::Initialize(){ - //////// temporary REGISTRATION PARAMETERS /////////////// +void MeshCF::Initialize() +{ + + //////// temporary REGISTRATION PARAMETERS /////////////// current_sim.ReSize(_SOURCE.nvertices()); - - - MVD=Calculate_MVD(_SOURCE); - - min_sigma=MVD; - _rel=boost::shared_ptr(new RELATIONS (_SOURCE,_TARGET,2*asin(4*MVD/(2*RAD)))); - _rel->estimate_adj(_TARGET.nvertices(),_SOURCE.nvertices()); - sim.Resize(_TARGET.nvertices(),_SOURCE.nvertices()); /// creates sparse sim kernel to fill with similarities of nearest neighbours only - - sim.set_reference(FEAT->get_reference_data()); sim.set_input(FEAT->get_input_data()); + + MVD = Calculate_MVD(_SOURCE); + + min_sigma = MVD; + _rel = boost::shared_ptr(new RELATIONS(_SOURCE, _TARGET, 2 * asin(4 * MVD / (2 * RAD)))); + _rel->estimate_adj(_TARGET.nvertices(), _SOURCE.nvertices()); + sim.Resize(_TARGET.nvertices(), _SOURCE.nvertices()); /// creates sparse sim kernel to fill with similarities of nearest neighbours only + + sim.set_reference(FEAT->get_reference_data()); + sim.set_input(FEAT->get_input_data()); sim.Initialize(_simmeasure); sim.set_relations(_rel); update_similarity(); - - } - - //// weighted least squares similarity gradient estimation - ColumnVector MeshCF::WLS_simgradient(const Tangs &T, int index, const vector &querypoints) - { - - NEWMESH::Pt point, v0, v1,v2,cr; - ColumnVector grad,gradtmp; - SpMat found(_TARGET.nvertices(),1); - Matrix Disp,Dispinv,Data; +} + +//// weighted least squares similarity gradient estimation +ColumnVector MeshCF::WLS_simgradient(const Tangs& T, int index, const vector& querypoints) +{ + + NEWMESH::Pt point, v0, v1, v2, cr; + ColumnVector grad, gradtmp; + SpMat found(_TARGET.nvertices(), 1); + Matrix Disp, Dispinv, Data; Matrix weights; - double x11,x21; - double y11,y21; - double SUM=0.0; - double JPsim=0.0; + double x11, x21; + double y11, y21; + double SUM = 0.0; + double JPsim = 0.0; ColumnVector dist(2); Pt origin; - - gradtmp.ReSize(2); gradtmp=0.0; - - Disp.ReSize(querypoints.size(),2); - weights.ReSize(querypoints.size(),querypoints.size()); - Data.ReSize(querypoints.size(),1); - Disp=0; weights=0; - point=_SOURCE.get_coord(index); + gradtmp.ReSize(2); + gradtmp = 0.0; + Disp.ReSize(querypoints.size(), 2); + weights.ReSize(querypoints.size(), querypoints.size()); + Data.ReSize(querypoints.size(), 1); + Disp = 0; + weights = 0; + point = _SOURCE.get_coord(index); - origin=T.e1*T.e2; + origin = T.e1 * T.e2; origin.normalize(); - origin=origin*RAD; + origin = origin * RAD; - projectPoint(point-origin,T,y11,y21); + projectPoint(point - origin, T, y11, y21); //#pragma omp critical - - for (unsigned int i=0;i0){ - - - // double si=2*RAD*asin(dist.norm()/(2*RAD))/dist.norm(); // geodesic distance - use this instead? - Disp(i+1,1)=x11; Disp(i+1,2)=x21; - - //////////// THE DISTANCES SHOULD BE CALCULATED FOR THE TANGENT PLANE///////////// - we ideally want an analytica expression - - weights(i+1,i+1)=_refweight(1,querypoints[i]+1)*exp(-(dist(1)*dist(1)+dist(2)*dist(2))/(2*min_sigma*min_sigma)); // - - SUM+=weights(i+1,i+1); - JPsim+=sim.Peek(querypoints[i]+1,index+1)*weights(i+1,i+1); - - } + for (unsigned int i = 0; i < querypoints.size(); i++) { + cr = _TARGET.get_coord(querypoints[i]); + projectPoint(cr - origin, T, x11, x21); + dist(1) = x11 - y11; + dist(2) = x21 - y21; + + if ((dist(1) * dist(1) + dist(2) * dist(2)) > 0) { + + // double si=2*RAD*asin(dist.norm()/(2*RAD))/dist.norm(); // geodesic distance - use this instead? + Disp(i + 1, 1) = x11; + Disp(i + 1, 2) = x21; + + //////////// THE DISTANCES SHOULD BE CALCULATED FOR THE TANGENT PLANE///////////// - we ideally want an analytica expression + + weights(i + 1, i + 1) = _refweight(1, querypoints[i] + 1) * exp(-(dist(1) * dist(1) + dist(2) * dist(2)) / (2 * min_sigma * min_sigma)); // + + SUM += weights(i + 1, i + 1); + JPsim += sim.Peek(querypoints[i] + 1, index + 1) * weights(i + 1, i + 1); + } } - - - if(SUM>0) - JPsim/=SUM; - - - for (unsigned int i=0;i 0) + JPsim /= SUM; + + for (unsigned int i = 0; i < querypoints.size(); i++) { + Data(i + 1, 1) = sim.Peek(querypoints[i] + 1, index + 1) - JPsim; // difference of query point to mean similarity } //estimates fits a gradient to the set samples and their similarity values using WLS - Matrix tmp=((Disp.t()*weights)*Disp); - if(tmp.Determinant()>1e-5){ - Dispinv=(tmp.i()*Disp.t())*weights; - gradtmp=Dispinv*Data; + Matrix tmp = ((Disp.t() * weights) * Disp); + if (tmp.Determinant() > 1e-5) { + Dispinv = (tmp.i() * Disp.t()) * weights; + gradtmp = Dispinv * Data; } - - - grad.ReSize(3); grad=0.0; - grad(1) += (gradtmp(1)*(T.e1).X + gradtmp(2)*(T.e2).X) ; - grad(2) += (gradtmp(1)*(T.e1).Y + gradtmp(2)*(T.e2).Y) ; - grad(3) += (gradtmp(1)*(T.e1).Z + gradtmp(2)*(T.e2).Z) ; - - - current_sim(index+1)=JPsim; + + grad.ReSize(3); + grad = 0.0; + grad(1) += (gradtmp(1) * (T.e1).X + gradtmp(2) * (T.e2).X); + grad(2) += (gradtmp(1) * (T.e1).Y + gradtmp(2) * (T.e2).Y); + grad(3) += (gradtmp(1) * (T.e1).Z + gradtmp(2) * (T.e2).Z); + + current_sim(index + 1) = JPsim; return grad; - - } - - - ////////////////////////////////// UPDATES //////////////////////////////////////// - - void MeshCF::update_similarity() - { - - - - for (int i=1;i<=_SOURCE.nvertices();i++) - _rel->update_RELATIONS_for_ind(i,_SOURCE); - - sim.set_input(FEAT->get_input_data()); +} + +////////////////////////////////// UPDATES //////////////////////////////////////// + +void MeshCF::update_similarity() +{ + + for (int i = 1; i <= _SOURCE.nvertices(); i++) + _rel->update_RELATIONS_for_ind(i, _SOURCE); + + sim.set_input(FEAT->get_input_data()); sim.set_reference(FEAT->get_reference_data()); - - for(int i=1;i<=_SOURCE.nvertices();i++){ - sim.calculate_sim_column(i); + for (int i = 1; i <= _SOURCE.nvertices(); i++) { + sim.calculate_sim_column(i); } - - } - - void MeshCF::update_similarity(const int &i,vector & points) - { - - _rel->update_w_querypoints_for_ind(i+1,points); - sim.calculate_sim_column(i+1); - - } - - ColumnVector MeshCF::Evaluate_SIMGradient(int i,const Tangs &T){ - - SpMat found(_TARGET.nvertices(),1); - int n0,n1,n2,t_ind; - NEWMESH::Pt point, v0, v1,v2; +} + +void MeshCF::update_similarity(const int& i, vector& points) +{ + + _rel->update_w_querypoints_for_ind(i + 1, points); + sim.calculate_sim_column(i + 1); +} + +ColumnVector MeshCF::Evaluate_SIMGradient(int i, const Tangs& T) +{ + + SpMat found(_TARGET.nvertices(), 1); + int n0, n1, n2, t_ind; + NEWMESH::Pt point, v0, v1, v2; vector querypoints; - bool update=false; + bool update = false; ColumnVector vecnew; - - point=_SOURCE.get_coord(i); - - if(_rel->Nrows(i+1)){ - t_ind=(int) (*_rel)(1,i+1); - - vecnew.ReSize(3); vecnew=0; - do{ - querypoints.clear(); - if(_TARGET.return_closest_points(t_ind-1,v0,v1,v2,point,n0,n1,n2)){ // finds nearest point in target mesh - /// obtains all the vertices connected to this point - if((_refweight(1,n0+1) > 0) && (_refweight(1,n1+1) > 0) && ( _refweight(1,n2+1) > 0) ){ - if(get_all_neighbours(i,querypoints, point,n0,_TARGET,*_rel,found)) update=true; - if(get_all_neighbours(i,querypoints, point,n1,_TARGET,*_rel,found) || update==true ) update=true; - if(get_all_neighbours(i,querypoints, point,n2,_TARGET,*_rel,found) || update==true ) update=true; - - if(update){ - update_similarity(i,querypoints) ; - } - /// calculates similarity gradient - vecnew=WLS_simgradient(T,i,querypoints); - vecnew=_inweight(1,i+1)*_refweight(1, t_ind)*vecnew; - update=false; - - }else{ update=false; current_sim(i+1)=0;} - }else{update=true; _rel->find_next_closest_neighbour(i+1,t_ind,point,_TARGET);} - }while(update==true); - } - + + point = _SOURCE.get_coord(i); + + if (_rel->Nrows(i + 1)) { + t_ind = (int)(*_rel)(1, i + 1); + + vecnew.ReSize(3); + vecnew = 0; + do { + querypoints.clear(); + if (_TARGET.return_closest_points(t_ind - 1, v0, v1, v2, point, n0, n1, n2)) { // finds nearest point in target mesh + /// obtains all the vertices connected to this point + if ((_refweight(1, n0 + 1) > 0) && (_refweight(1, n1 + 1) > 0) && (_refweight(1, n2 + 1) > 0)) { + if (get_all_neighbours(i, querypoints, point, n0, _TARGET, *_rel, found)) + update = true; + if (get_all_neighbours(i, querypoints, point, n1, _TARGET, *_rel, found) || update == true) + update = true; + if (get_all_neighbours(i, querypoints, point, n2, _TARGET, *_rel, found) || update == true) + update = true; + + if (update) { + update_similarity(i, querypoints); + } + /// calculates similarity gradient + vecnew = WLS_simgradient(T, i, querypoints); + vecnew = _inweight(1, i + 1) * _refweight(1, t_ind) * vecnew; + update = false; + + } else { + update = false; + current_sim(i + 1) = 0; + } + } else { + update = true; + _rel->find_next_closest_neighbour(i + 1, t_ind, point, _TARGET); + } + } while (update == true); + } + return vecnew; - } - - - /////////////// AFFINE REGISTRATION FUNCTIONS - from Alek Petrovic // - void affineMeshCF::Rotate_IN_mesh(const double &a1, const double &a2,const double & a3){ - - - for (int index=0; index < _SOURCE.nvertices(); index++){ - - NEWMESH::Pt cii = _SOURCE.get_coord(index); - NEWMAT::ColumnVector V(3), VR(3); - V(1) = cii.X; V(2) = cii.Y; V(3) = cii.Z; - VR = rotate_euler(V,a1,a2,a3); // in meshregfns - - NEWMESH::Pt ppc(VR(1), VR(2), VR(3)); - _SOURCE.set_coord(index,ppc); +} + +/////////////// AFFINE REGISTRATION FUNCTIONS - from Alek Petrovic // +void affineMeshCF::Rotate_IN_mesh(const double& a1, const double& a2, const double& a3) +{ + + for (int index = 0; index < _SOURCE.nvertices(); index++) { + + NEWMESH::Pt cii = _SOURCE.get_coord(index); + NEWMAT::ColumnVector V(3), VR(3); + V(1) = cii.X; + V(2) = cii.Y; + V(3) = cii.Z; + VR = rotate_euler(V, a1, a2, a3); // in meshregfns + + NEWMESH::Pt ppc(VR(1), VR(2), VR(3)); + _SOURCE.set_coord(index, ppc); } - - } - - double affineMeshCF::Affine_cost_mesh(const double & dw1, const double & dw2,const double &dw3){ - +} + +double affineMeshCF::Affine_cost_mesh(const double& dw1, const double& dw2, const double& dw3) +{ + double SUM = 0; - NEWMESH::newmesh tmp=_SOURCE; - Tangent Tang; // holds tangent plane basis at each point - - Rotate_IN_mesh(dw1,dw2,dw3); - - for (int index=0; index < _SOURCE.nvertices(); index++){ - if(_rel->Nrows(index+1)){ - Tangs T = Tang.calculate(index,_SOURCE); - Evaluate_SIMGradient(index,T); /// only need mean similarity from this most of this code is now redundant! - SUM+=current_sim(index+1); - } + NEWMESH::newmesh tmp = _SOURCE; + Tangent Tang; // holds tangent plane basis at each point + + Rotate_IN_mesh(dw1, dw2, dw3); + + for (int index = 0; index < _SOURCE.nvertices(); index++) { + if (_rel->Nrows(index + 1)) { + Tangs T = Tang.calculate(index, _SOURCE); + Evaluate_SIMGradient(index, T); /// only need mean similarity from this most of this code is now redundant! + SUM += current_sim(index + 1); + } } - - _SOURCE=tmp; + + _SOURCE = tmp; return SUM; - } - - NEWMESH::newmesh affineMeshCF::run(){ - if(_verbosity) - cout<<"Affine registration started"< 0.05){ - double step=_stepsize; - - per =_spacing; - for (int _iter=1; _iter <= _iters; _iter++){ - //Initially Euler angles are zero - Euler1 = 0; Euler2 = 0; Euler3 = 0; - - - NEWMESH::Pt grad; - - grad.X = (Affine_cost_mesh(Euler1+per, Euler2, Euler3)-grad_zero)/per; - - grad.Y = (Affine_cost_mesh(Euler1, Euler2+per, Euler3)-grad_zero)/per; - - grad.Z = (Affine_cost_mesh(Euler1, Euler2, Euler3+per)-grad_zero)/per; - - grad.normalize(); - Euler1 = Euler1 + step*grad.X; - Euler2 = Euler2 + step*grad.Y; - Euler3 = Euler3 + step*grad.Z; - if(_verbosity){ - cout<<"******: "<< _iter << " per " << per << " loop" << loop << " (loop*_iters)+ _iter " << (loop*_iters)+ _iter << endl; - cout<<"grad_zero: "< mingrad_zero){ mingrad_zero = grad_zero; min_iter=(loop*_iters)+_iter; RECfinal=mingrad_zero;} - - if((loop*_iters)+_iter -min_iter>0){ step*=0.5; _SOURCE=tmp;} - if(step<1e-3) break; - + while (_spacing > 0.05) { + double step = _stepsize; + + per = _spacing; + for (int _iter = 1; _iter <= _iters; _iter++) { + //Initially Euler angles are zero + Euler1 = 0; + Euler2 = 0; + Euler3 = 0; + + NEWMESH::Pt grad; + + grad.X = (Affine_cost_mesh(Euler1 + per, Euler2, Euler3) - grad_zero) / per; + + grad.Y = (Affine_cost_mesh(Euler1, Euler2 + per, Euler3) - grad_zero) / per; + + grad.Z = (Affine_cost_mesh(Euler1, Euler2, Euler3 + per) - grad_zero) / per; + + grad.normalize(); + Euler1 = Euler1 + step * grad.X; + Euler2 = Euler2 + step * grad.Y; + Euler3 = Euler3 + step * grad.Z; + if (_verbosity) { + cout << "******: " << _iter << " per " << per << " loop" << loop << " (loop*_iters)+ _iter " << (loop * _iters) + _iter << endl; + cout << "grad_zero: " << grad_zero << endl; + cout << "mingrad_zero: " << mingrad_zero << "min_iter " << min_iter << endl; + cout << "stepsize: " << step << endl; + } + tmp = _SOURCE; + Rotate_IN_mesh(Euler1, Euler2, Euler3); + grad_zero = Affine_cost_mesh(Euler1, Euler2, Euler3); + + if (grad_zero > mingrad_zero) { + mingrad_zero = grad_zero; + min_iter = (loop * _iters) + _iter; + RECfinal = mingrad_zero; + } + + if ((loop * _iters) + _iter - min_iter > 0) { + step *= 0.5; + _SOURCE = tmp; + } + if (step < 1e-3) + break; + } + loop++; + _spacing *= 0.5; } - loop++; - _spacing*=0.5; - -} - E(1) = Euler1; E(2) = Euler2; E(3) = Euler3; - if(_verbosity && (RECfinal >0) ) - cout<<"Affine improvement: "<< abs(((RECfinal-RECinit))/RECfinal*100)<<"%"<< endl; - - - return _SOURCE; - } - + if (_verbosity && (RECfinal > 0)) + cout << "Affine improvement: " << abs(((RECfinal - RECinit)) / RECfinal * 100) << "%" << endl; + return _SOURCE; } +} diff --git a/src/MSMRegLib/ContinuosOpt.h b/src/MSMRegLib/ContinuosOpt.h index eb06e9e..0f50e01 100644 --- a/src/MSMRegLib/ContinuosOpt.h +++ b/src/MSMRegLib/ContinuosOpt.h @@ -23,35 +23,36 @@ using namespace DISCRETEOPT; - -#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO- NOT USED ANY MORE? +#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO- NOT USED ANY MORE? using namespace NEWMESH; -namespace MESHREG{ - - class MESHREGException: public std::exception +namespace MESHREG { + +class MESHREGException : public std::exception { +private: + std::string m_msg; + +public: + MESHREGException(const std::string& msg) throw() + : m_msg(msg) { - private: - std::string m_msg; - public: - MESHREGException(const std::string& msg) throw(): m_msg(msg) {} - - virtual const char * what() const throw() { - return string("Fnirt: msg=" + m_msg).c_str(); - } - - ~MESHREGException() throw() {} - }; - - - class MeshCF { /// basic mesh cost function - uses the gradient of the similarity function, estimated using weighted least squares - - - protected: + } + + virtual const char* what() const throw() + { + return string("Fnirt: msg=" + m_msg).c_str(); + } + + ~MESHREGException() throw() { } +}; + +class MeshCF { /// basic mesh cost function - uses the gradient of the similarity function, estimated using weighted least squares + +protected: NEWMESH::newmesh _TARGET; // TARGET MESH NEWMESH::newmesh _SOURCE; // SOURCE MESH - + boost::shared_ptr _rel; // saves mesh neighbourhood information Matrix _inweight; // exclusion/weighting mask for cost function masking @@ -59,119 +60,129 @@ namespace MESHREG{ const boost::shared_ptr FEAT; /// holds data sparsesimkernel sim; // similarity matrix - - + double MVD; // mean vertex distance ///////// user defined parameters ///////// - int _simmeasure; + int _simmeasure; int _iters; // total iterations float _stepsize; float _spacing; - ////////////////////////////////////////// + ////////////////////////////////////////// - string m_outdir; - + vector BASIS; ///////////// tangent vector bases for all vertices - bool _verbosity; + bool _verbosity; ////// GRAD DESCENT PARAMETERS ///////////////// mutable ColumnVector current_sim; - double min_sigma; - double CF; + double CF; double totJP; double totJD; - - public: - - MeshCF(const NEWMESH::newmesh & target, - const NEWMESH::newmesh & source, - const Matrix T_cfweight, - const Matrix S_cfweight, - const boost::shared_ptr features) - : _TARGET(target),_SOURCE(source),_inweight(S_cfweight),_refweight(T_cfweight), FEAT(features) +public: + MeshCF(const NEWMESH::newmesh& target, + const NEWMESH::newmesh& source, + const Matrix T_cfweight, + const Matrix S_cfweight, + const boost::shared_ptr features) + : _TARGET(target) + , _SOURCE(source) + , _inweight(S_cfweight) + , _refweight(T_cfweight) + , FEAT(features) { - - //// DEFAULT PARAMETRISATION ///// - _simmeasure=3; - _iters=10000; - _verbosity=false; + + //// DEFAULT PARAMETRISATION ///// + _simmeasure = 3; + _iters = 10000; + _verbosity = false; } - MeshCF (const NEWMESH::newmesh target, const NEWMESH::newmesh &source, - const boost::shared_ptr features):_TARGET(target), _SOURCE(source),FEAT(features){ - _simmeasure=3; - _iters=20; - _verbosity=false; - _inweight.ReSize(1, _SOURCE.nvertices()); _refweight.ReSize(1, _TARGET.nvertices()); // if no cf weighting then set weighting to 1 by default - _inweight=1; _refweight=1; - - } - - void set_parameters(myparam PAR){ - myparam::iterator it; - it=PAR.find("iters");_iters=boost::get(it->second); - it=PAR.find("simmeasure");_simmeasure=boost::get(it->second); - it=PAR.find("verbosity");_verbosity=boost::get(it->second); - it=PAR.find("stepsize");_stepsize=boost::get(it->second); - it=PAR.find("gradsampling");_spacing=boost::get(it->second); - it=PAR.find("outdir");m_outdir=boost::get(it->second); + MeshCF(const NEWMESH::newmesh target, const NEWMESH::newmesh& source, + const boost::shared_ptr features) + : _TARGET(target) + , _SOURCE(source) + , FEAT(features) + { + _simmeasure = 3; + _iters = 20; + _verbosity = false; + _inweight.ReSize(1, _SOURCE.nvertices()); + _refweight.ReSize(1, _TARGET.nvertices()); // if no cf weighting then set weighting to 1 by default + _inweight = 1; + _refweight = 1; + } + void set_parameters(myparam PAR) + { + myparam::iterator it; + it = PAR.find("iters"); + _iters = boost::get(it->second); + it = PAR.find("simmeasure"); + _simmeasure = boost::get(it->second); + it = PAR.find("verbosity"); + _verbosity = boost::get(it->second); + it = PAR.find("stepsize"); + _stepsize = boost::get(it->second); + it = PAR.find("gradsampling"); + _spacing = boost::get(it->second); + it = PAR.find("outdir"); + m_outdir = boost::get(it->second); } ///////////////////// INITIALIZE /////////////////// - virtual void Initialize(); - void set_simmeasure(const int & simval){_simmeasure=simval;} - + virtual void Initialize(); + void set_simmeasure(const int& simval) { _simmeasure = simval; } + //////////////// MAKE UPDATES //////////////////// - - void update_similarity(); - void update_similarity(const int &, vector &); - void update_source(const NEWMESH::newmesh& M) {_SOURCE=M; }; - - //////////////// SIMILARITY GRADIENT ESTIMATION ///////////////////// + + void update_similarity(); + void update_similarity(const int&, vector&); + void update_source(const NEWMESH::newmesh& M) { _SOURCE = M; }; + + //////////////// SIMILARITY GRADIENT ESTIMATION ///////////////////// ///// similarity gradient via weighted regression - - ColumnVector WLS_simgradient(const Tangs &T, int ,const vector &); + ColumnVector WLS_simgradient(const Tangs& T, int, const vector&); //// prepares data for sim gradient calculation - - ColumnVector Evaluate_SIMGradient(int i,const Tangs &T); - - virtual NEWMESH::newmesh run()=0; - ////////////////// RETURNING FUNCTIONS /////////////////////// - NEWMESH::newmesh get_REG()const{return _SOURCE;} - }; + ColumnVector Evaluate_SIMGradient(int i, const Tangs& T); + virtual NEWMESH::newmesh run() = 0; + ////////////////// RETURNING FUNCTIONS /////////////////////// + + NEWMESH::newmesh get_REG() const { return _SOURCE; } +}; - class affineMeshCF: public MeshCF - { +class affineMeshCF : public MeshCF { +public: + affineMeshCF(const NEWMESH::newmesh& target, const NEWMESH::newmesh& source, const boost::shared_ptr features) + : MeshCF(target, source, features) + { + } + virtual ~affineMeshCF() {}; - public: - - affineMeshCF(const NEWMESH::newmesh & target, const NEWMESH::newmesh &source,const boost::shared_ptr features ): MeshCF(target,source,features){} - virtual ~ affineMeshCF() {}; - - void Initialize(){MeshCF::Initialize();} + void Initialize() { MeshCF::Initialize(); } /////////////// AFFINE FUNCTIONS - uses image gradients and euler rotations - taken from Alek Petrovic's implementation. - void Rotate_IN_mesh(const double &, const double &,const double &); - double Affine_cost_mesh(const double & , const double & ,const double &); + void Rotate_IN_mesh(const double&, const double&, const double&); + double Affine_cost_mesh(const double&, const double&, const double&); NEWMESH::newmesh run(); - ColumnVector return_transformation(){return REC;} - private: + ColumnVector return_transformation() { return REC; } +private: ColumnVector REC; affineMeshCF(); - virtual affineMeshCF& operator=(const affineMeshCF& inf) {throw MESHREGException("LM_MeshCF:: Assignment explicitly disallowed"); return(*this);} - - }; - + virtual affineMeshCF& operator=(const affineMeshCF& inf) + { + throw MESHREGException("LM_MeshCF:: Assignment explicitly disallowed"); + return (*this); + } +}; - } #endif diff --git a/src/MSMRegLib/Fusion.h b/src/MSMRegLib/Fusion.h index 135b15f..ea68440 100644 --- a/src/MSMRegLib/Fusion.h +++ b/src/MSMRegLib/Fusion.h @@ -6,21 +6,16 @@ /* CCOPYRIGHT */ - - #include - #ifdef HAS_HOCR #include "ELC/ELC.h" #endif - - #ifdef HAS_TBB -#include "tbb/parallel_for.h" #include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" #include "tbb/task_scheduler_init.h" #include "tbb/tick_count.h" using namespace tbb; @@ -37,129 +32,143 @@ using namespace FPD; using namespace detail; using namespace DISCRETEOPT; - -typedef double REAL; -struct UnaryData { REAL buffer[2]; }; -struct PairData { REAL buffer[4]; }; -struct TripletData { REAL buffer[8]; }; -struct QuartetData { REAL buffer[16]; }; - +typedef double REAL; +struct UnaryData { + REAL buffer[2]; +}; +struct PairData { + REAL buffer[4]; +}; +struct TripletData { + REAL buffer[8]; +}; +struct QuartetData { + REAL buffer[16]; +}; namespace ELCReduce { - template class PBF; +template +class PBF; } -template class QPBO; - +template +class QPBO; namespace MESHREG { #ifdef HAS_TBB - class computeTripletCosts{ +class computeTripletCosts { const boost::shared_ptr my_energy; const int* my_trip; const int* my_labels; const int my_current_label; - std::vector & my_DATA; + std::vector& my_DATA; - public: +public: // constructor copies the arguments into local storage - computeTripletCosts(const boost::shared_ptr & energy, const int *trip, const int *labels, const int & label, std::vector & DATA) : - my_energy(energy), my_trip(trip), my_labels(labels), my_current_label(label),my_DATA(DATA) - {} + computeTripletCosts(const boost::shared_ptr& energy, const int* trip, const int* labels, const int& label, std::vector& DATA) + : my_energy(energy) + , my_trip(trip) + , my_labels(labels) + , my_current_label(label) + , my_DATA(DATA) + { + } // overload () so it does a vector multiply - void operator() (const blocked_range &r) const { - for(size_t triplet=r.begin(); triplet!=r.end(); triplet++){ - const int nodeA = my_trip[triplet*3]; - const int nodeB = my_trip[triplet*3+1]; - const int nodeC = my_trip[triplet*3+2]; - - my_DATA[triplet].buffer[0] = my_energy->computeTripletCost(triplet,my_labels[nodeA],my_labels[nodeB],my_labels[nodeC]); //000 - my_DATA[triplet].buffer[1] = my_energy->computeTripletCost(triplet,my_labels[nodeA],my_labels[nodeB],my_current_label); //001 - my_DATA[triplet].buffer[2] = my_energy->computeTripletCost(triplet,my_labels[nodeA],my_current_label,my_labels[nodeC]); //010 - my_DATA[triplet].buffer[3] = my_energy->computeTripletCost(triplet,my_labels[nodeA],my_current_label,my_current_label); //011 - my_DATA[triplet].buffer[4] = my_energy->computeTripletCost(triplet,my_current_label,my_labels[nodeB],my_labels[nodeC]); //100 - my_DATA[triplet].buffer[5] = my_energy->computeTripletCost(triplet,my_current_label,my_labels[nodeB],my_current_label); //101 - my_DATA[triplet].buffer[6] = my_energy->computeTripletCost(triplet,my_current_label,my_current_label,my_labels[nodeC]); //110 - my_DATA[triplet].buffer[7] = my_energy->computeTripletCost(triplet,my_current_label,my_current_label,my_current_label); - } + void operator()(const blocked_range& r) const + { + for (size_t triplet = r.begin(); triplet != r.end(); triplet++) { + const int nodeA = my_trip[triplet * 3]; + const int nodeB = my_trip[triplet * 3 + 1]; + const int nodeC = my_trip[triplet * 3 + 2]; + + my_DATA[triplet].buffer[0] = my_energy->computeTripletCost(triplet, my_labels[nodeA], my_labels[nodeB], my_labels[nodeC]); //000 + my_DATA[triplet].buffer[1] = my_energy->computeTripletCost(triplet, my_labels[nodeA], my_labels[nodeB], my_current_label); //001 + my_DATA[triplet].buffer[2] = my_energy->computeTripletCost(triplet, my_labels[nodeA], my_current_label, my_labels[nodeC]); //010 + my_DATA[triplet].buffer[3] = my_energy->computeTripletCost(triplet, my_labels[nodeA], my_current_label, my_current_label); //011 + my_DATA[triplet].buffer[4] = my_energy->computeTripletCost(triplet, my_current_label, my_labels[nodeB], my_labels[nodeC]); //100 + my_DATA[triplet].buffer[5] = my_energy->computeTripletCost(triplet, my_current_label, my_labels[nodeB], my_current_label); //101 + my_DATA[triplet].buffer[6] = my_energy->computeTripletCost(triplet, my_current_label, my_current_label, my_labels[nodeC]); //110 + my_DATA[triplet].buffer[7] = my_energy->computeTripletCost(triplet, my_current_label, my_current_label, my_current_label); + } } +}; - }; - - class computeQuartetCosts{ +class computeQuartetCosts { const boost::shared_ptr my_energy; const int* my_quartet; const int* my_labels; const int my_current_label; - std::vector & my_DATA; + std::vector& my_DATA; - public: +public: // constructor copies the arguments into local storage - computeQuartetCosts(const boost::shared_ptr & energy, const int *quart, const int *labels, const int & label, std::vector & DATA) : - my_energy(energy), my_quartet(quart), my_labels(labels), my_current_label(label),my_DATA(DATA) - {} + computeQuartetCosts(const boost::shared_ptr& energy, const int* quart, const int* labels, const int& label, std::vector& DATA) + : my_energy(energy) + , my_quartet(quart) + , my_labels(labels) + , my_current_label(label) + , my_DATA(DATA) + { + } // overload () so it does a vector multiply - void operator() (const blocked_range &r) const { - for(size_t quartet=r.begin(); quartet!=r.end(); quartet++){ - const int nodeA = my_quartet[quartet*4]; - const int nodeB = my_quartet[quartet*4+1]; - const int nodeC = my_quartet[quartet*4+2]; - const int nodeD = my_quartet[quartet*4+3]; - - my_DATA[quartet].buffer[0] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_labels[nodeB],my_labels[nodeC],my_labels[nodeD]); - my_DATA[quartet].buffer[1] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_labels[nodeB],my_labels[nodeC],my_current_label); - my_DATA[quartet].buffer[2] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_labels[nodeB],my_current_label,my_labels[nodeD]); - my_DATA[quartet].buffer[3] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_labels[nodeB],my_current_label,my_current_label); - - my_DATA[quartet].buffer[4] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_current_label,my_labels[nodeC],my_labels[nodeD]); - my_DATA[quartet].buffer[5] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_current_label,my_labels[nodeC],my_current_label); - my_DATA[quartet].buffer[6] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_current_label,my_current_label,my_labels[nodeD]); - my_DATA[quartet].buffer[7] = my_energy->computeQuartetCost(quartet,my_labels[nodeA],my_current_label,my_current_label,my_current_label); - - my_DATA[quartet].buffer[8] = my_energy->computeQuartetCost(quartet,my_current_label,my_labels[nodeB],my_labels[nodeC],my_labels[nodeD]); - my_DATA[quartet].buffer[9] = my_energy->computeQuartetCost(quartet,my_current_label,my_labels[nodeB],my_labels[nodeC],my_current_label); - my_DATA[quartet].buffer[10] = my_energy->computeQuartetCost(quartet,my_current_label,my_labels[nodeB],my_current_label,my_labels[nodeD]); - my_DATA[quartet].buffer[11] = my_energy->computeQuartetCost(quartet,my_current_label,my_labels[nodeB],my_current_label,my_current_label); - - my_DATA[quartet].buffer[12] = my_energy->computeQuartetCost(quartet,my_current_label,my_current_label,my_labels[nodeC],my_labels[nodeD]); - my_DATA[quartet].buffer[13] = my_energy->computeQuartetCost(quartet,my_current_label,my_current_label,my_labels[nodeC],my_current_label); - my_DATA[quartet].buffer[14] = my_energy->computeQuartetCost(quartet,my_current_label,my_current_label,my_current_label,my_labels[nodeD]); - my_DATA[quartet].buffer[15] = my_energy->computeQuartetCost(quartet,my_current_label,my_current_label,my_current_label,my_current_label); - - - } + void operator()(const blocked_range& r) const + { + for (size_t quartet = r.begin(); quartet != r.end(); quartet++) { + const int nodeA = my_quartet[quartet * 4]; + const int nodeB = my_quartet[quartet * 4 + 1]; + const int nodeC = my_quartet[quartet * 4 + 2]; + const int nodeD = my_quartet[quartet * 4 + 3]; + + my_DATA[quartet].buffer[0] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_labels[nodeB], my_labels[nodeC], my_labels[nodeD]); + my_DATA[quartet].buffer[1] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_labels[nodeB], my_labels[nodeC], my_current_label); + my_DATA[quartet].buffer[2] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_labels[nodeB], my_current_label, my_labels[nodeD]); + my_DATA[quartet].buffer[3] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_labels[nodeB], my_current_label, my_current_label); + + my_DATA[quartet].buffer[4] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_current_label, my_labels[nodeC], my_labels[nodeD]); + my_DATA[quartet].buffer[5] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_current_label, my_labels[nodeC], my_current_label); + my_DATA[quartet].buffer[6] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_current_label, my_current_label, my_labels[nodeD]); + my_DATA[quartet].buffer[7] = my_energy->computeQuartetCost(quartet, my_labels[nodeA], my_current_label, my_current_label, my_current_label); + + my_DATA[quartet].buffer[8] = my_energy->computeQuartetCost(quartet, my_current_label, my_labels[nodeB], my_labels[nodeC], my_labels[nodeD]); + my_DATA[quartet].buffer[9] = my_energy->computeQuartetCost(quartet, my_current_label, my_labels[nodeB], my_labels[nodeC], my_current_label); + my_DATA[quartet].buffer[10] = my_energy->computeQuartetCost(quartet, my_current_label, my_labels[nodeB], my_current_label, my_labels[nodeD]); + my_DATA[quartet].buffer[11] = my_energy->computeQuartetCost(quartet, my_current_label, my_labels[nodeB], my_current_label, my_current_label); + + my_DATA[quartet].buffer[12] = my_energy->computeQuartetCost(quartet, my_current_label, my_current_label, my_labels[nodeC], my_labels[nodeD]); + my_DATA[quartet].buffer[13] = my_energy->computeQuartetCost(quartet, my_current_label, my_current_label, my_labels[nodeC], my_current_label); + my_DATA[quartet].buffer[14] = my_energy->computeQuartetCost(quartet, my_current_label, my_current_label, my_current_label, my_labels[nodeD]); + my_DATA[quartet].buffer[15] = my_energy->computeQuartetCost(quartet, my_current_label, my_current_label, my_current_label, my_current_label); + } } - - }; +}; #endif - enum Reduction - { +enum Reduction { ELC_HOCR, ELC_APPROX, HOCR - }; - class Fusion - { - public: +}; +class Fusion { +public: /** * Constructor. */ - Fusion() {} + Fusion() { } /** * Destructor. */ - ~Fusion() {} + ~Fusion() { } - template static void reduce_and_convert(ELCReduce::PBF&,OPTIMIZER&, Reduction); + template + static void reduce_and_convert(ELCReduce::PBF&, OPTIMIZER&, Reduction); /** * Runs the optimization. */ - static double optimize(boost::shared_ptr energy, Reduction reductionMode, bool debug=false); - }; + static double optimize(boost::shared_ptr energy, Reduction reductionMode, bool debug = false); +}; } diff --git a/src/MSMRegLib/groupmeshreg.cc b/src/MSMRegLib/groupmeshreg.cc index 8dd69ee..e8d22f1 100644 --- a/src/MSMRegLib/groupmeshreg.cc +++ b/src/MSMRegLib/groupmeshreg.cc @@ -11,219 +11,228 @@ namespace MESHREG { - void GroupMeshReg::Initialize_level(int level) - { - cout << " In Initialize level " << DATAlist.size() < sigma(MESHES.size(),_sigma_in[level]); + vector sigma(MESHES.size(), _sigma_in[level]); NEWMESH::newmesh CONTROL; // original low res icosphere mesh - CONTROL.make_mesh_from_icosa(_gridres[level] ); true_rescale(CONTROL,RAD); - FEAT=boost::shared_ptr(new featurespace(DATAlist)); + CONTROL.make_mesh_from_icosa(_gridres[level]); + true_rescale(CONTROL, RAD); + FEAT = boost::shared_ptr(new featurespace(DATAlist)); FEAT->set_smoothing_parameters(sigma); FEAT->set_cutthreshold(_threshold); // will also generate exclusion masks at the same mesh resolution as datagrid - FEAT->logtransform(_logtransform);// if true logtransforms AND normalises - FEAT->varnorm(_varnorm);// variance normalises + FEAT->logtransform(_logtransform); // if true logtransforms AND normalises + FEAT->varnorm(_varnorm); // variance normalises FEAT->intensitynormalize(_IN, _scale); // matches the intensities of the source to to the target (will rescale all to the top feature of the target if scale is true) FEAT->resamplingmethod(_dataInterpolator); FEAT->is_sparse(_issparse); - SPH_orig=FEAT->Initialize(_genesis[level],MESHES,_exclude); /// downsamples and smooths data, creates and exclusion mask if exclude is true + SPH_orig = FEAT->Initialize(_genesis[level], MESHES, _exclude); /// downsamples and smooths data, creates and exclusion mask if exclude is true cout << " after FEAT INIT " << endl; - if(cost[level]=="AFFINE"){ - throw MeshReg_error("GroupMeshREG ERROR:: affine not currently available"); - }else{ - - cout << " 1 " << endl; - bool multivariate=true; - if(FEAT->get_dim()==1){multivariate=false; if (_simval[level]==4) {throw MeshReg_error("MeshREG ERROR:: simval option 4 (alphaMI) is not suitable for univariate costfunctions");}} - - if(multivariate==true) throw MeshReg_error("GroupMeshREG ERROR:: multivariate not currently available"); - - PARAMETERS.insert(parameterPair("multivariate",multivariate)); // check whether data is multivariate (and NOT using patch based alignment) and add this to the parameter set - - cout << " create MODEL " << _debug << endl; - MODEL=boost::shared_ptr(new GroupDiscreteModel(PARAMETERS)); - cout << " after create Model " << endl; - if(_debug) MODEL->set_debug(); - // if(_L1path=="" && _quartet==true) throw MeshReg_error("GroupMeshREG ERROR::quartet version requires matlab path"); - //else MODEL->set_L1path(_L1path); - cout << " set feat " << endl; - MODEL->set_featurespace(FEAT); - cout << " set meshspace " << endl; - - MODEL->set_meshspace(SPH_orig,SPH_orig,MESHES.size()); - MODEL->Initialize(CONTROL); - - + if (cost[level] == "AFFINE") { + throw MeshReg_error("GroupMeshREG ERROR:: affine not currently available"); + } else { + + cout << " 1 " << endl; + bool multivariate = true; + if (FEAT->get_dim() == 1) { + multivariate = false; + if (_simval[level] == 4) { + throw MeshReg_error("MeshREG ERROR:: simval option 4 (alphaMI) is not suitable for univariate costfunctions"); + } + } + + if (multivariate == true) + throw MeshReg_error("GroupMeshREG ERROR:: multivariate not currently available"); + + PARAMETERS.insert(parameterPair("multivariate", multivariate)); // check whether data is multivariate (and NOT using patch based alignment) and add this to the parameter set + + cout << " create MODEL " << _debug << endl; + MODEL = boost::shared_ptr(new GroupDiscreteModel(PARAMETERS)); + cout << " after create Model " << endl; + if (_debug) + MODEL->set_debug(); + // if(_L1path=="" && _quartet==true) throw MeshReg_error("GroupMeshREG ERROR::quartet version requires matlab path"); + //else MODEL->set_L1path(_L1path); + cout << " set feat " << endl; + MODEL->set_featurespace(FEAT); + cout << " set meshspace " << endl; + + MODEL->set_meshspace(SPH_orig, SPH_orig, MESHES.size()); + MODEL->Initialize(CONTROL); } +} - } - - void GroupMeshReg::Evaluate() - { +void GroupMeshReg::Evaluate() +{ - cout << " in Evaluate " <<_level<< endl; + cout << " in Evaluate " << _level << endl; newmesh OLDREG; - for(int n=0;n REL; - double ang; ang=R.guess_angular_spacing(TEMPLATE.nvertices()); +void GroupMeshReg::saveTransformedData(const double& sigma, const string& filename) +{ + if (_verbose) + cout << " save transformed data " << endl; + + resampler R; + R.set_method("ADAP_BARY"); + boost::shared_ptr REL; + double ang; + ang = R.guess_angular_spacing(TEMPLATE.nvertices()); char fullpath[1000]; - - for(int n=0;n DATA; - - - REL = boost::shared_ptr ( new RELATIONS(MESHES[n],TEMPLATE,ang)); - REL->update_RELATIONS(MESHES[n]); - - set_data(DATAlist[n],DATA,MESHES[n]); - - R.resampledata(MESHES[n],TEMPLATE,DATA,0.0,REL); - - boost::shared_ptr pin =boost::dynamic_pointer_cast(DATA); - TEMPLATE.set_pvalues(DATA->AsMatrix()); - TEMPLATE.save(fullpath); + for (int n = 0; n < MESHES.size(); n++) { + sprintf(fullpath, "%stransformed_and_reprojected-%d%s", filename.c_str(), n, _dataformat.c_str()); + + boost::shared_ptr DATA; + + REL = boost::shared_ptr(new RELATIONS(MESHES[n], TEMPLATE, ang)); + REL->update_RELATIONS(MESHES[n]); + + set_data(DATAlist[n], DATA, MESHES[n]); + + R.resampledata(MESHES[n], TEMPLATE, DATA, 0.0, REL); + + boost::shared_ptr pin = boost::dynamic_pointer_cast(DATA); + TEMPLATE.set_pvalues(DATA->AsMatrix()); + TEMPLATE.save(fullpath); } - } - - ////// iterates over discrete optimisations///// - void GroupMeshReg::run_discrete_opt(vector &source){ - resampler R; R.set_method("ADAP_BARY"); - int iter=1; - - NEWMESH::newmesh transformed_controlgrid,targetmesh; +} + +////// iterates over discrete optimisations///// +void GroupMeshReg::run_discrete_opt(vector& source) +{ + resampler R; + R.set_method("ADAP_BARY"); + int iter = 1; + + NEWMESH::newmesh transformed_controlgrid, targetmesh; vector controlgrid; boost::shared_ptr controlgrid_neighbourhood; myparam::iterator it; - int res,_itersforlevel; + int res, _itersforlevel; int numNodes; - double energy=0,newenergy=0; + double energy = 0, newenergy = 0; char filename[1000]; - ofstream Energyout; - - it=PARAMETERS.find("CPres");res=boost::get(it->second); - it=PARAMETERS.find("iters");_itersforlevel=boost::get(it->second); - - numNodes=MODEL->getNumNodes(); - targetmesh=MODEL->get_TARGET(); - - - while(iter <= _itersforlevel){ - controlgrid.clear(); - cout << " reset meshspace " << endl; - for(int n=0;nreset_meshspace(source[n],n); // source mesh is updated and control point grids are reset - // sprintf(filename,"sourcebeforereg-level%d-it%d-m%d.surf.gii",_level, iter,n); source[n].save(filename); - controlgrid.push_back(MODEL->get_CPgrid(n)); - //sprintf(filename,"controlbeforereg-it%d-m%d.surf.gii",iter,n); controlgrid[n].save(filename); - - } - - cout << " MODEL->setupCostFunction(); " <setupCostFunction(); - - int *Labels=MODEL->getLabeling(); - -#ifdef HAS_HOCR + ofstream Energyout; - Reduction HOCR_mode; - - if(_discreteOPT.compare(0,4,"HOCR")==0) - HOCR_mode=HOCR; - else if(_discreteOPT=="ELC"){ - HOCR_mode=ELC_HOCR; - }else if(_discreteOPT=="ELC_approx"){ - HOCR_mode=ELC_APPROX; - }else {throw MeshReg_error("discrete optimisation mode is not available");} - - // tick_count start = tick_count::now(); - - cout << _discreteOPT << " optimise 2 " << endl; - srand (time(NULL)); - newenergy=Fusion::optimize(MODEL,HOCR_mode,_verbose); - -#endif // MODEL->saveSTRAINS(iter); - - - if(iter>1 && ((iter-1) % 2==0) && newenergy>=energy) { cout << iter << " level has converged" << (iter-1) %2 << endl; break;} - - - for (int i = 0; i applyLabeling(); - controlgrid_neighbourhood=MODEL->get_cp_neighbourhood(); - - // apply these choices in order to deform the CP grid - for(int n=0;nget_CPgrid(n); - cout << n << " transformed_controlgrid.nvertices() " << transformed_controlgrid.nvertices() << " controlgrid[n].nvertices() " << controlgrid[n].nvertices() << " source vertices " << " " << source[n].nvertices() << " " << controlgrid_neighbourhood->Ncols() << endl; - barycentric_mesh_interpolation(source[n],controlgrid[n],transformed_controlgrid,controlgrid_neighbourhood); - - unfold(transformed_controlgrid); - MODEL->reset_CPgrid(transformed_controlgrid,n); // source mesh is updated and control point grids are reset - //} - - //sprintf(filename,"controlgridtrans-%d-%d.surf",iter,res); - //transformed_controlgrid.save(filename); - //sprintf(filename,"sourcetrans-%d-%d.surf",iter,res); - //source.save(filename); - - unfold(source[n]); - } - energy=newenergy; - iter++; - } + it = PARAMETERS.find("CPres"); + res = boost::get(it->second); + it = PARAMETERS.find("iters"); + _itersforlevel = boost::get(it->second); - + numNodes = MODEL->getNumNodes(); + targetmesh = MODEL->get_TARGET(); - } -} - + while (iter <= _itersforlevel) { + controlgrid.clear(); + cout << " reset meshspace " << endl; + for (int n = 0; n < source.size(); n++) { + cout << n << " " << source[n].nvertices() << endl; + MODEL->reset_meshspace(source[n], n); // source mesh is updated and control point grids are reset + // sprintf(filename,"sourcebeforereg-level%d-it%d-m%d.surf.gii",_level, iter,n); source[n].save(filename); + controlgrid.push_back(MODEL->get_CPgrid(n)); + //sprintf(filename,"controlbeforereg-it%d-m%d.surf.gii",iter,n); controlgrid[n].save(filename); + } - + cout << " MODEL->setupCostFunction(); " << endl; + MODEL->setupCostFunction(); + + int* Labels = MODEL->getLabeling(); + +#ifdef HAS_HOCR + + Reduction HOCR_mode; + + if (_discreteOPT.compare(0, 4, "HOCR") == 0) + HOCR_mode = HOCR; + else if (_discreteOPT == "ELC") { + HOCR_mode = ELC_HOCR; + } else if (_discreteOPT == "ELC_approx") { + HOCR_mode = ELC_APPROX; + } else { + throw MeshReg_error("discrete optimisation mode is not available"); + } + + // tick_count start = tick_count::now(); + + cout << _discreteOPT << " optimise 2 " << endl; + srand(time(NULL)); + newenergy = Fusion::optimize(MODEL, HOCR_mode, _verbose); + +#endif // MODEL->saveSTRAINS(iter); + + if (iter > 1 && ((iter - 1) % 2 == 0) && newenergy >= energy) { + cout << iter << " level has converged" << (iter - 1) % 2 << endl; + break; + } + + for (int i = 0; i < numNodes; i++) { + if (_verbose) + cout << i << " _iter " << iter << " _iters " << _itersforlevel << " label " << Labels[i] << endl; + } + + MODEL->applyLabeling(); + controlgrid_neighbourhood = MODEL->get_cp_neighbourhood(); + + // apply these choices in order to deform the CP grid + for (int n = 0; n < source.size(); n++) { + transformed_controlgrid = MODEL->get_CPgrid(n); + cout << n << " transformed_controlgrid.nvertices() " << transformed_controlgrid.nvertices() << " controlgrid[n].nvertices() " << controlgrid[n].nvertices() << " source vertices " + << " " << source[n].nvertices() << " " << controlgrid_neighbourhood->Ncols() << endl; + barycentric_mesh_interpolation(source[n], controlgrid[n], transformed_controlgrid, controlgrid_neighbourhood); + + unfold(transformed_controlgrid); + MODEL->reset_CPgrid(transformed_controlgrid, n); // source mesh is updated and control point grids are reset + //} + + //sprintf(filename,"controlgridtrans-%d-%d.surf",iter,res); + //transformed_controlgrid.save(filename); + //sprintf(filename,"sourcetrans-%d-%d.surf",iter,res); + //source.save(filename); + + unfold(source[n]); + } + energy = newenergy; + iter++; + } +} +} diff --git a/src/MSMRegLib/groupmeshreg.h b/src/MSMRegLib/groupmeshreg.h index 24153ac..84d934f 100644 --- a/src/MSMRegLib/groupmeshreg.h +++ b/src/MSMRegLib/groupmeshreg.h @@ -9,64 +9,51 @@ #ifndef groupmeshreg_h #define groupmeshreg_h - #include "meshreg.h" #include "miscmaths/SpMat.h" - -#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO -#define D_DIST 0.25 // sampling distance along tangent plane for computing derivatives - 0.25 is what Bruce uses for FreeSurfer +#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO +#define D_DIST 0.25 // sampling distance along tangent plane for computing derivatives - 0.25 is what Bruce uses for FreeSurfer #ifndef SQR -#define SQR(x) ((x)*(x)) +#define SQR(x) ((x) * (x)) #endif namespace MESHREG { - - - class GroupMeshReg: public MeshReg { - - private: - + +class GroupMeshReg : public MeshReg { + +private: vector ALL_SPH_REG; - public: - +public: // Constructors - inline GroupMeshReg(){ }; - + inline GroupMeshReg() {}; + //MeshReg(int); - + // Destructor - inline ~GroupMeshReg(){}; - - + inline ~GroupMeshReg() {}; + void Initialize_level(int); void Evaluate(); - void Transform(const string &); - void saveTransformedData(const double &,const string &); - void run_discrete_opt(vector &); - - inline void saveSPH_reg(const string &filename) const { - char fullpath[1000]; - - for(int i=0;i&); + + inline void saveSPH_reg(const string& filename) const + { + char fullpath[1000]; + + for (int i = 0; i < ALL_SPH_REG.size(); i++) { + sprintf(fullpath, "%ssphere-%d.LR.reg%s", filename.c_str(), i, _surfformat.c_str()); + cout << i << " new save SPH " << fullpath << endl; + + ALL_SPH_REG[i].save(fullpath); + } } - }; +}; - - - } - - #endif - diff --git a/src/MSMRegLib/meshmodify.cc b/src/MSMRegLib/meshmodify.cc index 2243fed..52b85b4 100644 --- a/src/MSMRegLib/meshmodify.cc +++ b/src/MSMRegLib/meshmodify.cc @@ -10,442 +10,536 @@ //// NOTE SIM KERNEL IS TRANSPOSED RELATIVE TO ALEKS CODE TO CORRESPEND TO TRANSPOSED SPARSE MATRICES - input subjects represent columns namespace MESHREG { - void MeshModify::parse_reg_options(const string ¶meters) - { - string title="msm configuration parameters "; - string examples=""; - OptionParser options(title,examples); +void MeshModify::parse_reg_options(const string& parameters) +{ + string title = "msm configuration parameters "; + string examples = ""; + OptionParser options(title, examples); vector costdefault; - Option > optimizer(string("--opt"),costdefault, - string("optimisation method. Choice of: AFFINE,DISCRETE (default)"), - false,requires_argument); + Option> optimizer(string("--opt"), costdefault, + string("optimisation method. Choice of: AFFINE,DISCRETE (default)"), + false, requires_argument); vector intdefault; - Option > simval(string("--simval"), intdefault, - string("code for determining which similarty measure is used to assess cost during registration: options are 1) SSD; 2) pearsons correlation (default); 3) NMI;)"), - false, requires_argument); - - Option< vector > iterations(string("--it"), intdefault, - string("number of iterations at each resolution (default -–it=3,3,3)"), - false, requires_argument); - + Option> simval(string("--simval"), intdefault, + string("code for determining which similarty measure is used to assess cost during registration: options are 1) SSD; 2) pearsons correlation (default); 3) NMI;)"), + false, requires_argument); + + Option> iterations(string("--it"), intdefault, + string("number of iterations at each resolution (default -–it=3,3,3)"), + false, requires_argument); + vector floatdefault; - - Option< vector > sigma_in(string("--sigma_in"),floatdefault, - string("smoothing parameter for input image (default --sigma_in=2,2,2)"), - false, requires_argument); - - Option< vector > sigma_ref(string("--sigma_ref"), floatdefault, - string("Sigma parameter - smoothing parameter for reference image (set equal to sigma_in by default)"), - false, requires_argument); - - Option > lambda(string("--lambda"), floatdefault, - string("Lambda parameter - controls contribution of regulariser "), - false, requires_argument); - - Option > datagrid(string("--datagrid"),intdefault, - string("DATA grid resolution (default --datagrid=5,5,5). If parameter = 0 then the native mesh is used."), - false, requires_argument); - - Option > cpgrid(string("--CPgrid"),intdefault, - string("Control point grid resolution (default --CPgrid=2,3,4)"), - false, requires_argument); - - Option< vector > sampgrid(string("--SGgrid"),intdefault, - string("Sampling grid resolution (default = 2 levels higher than the control point grid)"), - false, requires_argument); - Option< vector > anatgrid(string("--anatgrid"),intdefault, - string("Anatomical grid resolution (default = 2 levels higher than the control point grid)"), - false, requires_argument); - - - Option< vector > alpha_knn(string("--aKNN"),intdefault, - string("Number of neighbours for estimation of kNN graph and alpha entropy measure (default --aKNN=5,5,5)"), - false, requires_argument); - - - vector cutthresholddefault(2,0); cutthresholddefault[1]=0.0001; - Option< vector > cutthreshold(string("--cutthr"),cutthresholddefault, - string("Upper and lower thresholds for defining cut vertices (default --cutthr=0,0)"), - false, requires_argument); - - - Option meshinterpolationmethod(string("--mInt"), "BARY", - string("Method used for mesh interpolations, options: TPS or BARY (default)"), - false,requires_argument); - - Option datainterpolationmethod(string("--dInt"), "ADAP_BARY", - string("Method used for data interpolations, options: GAUSSIAN or ADAP_BARY (default)"), - false,requires_argument); - + + Option> sigma_in(string("--sigma_in"), floatdefault, + string("smoothing parameter for input image (default --sigma_in=2,2,2)"), + false, requires_argument); + + Option> sigma_ref(string("--sigma_ref"), floatdefault, + string("Sigma parameter - smoothing parameter for reference image (set equal to sigma_in by default)"), + false, requires_argument); + + Option> lambda(string("--lambda"), floatdefault, + string("Lambda parameter - controls contribution of regulariser "), + false, requires_argument); + + Option> datagrid(string("--datagrid"), intdefault, + string("DATA grid resolution (default --datagrid=5,5,5). If parameter = 0 then the native mesh is used."), + false, requires_argument); + + Option> cpgrid(string("--CPgrid"), intdefault, + string("Control point grid resolution (default --CPgrid=2,3,4)"), + false, requires_argument); + + Option> sampgrid(string("--SGgrid"), intdefault, + string("Sampling grid resolution (default = 2 levels higher than the control point grid)"), + false, requires_argument); + Option> anatgrid(string("--anatgrid"), intdefault, + string("Anatomical grid resolution (default = 2 levels higher than the control point grid)"), + false, requires_argument); + + Option> alpha_knn(string("--aKNN"), intdefault, + string("Number of neighbours for estimation of kNN graph and alpha entropy measure (default --aKNN=5,5,5)"), + false, requires_argument); + + vector cutthresholddefault(2, 0); + cutthresholddefault[1] = 0.0001; + Option> cutthreshold(string("--cutthr"), cutthresholddefault, + string("Upper and lower thresholds for defining cut vertices (default --cutthr=0,0)"), + false, requires_argument); + + Option meshinterpolationmethod(string("--mInt"), "BARY", + string("Method used for mesh interpolations, options: TPS or BARY (default)"), + false, requires_argument); + + Option datainterpolationmethod(string("--dInt"), "ADAP_BARY", + string("Method used for data interpolations, options: GAUSSIAN or ADAP_BARY (default)"), + false, requires_argument); + #ifdef HAS_HOCR - Option regulariseroption(string("--regoption"), 1, - string("Choose option for regulariser form lambda*weight*pow(cost,rexp). Where cost can be PAIRWISE or TRI-CLIQUE based. Options are: 1) PAIRWISE - penalising diffences in rotations of neighbouring points (default); 2) TRI_CLIQUE Angle deviation penalty (for spheres); 3) TRI_CLIQUE: Strain-based (for spheres); 4) TRI_CLIQUE Angle deviation penalty (for anatomy); 5) TRI_CLIQUE: Strain-based (for anatomy)"), - false, requires_argument); - Option doptimizer(string("--dopt"),"FastPD", - string("discrete optimisation implementation. Choice of: FastPD (default), HOCR (will reduce to QBPO for pairwise), ELC, ELC_approx"), - false,requires_argument,false); - - Option tricliquelikeihood(string("--triclique"), false, - string("estimate similarity for triangular patches (rather than circular)"), - false, no_argument); - Option shear(string("--shearmod"), 0.4, - string("shear modulus (default 0.4); for use with --regoptions 3 "), - false,requires_argument); - Option bulk(string("--bulkmod"), 1.6, - string("bulk mod (default 1.6); for use with --regoptions 3 "), - false,requires_argument); - - Option grouplambda(string("--glambda_pairs"), 1, - string("scaling for pairwise term in greoup alignment"), - false,requires_argument,false); - Option kexponent(string("--k_exponent"), 2, - string("exponent inside strain equation (default 2)"), - false, requires_argument); + Option regulariseroption(string("--regoption"), 1, + string("Choose option for regulariser form lambda*weight*pow(cost,rexp). Where cost can be PAIRWISE or TRI-CLIQUE based. Options are: 1) PAIRWISE - penalising diffences in rotations of neighbouring points (default); 2) TRI_CLIQUE Angle deviation penalty (for spheres); 3) TRI_CLIQUE: Strain-based (for spheres); 4) TRI_CLIQUE Angle deviation penalty (for anatomy); 5) TRI_CLIQUE: Strain-based (for anatomy)"), + false, requires_argument); + Option doptimizer(string("--dopt"), "FastPD", + string("discrete optimisation implementation. Choice of: FastPD (default), HOCR (will reduce to QBPO for pairwise), ELC, ELC_approx"), + false, requires_argument, false); + + Option tricliquelikeihood(string("--triclique"), false, + string("estimate similarity for triangular patches (rather than circular)"), + false, no_argument); + Option shear(string("--shearmod"), 0.4, + string("shear modulus (default 0.4); for use with --regoptions 3 "), + false, requires_argument); + Option bulk(string("--bulkmod"), 1.6, + string("bulk mod (default 1.6); for use with --regoptions 3 "), + false, requires_argument); + + Option grouplambda(string("--glambda_pairs"), 1, + string("scaling for pairwise term in greoup alignment"), + false, requires_argument, false); + Option kexponent(string("--k_exponent"), 2, + string("exponent inside strain equation (default 2)"), + false, requires_argument); #endif - - Option expscaling(string("--scaleexp"), 1, - string("Scaling for weight exponent (default 1.0)"), - false,requires_argument,false); - - Option regulariserexp(string("--regexp"), 2.0, - string("Regulariser exponent 'rexp' (default 2.0)"), - false,requires_argument); - - Option distweight(string("--weight"), false, - string("weight regulariser cost using areal distortion weighting"), - false, no_argument); - Option anorm(string("--anorm"), false, - string("norm regulariser cost using mean angle (for HCP compatibility)"), - false, no_argument); - Option rescale_labels(string("--rescaleL"), false, - string("rescale label grid rather than using barycentres"), - false, no_argument); - - Option maxdist(string("--maxdist"), 4, - string("Set areal distortion threshold (default 4); for use with --regoptions 2 "), - false,requires_argument,false); - - Option pottsenergy(string("--potts"),0.0, - string("Use potts model for mrf regulariser (strain only thus far). Supply threshold value"), - false, requires_argument, false); - - Option controlptrange(string("--cprange"), 1.0, - string("Range (as % control point spacing) of data samples (default 1) "), - false,requires_argument,false); - - - Option logtransform(string("--log"), false, - string("log transform and normalise the data"), - false, no_argument); - Option intensitynormalize(string("--IN"), false, - string("Normalize intensity ranges using histogram matching "), - false, no_argument); - Option intensitynormalizewcut(string("--INc"), false, - string("Normalize intensity ranges using histogram matching excluding cut"), - false, no_argument); - Option variancenormalize(string("--VN"), false, - string("Variance normalize data "), - false, no_argument); - - Option scaleintensity(string("--scale"), false, - string("Scale intensity ranges of a features in multivariate data to be equal to that of the first (useful for multimodal contrasts)"), - false, no_argument); - Option exclude(string("--excl"), false, - string("Ignore the cut when resampling the data"), - false, no_argument); - - Option quartet(string("-Q"), false, - string("Estimate quartet low rank cost for group reg"), - false, no_argument,false); - - ///// AFFINE OPTIONS ///////////////////////// - Option affinestepsize(string("--stepsize"), 0.01, - string("gradient stepping for affine optimisation (default 0.01)"), - false, requires_argument); - - Option gradsampling(string("--gradsampling"), 0.5, - string("Determines the finite distance spacing for the affine gradient calculation (default 0.5)"), - false,requires_argument); - Option threads(string("--numthreads"), 1, - string("number of threads for tbb (default 1)"), - false,requires_argument); - int nonoptarg; - - try { - // must include all wanted options here (the order determines how - // the help message is printed) - options.add(optimizer); - options.add(simval); - options.add(iterations); - options.add(sigma_in); - options.add(sigma_ref); - options.add(lambda); - options.add(datagrid); - options.add(cpgrid); - options.add(sampgrid); - options.add(anatgrid); - options.add(alpha_knn); - options.add(cutthreshold); - options.add(meshinterpolationmethod); - options.add(datainterpolationmethod); + + Option expscaling(string("--scaleexp"), 1, + string("Scaling for weight exponent (default 1.0)"), + false, requires_argument, false); + + Option regulariserexp(string("--regexp"), 2.0, + string("Regulariser exponent 'rexp' (default 2.0)"), + false, requires_argument); + + Option distweight(string("--weight"), false, + string("weight regulariser cost using areal distortion weighting"), + false, no_argument); + Option anorm(string("--anorm"), false, + string("norm regulariser cost using mean angle (for HCP compatibility)"), + false, no_argument); + Option rescale_labels(string("--rescaleL"), false, + string("rescale label grid rather than using barycentres"), + false, no_argument); + + Option maxdist(string("--maxdist"), 4, + string("Set areal distortion threshold (default 4); for use with --regoptions 2 "), + false, requires_argument, false); + + Option pottsenergy(string("--potts"), 0.0, + string("Use potts model for mrf regulariser (strain only thus far). Supply threshold value"), + false, requires_argument, false); + + Option controlptrange(string("--cprange"), 1.0, + string("Range (as % control point spacing) of data samples (default 1) "), + false, requires_argument, false); + + Option logtransform(string("--log"), false, + string("log transform and normalise the data"), + false, no_argument); + Option intensitynormalize(string("--IN"), false, + string("Normalize intensity ranges using histogram matching "), + false, no_argument); + Option intensitynormalizewcut(string("--INc"), false, + string("Normalize intensity ranges using histogram matching excluding cut"), + false, no_argument); + Option variancenormalize(string("--VN"), false, + string("Variance normalize data "), + false, no_argument); + + Option scaleintensity(string("--scale"), false, + string("Scale intensity ranges of a features in multivariate data to be equal to that of the first (useful for multimodal contrasts)"), + false, no_argument); + Option exclude(string("--excl"), false, + string("Ignore the cut when resampling the data"), + false, no_argument); + + Option quartet(string("-Q"), false, + string("Estimate quartet low rank cost for group reg"), + false, no_argument, false); + + ///// AFFINE OPTIONS ///////////////////////// + Option affinestepsize(string("--stepsize"), 0.01, + string("gradient stepping for affine optimisation (default 0.01)"), + false, requires_argument); + + Option gradsampling(string("--gradsampling"), 0.5, + string("Determines the finite distance spacing for the affine gradient calculation (default 0.5)"), + false, requires_argument); + Option threads(string("--numthreads"), 1, + string("number of threads for tbb (default 1)"), + false, requires_argument); + int nonoptarg; + + try { + // must include all wanted options here (the order determines how + // the help message is printed) + options.add(optimizer); + options.add(simval); + options.add(iterations); + options.add(sigma_in); + options.add(sigma_ref); + options.add(lambda); + options.add(datagrid); + options.add(cpgrid); + options.add(sampgrid); + options.add(anatgrid); + options.add(alpha_knn); + options.add(cutthreshold); + options.add(meshinterpolationmethod); + options.add(datainterpolationmethod); #ifdef HAS_HOCR - options.add(regulariseroption); - options.add(doptimizer); - options.add(tricliquelikeihood); - options.add(shear); - options.add(bulk); - options.add(grouplambda); - options.add(kexponent); + options.add(regulariseroption); + options.add(doptimizer); + options.add(tricliquelikeihood); + options.add(shear); + options.add(bulk); + options.add(grouplambda); + options.add(kexponent); #endif - options.add(expscaling); - options.add(regulariserexp); - options.add(distweight); - options.add(anorm); - options.add(rescale_labels); - options.add(maxdist); - options.add(pottsenergy); - options.add(controlptrange); - options.add(logtransform); - options.add(intensitynormalize); - options.add(intensitynormalizewcut); - - options.add(variancenormalize); - options.add(scaleintensity); - options.add(exclude); - options.add(quartet); - options.add(affinestepsize); - options.add(gradsampling); - options.add(threads); - - if(parameters=="usage"){ - options.usage(); - exit(2); + options.add(expscaling); + options.add(regulariserexp); + options.add(distweight); + options.add(anorm); + options.add(rescale_labels); + options.add(maxdist); + options.add(pottsenergy); + options.add(controlptrange); + options.add(logtransform); + options.add(intensitynormalize); + options.add(intensitynormalizewcut); + + options.add(variancenormalize); + options.add(scaleintensity); + options.add(exclude); + options.add(quartet); + options.add(affinestepsize); + options.add(gradsampling); + options.add(threads); + + if (parameters == "usage") { + options.usage(); + exit(2); + } else if (parameters != "") { + nonoptarg = options.parse_config_file(parameters); + } + + } catch (Utilities::X_OptionError& e) { + + options.usage(); + cerr << "\n" + << e.what() << "\n"; + exit(EXIT_FAILURE); + } catch (std::exception& e) { + cerr << "\n" + << e.what() << "\n"; + exit(EXIT_FAILURE); } - else if(parameters!=""){ - nonoptarg = options.parse_config_file(parameters); + + if (!options.check_compulsory_arguments()) { + options.usage(); + + exit(2); + } + + if (parameters == "") { + /// if no config is supplied use sulc config (as of Sept 2014) as default + cost.resize(3, "DISCRETE"); + cost.insert(cost.begin(), "AFFINE"); + _resolutionlevels = cost.size(); + _lambda.resize(4, 0); + _lambda[1] = 0.1; + _lambda[2] = 0.2; + _lambda[3] = 0.3; + _simval.resize(4, 2); + _simval[0] = 1; + _sigma_in.resize(4, 2); + _sigma_in[2] = 3; + _sigma_in[3] = 2; + _sigma_ref.resize(4, 2); + _sigma_ref[2] = 1.5; + _sigma_ref[3] = 1; + _iters.resize(4, 3); + _iters[0] = 50; + _alpha_kNN.resize(cost.size(), 5); + _gridres.resize(4, 0); + _gridres[1] = 2; + _gridres[2] = 3; + _gridres[3] = 4; + _anatres.resize(4, 0); + _anatres[1] = 4; + _anatres[2] = 5; + _anatres[3] = 6; + + _genesis.resize(4, 4); + _genesis[2] = 5; + _genesis[3] = 6; + _sampres.resize(4, 0); + _sampres[1] = 4; + _sampres[2] = 5; + _sampres[3] = 6; + + } else { + cost = optimizer.value(); + _lambda = lambda.value(); + + // now check for assignments and else set defaults + if (simval.set()) { + _simval = simval.value(); + } else + _simval.resize(cost.size(), 2); + + if (iterations.set()) { + _iters = iterations.value(); + } else + _iters.resize(cost.size(), 3); + + if (sigma_in.set()) { + _sigma_in = sigma_in.value(); + } else + _sigma_in.resize(cost.size(), 2); + + if (sigma_ref.set()) { + _sigma_ref = sigma_ref.value(); + } else + _sigma_ref = _sigma_in; + + if (datagrid.set()) { + _genesis = datagrid.value(); + } else + _genesis.resize(cost.size(), 5); + + if (cpgrid.set()) { + _gridres = cpgrid.value(); + } else { + _gridres.resize(cost.size(), 2); + for (unsigned int i = 1; i < cost.size(); i++) + _gridres[i] = _gridres[i - 1] + 1; + } + + if (anatgrid.set()) { + _anatres = anatgrid.value(); + } else { + _anatres.resize(cost.size(), 2); + for (unsigned int i = 0; i < cost.size(); i++) + _anatres[i] = _gridres[i] + 2; + } + + if (sampgrid.set()) { + _sampres = sampgrid.value(); + } else { + _sampres.resize(cost.size()); + for (unsigned int i = 0; i < cost.size(); i++) + _sampres[i] = _gridres[i] + 2; + } + + if (alpha_knn.set()) { + _alpha_kNN = alpha_knn.value(); + } else + _alpha_kNN.resize(cost.size(), 5); } - - } - catch(Utilities::X_OptionError& e) { - - options.usage(); - cerr << "\n" << e.what() << "\n"; - exit(EXIT_FAILURE); - } - catch(std::exception &e) { - cerr << "\n" << e.what() << "\n"; - exit(EXIT_FAILURE); - } - - if( ! options.check_compulsory_arguments()){ - options.usage(); - - exit(2); - } - - if(parameters==""){ - /// if no config is supplied use sulc config (as of Sept 2014) as default - cost.resize(3,"DISCRETE"); cost.insert(cost.begin(),"AFFINE"); _resolutionlevels=cost.size(); - _lambda.resize(4,0); _lambda[1]=0.1;_lambda[2]=0.2;_lambda[3]=0.3; - _simval.resize(4,2); _simval[0]=1; - _sigma_in.resize(4,2); _sigma_in[2]=3;_sigma_in[3]=2; - _sigma_ref.resize(4,2); _sigma_ref[2]=1.5;_sigma_ref[3]=1; - _iters.resize(4,3); _iters[0]=50; - _alpha_kNN.resize(cost.size(),5); - _gridres.resize(4,0); _gridres[1]=2;_gridres[2]=3;_gridres[3]=4; - _anatres.resize(4,0); _anatres[1]=4;_anatres[2]=5;_anatres[3]=6; - - _genesis.resize(4,4); _genesis[2]=5;_genesis[3]=6; - _sampres.resize(4,0); _sampres[1]=4;_sampres[2]=5;_sampres[3]=6; - - } - else{ - cost=optimizer.value(); - _lambda=lambda.value(); - - // now check for assignments and else set defaults - if(simval.set()){_simval=simval.value();} - else _simval.resize(cost.size(),2); - - if(iterations.set()){_iters=iterations.value();} - else _iters.resize(cost.size(),3); - - if(sigma_in.set()){_sigma_in=sigma_in.value();} - else _sigma_in.resize(cost.size(),2); - - if(sigma_ref.set()){_sigma_ref=sigma_ref.value();} - else _sigma_ref=_sigma_in; - - if(datagrid.set()){_genesis=datagrid.value();} - else _genesis.resize(cost.size(),5); - - if(cpgrid.set()){_gridres=cpgrid.value();} - else {_gridres.resize(cost.size(),2); - for (unsigned int i=1;i1 && _discreteOPT=="FastPD"){throw MeshReg_error("MeshREG ERROR:: you cannot run higher order clique regularisers with fastPD ");} - if((int) _threshold.size()!=2){throw MeshReg_error("MeshREG ERROR:: the cut threshold does not contain a limit for upper and lower threshold (too few inputs)");} - if((int) _simval.size()!=_resolutionlevels) {cout << _simval.size() << " " << _resolutionlevels << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent: --simval");} - if((int)_iters.size()!=_resolutionlevels) {cout << "2 " << endl; throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--it");} - if((int)_sigma_in.size()!=_resolutionlevels) {cout << "3 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent: --sigma_in");} - if((int)_sigma_ref.size()!=_resolutionlevels) {cout << "4 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--sigma_ref");} - if((int)cost.size()!=_resolutionlevels) {cout << "5" << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--opt");} - if((int)_lambda.size()!=_resolutionlevels) {cout << "6 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--lambda");} - if((int)_genesis.size()!=_resolutionlevels) {cout << "7 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--datagrid");} - if((int)_gridres.size()!=_resolutionlevels) {cout << "8 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--CPgrid");} - if((int)_sampres.size()!=_resolutionlevels) {cout << "9 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--SGres");} - if((int)_alpha_kNN.size()!=_resolutionlevels) {cout << "10 " << endl;throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--aKNN");} - - + if (intensitynormalizewcut.set()) { + _IN = intensitynormalizewcut.value(); + _cut = true; + } else { + _IN = intensitynormalize.value(); + _cut = false; + } + _varnorm = variancenormalize.value(); + _exclude = exclude.value(); + _quartet = quartet.value(); + _meshInterpolator = meshinterpolationmethod.value(); + _dataInterpolator = datainterpolationmethod.value(); + _weight = distweight.value(); + _regoption2norm = anorm.value(); + _potts = pottsenergy.value(); + _threshold = cutthreshold.value(); + _regscaling = expscaling.value(); + _regexp = regulariserexp.value(); + _maxdist = maxdist.value(); + _cprange = controlptrange.value(); + _affinestepsize = affinestepsize.value(); + _affinegradsampling = gradsampling.value(); + _numthreads = threads.value(); + _rescale_labels = rescale_labels.value(); + + if (_verbose) { + cout << "cost.size() " << cost.size() << " " << cost << endl; + cout << " iters " << _iters << endl; + cout << "lambda " << _lambda << endl; + cout << " sigmain " << _sigma_in << endl; + cout << " sigmaref " << _sigma_ref << endl; + cout << " datagrid " << _genesis << endl; + cout << " cp gridres " << _gridres << endl; + cout << " sp grid " << _sampres << endl; + cout << " alpha_knn " << _alpha_kNN << endl; + + cout << " in parse options " + << " _simval " << _simval << " interations " << _iters << " input sigma " << _sigma_in << " ref sigma " << _sigma_ref << " lambda " << _lambda << " _genesis " << _genesis << " _gridres " << _gridres << " _sampres " << _sampres << " opt " << cost << " _scale " << _scale << " mesh interpolator " << _meshInterpolator << " discrete implementation " << _discreteOPT << " regoption " << _regmode << " potts " << _potts << endl; + } + + if (_regmode > 1 && _discreteOPT == "FastPD") { + throw MeshReg_error("MeshREG ERROR:: you cannot run higher order clique regularisers with fastPD "); + } + if ((int)_threshold.size() != 2) { + throw MeshReg_error("MeshREG ERROR:: the cut threshold does not contain a limit for upper and lower threshold (too few inputs)"); + } + if ((int)_simval.size() != _resolutionlevels) { + cout << _simval.size() << " " << _resolutionlevels << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent: --simval"); + } + if ((int)_iters.size() != _resolutionlevels) { + cout << "2 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--it"); + } + if ((int)_sigma_in.size() != _resolutionlevels) { + cout << "3 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent: --sigma_in"); + } + if ((int)_sigma_ref.size() != _resolutionlevels) { + cout << "4 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--sigma_ref"); + } + if ((int)cost.size() != _resolutionlevels) { + cout << "5" << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--opt"); + } + if ((int)_lambda.size() != _resolutionlevels) { + cout << "6 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--lambda"); + } + if ((int)_genesis.size() != _resolutionlevels) { + cout << "7 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--datagrid"); + } + if ((int)_gridres.size() != _resolutionlevels) { + cout << "8 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--CPgrid"); + } + if ((int)_sampres.size() != _resolutionlevels) { + cout << "9 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--SGres"); + } + if ((int)_alpha_kNN.size() != _resolutionlevels) { + cout << "10 " << endl; + throw MeshReg_error("MeshREG ERROR:: config file parameter list lengths are inconsistent:--aKNN"); + } } - - void MeshModify::fix_parameters_for_level(const int & i){ + +void MeshModify::fix_parameters_for_level(const int& i) +{ PARAMETERS.clear(); - - PARAMETERS.insert(parameterPair("lambda",_lambda[i])); - PARAMETERS.insert(parameterPair("lambda_pairs",_pairwiselambda)); - PARAMETERS.insert(parameterPair("set_lambda_pairs",_set_group_lambda)); - PARAMETERS.insert(parameterPair("iters",_iters[i])); - PARAMETERS.insert(parameterPair("simmeasure",_simval[i])); - PARAMETERS.insert(parameterPair("sigma_in",_sigma_in[i])); - PARAMETERS.insert(parameterPair("CPres",_gridres[i])); - PARAMETERS.insert(parameterPair("SGres",_sampres[i])); - PARAMETERS.insert(parameterPair("anatres",_anatres[i])); - PARAMETERS.insert(parameterPair("quartet",_quartet)); - PARAMETERS.insert(parameterPair("regularisermode",_regmode)); - PARAMETERS.insert(parameterPair("TriLikelihood",_tricliquelikeihood)); - PARAMETERS.insert(parameterPair("rescalelabels",_rescale_labels)); - PARAMETERS.insert(parameterPair("maxdistortion",_maxdist)); - PARAMETERS.insert(parameterPair("shearmodulus",_shearmod)); - PARAMETERS.insert(parameterPair("bulkmodulus",_bulkmod)); - PARAMETERS.insert(parameterPair("pottsthreshold",_potts)); - PARAMETERS.insert(parameterPair("range",_cprange)); - PARAMETERS.insert(parameterPair("exponent",_regexp)); - PARAMETERS.insert(parameterPair("weight",_weight)); - PARAMETERS.insert(parameterPair("anorm",_regoption2norm)); - PARAMETERS.insert(parameterPair("scaling",_regscaling)); - PARAMETERS.insert(parameterPair("kNN",_alpha_kNN[i])); - PARAMETERS.insert(parameterPair("verbosity",_verbose)); - PARAMETERS.insert(parameterPair("outdir",_outdir)); - PARAMETERS.insert(parameterPair("stepsize",_affinestepsize)); - PARAMETERS.insert(parameterPair("gradsampling",_affinegradsampling)); - PARAMETERS.insert(parameterPair("numthreads",_numthreads)); - PARAMETERS.insert(parameterPair("kexponent",_k_exp)); - - - } - - - void MeshModify::check(){ - - if(((MESHES[0].get_coord(0)).norm()- RAD) > 1e-5){ throw MeshReg_error("MeshModify ERROR:: input mesh radius has not been normalised to RAD=100");} - if(IN_CFWEIGHTING.get() && (IN_CFWEIGHTING->get_coord(0).norm()-RAD)>1e-5 ){throw MeshReg_error("MeshModify ERROR:: input exclusion mesh radius has not been normalised to RAD=100");} - if(REF_CFWEIGHTING.get() && (REF_CFWEIGHTING->get_coord(0).norm()-RAD)>1e-5 ){throw MeshReg_error("MeshModify ERROR::reference exclusion mesh radius has not been normalised to RAD=100");} - + + PARAMETERS.insert(parameterPair("lambda", _lambda[i])); + PARAMETERS.insert(parameterPair("lambda_pairs", _pairwiselambda)); + PARAMETERS.insert(parameterPair("set_lambda_pairs", _set_group_lambda)); + PARAMETERS.insert(parameterPair("iters", _iters[i])); + PARAMETERS.insert(parameterPair("simmeasure", _simval[i])); + PARAMETERS.insert(parameterPair("sigma_in", _sigma_in[i])); + PARAMETERS.insert(parameterPair("CPres", _gridres[i])); + PARAMETERS.insert(parameterPair("SGres", _sampres[i])); + PARAMETERS.insert(parameterPair("anatres", _anatres[i])); + PARAMETERS.insert(parameterPair("quartet", _quartet)); + PARAMETERS.insert(parameterPair("regularisermode", _regmode)); + PARAMETERS.insert(parameterPair("TriLikelihood", _tricliquelikeihood)); + PARAMETERS.insert(parameterPair("rescalelabels", _rescale_labels)); + PARAMETERS.insert(parameterPair("maxdistortion", _maxdist)); + PARAMETERS.insert(parameterPair("shearmodulus", _shearmod)); + PARAMETERS.insert(parameterPair("bulkmodulus", _bulkmod)); + PARAMETERS.insert(parameterPair("pottsthreshold", _potts)); + PARAMETERS.insert(parameterPair("range", _cprange)); + PARAMETERS.insert(parameterPair("exponent", _regexp)); + PARAMETERS.insert(parameterPair("weight", _weight)); + PARAMETERS.insert(parameterPair("anorm", _regoption2norm)); + PARAMETERS.insert(parameterPair("scaling", _regscaling)); + PARAMETERS.insert(parameterPair("kNN", _alpha_kNN[i])); + PARAMETERS.insert(parameterPair("verbosity", _verbose)); + PARAMETERS.insert(parameterPair("outdir", _outdir)); + PARAMETERS.insert(parameterPair("stepsize", _affinestepsize)); + PARAMETERS.insert(parameterPair("gradsampling", _affinegradsampling)); + PARAMETERS.insert(parameterPair("numthreads", _numthreads)); + PARAMETERS.insert(parameterPair("kexponent", _k_exp)); } - void MeshModify::Initialize() - { - +void MeshModify::check() +{ + + if (((MESHES[0].get_coord(0)).norm() - RAD) > 1e-5) { + throw MeshReg_error("MeshModify ERROR:: input mesh radius has not been normalised to RAD=100"); + } + if (IN_CFWEIGHTING.get() && (IN_CFWEIGHTING->get_coord(0).norm() - RAD) > 1e-5) { + throw MeshReg_error("MeshModify ERROR:: input exclusion mesh radius has not been normalised to RAD=100"); + } + if (REF_CFWEIGHTING.get() && (REF_CFWEIGHTING->get_coord(0).norm() - RAD) > 1e-5) { + throw MeshReg_error("MeshModify ERROR::reference exclusion mesh radius has not been normalised to RAD=100"); + } +} + +void MeshModify::Initialize() +{ + check(); - } - - - void MeshModify::set_output_format(string type){ - - if(type=="GIFTI"){ - _surfformat=".surf.gii"; - _dataformat=".func.gii"; - } - else if (type=="ASCII" || type=="ASCII_MAT" ){ - _surfformat=".asc"; - if(type=="ASCII") - _dataformat=".dpv"; - else - _dataformat=".txt"; // for multivariate - } - else{ - _surfformat=".vtk"; - _dataformat=".txt"; - } - - } - - //// each Matrix can have a different number of rows, for example if the user supplies a costfuncion weighting mask for multivariate features only on the reference, and also sets exclusion weighting then the reference weighting will be multivariate and the source weighting will be univariate - this combines into one mask on the source grid (therefore resampling much be reimplemented at every registration step) - Matrix MeshModify::combine_costfunction_weighting(const Matrix & sourceweight, const Matrix & resampledtargetweight){ +} + +void MeshModify::set_output_format(string type) +{ + + if (type == "GIFTI") { + _surfformat = ".surf.gii"; + _dataformat = ".func.gii"; + } else if (type == "ASCII" || type == "ASCII_MAT") { + _surfformat = ".asc"; + if (type == "ASCII") + _dataformat = ".dpv"; + else + _dataformat = ".txt"; // for multivariate + } else { + _surfformat = ".vtk"; + _dataformat = ".txt"; + } +} + +//// each Matrix can have a different number of rows, for example if the user supplies a costfuncion weighting mask for multivariate features only on the reference, and also sets exclusion weighting then the reference weighting will be multivariate and the source weighting will be univariate - this combines into one mask on the source grid (therefore resampling much be reimplemented at every registration step) +Matrix MeshModify::combine_costfunction_weighting(const Matrix& sourceweight, const Matrix& resampledtargetweight) +{ Matrix NEW; int nrows; - if(sourceweight.Nrows()>=resampledtargetweight.Nrows()){ NEW=sourceweight; nrows=resampledtargetweight.Nrows();} - else{ NEW=resampledtargetweight; nrows=sourceweight.Nrows();} - - for (int i=1;i<=NEW.Ncols();i++){ - for (int j=1;j<=nrows;j++){ - NEW(j,i)=(sourceweight(j,i)+resampledtargetweight(j,i))/2; - } + if (sourceweight.Nrows() >= resampledtargetweight.Nrows()) { + NEW = sourceweight; + nrows = resampledtargetweight.Nrows(); + } else { + NEW = resampledtargetweight; + nrows = sourceweight.Nrows(); + } + for (int i = 1; i <= NEW.Ncols(); i++) { + for (int j = 1; j <= nrows; j++) { + NEW(j, i) = (sourceweight(j, i) + resampledtargetweight(j, i)) / 2; + } } - + return NEW; - } - +} + } diff --git a/src/MSMRegLib/meshmodify.h b/src/MSMRegLib/meshmodify.h index bd9d524..8238e30 100644 --- a/src/MSMRegLib/meshmodify.h +++ b/src/MSMRegLib/meshmodify.h @@ -9,9 +9,9 @@ #ifndef meshmodify_h #define meshmodify_h -#include #include "ContinuosOpt.h" #include +#include using namespace FPD; using namespace std; @@ -22,20 +22,22 @@ using namespace DISCRETEOPT; namespace MESHREG { - class MeshReg_error: public std::exception +class MeshReg_error : public std::exception { +public: + MeshReg_error(const string& pmsg) throw() + : msg(pmsg) { - public: - MeshReg_error(const string& pmsg) throw() : msg(pmsg) {} - const char *what() const throw() {return(string("MESHREG::" + msg).c_str());} - ~MeshReg_error() throw() {} - private: - string msg; - }; - class MeshModify{ + } + const char* what() const throw() { return (string("MESHREG::" + msg).c_str()); } + ~MeshReg_error() throw() { } - protected: +private: + string msg; +}; +class MeshModify { - Tangent Tang; // holds tangent plane basis at each point +protected: + Tangent Tang; // holds tangent plane basis at each point vector datarange; // for processing only a range of data points - primarily only used for segmentation, likely temporary // use smart pointers allows for checking presence of these data objects before code is run @@ -45,13 +47,13 @@ namespace MESHREG { string _surfformat; string _dataformat; - vector MESHES; // original input (moving) mesh + vector MESHES; // original input (moving) mesh NEWMESH::newmesh TEMPLATE; - NEWMESH::newmesh transformed_mesh; // original input (moving) mesh in transformed position (i.e. from previous alignment step) + NEWMESH::newmesh transformed_mesh; // original input (moving) mesh in transformed position (i.e. from previous alignment step) NEWMESH::newmesh in_anat; NEWMESH::newmesh ref_anat; NEWMESH::newmesh SPH_orig; // original low res icosphere mesh - NEWMESH::newmesh SPH_reg; // transformed low res icosphere mesh + NEWMESH::newmesh SPH_reg; // transformed low res icosphere mesh NEWMESH::newmesh ANAT_orig; // original low res icosphere mesh // NEWMESH::newmesh ANAT_ref; // transformed low res icosphere mesh @@ -76,28 +78,27 @@ namespace MESHREG { string _L1path; //// REGISTRATION PARAMETERS ///////////// myparam PARAMETERS; - vector cost; // controls registration method i.e. affine, discrete, gradient descent - vector _genesis; // ico mesh resolution at this level + vector cost; // controls registration method i.e. affine, discrete, gradient descent + vector _genesis; // ico mesh resolution at this level - vector _sigma_in; // smoothing of input - vector _sigma_ref; // smoothing of reference + vector _sigma_in; // smoothing of input + vector _sigma_ref; // smoothing of reference vector _simval; // code determines how similarity is assessed 1 is aleks' correlation measure 2 is conventional correlation 3=SSD 4=NMI 5 alpha entropy - vector _lambda; // controls regularisation - vector _threshold; // controls cut exclusion (2D upper and lower thresholds for defining cut vertices) + vector _lambda; // controls regularisation + vector _threshold; // controls cut exclusion (2D upper and lower thresholds for defining cut vertices) vector _iters; // total per resolution level vector _gridres; // control point grid resolution (for discrete reg) vector _anatres; // control point grid resolution (for discrete reg) vector _sampres; // sampling grid for discrete reg (should be higher than control point) - vector _alpha_kNN; // for alpha mutual information + vector _alpha_kNN; // for alpha mutual information bool _scale; // rescale all features to have distribution of the first feature in a multivariate set - - double MVD; //mean inter-vertex distance + double MVD; //mean inter-vertex distance bool _verbose; - bool _exclude; // exclusion zone - bool _cut; // exclusion zone + bool _exclude; // exclusion zone + bool _cut; // exclusion zone bool _varnorm; // variance normalise bool _initialise; @@ -113,7 +114,7 @@ namespace MESHREG { bool _rescale_labels; float _k_exp; float _potts; - int _resolutionlevels; /// default 1 + int _resolutionlevels; /// default 1 int _regmode; //regulariser option int _numthreads; /////////// REGULARISER OPTIONS ////////////// @@ -123,7 +124,7 @@ namespace MESHREG { float _pairwiselambda; ///scaling for group alignment float _maxdist; // max areal disortion allowed before scaling is applied float _shearmod; // for strain regulariser - float _bulkmod; /// for strain regulariser + float _bulkmod; /// for strain regulariser float _cprange; int _featlength; @@ -131,118 +132,171 @@ namespace MESHREG { float _affinestepsize; float _affinegradsampling; - - - public: - +public: // Constructors - inline MeshModify(){ - MESHES.resize(2,newmesh()); - _verbose=false; - _resolutionlevels=0; - _issparse=false; - _debug=false; - _set_group_lambda=false; - _usetraining=false; - _tricliquelikeihood=false; - _quartet=false; - _anat=false; - _concattraining=false; - _rescale_labels=false; - _potts=0.0; - _surfformat=".surf"; - _dataformat=".func"; - _discreteOPT="FastPD"; - _L1path=""; - _cprange=1; - _bulkmod=1.6; - _shearmod=0.4; - _numthreads=1; - _k_exp = 2.0; - FEAT=boost::shared_ptr(new featurespace()); + inline MeshModify() + { + MESHES.resize(2, newmesh()); + _verbose = false; + _resolutionlevels = 0; + _issparse = false; + _debug = false; + _set_group_lambda = false; + _usetraining = false; + _tricliquelikeihood = false; + _quartet = false; + _anat = false; + _concattraining = false; + _rescale_labels = false; + _potts = 0.0; + _surfformat = ".surf"; + _dataformat = ".func"; + _discreteOPT = "FastPD"; + _L1path = ""; + _cprange = 1; + _bulkmod = 1.6; + _shearmod = 0.4; + _numthreads = 1; + _k_exp = 2.0; + FEAT = boost::shared_ptr(new featurespace()); }; // Destructor - virtual inline ~MeshModify(){}; + virtual inline ~MeshModify() {}; //// parses config file - void parse_reg_options(const string &); + void parse_reg_options(const string&); ////// sets up parameter space for one resolution level of the registration - void fix_parameters_for_level(const int & ); + void fix_parameters_for_level(const int&); - inline NEWMESH::Pt setpoint( double X, double Y, double Z){Pt p; p.X=X;p.Y=Y;p.Z=Z; return p;} + inline NEWMESH::Pt setpoint(double X, double Y, double Z) + { + Pt p; + p.X = X; + p.Y = Y; + p.Z = Z; + return p; + } // Initialize /// reads high resolution input mesh - inline void set_input(const NEWMESH::newmesh &M) {MESHES[0]=M; recentre(MESHES[0]);true_rescale(MESHES[0],RAD); }; + inline void set_input(const NEWMESH::newmesh& M) + { + MESHES[0] = M; + recentre(MESHES[0]); + true_rescale(MESHES[0], RAD); + }; //// reads high resolution target mesh - inline void set_reference(const NEWMESH::newmesh &M) {MESHES[1]= M; recentre(MESHES[1]); true_rescale(MESHES[1],RAD); }; + inline void set_reference(const NEWMESH::newmesh& M) + { + MESHES[1] = M; + recentre(MESHES[1]); + true_rescale(MESHES[1], RAD); + }; /// reads high resolution input mesh from path - inline void set_input(const string &M) {MESHES[0].load(M); recentre(MESHES[0]); true_rescale(MESHES[0],RAD); }; - - inline void set_inputs(string s){ - vector meshlist=read_ascii_list(s); - newmesh tmp; - MESHES.clear(); - for(unsigned int i=0;i meshlist = read_ascii_list(s); + newmesh tmp; + MESHES.clear(); + for (unsigned int i = 0; i < meshlist.size(); i++) { + if (_verbose) + cout << i << " " << meshlist[i] << endl; + tmp.load(meshlist[i]); + MESHES.push_back(tmp); + } } /// reads high resolution target mesh from path - inline void set_reference(const string &M) {MESHES[1].load(M); recentre(MESHES[1]); true_rescale(MESHES[1],RAD); }; - - inline void set_template(const string &M) {TEMPLATE.load(M); recentre(TEMPLATE); true_rescale(TEMPLATE,RAD); }; + inline void set_reference(const string& M) + { + MESHES[1].load(M); + recentre(MESHES[1]); + true_rescale(MESHES[1], RAD); + }; + inline void set_template(const string& M) + { + TEMPLATE.load(M); + recentre(TEMPLATE); + true_rescale(TEMPLATE, RAD); + }; - inline void set_anatomical(const string &M1,const string &M2) {_anat=true; in_anat.load(M1); ref_anat.load(M2);}; + inline void set_anatomical(const string& M1, const string& M2) + { + _anat = true; + in_anat.load(M1); + ref_anat.load(M2); + }; /// transformed mesh allows registration to be initialised using a transformation from a previous iteration - inline void set_transformed(const string &M) {transformed_mesh.load(M);true_rescale(MESHES[1],RAD); _initialise=true; }; + inline void set_transformed(const string& M) + { + transformed_mesh.load(M); + true_rescale(MESHES[1], RAD); + _initialise = true; + }; //// reads costfunction weighting mask for input data - inline void set_input_cfweighting(string E) { IN_CFWEIGHTING= boost::shared_ptr(new NEWMESH::newmesh(MESHES[0])); IN_CFWEIGHTING->load(E,false,false); true_rescale(*IN_CFWEIGHTING,RAD); }; + inline void set_input_cfweighting(string E) + { + IN_CFWEIGHTING = boost::shared_ptr(new NEWMESH::newmesh(MESHES[0])); + IN_CFWEIGHTING->load(E, false, false); + true_rescale(*IN_CFWEIGHTING, RAD); + }; /// reads costfunction weighting mask for target data - inline void set_reference_cfweighting(string E) {REF_CFWEIGHTING= boost::shared_ptr(new NEWMESH::newmesh(MESHES[1])); REF_CFWEIGHTING->load(E,false,false); true_rescale(*REF_CFWEIGHTING,RAD);}; + inline void set_reference_cfweighting(string E) + { + REF_CFWEIGHTING = boost::shared_ptr(new NEWMESH::newmesh(MESHES[1])); + REF_CFWEIGHTING->load(E, false, false); + true_rescale(*REF_CFWEIGHTING, RAD); + }; /// sets output path - inline void set_outdir(string s) {_outdir=s;}; + inline void set_outdir(string s) { _outdir = s; }; /// sets output format void set_output_format(string type); //// leads to additional outputs being saved out - inline void set_debug(bool test) {_debug=test;}; + inline void set_debug(bool test) { _debug = test; }; //////// sets path to input data - inline void set_CMpathin(string s){CMfile_in = s;}; + inline void set_CMpathin(string s) { CMfile_in = s; }; /// sets path to reference data - inline void set_CMpathref(string s){CMfile_ref=s;}; + inline void set_CMpathref(string s) { CMfile_ref = s; }; /// gets all paths to training data - inline void set_training(string s, bool concat){DATAlist=read_ascii_list(s); _concattraining=concat; _usetraining=true;}; - - inline void set_data_list(string s){DATAlist=read_ascii_list(s); }; + inline void set_training(string s, bool concat) + { + DATAlist = read_ascii_list(s); + _concattraining = concat; + _usetraining = true; + }; + inline void set_data_list(string s) { DATAlist = read_ascii_list(s); }; - inline void set_matlab(string s){_L1path=s;} + inline void set_matlab(string s) { _L1path = s; } - inline void set_datarange(const vector range){datarange=range;}; + inline void set_datarange(const vector range) { datarange = range; }; void Initialize(); - virtual void Initialize_level(int)=0; // for multires registration + virtual void Initialize_level(int) = 0; // for multires registration - void print_config_options(){parse_reg_options("usage");} - void set_verbosity(bool V){_verbose=V;} - void is_sparse(bool sp){_issparse=sp;}; /// input data is sparse + void print_config_options() { parse_reg_options("usage"); } + void set_verbosity(bool V) { _verbose = V; } + void is_sparse(bool sp) { _issparse = sp; }; /// input data is sparse void check(); // checks you have all the necessary data ////////COMMON FUNCTIONS//////////////// - virtual void Evaluate()=0; - virtual void Transform(const string &)=0; + virtual void Evaluate() = 0; + virtual void Transform(const string&) = 0; ////// UPDATING ///////// @@ -250,32 +304,25 @@ namespace MESHREG { ////// RETURNING FUNCTIONS ///////// - inline NEWMESH::newmesh return_registered_input_mesh()const {return MESHES[0];}; + inline NEWMESH::newmesh return_registered_input_mesh() const { return MESHES[0]; }; - inline string get_indata_path()const {return CMfile_in;}; - inline string get_surf_format()const {return _surfformat;}; - inline string get_refdata_path()const {return CMfile_ref;}; + inline string get_indata_path() const { return CMfile_in; }; + inline string get_surf_format() const { return _surfformat; }; + inline string get_refdata_path() const { return CMfile_ref; }; /// save low resolution estimate of registration - virtual inline void saveSPH_reg(const string &filename) const { - char fullpath[1000]; - cout << " orig save SPH " << endl; - sprintf(fullpath,"%ssphere.LR.reg%s",filename.c_str(),_surfformat.c_str()); - SPH_reg.save(fullpath); - - - + virtual inline void saveSPH_reg(const string& filename) const + { + char fullpath[1000]; + cout << " orig save SPH " << endl; + sprintf(fullpath, "%ssphere.LR.reg%s", filename.c_str(), _surfformat.c_str()); + SPH_reg.save(fullpath); } /// saves transformed and reprojected data - virtual void saveTransformedData(const double &,const string &filename)=0; - - Matrix combine_costfunction_weighting(const Matrix &, const Matrix &); - }; + virtual void saveTransformedData(const double&, const string& filename) = 0; + Matrix combine_costfunction_weighting(const Matrix&, const Matrix&); +}; } - - - - #endif diff --git a/src/MSMRegLib/meshreg.cc b/src/MSMRegLib/meshreg.cc index 4e1d3ce..5354dc7 100644 --- a/src/MSMRegLib/meshreg.cc +++ b/src/MSMRegLib/meshreg.cc @@ -10,293 +10,296 @@ namespace MESHREG { - - void MeshReg::run_multiresolutions(const int &levels, const double &sigma, const string ¶meters){ -#ifdef HAS_TBB +void MeshReg::run_multiresolutions(const int& levels, const double& sigma, const string& parameters) +{ +#ifdef HAS_TBB tick_count start = tick_count::now(); -#else - clock_t start; start=clock(); -#endif - - - - srand (time(NULL)); - - parse_reg_options(parameters); - if(levels!=0) _resolutionlevels=levels; - - - - for(int i=0;i<_resolutionlevels;i++){ - _level=i+1; - if(_verbose) cout << " Initialising level " << i+1 << endl; - ///// set parameters ///////////////// - fix_parameters_for_level(i); - Initialize_level(i); - Evaluate(); - if(cost[i]=="AFFINE") affinecf.reset(); // clear memory following affine initilisalisation - } - - if(_verbose){ -#ifdef HAS_TBB - tick_count end = tick_count::now(); - cout<<"Time elapsed: " << (end - start).seconds() << endl; #else - cout<<"Time elapsed: " << ( clock() - start ) / (double) CLOCKS_PER_SEC << endl; + clock_t start; + start = clock(); #endif - } - /////////////////// WRITE OUT DATA ACCORDING TO FORMAT ///////////////////////// - - Transform(_outdir); - - - saveSPH_reg(_outdir); - saveTransformedData(sigma,_outdir); - + srand(time(NULL)); + + parse_reg_options(parameters); + if (levels != 0) + _resolutionlevels = levels; + + for (int i = 0; i < _resolutionlevels; i++) { + _level = i + 1; + if (_verbose) + cout << " Initialising level " << i + 1 << endl; + ///// set parameters ///////////////// + fix_parameters_for_level(i); + Initialize_level(i); + Evaluate(); + if (cost[i] == "AFFINE") + affinecf.reset(); // clear memory following affine initilisalisation + } + + if (_verbose) { +#ifdef HAS_TBB + tick_count end = tick_count::now(); + cout << "Time elapsed: " << (end - start).seconds() << endl; +#else + cout << "Time elapsed: " << (clock() - start) / (double)CLOCKS_PER_SEC << endl; +#endif + } + /////////////////// WRITE OUT DATA ACCORDING TO FORMAT ///////////////////////// + Transform(_outdir); - } + saveSPH_reg(_outdir); + saveTransformedData(sigma, _outdir); +} - - - void MeshReg::Initialize_level(int level) - { +void MeshReg::Initialize_level(int level) +{ MeshModify::Initialize(); Matrix CombinedWeight; - vector sigma(2,0); - sigma[0]=_sigma_in[level]; sigma[1]=_sigma_ref[level]; - // MESHES[0].save("inputinsavetransformed_orig.surf.gii"); - //MESHES[1].save("refinsavetransformed_orig.surf.gii"); - + vector sigma(2, 0); + sigma[0] = _sigma_in[level]; + sigma[1] = _sigma_ref[level]; + // MESHES[0].save("inputinsavetransformed_orig.surf.gii"); + //MESHES[1].save("refinsavetransformed_orig.surf.gii"); ////////////// INITIALIZE FEATURESPACE //////////////////////////////////// - if(_usetraining){ - FEAT=boost::shared_ptr(new featurespace(CMfile_in,DATAlist)); + if (_usetraining) { + FEAT = boost::shared_ptr(new featurespace(CMfile_in, DATAlist)); - } - else - FEAT=boost::shared_ptr(new featurespace(CMfile_in,CMfile_ref)); - + } else + FEAT = boost::shared_ptr(new featurespace(CMfile_in, CMfile_ref)); FEAT->set_smoothing_parameters(sigma); FEAT->set_cutthreshold(_threshold); // will also generate exclusion masks at the same mesh resolution as datagrid - FEAT->logtransform(_logtransform);// if true logtransforms AND normalises - FEAT->varnorm(_varnorm);// variance normalises - FEAT->intensitynormalize(_IN, _scale,_cut); // matches the intensities of the source to to the target (will rescale all to the top feature of the target if scale is true) + FEAT->logtransform(_logtransform); // if true logtransforms AND normalises + FEAT->varnorm(_varnorm); // variance normalises + FEAT->intensitynormalize(_IN, _scale, _cut); // matches the intensities of the source to to the target (will rescale all to the top feature of the target if scale is true) FEAT->resamplingmethod(_dataInterpolator); FEAT->is_sparse(_issparse); - SPH_orig=FEAT->Initialize(_genesis[level],MESHES,_exclude); /// downsamples and smooths data, creates and exclusion mask if exclude is true - MVD=Calculate_MVD(SPH_orig); - boost::shared_ptr IN_EXCL=FEAT->get_input_excl(); - boost::shared_ptr REF_EXCL=FEAT->get_reference_excl(); - - SPHin_CFWEIGHTING=downsample_cfweighting(_sigma_in[level],SPH_orig,IN_CFWEIGHTING,IN_EXCL); /// COST FUNCTION WEIGHTINGS ARE IN ADDITION TO EXCLUSION MASKS - EXCLUSION MASKS ARE BINARY - SPHref_CFWEIGHTING=downsample_cfweighting(_sigma_ref[level],SPH_orig,REF_CFWEIGHTING,REF_EXCL); - - if(cost[level]=="AFFINE"){ /// currently the affine alignment uses a different class to the discrete, but will hopefully implement an affine discrete optimisation soon - affinecf = boost::shared_ptr(new affineMeshCF(SPH_orig,SPH_orig,FEAT)); - affinecf->set_parameters(PARAMETERS); - if(_simval[level]!=1) affinecf->set_simmeasure(1); - affinecf->Initialize(); - _isaffine=true; + SPH_orig = FEAT->Initialize(_genesis[level], MESHES, _exclude); /// downsamples and smooths data, creates and exclusion mask if exclude is true + MVD = Calculate_MVD(SPH_orig); + boost::shared_ptr IN_EXCL = FEAT->get_input_excl(); + boost::shared_ptr REF_EXCL = FEAT->get_reference_excl(); + + SPHin_CFWEIGHTING = downsample_cfweighting(_sigma_in[level], SPH_orig, IN_CFWEIGHTING, IN_EXCL); /// COST FUNCTION WEIGHTINGS ARE IN ADDITION TO EXCLUSION MASKS - EXCLUSION MASKS ARE BINARY + SPHref_CFWEIGHTING = downsample_cfweighting(_sigma_ref[level], SPH_orig, REF_CFWEIGHTING, REF_EXCL); + + if (cost[level] == "AFFINE") { /// currently the affine alignment uses a different class to the discrete, but will hopefully implement an affine discrete optimisation soon + affinecf = boost::shared_ptr(new affineMeshCF(SPH_orig, SPH_orig, FEAT)); + affinecf->set_parameters(PARAMETERS); + if (_simval[level] != 1) + affinecf->set_simmeasure(1); + affinecf->Initialize(); + _isaffine = true; } - if(cost[level]=="DISCRETE"){ - if(_simval[level]==3) cout << " warning NMI similarity measure does not take into account cost function weights or exclusion values" << endl; - bool multivariate; - if(FEAT->get_dim()==1){multivariate=false; if (_simval[level]==4) {throw MeshReg_error("MeshREG ERROR:: simval option 4 (alphaMI) is not suitable for univariate costfunctions");}} - else multivariate=true; - - PARAMETERS.insert(parameterPair("multivariate",multivariate)); // check whether data is multivariate (and NOT using patch based alignment) and add this to the parameter set - - MODEL=boost::shared_ptr(new NonLinearSRegDiscreteModel(PARAMETERS)); - - if(_usetraining){ - MODEL->set_L1path(_L1path); - } - if(_debug) MODEL->set_debug(); - - MODEL->set_featurespace(FEAT,_concattraining); - MODEL->set_meshspace(SPH_orig,SPH_orig); - NEWMESH::newmesh CONTROL; // original low res icosphere mesh - CONTROL.make_mesh_from_icosa(_gridres[level] ); true_rescale(CONTROL,RAD); - - if(_anat){ - vector > ANAT_face_neighbourhood; - vector > ANAT_to_CP_baryweights; - newmesh aICO=resample_anatomy(CONTROL,ANAT_to_CP_baryweights, ANAT_face_neighbourhood, level); - newmesh ANAT_target=mesh_resample(ref_anat,MESHES[1],aICO); - - MODEL->set_anatomical_meshspace(aICO,ANAT_target,aICO,ANAT_orig); - MODEL->set_anatomical_neighbourhood(ANAT_to_CP_baryweights,ANAT_face_neighbourhood); - - }else{if(_regmode==5){throw MeshReg_error("STRAINS based regularisation requires anatomical meshes");} - else if(_regmode==4){throw MeshReg_error("You have specified angular based penalisation of anatomical warp, for which you require anatomical meshes");}} - - - MODEL->Initialize(CONTROL); - - - - - _isaffine=false; + if (cost[level] == "DISCRETE") { + if (_simval[level] == 3) + cout << " warning NMI similarity measure does not take into account cost function weights or exclusion values" << endl; + bool multivariate; + if (FEAT->get_dim() == 1) { + multivariate = false; + if (_simval[level] == 4) { + throw MeshReg_error("MeshREG ERROR:: simval option 4 (alphaMI) is not suitable for univariate costfunctions"); + } + } else + multivariate = true; + + PARAMETERS.insert(parameterPair("multivariate", multivariate)); // check whether data is multivariate (and NOT using patch based alignment) and add this to the parameter set + + MODEL = boost::shared_ptr(new NonLinearSRegDiscreteModel(PARAMETERS)); + + if (_usetraining) { + MODEL->set_L1path(_L1path); + } + if (_debug) + MODEL->set_debug(); + + MODEL->set_featurespace(FEAT, _concattraining); + MODEL->set_meshspace(SPH_orig, SPH_orig); + NEWMESH::newmesh CONTROL; // original low res icosphere mesh + CONTROL.make_mesh_from_icosa(_gridres[level]); + true_rescale(CONTROL, RAD); + + if (_anat) { + vector> ANAT_face_neighbourhood; + vector> ANAT_to_CP_baryweights; + newmesh aICO = resample_anatomy(CONTROL, ANAT_to_CP_baryweights, ANAT_face_neighbourhood, level); + newmesh ANAT_target = mesh_resample(ref_anat, MESHES[1], aICO); + + MODEL->set_anatomical_meshspace(aICO, ANAT_target, aICO, ANAT_orig); + MODEL->set_anatomical_neighbourhood(ANAT_to_CP_baryweights, ANAT_face_neighbourhood); + + } else { + if (_regmode == 5) { + throw MeshReg_error("STRAINS based regularisation requires anatomical meshes"); + } else if (_regmode == 4) { + throw MeshReg_error("You have specified angular based penalisation of anatomical warp, for which you require anatomical meshes"); + } + } + + MODEL->Initialize(CONTROL); + + _isaffine = false; } - - - - } +} - newmesh MeshReg::resample_anatomy(newmesh control_grid, vector > &baryweights, vector > & ANAT_to_CPgrid_neighbours,int level){ +newmesh MeshReg::resample_anatomy(newmesh control_grid, vector>& baryweights, vector>& ANAT_to_CPgrid_neighbours, int level) +{ + + if (in_anat.nvertices() != MESHES[0].nvertices() || ref_anat.nvertices() != MESHES[1].nvertices()) { + throw MeshReg_error("MeshREG ERROR:: input/reference anatomical mesh resolution is inconconsistent with input/reference spherical mesh resolution "); + } - if(in_anat.nvertices()!=MESHES[0].nvertices() || ref_anat.nvertices()!=MESHES[1].nvertices()) {throw MeshReg_error("MeshREG ERROR:: input/reference anatomical mesh resolution is inconconsistent with input/reference spherical mesh resolution ");} - - newmesh ANAT_ico=control_grid; + newmesh ANAT_ico = control_grid; resampler R; - + ///// save face neighbourhood relationships during retesselation //// - vector > FACE_neighbours, FACE_neighbours_tmp; + vector> FACE_neighbours, FACE_neighbours_tmp; vector tmp; - Pt v0,v1,v2; - int id0,id1,id2; - - if( (_anatres[level]-_gridres[level]) > 0) { - for (int i=0;i<(_anatres[level]-_gridres[level]) ;i++){ - ANAT_ico.retessellate(FACE_neighbours_tmp); - if(i>0) { - ANAT_to_CPgrid_neighbours.clear(); - for(unsigned int j=0;j 0) { + for (int i = 0; i < (_anatres[level] - _gridres[level]); i++) { + ANAT_ico.retessellate(FACE_neighbours_tmp); + if (i > 0) { + ANAT_to_CPgrid_neighbours.clear(); + for (unsigned int j = 0; j < FACE_neighbours.size(); j++) { + ANAT_to_CPgrid_neighbours.push_back(tmp); + for (unsigned int k = 0; k < FACE_neighbours[j].size(); k++) { + ANAT_to_CPgrid_neighbours[j].insert(ANAT_to_CPgrid_neighbours[j].begin(), FACE_neighbours_tmp[FACE_neighbours[j][k]].begin(), FACE_neighbours_tmp[FACE_neighbours[j][k]].end()); + } + } + FACE_neighbours = ANAT_to_CPgrid_neighbours; + } else { + FACE_neighbours = FACE_neighbours_tmp; + } + + FACE_neighbours_tmp.clear(); + } + + if (ANAT_to_CPgrid_neighbours.size() == 0) { + ANAT_to_CPgrid_neighbours = FACE_neighbours; + } // i.e. for one increase in resolution use result directly from restesselation + + } else { + for (int i = 0; i < control_grid.ntriangles(); i++) { + ANAT_to_CPgrid_neighbours.push_back(tmp); + ANAT_to_CPgrid_neighbours[i].push_back(i); + } } - true_rescale(ANAT_ico,RAD); - - /// now get barycentric weights - baryweights.resize(ANAT_ico.nvertices(),map ()); - - for(unsigned int i=0;i()); + + for (unsigned int i = 0; i < ANAT_to_CPgrid_neighbours.size(); i++) { + id0 = control_grid.get_triangle_vertexID(i, 0); + id1 = control_grid.get_triangle_vertexID(i, 1); + id2 = control_grid.get_triangle_vertexID(i, 2); + v0 = control_grid.get_triangle_vertex(i, 0); + v1 = control_grid.get_triangle_vertex(i, 1); + v2 = control_grid.get_triangle_vertex(i, 2); + + for (unsigned int j = 0; j < ANAT_to_CPgrid_neighbours[i].size(); j++) { + for (int k = 0; k < 3; k++) { + Pt ci = ANAT_ico.get_triangle_vertex(ANAT_to_CPgrid_neighbours[i][j], k); + int id = ANAT_ico.get_triangle_vertexID(ANAT_to_CPgrid_neighbours[i][j], k); + baryweights[id] = get_barycentric_weights(v0, v1, v2, ci, id0, id1, id2); + // ANAT_ico.set_pvalue(id,i); + } + } } - - ANAT_orig=mesh_resample(in_anat,MESHES[0],ANAT_ico); - - + + ANAT_orig = mesh_resample(in_anat, MESHES[0], ANAT_ico); + return ANAT_ico; - } +} - Matrix MeshReg::downsample_cfweighting(const double &sigma , NEWMESH::newmesh SPH, boost::shared_ptr CFWEIGHTING, boost::shared_ptr EXCL){ +Matrix MeshReg::downsample_cfweighting(const double& sigma, NEWMESH::newmesh SPH, boost::shared_ptr CFWEIGHTING, boost::shared_ptr EXCL) +{ resampler R; Matrix DATA; R.set_method("NN"); - - - if(EXCL.get()){ - if(CFWEIGHTING.get()){ - DATA=CFWEIGHTING->get_pvalues(); - }else{ - CFWEIGHTING=boost::shared_ptr(new newmesh(*EXCL)); // if no CF weighting mask is supplied, then CF weighting is just equal to the EXCLUSION mask - DATA=CFWEIGHTING->get_pvalues(); - } - - /// resample onto reference mesh and print - R.resampledata(*CFWEIGHTING,SPH,EXCL,DATA,sigma); /// resample onto the data grid with smoothing - - - } - else if(CFWEIGHTING.get()){ - DATA=CFWEIGHTING->get_pvalues(); - R.resampledata(*CFWEIGHTING,SPH,EXCL,DATA,0); - } - else{ - DATA.ReSize(1,SPH.nvertices()); DATA=1; - + + if (EXCL.get()) { + if (CFWEIGHTING.get()) { + DATA = CFWEIGHTING->get_pvalues(); + } else { + CFWEIGHTING = boost::shared_ptr(new newmesh(*EXCL)); // if no CF weighting mask is supplied, then CF weighting is just equal to the EXCLUSION mask + DATA = CFWEIGHTING->get_pvalues(); + } + + /// resample onto reference mesh and print + R.resampledata(*CFWEIGHTING, SPH, EXCL, DATA, sigma); /// resample onto the data grid with smoothing + + } else if (CFWEIGHTING.get()) { + DATA = CFWEIGHTING->get_pvalues(); + R.resampledata(*CFWEIGHTING, SPH, EXCL, DATA, 0); + } else { + DATA.ReSize(1, SPH.nvertices()); + DATA = 1; } return DATA; - } +} - ///////////////////////////////////// MAIN FUNCTION ////////////////////////////////// - - void MeshReg::Evaluate() { +///////////////////////////////////// MAIN FUNCTION ////////////////////////////////// + +void MeshReg::Evaluate() +{ ///Initiallise deformation mesh - - SPH_reg=project_CPgrid(SPH_orig,SPH_reg); // first project data grid through any predefined transformation or, from transformation from previous resolution level - - if(_isaffine){ - affinecf->update_source(SPH_reg); - SPH_reg=affinecf->run(); - } - else{ - // sprintf(filename,"SPHreg-EVal%d.surf", _level); SPH_reg.save(filename); - run_discrete_opt(SPH_reg); - + SPH_reg = project_CPgrid(SPH_orig, SPH_reg); // first project data grid through any predefined transformation or, from transformation from previous resolution level + + if (_isaffine) { + affinecf->update_source(SPH_reg); + SPH_reg = affinecf->run(); + } else { + // sprintf(filename,"SPHreg-EVal%d.surf", _level); SPH_reg.save(filename); + run_discrete_opt(SPH_reg); } - if(_verbose) cout << "exit main algorithm " << endl; - - } - - - void MeshReg::Transform(const string &filename){ + if (_verbose) + cout << "exit main algorithm " << endl; +} + +void MeshReg::Transform(const string& filename) +{ newmesh INtransformed; char fullpath[1000]; // char buffer[1000]; - - if(_verbose) cout << " Transform " << endl; - if(!_meshInterpolator.compare("BARY")){ barycentric_mesh_interpolation(MESHES[0],SPH_orig,SPH_reg); } - else{ - if(SPH_orig.nvertices()MESHES[0].nvertices()){ - project(MESHES[0],SPH_orig,SPH_reg,2*asin(MVD/RAD)); // for above reason local affine projections work better than TPS in this instance - unfold(MESHES[0]); - }else{ MESHES[0]=SPH_reg;} + + if (_verbose) + cout << " Transform " << endl; + if (!_meshInterpolator.compare("BARY")) { + barycentric_mesh_interpolation(MESHES[0], SPH_orig, SPH_reg); + } else { + if (SPH_orig.nvertices() < MESHES[0].nvertices()) { // TPS interpolation, matrices can be singular if there aren't enough samples range is controlled by angle 2*asin(MVD/RAD) + upsample_transform_RBF(MESHES[0], SPH_orig, SPH_reg, 2 * asin(MVD / RAD)); + } else if (SPH_orig.nvertices() > MESHES[0].nvertices()) { + project(MESHES[0], SPH_orig, SPH_reg, 2 * asin(MVD / RAD)); // for above reason local affine projections work better than TPS in this instance + unfold(MESHES[0]); + } else { + MESHES[0] = SPH_reg; + } } - sprintf(fullpath,"%ssphere.reg%s",filename.c_str(), _surfformat.c_str()); + sprintf(fullpath, "%ssphere.reg%s", filename.c_str(), _surfformat.c_str()); MESHES[0].save(fullpath); - - } +} - void MeshReg::saveTransformedData(const double &sigma, const string &filename){ - if(_verbose) cout << " save transformed data " << endl; +void MeshReg::saveTransformedData(const double& sigma, const string& filename) +{ + if (_verbose) + cout << " save transformed data " << endl; char fullpath[1000]; - sprintf(fullpath,"%stransformed_and_reprojected%s",filename.c_str(),_dataformat.c_str()); + sprintf(fullpath, "%stransformed_and_reprojected%s", filename.c_str(), _dataformat.c_str()); resampler R; - boost::shared_ptr REL; + boost::shared_ptr REL; double ang; boost::shared_ptr DATA; @@ -304,276 +307,272 @@ namespace MESHREG { boost::shared_ptr IN_EXCL; boost::shared_ptr REF_EXCL; - if(sigma<1e-3){ R.set_method("ADAP_BARY"); - if(MESHES[1].nvertices() > MESHES[0].nvertices()){ang=R.guess_angular_spacing(MESHES[0].nvertices()); } - else{ang=R.guess_angular_spacing(MESHES[0].nvertices()); } - } - else{ R.set_method("GAUSSIAN"); ang=2*asin(sigma/(RAD));} - - REL = boost::shared_ptr ( new RELATIONS(MESHES[1],MESHES[0],ang)); + if (sigma < 1e-3) { + R.set_method("ADAP_BARY"); + if (MESHES[1].nvertices() > MESHES[0].nvertices()) { + ang = R.guess_angular_spacing(MESHES[0].nvertices()); + } else { + ang = R.guess_angular_spacing(MESHES[0].nvertices()); + } + } else { + R.set_method("GAUSSIAN"); + ang = 2 * asin(sigma / (RAD)); + } + + REL = boost::shared_ptr(new RELATIONS(MESHES[1], MESHES[0], ang)); REL->update_RELATIONS(MESHES[1]); - - if(_usetraining){ - set_data(CMfile_in,DATA,MESHES[0]); - R.resampledata(MESHES[0],MESHES[1],IN_EXCL,DATA,sigma,REL); + if (_usetraining) { + set_data(CMfile_in, DATA, MESHES[0]); + R.resampledata(MESHES[0], MESHES[1], IN_EXCL, DATA, sigma, REL); + + } else { + /// binarize costfunction weights for use as exclusion masks during resampling //// + + set_data(CMfile_in, DATA, MESHES[0]); + set_data(CMfile_ref, DATAREF, MESHES[1]); + + if (_exclude) { // no longer necessary as EXCL masks aren't downsampled anymore? Could save from initialisation + IN_EXCL = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(MESHES[0], DATA->AsMatrix(), _threshold[0], _threshold[1]))); + REF_EXCL = boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(MESHES[1], DATAREF->AsMatrix(), _threshold[0], _threshold[1]))); + } + + if (_IN) { /// INTENSITY NORMALIZE + if (_verbose) + cout << " intensity normalise " << endl; + multivariate_histogram_normalization(*DATA, *DATAREF, IN_EXCL, REF_EXCL); + MESHES[0].set_pvalues(DATA->AsMatrix()); + //MESHES[0].save("intensity_normalised.func.gii"); + } + + /// resample onto reference mesh and print + + R.resampledata(MESHES[0], MESHES[1], IN_EXCL, DATA, sigma, REL); } - else{ - /// binarize costfunction weights for use as exclusion masks during resampling //// - - - - set_data(CMfile_in,DATA,MESHES[0]); - set_data(CMfile_ref,DATAREF,MESHES[1]); - - - if(_exclude){ // no longer necessary as EXCL masks aren't downsampled anymore? Could save from initialisation - IN_EXCL= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(MESHES[0],DATA->AsMatrix(),_threshold[0],_threshold[1]))); - REF_EXCL= boost::shared_ptr(new NEWMESH::newmesh(create_exclusion(MESHES[1],DATAREF->AsMatrix(),_threshold[0],_threshold[1]))); - - } - - if(_IN){ /// INTENSITY NORMALIZE - if(_verbose) cout << " intensity normalise " << endl; - multivariate_histogram_normalization(*DATA,*DATAREF,IN_EXCL,REF_EXCL); - MESHES[0].set_pvalues(DATA->AsMatrix()); - //MESHES[0].save("intensity_normalised.func.gii"); - } - - - /// resample onto reference mesh and print - - R.resampledata(MESHES[0],MESHES[1],IN_EXCL,DATA,sigma,REL); + newmesh TRANSFORMED = MESHES[1]; + boost::shared_ptr pin = boost::dynamic_pointer_cast(DATA); + + if (pin) { + + TRANSFORMED.set_pvalues(DATA->AsMatrix()); + // cout << "write " << endl; + TRANSFORMED.save(fullpath); + } else + DATA->Print(fullpath); + + if (_anat) { + char filename2[1000]; + + newmesh ANAT_TRANS = projectmesh(MESHES[0], MESHES[1], ref_anat); + sprintf(filename2, "%sanat.reg.surf", _outdir.c_str()); + ANAT_TRANS.save(filename2); + boost::shared_ptr VECS; + VECS = boost::shared_ptr(new Matrix); + in_anat.estimate_normals(); + ANAT_TRANS.estimate_normals(); + newmesh STRAINSmesh = calculate_strains(2, in_anat, ANAT_TRANS, VECS); + calculate_triangular_strains(in_anat, ANAT_TRANS); + sprintf(filename2, "%sSTRAINS.func", _outdir.c_str()); + + STRAINSmesh.save(filename2); } +} - - - newmesh TRANSFORMED=MESHES[1]; - boost::shared_ptr pin =boost::dynamic_pointer_cast(DATA); - - if(pin){ - - TRANSFORMED.set_pvalues(DATA->AsMatrix()); - // cout << "write " << endl; - TRANSFORMED.save(fullpath); - }else DATA->Print(fullpath); - - if(_anat){ - char filename2[1000]; - - newmesh ANAT_TRANS=projectmesh(MESHES[0],MESHES[1],ref_anat); - sprintf(filename2,"%sanat.reg.surf",_outdir.c_str()); - ANAT_TRANS.save(filename2); - boost::shared_ptr VECS; VECS= boost::shared_ptr (new Matrix); - in_anat.estimate_normals(); ANAT_TRANS.estimate_normals(); - newmesh STRAINSmesh=calculate_strains(2,in_anat,ANAT_TRANS,VECS);calculate_triangular_strains(in_anat,ANAT_TRANS); - sprintf(filename2,"%sSTRAINS.func",_outdir.c_str()); - - - STRAINSmesh.save(filename2); +////////////////////// PROJECT TRANSFORMATION FROM PREVIOUS LEVEL TO UPSAMPLED SOURCE //////////////////////////////////// +NEWMESH::newmesh MeshReg::project_CPgrid(NEWMESH::newmesh SPH_in, NEWMESH::newmesh REG, int num) +{ /// num indices which warp for group registration + + if (_level == 1) { + if (transformed_mesh.nvertices() > 0) { + //// project into alignment with transformed mesh + if (transformed_mesh == MESHES[num]) { + cout << " WARNING:: transformed mesh has the same coordinates as the input mesh " << endl; + } else { + // unfold(transformed_mesh); + barycentric_mesh_interpolation(SPH_in, MESHES[num], transformed_mesh); + if (MODEL.get()) + MODEL->warp_CPgrid(MESHES[num], transformed_mesh, num); // for tri clique model control grid is continously deformed + // SPH_in.save("SPH_in.surf"); + } + } + + } else { + ///// following first round always start by projecting Control and data grids through warp at previous level + + /////////// PROJECT CPgrid into alignment with warp from previous level + NEWMESH::newmesh icotmp; + + int ico = REG.get_ico_resolution(); + icotmp.make_mesh_from_icosa(ico); + true_rescale(icotmp, RAD); + + ///// projecct datagrid though warp defined for the high resolution meshes (the equivalent to if registration is run one level at a time ) + newmesh inorig = MESHES[0]; + newmesh incurrent = MESHES[0]; + + barycentric_mesh_interpolation(incurrent, icotmp, REG); + barycentric_mesh_interpolation(SPH_in, inorig, incurrent); + if (MODEL.get()) + MODEL->warp_CPgrid(inorig, incurrent); + + if (_debug) { + char filename[1000]; + sprintf(filename, "%ssphere.regLR.Res%d.surf", _outdir.c_str(), _level); + incurrent.save(filename); + } + + // if(SPH_orig.nvertices()==REG.nvertices()){SPH_in=REG;} //// if resolution of data grid has not changed just initialise equal to previous warp + //else{ + // double MVDtmp=Calculate_MVD(icotmp); + + // if(SPH_orig.nvertices()0){ - //// project into alignment with transformed mesh - if(transformed_mesh==MESHES[num]){ - cout << " WARNING:: transformed mesh has the same coordinates as the input mesh " << endl; - }else{ - // unfold(transformed_mesh); - barycentric_mesh_interpolation(SPH_in,MESHES[num],transformed_mesh); - if(MODEL.get()) MODEL->warp_CPgrid(MESHES[num],transformed_mesh,num); // for tri clique model control grid is continously deformed - // SPH_in.save("SPH_in.surf"); - } - } - - }else { - ///// following first round always start by projecting Control and data grids through warp at previous level - - /////////// PROJECT CPgrid into alignment with warp from previous level - NEWMESH::newmesh icotmp; - - int ico=REG.get_ico_resolution(); - icotmp.make_mesh_from_icosa(ico); true_rescale(icotmp,RAD); - - - ///// projecct datagrid though warp defined for the high resolution meshes (the equivalent to if registration is run one level at a time ) - newmesh inorig=MESHES[0]; - newmesh incurrent=MESHES[0]; - - barycentric_mesh_interpolation(incurrent,icotmp,REG); - barycentric_mesh_interpolation(SPH_in,inorig,incurrent); - if(MODEL.get()) MODEL->warp_CPgrid(inorig,incurrent); - - if(_debug){ - char filename[1000]; - sprintf(filename,"%ssphere.regLR.Res%d.surf" ,_outdir.c_str(),_level); - incurrent.save(filename); - } - - - // if(SPH_orig.nvertices()==REG.nvertices()){SPH_in=REG;} //// if resolution of data grid has not changed just initialise equal to previous warp - //else{ - // double MVDtmp=Calculate_MVD(icotmp); - - // if(SPH_orig.nvertices() controlgrid_neighbourhood; myparam::iterator it; Matrix ResampledRefWeight; Matrix CombinedWeight; - newmesh sourcetmp=source; + newmesh sourcetmp = source; int _itersforlevel; int numNodes; - double energy=0,newenergy=0; - - - it=PARAMETERS.find("iters");_itersforlevel=boost::get(it->second); - - numNodes=MODEL->getNumNodes(); - targetmesh=MODEL->get_TARGET(); - controlgrid=MODEL->get_CPgrid(); - - while(iter <= _itersforlevel){ - - //////// resample and combine the reference cost function weighting with the source - ResampledRefWeight=SPHref_CFWEIGHTING; - - - R.resampledata(targetmesh,source,ResampledRefWeight,0); - - CombinedWeight=combine_costfunction_weighting(SPHin_CFWEIGHTING,ResampledRefWeight); // elementwise multiplication - - - MODEL->reset_meshspace(source); // source mesh is updated and control point grids are reset - MODEL->setupCostFunctionWeighting(CombinedWeight); - MODEL->setupCostFunction(); - - int *Labels=MODEL->getLabeling(); - if(_verbose) cout << "run optimisation" << endl; - - if(_discreteOPT=="FastPD"){ - MODEL->computeUnaryCosts(); - MODEL->computePairwiseCosts(); - - - FastPD opt(MODEL, 100 ); - newenergy = opt.run(); - - boost::shared_ptr reltmp=MODEL->get_cp_neighbourhood(); - opt.getLabeling(Labels); - - }else { -#ifdef HAS_HOCR + double energy = 0, newenergy = 0; - Reduction HOCR_mode; + it = PARAMETERS.find("iters"); + _itersforlevel = boost::get(it->second); - if(_discreteOPT.compare(0,4,"HOCR")==0) - HOCR_mode=HOCR; - else if(_discreteOPT=="ELC"){ - HOCR_mode=ELC_HOCR; - }else if(_discreteOPT=="ELC_approx"){ - HOCR_mode=ELC_APPROX; - }else {throw MeshReg_error("discrete optimisation mode is not available");} - + numNodes = MODEL->getNumNodes(); + targetmesh = MODEL->get_TARGET(); + controlgrid = MODEL->get_CPgrid(); - srand (time(NULL)); - newenergy=Fusion::optimize(MODEL,HOCR_mode,_verbose); + while (iter <= _itersforlevel) { + //////// resample and combine the reference cost function weighting with the source + ResampledRefWeight = SPHref_CFWEIGHTING; -#endif - } - - - if(iter>1 && ((iter-1) % 2==0) && (energy -newenergy < 0.001) ) - { if(_verbose) cout << iter << " level has converged" << (iter-1) %2 << " newenergy " << newenergy << " energy " << energy << " energy- newenergy " << energy -newenergy << endl; break;} - else {if(_verbose) cout << " newenergy " << newenergy << " energy " << energy << " energy- newenergy " << energy -newenergy << endl;} - - - // - //Run optimization - // - //Get labeling result - - if(_verbose) cout << "Output Control Point Label assignment:" << endl; - for (int i = 0; i evaluateTotalCostSum(); - /// get labelling choices from the FastPD optimiser - MODEL->applyLabeling(); - // apply these choices in order to deform the CP grid - transformed_controlgrid=MODEL->get_CPgrid(); - controlgrid_neighbourhood=MODEL->get_cp_neighbourhood(); - - /// use the control point updates to warp the source mesh - if(!_meshInterpolator.compare("BARY")){ - - barycentric_mesh_interpolation(source,controlgrid,transformed_controlgrid,controlgrid_neighbourhood); - } - else{ - upsample_transform_RBF(source,controlgrid,transformed_controlgrid,*controlgrid_neighbourhood); - } - //if(iter==2) exit(1); - // if(_discreteOPT.compare(0,4,"HOCR")==0){ - controlgrid=transformed_controlgrid; /// higher order frameowrk continuous deforms the CP grid whereas the original FW resets the grid each time - //controlgrid.save("transformed_controlgrid.surf"); - - //cout << " unfold " << endl; - unfold(transformed_controlgrid); - // cout << " reset control grid " << endl; - MODEL->reset_CPgrid(transformed_controlgrid); // source mesh is updated and control point grids are reset -//transformed_controlgrid.save("transformed_controlgridunfold.surf"); -//source.save("source.surf"); - - - unfold(source); - // source.save("sourceunfold.surf"); - - energy=newenergy; - iter++; - } + R.resampledata(targetmesh, source, ResampledRefWeight, 0); + + CombinedWeight = combine_costfunction_weighting(SPHin_CFWEIGHTING, ResampledRefWeight); // elementwise multiplication - + MODEL->reset_meshspace(source); // source mesh is updated and control point grids are reset + MODEL->setupCostFunctionWeighting(CombinedWeight); + MODEL->setupCostFunction(); - } + int* Labels = MODEL->getLabeling(); + if (_verbose) + cout << "run optimisation" << endl; + if (_discreteOPT == "FastPD") { + MODEL->computeUnaryCosts(); + MODEL->computePairwiseCosts(); + + FastPD opt(MODEL, 100); + newenergy = opt.run(); + + boost::shared_ptr reltmp = MODEL->get_cp_neighbourhood(); + opt.getLabeling(Labels); + + } else { +#ifdef HAS_HOCR + + Reduction HOCR_mode; + + if (_discreteOPT.compare(0, 4, "HOCR") == 0) + HOCR_mode = HOCR; + else if (_discreteOPT == "ELC") { + HOCR_mode = ELC_HOCR; + } else if (_discreteOPT == "ELC_approx") { + HOCR_mode = ELC_APPROX; + } else { + throw MeshReg_error("discrete optimisation mode is not available"); + } + + srand(time(NULL)); + newenergy = Fusion::optimize(MODEL, HOCR_mode, _verbose); + +#endif + } + + if (iter > 1 && ((iter - 1) % 2 == 0) && (energy - newenergy < 0.001)) { + if (_verbose) + cout << iter << " level has converged" << (iter - 1) % 2 << " newenergy " << newenergy << " energy " << energy << " energy- newenergy " << energy - newenergy << endl; + break; + } else { + if (_verbose) + cout << " newenergy " << newenergy << " energy " << energy << " energy- newenergy " << energy - newenergy << endl; + } + + // + //Run optimization + // + //Get labeling result + + if (_verbose) + cout << "Output Control Point Label assignment:" << endl; + for (int i = 0; i < numNodes; i++) { + if (_verbose) + cout << i << " _iter " << iter << " _iters " << _itersforlevel << " label " << Labels[i] << endl; + } + //Get initial energy + // double m_initial_energy = opt.getInitialEnergy(); + // double energybedorelabeling=energy->evaluateTotalCostSum(); + /// get labelling choices from the FastPD optimiser + MODEL->applyLabeling(); + // apply these choices in order to deform the CP grid + transformed_controlgrid = MODEL->get_CPgrid(); + controlgrid_neighbourhood = MODEL->get_cp_neighbourhood(); + + /// use the control point updates to warp the source mesh + if (!_meshInterpolator.compare("BARY")) { + + barycentric_mesh_interpolation(source, controlgrid, transformed_controlgrid, controlgrid_neighbourhood); + } else { + upsample_transform_RBF(source, controlgrid, transformed_controlgrid, *controlgrid_neighbourhood); + } + //if(iter==2) exit(1); + // if(_discreteOPT.compare(0,4,"HOCR")==0){ + controlgrid = transformed_controlgrid; /// higher order frameowrk continuous deforms the CP grid whereas the original FW resets the grid each time + //controlgrid.save("transformed_controlgrid.surf"); + + //cout << " unfold " << endl; + unfold(transformed_controlgrid); + // cout << " reset control grid " << endl; + MODEL->reset_CPgrid(transformed_controlgrid); // source mesh is updated and control point grids are reset + //transformed_controlgrid.save("transformed_controlgridunfold.surf"); + //source.save("source.surf"); + + unfold(source); + // source.save("sourceunfold.surf"); + + energy = newenergy; + iter++; + } } - - +} diff --git a/src/MSMRegLib/meshreg.h b/src/MSMRegLib/meshreg.h index c3e3a6a..39cf325 100644 --- a/src/MSMRegLib/meshreg.h +++ b/src/MSMRegLib/meshreg.h @@ -9,100 +9,94 @@ #ifndef meshreg_h #define meshreg_h - #include "meshmodify.h" #include "miscmaths/SpMat.h" - -#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO -#define D_DIST 0.25 // sampling distance along tangent plane for computing derivatives - 0.25 is what Bruce uses for FreeSurfer +#define CORLIM 1E-10 // when calculating corrzero consider any correlations below this value to be ZERO +#define D_DIST 0.25 // sampling distance along tangent plane for computing derivatives - 0.25 is what Bruce uses for FreeSurfer #ifndef SQR -#define SQR(x) ((x)*(x)) +#define SQR(x) ((x) * (x)) #endif namespace MESHREG { - struct spcoord - { +struct spcoord { double theta; double phi; - + int ind; - }; - - struct SortPhi - { - bool operator() (const spcoord& m1, const spcoord& m2) - { return m1.phi < m2.phi; } - }; - - struct SortAscTheta - { - bool operator() (const spcoord& m1, const spcoord& m2) - { return m1.theta < m2.theta; } - }; - - struct SortDecTheta - { - bool operator() (const spcoord& m1, const spcoord& m2) - {return m1.theta > m2.theta; } - }; - - - class MeshReg: public MeshModify { - - private: - +}; + +struct SortPhi { + bool operator()(const spcoord& m1, const spcoord& m2) + { + return m1.phi < m2.phi; + } +}; + +struct SortAscTheta { + bool operator()(const spcoord& m1, const spcoord& m2) + { + return m1.theta < m2.theta; + } +}; + +struct SortDecTheta { + bool operator()(const spcoord& m1, const spcoord& m2) + { + return m1.theta > m2.theta; + } +}; + +class MeshReg : public MeshModify { + +private: newmesh icoref; newmesh ANAT_RES; - + bool _isaffine; boost::shared_ptr affinecf; - protected: +protected: int _level; boost::shared_ptr MODEL; - public: - + +public: // Constructors - inline MeshReg(){_isaffine=false; _level=0;}; - + inline MeshReg() + { + _isaffine = false; + _level = 0; + }; + //MeshReg(int); - + // Destructor - inline ~MeshReg(){}; - + inline ~MeshReg() {}; + //////////////// INITIALIZATION //////////////////// //// loops over steps/resolution levels - void run_multiresolutions(const int &, const double &, const string &); + void run_multiresolutions(const int&, const double&, const string&); ///// initialises featurespace and cost function model for each step (either a single resolution level of the discrete opt or an Affine step) void Initialize_level(int); /// downsample anatomy - newmesh resample_anatomy(newmesh, vector > &, vector > &,int ); + newmesh resample_anatomy(newmesh, vector>&, vector>&, int); ///// additionally resamples the costfunction weighting to match the downsampled data grids for that resolution leve; - Matrix downsample_cfweighting(const double &, NEWMESH::newmesh, boost::shared_ptr, boost::shared_ptr); - + Matrix downsample_cfweighting(const double&, NEWMESH::newmesh, boost::shared_ptr, boost::shared_ptr); + //////////////// RUN ////////////////////// void Evaluate(); - void Transform(const string &); - void saveTransformedData(const double &,const string &); + void Transform(const string&); + void saveTransformedData(const double&, const string&); ///// projects warp from a lower resolution level to the next one - NEWMESH::newmesh project_CPgrid(NEWMESH::newmesh,NEWMESH::newmesh, int num=0); + NEWMESH::newmesh project_CPgrid(NEWMESH::newmesh, NEWMESH::newmesh, int num = 0); /////// runs all iterations of the discrete optimisation for each resolution level - void run_discrete_opt(NEWMESH::newmesh &); - - - }; - - - - -} + void run_discrete_opt(NEWMESH::newmesh&); +}; - +} #endif - From 468afdd7df0997f42de1aa87cad0305dc000a5c7 Mon Sep 17 00:00:00 2001 From: Eric Kerfoot Date: Tue, 5 Oct 2021 16:47:36 +0100 Subject: [PATCH 2/2] Formatting further --- src/DiscreteOpt/DiscreteCostFunction.cpp | 1880 +++++++++-------- src/DiscreteOpt/DiscreteGroupCostFunction.cpp | 683 +++--- src/DiscreteOpt/DiscreteGroupModel.cpp | 491 +++-- src/DiscreteOpt/DiscreteModel.cpp | 785 +++---- src/MSMRegLib/Fusion.cpp | 485 ++--- 5 files changed, 2167 insertions(+), 2157 deletions(-) diff --git a/src/DiscreteOpt/DiscreteCostFunction.cpp b/src/DiscreteOpt/DiscreteCostFunction.cpp index c6169d6..e2c9969 100644 --- a/src/DiscreteOpt/DiscreteCostFunction.cpp +++ b/src/DiscreteOpt/DiscreteCostFunction.cpp @@ -8,1105 +8,1115 @@ #include "DiscreteCostFunction.h" #include -namespace DISCRETEOPT{ - - //================================BASECLASS===========================================================================// - DiscreteCostFunction::DiscreteCostFunction()// m_is_memory(false), m_is_memory_triplets(false) - : m_num_nodes(0), m_num_labels(0), m_num_pairs(0), m_num_triplets(0), m_num_quartets(0), unarycosts(0), paircosts(0),pairweights(0), _pairs(0), _triplets(0), _quartets(0)//, tripletcosts(0), quartetcosts(0), pairweights(0), tripletweights(0), - { - } - - //====================================================================================================================// - DiscreteCostFunction::~DiscreteCostFunction() - { - if(unarycosts) { delete[] unarycosts; unarycosts = 0; } // replace pointers with special pointers? - if(paircosts) { delete[] paircosts; paircosts = 0; } - // if(quartetcosts) { delete[] quartetcosts; quartetcosts = 0; } - if(pairweights) { delete[] pairweights; pairweights = 0; } - // if(tripletcosts) { delete[] tripletcosts; tripletcosts = 0; } - // if(tripletweights) { delete[] tripletweights; tripletweights = 0; } - } - - //====================================================================================================================// - void DiscreteCostFunction::initialize(int numNodes,int numLabels, int numPairs, int numTriplets, int numQuartets) - { - - if (m_num_nodes != numNodes || m_num_labels != numLabels) - { - if (unarycosts){ delete [] unarycosts; } - unarycosts = new double[numNodes*numLabels]; - } - - if (m_num_pairs != numPairs || m_num_labels != numLabels) - { - - if (paircosts) delete [] paircosts; - if (pairweights) delete [] pairweights; - paircosts = new double[numPairs*numLabels*numLabels]; - pairweights = new double[numPairs*numLabels*numLabels]; // not used? delete? - } - - m_num_nodes = numNodes; - m_num_labels = numLabels; - m_num_pairs = numPairs; - m_num_triplets = numTriplets; - m_num_quartets = numQuartets; - - - std::fill(unarycosts,unarycosts+m_num_labels*m_num_nodes,0.0f); - std::fill(paircosts,paircosts+m_num_labels*m_num_labels*m_num_pairs,0.0f); - std::fill(pairweights,pairweights+m_num_labels*m_num_labels*m_num_pairs,0.0f); - - } - - //====================================================================================================================// - void DiscreteCostFunction::reset() - { - if(unarycosts) std::fill(unarycosts,unarycosts+m_num_labels*m_num_nodes,0.0f); - if(paircosts) std::fill(paircosts,paircosts+m_num_labels*m_num_labels*m_num_pairs,0.0f); - if(pairweights) std::fill(pairweights,pairweights+m_num_pairs,0.0f); - - } - - //====================================================================================================================// - void DiscreteCostFunction::initPairWeights(const double *weights) // for msm distortion weights we modify pairwise costs rather than adding a weight - { - if(!pairweights) pairweights = new double[m_num_pairs]; - - if(weights) - { - for(int p = 0; p < m_num_pairs; ++p) - { - pairweights[p] = weights[p]; - } - } - else - { - std::fill(pairweights,pairweights+m_num_pairs,1.0f); - } - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluateTotalCostSumZeroLabeling() - { - int label = 0; - double cost_sum_unary = 0.0f; - double cost_sum_pairwise = 0.0f; - double cost_sum_triplet = 0.0f; - double cost_sum_quartet = 0.0f; - - for(int i = 0; i < m_num_nodes; ++i){ - cost_sum_unary += computeUnaryCost(i,label); - } - for(int p = 0; p < m_num_pairs; ++p) - { - cost_sum_pairwise += computePairwiseCost(p,label,label); - } - for(int t = 0; t < m_num_triplets; ++t) - { - cost_sum_triplet += computeTripletCost(t,label,label,label); - } - - for(int q = 0; q < m_num_quartets; ++q) - { - - cost_sum_quartet += computeQuartetCost(q,label,label,label,label); - } - - if(_debug) cout << m_num_quartets << " cost_sum_unary " << cost_sum_unary << " cost_sum_pairwise " << cost_sum_pairwise << " cost_sum_triplet " << cost_sum_triplet << " cost_sum_quartet " << cost_sum_quartet << " total " << cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet << " m_num_triplets " << m_num_triplets << endl; - - return cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet; - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluateTotalCostSum(const int *labeling, const int *pairs, const int *triplets, const int *quartets) - { - double cost_sum_unary = 0.0f; - double cost_sum_pairwise = 0.0f; - double cost_sum_triplet = 0.0f; - double cost_sum_quartet = 0.0f; - for(int i = 0; i < m_num_nodes; ++i){ - cost_sum_unary += computeUnaryCost(i,labeling[i]); - } - - for(int p = 0; p < m_num_pairs; ++p) - { - const int index = p*2; - cost_sum_pairwise += computePairwiseCost(p,labeling[pairs[index]],labeling[pairs[index+1]]); - } - - for(int t = 0; t < m_num_triplets; ++t) - { - const int index = t*3; - cost_sum_triplet += computeTripletCost(t,labeling[triplets[index]],labeling[triplets[index+1]],labeling[triplets[index+2]]); - //cout << t << " " << cost_sum_triplet << " abeling[triplets[index]] " << labeling[triplets[index]] << " " << labeling[triplets[index+1]] << " " << labeling[triplets[index+2]] << endl; - if (cost_sum_triplet!=cost_sum_triplet) cout << " cost_sum_triplet!=cost_sum_triplet " << endl; - } - - for(int q = 0; q < m_num_quartets; ++q) - { - const int index = q*4; - cost_sum_quartet += computeQuartetCost(q,labeling[quartets[index]],labeling[quartets[index+1]],labeling[quartets[index+2]],labeling[quartets[index+3]]); - } - - if(_verbosity) cout << m_num_quartets << " cost_sum_unary " << cost_sum_unary << " cost_sum_pairwise " << cost_sum_pairwise << " cost_sum_triplet " << cost_sum_triplet << " cost_sum_quartet " << cost_sum_quartet <<" total " << cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet << " m_num_triplets 2 " << m_num_triplets << endl; - return cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet; - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluateUnaryCostSum(const int *labeling) - { - double cost_sum_unary = 0.0f; - for(int i = 0; i < m_num_nodes; ++i) - cost_sum_unary += computeUnaryCost(i,labeling[i]);// unarycosts[labeling[i]*m_num_nodes+i]; - return cost_sum_unary; - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluatePairwiseCostSum(const int *labeling, const int *pairs) - { - double cost_sum_pairwise = 0.0f; - for(int p = 0; p < m_num_pairs; ++p) - { - const int index = p*2; - cost_sum_pairwise += computePairwiseCost(p,labeling[pairs[index]],labeling[pairs[index+1]]); - } - return cost_sum_pairwise; - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluateTripletCostSum(const int *labeling, const int *triplets) - { - double cost_sum_triplet = 0.0f; - for(int t = 0; t < m_num_triplets; ++t) - { - const int index = t*3; - cost_sum_triplet += computeTripletCost(t,labeling[triplets[index]],labeling[triplets[index+1]],labeling[triplets[index+2]]); - } - return cost_sum_triplet; - } - - //====================================================================================================================// - double DiscreteCostFunction::evaluateQuartetCostSum(const int *labeling, const int *quartets) - { - double cost_sum_quartet = 0.0f; - for(int q = 0; q < m_num_quartets; ++q) - { - const int index = q*3; - cost_sum_quartet += computeQuartetCost(q,labeling[quartets[index]],labeling[quartets[index+1]],labeling[quartets[index+2]],labeling[quartets[index+3]]); - } - return cost_sum_quartet; - } - //================================GENERIC SURFACE CLASS===========================================================================// - SRegDiscreteCostFunction::SRegDiscreteCostFunction() :_simmeasure(2) - { - _reglambda=0; _debug=false; _MEANANGLE=0; _verbosity=false; _outdir=""; _concat=false; _sigma=1; - } - - //====================================================================================================================// - void SRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) - { - - if(_TARGET.nvertices()==0 || _SOURCE.nvertices()==0) { throw DISCRETEOPTHOCRException("CostFunction::You must supply source and target meshes.");} - // _AREALDIST.ReSize(_SOURCE.nvertices()); _AREALDIST=0.0; - if(_HIGHREScfweight.Ncols()!=_SOURCE.nvertices()) _HIGHREScfweight.ReSize(1, _SOURCE.nvertices()); - if(_HIGHREScfweight.Nrows()!=1 && _HIGHREScfweight.Nrows()!=FEAT->get_dim()){throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: costfunction weighting has dimensions incompatible with data");} - DiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); - - - } - - void SRegDiscreteCostFunction::set_parameters(myparam & ALLPARAMS){ - - myparam::iterator it; - it=ALLPARAMS.find("lambda");_reglambda=boost::get(it->second); - it=ALLPARAMS.find("range");_controlptrange=boost::get(it->second); - it=ALLPARAMS.find("CPres");_RES=boost::get(it->second); - it=ALLPARAMS.find("anatres");_aRES=boost::get(it->second); - it=ALLPARAMS.find("simmeasure");_simmeasure=boost::get(it->second); sim.set_simval(_simmeasure); - it=ALLPARAMS.find("verbosity");_verbosity=boost::get(it->second); - it=ALLPARAMS.find("outdir");_outdir=boost::get(it->second); - it=ALLPARAMS.find("regularisermode");_rmode=boost::get(it->second); - it=ALLPARAMS.find("sigma_in");_sigma=boost::get(it->second); - it=ALLPARAMS.find("numthreads");_threads=boost::get(it->second); - - } - - void SRegDiscreteCostFunction::initialize_regulariser(){ - - if(_aSOURCE.nvertices()>0 && _rmode>=3){ - - - anatMVD=2*asin(Calculate_MaxVD(_aICO)/RAD); - _anatrel.Initialize(_aICO,_TARGEThi,anatMVD); - - } - - } - - newmesh SRegDiscreteCostFunction::project_anatomical(){ - newmesh TRANS; - newmesh _aICOtrans=_aICO; - barycentric_mesh_interpolation(_aICOtrans,_ORIG,_SOURCE); - TRANS=projectmesh(_aICOtrans,(_TARGEThi),(_aTARGET)); - - return TRANS; - } - - - /// this is for debug - - void SRegDiscreteCostFunction::reset_anatomical(const string &outdir, const int &iter){ - - - newmesh STRAINSmesh; - ColumnVector strainstmp(_aSOURCE.ntriangles()); - double perc=0; - _iter=iter; - if(_aSOURCE.nvertices()>0 ) { - - _aSOURCEtrans=project_anatomical(); - MAXstrain=0; - - for (int i=0;i<_aSOURCE.ntriangles();i++){ - strainstmp(i+1)=calculate_triangular_strain(i,_aSOURCE,_aSOURCEtrans,_mu,_kappa); - if(strainstmp(i+1)>MAXstrain) - MAXstrain=strainstmp(i+1); - } - - if(MAXstrain>1e-8){ - Histogram strainHist(strainstmp,256); - - perc=strainHist.getPercentile(0.95); - } - - if(iter==1) strain95=perc; - - } - - } - //====================================================================================================================// - //================================AFFINE SURFACE CLASS===========================================================================// - //AffineSRegDiscreteCostFunction::AffineSRegDiscreteCostFunction() - // : _iters(50) - //{ - //} - - //====================================================================================================================// - //================================Non Linear SURFACE CLASS===========================================================================// - NonLinearSRegDiscreteCostFunction::NonLinearSRegDiscreteCostFunction() - { - _expscaling = 1; - _k_exp = 2.0; - _maxdist=4; _rexp=2; - _kNN=5; _rmode=1; - _mu=0.4; _kappa=1.6; - } - - void NonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets,int numQuartets) - { - ///// initialise CF weightings - SRegDiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); - - } - - void NonLinearSRegDiscreteCostFunction::set_parameters(myparam & ALLPARAMS){ - myparam::iterator it; - it=ALLPARAMS.find("maxdistortion");_maxdist=boost::get(it->second); - it=ALLPARAMS.find("exponent");_rexp=boost::get(it->second); - it=ALLPARAMS.find("weight");_dweight=boost::get(it->second); - it=ALLPARAMS.find("anorm");_anorm=boost::get(it->second); - it=ALLPARAMS.find("scaling");_expscaling=boost::get(it->second); - it=ALLPARAMS.find("shearmodulus");_mu=boost::get(it->second); - it=ALLPARAMS.find("bulkmodulus");_kappa=boost::get(it->second); - it=ALLPARAMS.find("kexponent");_k_exp=boost::get(it->second); - - it=ALLPARAMS.find("kNN");_kNN=boost::get(it->second); - it=ALLPARAMS.find("pottsthreshold");_pottsthreshold=boost::get(it->second); - - SRegDiscreteCostFunction::set_parameters(ALLPARAMS); - - - } - - - double NonLinearSRegDiscreteCostFunction::computeTripletCost(int triplet, int labelA, int labelB, int labelC){ - - vector id; - Pt normal; - map v; - Pt v0,v1,v2; - double cost=0; - double weight=1.0; - double distortion=1; - double likelihood=0; ///////////// WILL ONLY BE ESTIMATED FOR HOCR method - char filename[1000]; - - map transformed_points; - - if(triplet==0 && _debug){ sumlikelihood=0; sumregcost=0; } - // sprintf(filename,"CPgridintrip-%d.surf",_iter); - // _CPgrid.save(filename) ; - // sprintf(filename,"SOURCEintrip-%d.surf",_iter); - - // _SOURCE.save("filename"); - //_SOURCE.save("SOURCEintrip.func"); } - if(!_triplets){throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: must run settripletss() prior to computTripleCost ");} - - - v0=_CPgrid.get_coord(_triplets[3*triplet]); - v1=_CPgrid.get_coord(_triplets[3*triplet+1]); - v2=_CPgrid.get_coord(_triplets[3*triplet+2]); - - - - - id.push_back(_triplets[3*triplet]); - id.push_back(_triplets[3*triplet+1]); - id.push_back(_triplets[3*triplet+2]); - - - v[id[0]]=(*ROTATIONS)[id[0]]*_labels[labelA]; - v[id[1]]=(*ROTATIONS)[id[1]]*_labels[labelB]; - v[id[2]]=(*ROTATIONS)[id[2]]*_labels[labelC]; - - likelihood=triplet_likelihood(triplet,id[0],id[1],id[2],v[id[0]],v[id[1]],v[id[2]]); - - - Triangle TRI(v[id[0]],v[id[1]],v[id[2]],0); - - Triangle TRI_noDEF(v0,v1,v2,0); - NEWMESH::Pt norm_new= TRI.normal(); - NEWMESH::Pt norm_old = TRI_noDEF.normal(); - /// only estimate cost if it doesn't cause folding - if((norm_new|norm_old) < 0){ cost=1; weight+=1e6 ; - //cout << triplet << " triplet fold " << labelA << " " << labelB << " " << labelC << endl; - } - else{ - - - switch(_rmode) { - case 2: - { - vector deformed_angles, orig_angles; - Pt o_v0,o_v1,o_v2; - double val=0,tweight=1; - double diff=0; - Triangle TRI_ORIG; - - o_v0=_ORIG.get_coord(_triplets[3*triplet]); - o_v1=_ORIG.get_coord(_triplets[3*triplet+1]); - o_v2=_ORIG.get_coord(_triplets[3*triplet+2]); - TRI_ORIG.set(o_v0,o_v1,o_v2,0); - deformed_angles=TRI.get_angles(); - orig_angles=TRI_ORIG.get_angles(); - distortion=log2(TRI.area()/TRI_ORIG.area()); - - if(_dweight && distortion!=1){ - tweight=exp(abs(distortion-1)); - - }else{tweight=1;} - - for (int i=0;i<3;i++){ - - val=deformed_angles[i]-orig_angles[i]; - diff+=val*val; - - } - - cost=tweight*(sqrt(diff)); - if(_anorm){ weight*=(1/_MEANANGLE);} - - break; - } - case 3:{ - - //// - Pt o_v0,o_v1,o_v2; - Triangle TRI_ORIG; - - o_v0=_ORIG.get_coord(_triplets[3*triplet]); - o_v1=_ORIG.get_coord(_triplets[3*triplet+1]); - o_v2=_ORIG.get_coord(_triplets[3*triplet+2]); - TRI_ORIG.set(o_v0,o_v1,o_v2,0); - - - cost=calculate_triangular_strain(TRI_ORIG, TRI, _mu, _kappa, boost::shared_ptr(), _k_exp); - // if(write) cout << triplet << " " << labelA << " " << labelB << " " << labelC << " " << cost << " (v0- v[id[0]]).norm() " << (v0- v[id[0]]).norm() << endl; - - - break; - } - case 4: - { - vector deformed_angles, orig_angles; - double val=0; - double diff=0; - double tweight=1,distortion; - Triangle TRIorig,TRItrans; - map moved2; - map transformed_points; - - for (unsigned int n=0;n moved2; - map transformed_points; - - - for (unsigned int n=0;n(), _k_exp); - - - } - - - cost=cost/NEARESTFACES[triplet].size(); - - - - break; - } - default: - throw DISCRETEOPTHOCRException("DiscreteModel computeTripletCost regoption does not exist"); - - - - } - } - - - if(abs(cost)<1e-8){ cost=0; } - if(_debug){ sumlikelihood+=likelihood; - sumregcost+=weight*_reglambda*MISCMATHS::pow(cost,_rexp); - } - cost=likelihood+ weight*_reglambda*MISCMATHS::pow(cost,_rexp); - - - return cost; // normalise to try and ensure equivalent lambda for each resolution level - } - - double NonLinearSRegDiscreteCostFunction::computePairwiseCost(int pair, int labelA, int labelB){ - - Matrix fullrotA,fullrotB; - Matrix R1,R2,R_diff,logR,R_diff2,logR2; - double theta_MVD=2*asin(MVDmax/(2*RAD)); - double cost=0; - - if(!_pairs){throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: must run setPairs() prior to computePairwiseCost ");} - - R1=estimate_rotation_matrix(_CPgrid.get_coord(_pairs[2*pair]),(*ROTATIONS)[_pairs[2*pair]]*_labels[labelA]); /// with additional rotation estimated for this label - R2=estimate_rotation_matrix(_CPgrid.get_coord(_pairs[2*pair+1]),(*ROTATIONS)[_pairs[2*pair+1]]*_labels[labelB]); - - R_diff=R1.t()*R2; - - double theta=acos((R_diff.Trace()-1)/2); - double weight=1; - double totalcost=0.0; - - /// check for flipping //// - Pt v0,v1; - v0=_CPgrid.get_coord(_pairs[2*pair]); - v1=_CPgrid.get_coord(_pairs[2*pair+1]); - - - _CPgrid.set_coord(_pairs[2*pair],(*ROTATIONS)[_pairs[2*pair]]*_labels[labelA]); - _CPgrid.set_coord(_pairs[2*pair+1],(*ROTATIONS)[_pairs[2*pair+1]]*_labels[labelB]); - - - - ///////////////////////////////////////// - - - if(fabs(1-(R_diff.Trace()-1)/2) > EPSILON){ - - - for(vector::const_iterator j=_CPgrid.tIDbegin(_pairs[2*pair]); j!=_CPgrid.tIDend(_pairs[2*pair]);j++){ - Triangle TRI_trans=_CPgrid.get_triangle(*j); - Triangle TRI_orig=_oCPgrid.get_triangle(*j); - Pt norm_orig=TRI_orig.normal(); - Pt norm_trans=TRI_trans.normal(); - if((norm_orig|norm_trans) < 0){ cost=1; weight+=1e6 ; break;} - // cout < &vertex, map & moved, map &transformed){ - Triangle TRItrans; - +namespace DISCRETEOPT { + +//================================BASECLASS===========================================================================// +DiscreteCostFunction::DiscreteCostFunction() // m_is_memory(false), m_is_memory_triplets(false) + : m_num_nodes(0) + , m_num_labels(0) + , m_num_pairs(0) + , m_num_triplets(0) + , m_num_quartets(0) + , unarycosts(0) + , paircosts(0) + , pairweights(0) + , _pairs(0) + , _triplets(0) + , _quartets(0) //, tripletcosts(0), quartetcosts(0), pairweights(0), tripletweights(0), +{ +} - Pt newPt; - int tindex; - map weight; +//====================================================================================================================// +DiscreteCostFunction::~DiscreteCostFunction() +{ + if (unarycosts) { + delete[] unarycosts; + unarycosts = 0; + } // replace pointers with special pointers? + if (paircosts) { + delete[] paircosts; + paircosts = 0; + } + // if(quartetcosts) { delete[] quartetcosts; quartetcosts = 0; } + if (pairweights) { + delete[] pairweights; + pairweights = 0; + } + // if(tripletcosts) { delete[] tripletcosts; tripletcosts = 0; } + // if(tripletweights) { delete[] tripletweights; tripletweights = 0; } +} - for(int i=0;i<3;i++){ // for each point in face +//====================================================================================================================// +void DiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + if (m_num_nodes != numNodes || m_num_labels != numLabels) { + if (unarycosts) { + delete[] unarycosts; + } + unarycosts = new double[numNodes * numLabels]; + } - tindex=_aSOURCE.get_triangle_vertexID(NEARESTFACES[trip][n],i); - if(moved.find(tindex) == moved.end()) { - moved[tindex]=true; - newPt.X=0; newPt.Y=0;newPt.Z=0; + if (m_num_pairs != numPairs || m_num_labels != numLabels) { - for (std::map::iterator it= _ANATbaryweights[tindex].begin(); it!= _ANATbaryweights[tindex].end(); ++it){ + if (paircosts) + delete[] paircosts; + if (pairweights) + delete[] pairweights; + paircosts = new double[numPairs * numLabels * numLabels]; + pairweights = new double[numPairs * numLabels * numLabels]; // not used? delete? + } - newPt+=vertex[it->first]*it->second; - } + m_num_nodes = numNodes; + m_num_labels = numLabels; + m_num_pairs = numPairs; + m_num_triplets = numTriplets; + m_num_quartets = numQuartets; + std::fill(unarycosts, unarycosts + m_num_labels * m_num_nodes, 0.0f); + std::fill(paircosts, paircosts + m_num_labels * m_num_labels * m_num_pairs, 0.0f); + std::fill(pairweights, pairweights + m_num_labels * m_num_labels * m_num_pairs, 0.0f); +} +//====================================================================================================================// +void DiscreteCostFunction::reset() +{ + if (unarycosts) + std::fill(unarycosts, unarycosts + m_num_labels * m_num_nodes, 0.0f); + if (paircosts) + std::fill(paircosts, paircosts + m_num_labels * m_num_labels * m_num_pairs, 0.0f); + if (pairweights) + std::fill(pairweights, pairweights + m_num_pairs, 0.0f); +} - weight=R.get_barycentric_weight_for_ind(tindex,anatMVD,newPt,_TARGEThi, _anatrel); +//====================================================================================================================// +void DiscreteCostFunction::initPairWeights(const double* weights) // for msm distortion weights we modify pairwise costs rather than adding a weight +{ + if (!pairweights) + pairweights = new double[m_num_pairs]; + + if (weights) { + for (int p = 0; p < m_num_pairs; ++p) { + pairweights[p] = weights[p]; + } + } else { + std::fill(pairweights, pairweights + m_num_pairs, 1.0f); + } +} - newPt.X=0; newPt.Y=0; newPt.Z=0; - for (std::map::iterator it= weight.begin(); it!= weight.end(); ++it){ +//====================================================================================================================// +double DiscreteCostFunction::evaluateTotalCostSumZeroLabeling() +{ + int label = 0; + double cost_sum_unary = 0.0f; + double cost_sum_pairwise = 0.0f; + double cost_sum_triplet = 0.0f; + double cost_sum_quartet = 0.0f; + + for (int i = 0; i < m_num_nodes; ++i) { + cost_sum_unary += computeUnaryCost(i, label); + } + for (int p = 0; p < m_num_pairs; ++p) { + cost_sum_pairwise += computePairwiseCost(p, label, label); + } + for (int t = 0; t < m_num_triplets; ++t) { + cost_sum_triplet += computeTripletCost(t, label, label, label); + } - newPt+=_aTARGET.get_coord(it->first)*it->second; + for (int q = 0; q < m_num_quartets; ++q) { - } - transformed[tindex]=newPt; + cost_sum_quartet += computeQuartetCost(q, label, label, label, label); + } - TRItrans.set_vertice(i, newPt); + if (_debug) + cout << m_num_quartets << " cost_sum_unary " << cost_sum_unary << " cost_sum_pairwise " << cost_sum_pairwise << " cost_sum_triplet " << cost_sum_triplet << " cost_sum_quartet " << cost_sum_quartet << " total " << cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet << " m_num_triplets " << m_num_triplets << endl; - }else - TRItrans.set_vertice(i, transformed[tindex]); - } + return cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet; +} - return TRItrans; - } +//====================================================================================================================// +double DiscreteCostFunction::evaluateTotalCostSum(const int* labeling, const int* pairs, const int* triplets, const int* quartets) +{ + double cost_sum_unary = 0.0f; + double cost_sum_pairwise = 0.0f; + double cost_sum_triplet = 0.0f; + double cost_sum_quartet = 0.0f; + for (int i = 0; i < m_num_nodes; ++i) { + cost_sum_unary += computeUnaryCost(i, labeling[i]); + } - void NonLinearSRegDiscreteCostFunction::resample_weights(){ ///////// TAKE DATA TERM WEIGHTING AS MAXIMUM OF WEIGHTS ACROSS ALL DIMENSIONS ////////////// + for (int p = 0; p < m_num_pairs; ++p) { + const int index = p * 2; + cost_sum_pairwise += computePairwiseCost(p, labeling[pairs[index]], labeling[pairs[index + 1]]); + } - R.set_method("ADAP_BARY"); - double maxweight; - AbsoluteWeights.ReSize(_SOURCE.nvertices()); AbsoluteWeights=0; + for (int t = 0; t < m_num_triplets; ++t) { + const int index = t * 3; + cost_sum_triplet += computeTripletCost(t, labeling[triplets[index]], labeling[triplets[index + 1]], labeling[triplets[index + 2]]); + //cout << t << " " << cost_sum_triplet << " abeling[triplets[index]] " << labeling[triplets[index]] << " " << labeling[triplets[index+1]] << " " << labeling[triplets[index+2]] << endl; + if (cost_sum_triplet != cost_sum_triplet) + cout << " cost_sum_triplet!=cost_sum_triplet " << endl; + } - for (int k=1;k<=_SOURCE.nvertices();k++){ + for (int q = 0; q < m_num_quartets; ++q) { + const int index = q * 4; + cost_sum_quartet += computeQuartetCost(q, labeling[quartets[index]], labeling[quartets[index + 1]], labeling[quartets[index + 2]], labeling[quartets[index + 3]]); + } - maxweight=0; - for (int j=1;j<=_HIGHREScfweight.Nrows();j++){ - if(_HIGHREScfweight(j,k)>maxweight) - maxweight=_HIGHREScfweight(j,k); - } - AbsoluteWeights(k)=maxweight; - } + if (_verbosity) + cout << m_num_quartets << " cost_sum_unary " << cost_sum_unary << " cost_sum_pairwise " << cost_sum_pairwise << " cost_sum_triplet " << cost_sum_triplet << " cost_sum_quartet " << cost_sum_quartet << " total " << cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet << " m_num_triplets 2 " << m_num_triplets << endl; + return cost_sum_unary + cost_sum_pairwise + cost_sum_triplet + cost_sum_quartet; +} - ////////////////////////// resample to CPGRID ///////////////////////////////////// - R.resampledata(_SOURCE,_CPgrid,AbsoluteWeights,2*asin(MVDmax/RAD),_controlrel); +//====================================================================================================================// +double DiscreteCostFunction::evaluateUnaryCostSum(const int* labeling) +{ + double cost_sum_unary = 0.0f; + for (int i = 0; i < m_num_nodes; ++i) + cost_sum_unary += computeUnaryCost(i, labeling[i]); // unarycosts[labeling[i]*m_num_nodes+i]; + return cost_sum_unary; +} +//====================================================================================================================// +double DiscreteCostFunction::evaluatePairwiseCostSum(const int* labeling, const int* pairs) +{ + double cost_sum_pairwise = 0.0f; + for (int p = 0; p < m_num_pairs; ++p) { + const int index = p * 2; + cost_sum_pairwise += computePairwiseCost(p, labeling[pairs[index]], labeling[pairs[index + 1]]); + } + return cost_sum_pairwise; +} +//====================================================================================================================// +double DiscreteCostFunction::evaluateTripletCostSum(const int* labeling, const int* triplets) +{ + double cost_sum_triplet = 0.0f; + for (int t = 0; t < m_num_triplets; ++t) { + const int index = t * 3; + cost_sum_triplet += computeTripletCost(t, labeling[triplets[index]], labeling[triplets[index + 1]], labeling[triplets[index + 2]]); + } + return cost_sum_triplet; +} - } +//====================================================================================================================// +double DiscreteCostFunction::evaluateQuartetCostSum(const int* labeling, const int* quartets) +{ + double cost_sum_quartet = 0.0f; + for (int q = 0; q < m_num_quartets; ++q) { + const int index = q * 3; + cost_sum_quartet += computeQuartetCost(q, labeling[quartets[index]], labeling[quartets[index + 1]], labeling[quartets[index + 2]], labeling[quartets[index + 3]]); + } + return cost_sum_quartet; +} +//================================GENERIC SURFACE CLASS===========================================================================// +SRegDiscreteCostFunction::SRegDiscreteCostFunction() + : _simmeasure(2) +{ + _reglambda = 0; + _debug = false; + _MEANANGLE = 0; + _verbosity = false; + _outdir = ""; + _concat = false; + _sigma = 1; +} +//====================================================================================================================// +void SRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ - void NonLinearSRegDiscreteCostFunction::get_target_data(const int& node,const Matrix &PtROTATOR){//, const RELATIONS &cpneighbours - Pt v0,v1,v2,CP,tmp; - int n0,n1,n2; - int ind,sourceind; + if (_TARGET.nvertices() == 0 || _SOURCE.nvertices() == 0) { + throw DISCRETEOPTHOCRException("CostFunction::You must supply source and target meshes."); + } + // _AREALDIST.ReSize(_SOURCE.nvertices()); _AREALDIST=0.0; + if (_HIGHREScfweight.Ncols() != _SOURCE.nvertices()) + _HIGHREScfweight.ReSize(1, _SOURCE.nvertices()); + if (_HIGHREScfweight.Nrows() != 1 && _HIGHREScfweight.Nrows() != FEAT->get_dim()) { + throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: costfunction weighting has dimensions incompatible with data"); + } + DiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); +} - reset_target_data(node); - ind=-1; +void SRegDiscreteCostFunction::set_parameters(myparam& ALLPARAMS) +{ + myparam::iterator it; + it = ALLPARAMS.find("lambda"); + _reglambda = boost::get(it->second); + it = ALLPARAMS.find("range"); + _controlptrange = boost::get(it->second); + it = ALLPARAMS.find("CPres"); + _RES = boost::get(it->second); + it = ALLPARAMS.find("anatres"); + _aRES = boost::get(it->second); + it = ALLPARAMS.find("simmeasure"); + _simmeasure = boost::get(it->second); + sim.set_simval(_simmeasure); + it = ALLPARAMS.find("verbosity"); + _verbosity = boost::get(it->second); + it = ALLPARAMS.find("outdir"); + _outdir = boost::get(it->second); + it = ALLPARAMS.find("regularisermode"); + _rmode = boost::get(it->second); + it = ALLPARAMS.find("sigma_in"); + _sigma = boost::get(it->second); + it = ALLPARAMS.find("numthreads"); + _threads = boost::get(it->second); +} - for(unsigned int i=0;i<_sourceinrange[node-1].size();i++){ - sourceind=_sourceinrange[node-1][i]; +void SRegDiscreteCostFunction::initialize_regulariser() +{ - tmp=PtROTATOR*_SOURCE.get_coord(sourceind-1); + if (_aSOURCE.nvertices() > 0 && _rmode >= 3) { + anatMVD = 2 * asin(Calculate_MaxVD(_aICO) / RAD); + _anatrel.Initialize(_aICO, _TARGEThi, anatMVD); + } +} - get_data_index(node-1,sourceind-1,ind); +newmesh SRegDiscreteCostFunction::project_anatomical() +{ + newmesh TRANS; + newmesh _aICOtrans = _aICO; + barycentric_mesh_interpolation(_aICOtrans, _ORIG, _SOURCE); + TRANS = projectmesh(_aICOtrans, (_TARGEThi), (_aTARGET)); - vector< pair > NEIGHBOURS=_targetrel->update_RELATIONS_for_ind(tmp); + return TRANS; +} - if(!_TARGET.return_closest_points(NEIGHBOURS[0].second,v0,v1,v2,tmp,n0,n1,n2)){ +/// this is for debug - for (unsigned int s=1;s 0) { - } + _aSOURCEtrans = project_anatomical(); + MAXstrain = 0; - resample_target_data(v0,v1,v2,tmp,n0,n1,n2,ind); + for (int i = 0; i < _aSOURCE.ntriangles(); i++) { + strainstmp(i + 1) = calculate_triangular_strain(i, _aSOURCE, _aSOURCEtrans, _mu, _kappa); + if (strainstmp(i + 1) > MAXstrain) + MAXstrain = strainstmp(i + 1); + } + if (MAXstrain > 1e-8) { + Histogram strainHist(strainstmp, 256); - } + perc = strainHist.getPercentile(0.95); + } - } + if (iter == 1) + strain95 = perc; + } +} +//====================================================================================================================// +//================================AFFINE SURFACE CLASS===========================================================================// +//AffineSRegDiscreteCostFunction::AffineSRegDiscreteCostFunction() +// : _iters(50) +//{ +//} + +//====================================================================================================================// +//================================Non Linear SURFACE CLASS===========================================================================// +NonLinearSRegDiscreteCostFunction::NonLinearSRegDiscreteCostFunction() +{ + _expscaling = 1; + _k_exp = 2.0; + _maxdist = 4; + _rexp = 2; + _kNN = 5; + _rmode = 1; + _mu = 0.4; + _kappa = 1.6; +} - void NonLinearSRegDiscreteCostFunction::get_target_data(const int& triplet,const Pt& new_CP0,const Pt& new_CP1,const Pt& new_CP2){ - Pt v0,v1,v2,SP,tmp2,tmp; - Pt CP0,CP1,CP2; - int n0,n1,n2; - int ind,sourceind; +void NonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + ///// initialise CF weightings + SRegDiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); +} - reset_target_data(triplet); - ind=-1; +void NonLinearSRegDiscreteCostFunction::set_parameters(myparam& ALLPARAMS) +{ + myparam::iterator it; + it = ALLPARAMS.find("maxdistortion"); + _maxdist = boost::get(it->second); + it = ALLPARAMS.find("exponent"); + _rexp = boost::get(it->second); + it = ALLPARAMS.find("weight"); + _dweight = boost::get(it->second); + it = ALLPARAMS.find("anorm"); + _anorm = boost::get(it->second); + it = ALLPARAMS.find("scaling"); + _expscaling = boost::get(it->second); + it = ALLPARAMS.find("shearmodulus"); + _mu = boost::get(it->second); + it = ALLPARAMS.find("bulkmodulus"); + _kappa = boost::get(it->second); + it = ALLPARAMS.find("kexponent"); + _k_exp = boost::get(it->second); + + it = ALLPARAMS.find("kNN"); + _kNN = boost::get(it->second); + it = ALLPARAMS.find("pottsthreshold"); + _pottsthreshold = boost::get(it->second); + + SRegDiscreteCostFunction::set_parameters(ALLPARAMS); +} - CP0=_CPgrid.get_coord(_triplets[3*(triplet-1)]); - CP1=_CPgrid.get_coord(_triplets[3*(triplet-1)+1]); - CP2=_CPgrid.get_coord(_triplets[3*(triplet-1)+2]); +double NonLinearSRegDiscreteCostFunction::computeTripletCost(int triplet, int labelA, int labelB, int labelC) +{ + vector id; + Pt normal; + map v; + Pt v0, v1, v2; + double cost = 0; + double weight = 1.0; + double distortion = 1; + double likelihood = 0; ///////////// WILL ONLY BE ESTIMATED FOR HOCR method + char filename[1000]; - for(unsigned int i=0;i<_sourceinrange[triplet-1].size();i++){ - sourceind=_sourceinrange[triplet-1][i]; - SP=_SOURCE.get_coord(sourceind-1); - projectPoint(CP0,CP1,CP2,SP); - tmp= barycentric(CP0,CP1,CP2,SP,new_CP0,new_CP1,new_CP2); + map transformed_points; - tmp.normalize(); ////////// ASSUMING SPHERE"S ORIGIN IS 0,0,0 (which we can project from the face to the surface of the sphere this way - tmp=tmp*RAD; - get_data_index(triplet-1,sourceind-1,ind); + if (triplet == 0 && _debug) { + sumlikelihood = 0; + sumregcost = 0; + } + // sprintf(filename,"CPgridintrip-%d.surf",_iter); + // _CPgrid.save(filename) ; + // sprintf(filename,"SOURCEintrip-%d.surf",_iter); + + // _SOURCE.save("filename"); + //_SOURCE.save("SOURCEintrip.func"); } + if (!_triplets) { + throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: must run settripletss() prior to computTripleCost "); + } - vector< pair > NEIGHBOURS=_targetrel->update_RELATIONS_for_ind(tmp); + v0 = _CPgrid.get_coord(_triplets[3 * triplet]); + v1 = _CPgrid.get_coord(_triplets[3 * triplet + 1]); + v2 = _CPgrid.get_coord(_triplets[3 * triplet + 2]); + + id.push_back(_triplets[3 * triplet]); + id.push_back(_triplets[3 * triplet + 1]); + id.push_back(_triplets[3 * triplet + 2]); + + v[id[0]] = (*ROTATIONS)[id[0]] * _labels[labelA]; + v[id[1]] = (*ROTATIONS)[id[1]] * _labels[labelB]; + v[id[2]] = (*ROTATIONS)[id[2]] * _labels[labelC]; + + likelihood = triplet_likelihood(triplet, id[0], id[1], id[2], v[id[0]], v[id[1]], v[id[2]]); + + Triangle TRI(v[id[0]], v[id[1]], v[id[2]], 0); + + Triangle TRI_noDEF(v0, v1, v2, 0); + NEWMESH::Pt norm_new = TRI.normal(); + NEWMESH::Pt norm_old = TRI_noDEF.normal(); + /// only estimate cost if it doesn't cause folding + if ((norm_new | norm_old) < 0) { + cost = 1; + weight += 1e6; + //cout << triplet << " triplet fold " << labelA << " " << labelB << " " << labelC << endl; + } else { + + switch (_rmode) { + case 2: { + vector deformed_angles, orig_angles; + Pt o_v0, o_v1, o_v2; + double val = 0, tweight = 1; + double diff = 0; + Triangle TRI_ORIG; + + o_v0 = _ORIG.get_coord(_triplets[3 * triplet]); + o_v1 = _ORIG.get_coord(_triplets[3 * triplet + 1]); + o_v2 = _ORIG.get_coord(_triplets[3 * triplet + 2]); + TRI_ORIG.set(o_v0, o_v1, o_v2, 0); + deformed_angles = TRI.get_angles(); + orig_angles = TRI_ORIG.get_angles(); + distortion = log2(TRI.area() / TRI_ORIG.area()); + + if (_dweight && distortion != 1) { + tweight = exp(abs(distortion - 1)); + + } else { + tweight = 1; + } + + for (int i = 0; i < 3; i++) { + + val = deformed_angles[i] - orig_angles[i]; + diff += val * val; + } + + cost = tweight * (sqrt(diff)); + if (_anorm) { + weight *= (1 / _MEANANGLE); + } + + break; + } + case 3: { + + //// + Pt o_v0, o_v1, o_v2; + Triangle TRI_ORIG; + + o_v0 = _ORIG.get_coord(_triplets[3 * triplet]); + o_v1 = _ORIG.get_coord(_triplets[3 * triplet + 1]); + o_v2 = _ORIG.get_coord(_triplets[3 * triplet + 2]); + TRI_ORIG.set(o_v0, o_v1, o_v2, 0); + + cost = calculate_triangular_strain(TRI_ORIG, TRI, _mu, _kappa, boost::shared_ptr(), _k_exp); + // if(write) cout << triplet << " " << labelA << " " << labelB << " " << labelC << " " << cost << " (v0- v[id[0]]).norm() " << (v0- v[id[0]]).norm() << endl; + + break; + } + case 4: { + vector deformed_angles, orig_angles; + double val = 0; + double diff = 0; + double tweight = 1, distortion; + Triangle TRIorig, TRItrans; + map moved2; + map transformed_points; + + for (unsigned int n = 0; n < NEARESTFACES[triplet].size(); n++) { + + // for each face with each CP triangle + TRIorig = _aSOURCE.get_triangle(NEARESTFACES[triplet][n]); + TRItrans = deform_anatomy(triplet, n, v, moved2, transformed_points); + + deformed_angles = TRItrans.get_angles(); + orig_angles = TRIorig.get_angles(); + distortion = log2(TRItrans.area() / TRIorig.area()); + if (_dweight && distortion != 1) { + tweight = exp(abs(distortion - 1)); + + } else { + tweight = 1; + } + + for (int i = 0; i < 3; i++) { + + val = deformed_angles[i] - orig_angles[i]; + diff += val * val; + } + + diff = tweight * sqrt(diff); + cost += diff; + } + + cost = cost / NEARESTFACES[triplet].size(); + + break; + } + case 5: { + + Triangle TRIorig, TRItrans; + map moved2; + map transformed_points; + + for (unsigned int n = 0; n < NEARESTFACES[triplet].size(); n++) { + // for each face with each CP triangle + TRIorig = _aSOURCE.get_triangle(NEARESTFACES[triplet][n]); + TRItrans = deform_anatomy(triplet, n, v, moved2, transformed_points); + + cost += calculate_triangular_strain(TRIorig, TRItrans, _mu, _kappa, boost::shared_ptr(), _k_exp); + } + + cost = cost / NEARESTFACES[triplet].size(); + + break; + } + default: + throw DISCRETEOPTHOCRException("DiscreteModel computeTripletCost regoption does not exist"); + } + } + if (abs(cost) < 1e-8) { + cost = 0; + } + if (_debug) { + sumlikelihood += likelihood; + sumregcost += weight * _reglambda * MISCMATHS::pow(cost, _rexp); + } + cost = likelihood + weight * _reglambda * MISCMATHS::pow(cost, _rexp); - if(!_TARGET.return_closest_points(NEIGHBOURS[0].second,v0,v1,v2,tmp,n0,n1,n2)){ + return cost; // normalise to try and ensure equivalent lambda for each resolution level +} - for (unsigned int s=1;s EPSILON) { + for (vector::const_iterator j = _CPgrid.tIDbegin(_pairs[2 * pair]); j != _CPgrid.tIDend(_pairs[2 * pair]); j++) { + Triangle TRI_trans = _CPgrid.get_triangle(*j); + Triangle TRI_orig = _oCPgrid.get_triangle(*j); + Pt norm_orig = TRI_orig.normal(); + Pt norm_trans = TRI_trans.normal(); + if ((norm_orig | norm_trans) < 0) { + cost = 1; + weight += 1e6; + break; + } + // cout < ()); - _sourceinrange.clear(); _sourceinrange.resize(_CPgrid.nvertices(), vector ()); - _targetdata.clear(); _targetdata.resize(_CPgrid.nvertices(), vector ()); - _weights.clear(); _weights.resize(_CPgrid.nvertices(), vector ()); + if (_rexp == 1) + totalcost = weight * _reglambda * cost; + else + totalcost = weight * _reglambda * MISCMATHS::pow(cost, _rexp); + } - } + _CPgrid.set_coord(_pairs[2 * pair], v0); + _CPgrid.set_coord(_pairs[2 * pair + 1], v1); + return totalcost; +} - void UnivariateNonLinearSRegDiscreteCostFunction::get_source_data(){ //const RELATIONS &cpneighbours - // get source data - int sourceind,ind;//index; - double distance,weight; - ind=-1; +void NonLinearSRegDiscreteCostFunction::computePairwiseCosts(const int* pairs) +{ + int pair = 0; + Matrix fullrotA, fullrotB, fullrotA_2, fullrotB_2; + Matrix R1_B, R2_B, R_diff, logR, R_diff2, logR2; - for (unsigned int i=0;i<_sourcedata.size();i++) _sourcedata[i].clear(); - for (int k=1;k<=_sourcerel.Ncols();k++){ + while (pair < m_num_pairs) { + for (unsigned int j = 0; j < _labels.size(); j++) { - for(int i=1;i<=_sourcerel.Nrows(k);i++){ - sourceind=_sourcerel(i,k); - if(within_controlpt_range(k-1,sourceind-1,distance)){ + for (unsigned int k = 0; k < _labels.size(); k++) { - get_data_index(k-1,sourceind-1,ind); - _sourceinrange[k-1].push_back(sourceind); - for(int d=1;d<=FEAT->get_dim();d++){ - _sourcedata[ind].push_back(FEAT->get_input_val(d,sourceind)); - // cout << i << " " << k << " " << ind << " " << sourceind << " FEAT->get_input_val(d,sourceind) " << FEAT->get_input_val(d,sourceind) << " _sourcerel.Nrows(k) " << _sourcerel.Nrows(k) << endl; - if(_HIGHREScfweight.Nrows()>=d) weight=_HIGHREScfweight(d,sourceind); else weight=1; + paircosts[pair * m_num_labels * m_num_labels + k * m_num_labels + j] = computePairwiseCost(pair, j, k); + pairweights[pair * m_num_labels * m_num_labels + k * m_num_labels + j] = 1; + } + } + // coudl use wcosts to downweight points that have no intensity gradient + pair++; + } +} - _weights[ind].push_back(weight); - } - } - } +void NonLinearSRegDiscreteCostFunction::computeUnaryCosts() +{ + /// for each control point resample data into blocks each influencing a single control point + for (int j = 0; j < m_num_labels; j++) { - } - resample_weights(); + //// calculates similarity + for (int k = 0; k < _CPgrid.nvertices(); k++) { + unarycosts[j * m_num_nodes + k] = computeUnaryCost(k, j); + } + } +} +Triangle NonLinearSRegDiscreteCostFunction::deform_anatomy(const int& trip, const int& n, map& vertex, map& moved, map& transformed) +{ + Triangle TRItrans; - } + Pt newPt; + int tindex; + map weight; + for (int i = 0; i < 3; i++) { // for each point in face - double UnivariateNonLinearSRegDiscreteCostFunction::computeUnaryCost(int node, int label){ - Matrix ROT; - Pt newpt,CP; + tindex = _aSOURCE.get_triangle_vertexID(NEARESTFACES[trip][n], i); + if (moved.find(tindex) == moved.end()) { + moved[tindex] = true; + newPt.X = 0; + newPt.Y = 0; + newPt.Z = 0; + for (std::map::iterator it = _ANATbaryweights[tindex].begin(); it != _ANATbaryweights[tindex].end(); ++it) { - newpt=(*ROTATIONS)[node]*_labels[label]; // this rotates the label set over the control point - CP=_CPgrid.get_coord(node); - ROT=estimate_rotation_matrix(CP,newpt); // this Matrix will rotate control point k to the label - get_target_data(node+1,ROT); + newPt += vertex[it->first] * it->second; + } - double cost=AbsoluteWeights(node+1)*sim.get_sim_for_min(_sourcedata[node], _targetdata[node],_weights[node]);// weights similarity by cost function weighting + weight = R.get_barycentric_weight_for_ind(tindex, anatMVD, newPt, _TARGEThi, _anatrel); + newPt.X = 0; + newPt.Y = 0; + newPt.Z = 0; + for (std::map::iterator it = weight.begin(); it != weight.end(); ++it) { - if(_simmeasure==1 || _simmeasure==2) - return cost; - else - return -cost; - } + newPt += _aTARGET.get_coord(it->first) * it->second; + } + transformed[tindex] = newPt; - void UnivariateNonLinearSRegDiscreteCostFunction::resample_target_data(const Pt &v0, const Pt &v1, const Pt &v2, const Pt &tmp, const int &n0, const int &n1, const int &n2, int &index){ - for(int d=1;d<=FEAT->get_dim();d++){ - double targint=barycentric(v0,v1,v2,tmp,FEAT->get_ref_val(d,n0 + 1),FEAT->get_ref_val(d,n1 + 1),FEAT->get_ref_val(d,n2 + 1)); - _targetdata[index].push_back(targint); - } + TRItrans.set_vertice(i, newPt); + } else + TRItrans.set_vertice(i, transformed[tindex]); + } - } + return TRItrans; +} +void NonLinearSRegDiscreteCostFunction::resample_weights() +{ ///////// TAKE DATA TERM WEIGHTING AS MAXIMUM OF WEIGHTS ACROSS ALL DIMENSIONS ////////////// - //====================================================================================================================// - //================================Multivariate Non Linear SURFACE CLASS===========================================================================// + R.set_method("ADAP_BARY"); + double maxweight; + AbsoluteWeights.ReSize(_SOURCE.nvertices()); + AbsoluteWeights = 0; - void MultivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) - { - NonLinearSRegDiscreteCostFunction::initialize(numNodes, numLabels,numPairs,numTriplets,numQuartets); - _sourcedata.clear(); _sourcedata.resize(_SOURCE.nvertices(), vector ()); - _sourceinrange.clear(); _sourceinrange.resize(_CPgrid.nvertices(), vector ()); - _targetdata.clear(); _targetdata.resize(_SOURCE.nvertices(), vector ()); - _weights.clear(); _weights.resize(_SOURCE.nvertices(), vector ()); + for (int k = 1; k <= _SOURCE.nvertices(); k++) { - } + maxweight = 0; + for (int j = 1; j <= _HIGHREScfweight.Nrows(); j++) { + if (_HIGHREScfweight(j, k) > maxweight) + maxweight = _HIGHREScfweight(j, k); + } + AbsoluteWeights(k) = maxweight; + } - void MultivariateNonLinearSRegDiscreteCostFunction::get_source_data(){ - // get source data - double distance,weight; - int ind=0; - for (unsigned int i=0;i<_sourcedata.size();i++) _sourcedata[i].clear(); + ////////////////////////// resample to CPGRID ///////////////////////////////////// + R.resampledata(_SOURCE, _CPgrid, AbsoluteWeights, 2 * asin(MVDmax / RAD), _controlrel); +} - for (int k=0;k<_SOURCE.nvertices();k++){ +void NonLinearSRegDiscreteCostFunction::get_target_data(const int& node, const Matrix& PtROTATOR) +{ //, const RELATIONS &cpneighbours + Pt v0, v1, v2, CP, tmp; + int n0, n1, n2; + int ind, sourceind; - for (int j=1;j<=_controlrel->Nrows(k+1);j++){ - ind=(*_controlrel)(j,k+1); - if(within_controlpt_range(ind-1,k,distance)){ - _sourceinrange[ind-1].push_back(k+1); - } - } + reset_target_data(node); + ind = -1; - for(int d=1;d<=FEAT->get_dim();d++){ - _sourcedata[k].push_back(FEAT->get_input_val(d,k+1)); + for (unsigned int i = 0; i < _sourceinrange[node - 1].size(); i++) { + sourceind = _sourceinrange[node - 1][i]; - if(_HIGHREScfweight.Nrows()>=d) weight=_HIGHREScfweight(d,k+1); else weight=1; - _weights[k].push_back(weight); - } + tmp = PtROTATOR * _SOURCE.get_coord(sourceind - 1); - } + get_data_index(node - 1, sourceind - 1, ind); - resample_weights(); + vector> NEIGHBOURS = _targetrel->update_RELATIONS_for_ind(tmp); - } + if (!_TARGET.return_closest_points(NEIGHBOURS[0].second, v0, v1, v2, tmp, n0, n1, n2)) { + for (unsigned int s = 1; s < NEIGHBOURS.size(); s++) { - double MultivariateNonLinearSRegDiscreteCostFunction::computeUnaryCost(int node, int label){ - Matrix ROT; - Pt newpt,CP; - double cost =0; + if (_TARGET.return_closest_points(NEIGHBOURS[s].second, v0, v1, v2, tmp, n0, n1, n2)) { + break; + } + if (s == NEIGHBOURS.size() - 1) { + cout << ind << " can't find face intersections " + << " " << NEIGHBOURS[0].second << endl; + n0 = n1 = n2 = NEIGHBOURS[0].second; + } + } + } - newpt=(*ROTATIONS)[node]*_labels[label]; // this rotates the label set over the control point - CP=_CPgrid.get_coord(node); - ROT=estimate_rotation_matrix(CP,newpt); // this Matrix will rotate control point k to the label - get_target_data(node+1,ROT); + resample_target_data(v0, v1, v2, tmp, n0, n1, n2, ind); + } +} - for (unsigned int i=0;i< _sourceinrange[node].size();i++){ +void NonLinearSRegDiscreteCostFunction::get_target_data(const int& triplet, const Pt& new_CP0, const Pt& new_CP1, const Pt& new_CP2) +{ + Pt v0, v1, v2, SP, tmp2, tmp; + Pt CP0, CP1, CP2; + int n0, n1, n2; + int ind, sourceind; - cost+=sim.get_sim_for_min(_sourcedata[_sourceinrange[node][i]-1], _targetdata[_sourceinrange[node][i]-1],_weights[_sourceinrange[node][i]-1]);// weights similarity by cost function weighting + reset_target_data(triplet); + ind = -1; - } + CP0 = _CPgrid.get_coord(_triplets[3 * (triplet - 1)]); + CP1 = _CPgrid.get_coord(_triplets[3 * (triplet - 1) + 1]); + CP2 = _CPgrid.get_coord(_triplets[3 * (triplet - 1) + 2]); - if(_sourceinrange[node].size()>0) cost/=_sourceinrange[node].size(); + for (unsigned int i = 0; i < _sourceinrange[triplet - 1].size(); i++) { + sourceind = _sourceinrange[triplet - 1][i]; + SP = _SOURCE.get_coord(sourceind - 1); + projectPoint(CP0, CP1, CP2, SP); + tmp = barycentric(CP0, CP1, CP2, SP, new_CP0, new_CP1, new_CP2); - if(_simmeasure==1 || _simmeasure==2) - return AbsoluteWeights(node+1)*cost; - else - return -AbsoluteWeights(node+1)*cost; + tmp.normalize(); ////////// ASSUMING SPHERE"S ORIGIN IS 0,0,0 (which we can project from the face to the surface of the sphere this way + tmp = tmp * RAD; + get_data_index(triplet - 1, sourceind - 1, ind); - } + vector> NEIGHBOURS = _targetrel->update_RELATIONS_for_ind(tmp); + if (!_TARGET.return_closest_points(NEIGHBOURS[0].second, v0, v1, v2, tmp, n0, n1, n2)) { - void MultivariateNonLinearSRegDiscreteCostFunction::resample_target_data(const Pt &v0, const Pt &v1, const Pt &v2, const Pt &tmp, const int &n0, const int &n1, const int &n2, int &index){ + for (unsigned int s = 1; s < NEIGHBOURS.size(); s++) { - barycentric2(v0,v1,v2,tmp,n0+1,n1+1,n2+1,*FEAT->get_reference_data(),_targetdata[index]); + if (_TARGET.return_closest_points(NEIGHBOURS[s].second, v0, v1, v2, tmp, n0, n1, n2)) { + break; + } + if (s == NEIGHBOURS.size() - 1) { + cout << ind << " can't find face intersections " + << " " << NEIGHBOURS[0].second << endl; + n0 = n1 = n2 = NEIGHBOURS[0].second; + } + } + } - } + resample_target_data(v0, v1, v2, tmp, n0, n1, n2, ind); + } +} +//====================================================================================================================// +//================================ UNIVARIATE Non Linear SURFACE CLASS===========================================================================// +void UnivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + NonLinearSRegDiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); + _sourcedata.clear(); + _sourcedata.resize(_CPgrid.nvertices(), vector()); + _sourceinrange.clear(); + _sourceinrange.resize(_CPgrid.nvertices(), vector()); + _targetdata.clear(); + _targetdata.resize(_CPgrid.nvertices(), vector()); + _weights.clear(); + _weights.resize(_CPgrid.nvertices(), vector()); +} - void HOUnivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets,int numQuartets) - { - NonLinearSRegDiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); - _sourcedata.clear(); _sourcedata.resize(_CPgrid.ntriangles(), vector ()); - _sourceinrange.clear(); _sourceinrange.resize(_CPgrid.ntriangles(), vector ()); - _targetdata.clear(); _targetdata.resize(_CPgrid.ntriangles(), vector ()); - _weights.clear(); _weights.resize(_CPgrid.ntriangles(), vector ()); +void UnivariateNonLinearSRegDiscreteCostFunction::get_source_data() +{ //const RELATIONS &cpneighbours + // get source data + int sourceind, ind; //index; + double distance, weight; + ind = -1; + + for (unsigned int i = 0; i < _sourcedata.size(); i++) + _sourcedata[i].clear(); + for (int k = 1; k <= _sourcerel.Ncols(); k++) { + + for (int i = 1; i <= _sourcerel.Nrows(k); i++) { + sourceind = _sourcerel(i, k); + if (within_controlpt_range(k - 1, sourceind - 1, distance)) { + + get_data_index(k - 1, sourceind - 1, ind); + _sourceinrange[k - 1].push_back(sourceind); + for (int d = 1; d <= FEAT->get_dim(); d++) { + _sourcedata[ind].push_back(FEAT->get_input_val(d, sourceind)); + // cout << i << " " << k << " " << ind << " " << sourceind << " FEAT->get_input_val(d,sourceind) " << FEAT->get_input_val(d,sourceind) << " _sourcerel.Nrows(k) " << _sourcerel.Nrows(k) << endl; + if (_HIGHREScfweight.Nrows() >= d) + weight = _HIGHREScfweight(d, sourceind); + else + weight = 1; + + _weights[ind].push_back(weight); + } + } + } + } + resample_weights(); +} +double UnivariateNonLinearSRegDiscreteCostFunction::computeUnaryCost(int node, int label) +{ + Matrix ROT; + Pt newpt, CP; - } + newpt = (*ROTATIONS)[node] * _labels[label]; // this rotates the label set over the control point + CP = _CPgrid.get_coord(node); + ROT = estimate_rotation_matrix(CP, newpt); // this Matrix will rotate control point k to the label + get_target_data(node + 1, ROT); + double cost = AbsoluteWeights(node + 1) * sim.get_sim_for_min(_sourcedata[node], _targetdata[node], _weights[node]); // weights similarity by cost function weighting - void HOUnivariateNonLinearSRegDiscreteCostFunction::get_source_data(){ //const RELATIONS &cpneighbours - // get source data - int sourceind;//index; - double weight; - R.set_method("ADAP_BARY"); + if (_simmeasure == 1 || _simmeasure == 2) + return cost; + else + return -cost; +} - for (unsigned int i=0;i<_sourcedata.size();i++) _sourcedata[i].clear(); +void UnivariateNonLinearSRegDiscreteCostFunction::resample_target_data(const Pt& v0, const Pt& v1, const Pt& v2, const Pt& tmp, const int& n0, const int& n1, const int& n2, int& index) +{ + for (int d = 1; d <= FEAT->get_dim(); d++) { + double targint = barycentric(v0, v1, v2, tmp, FEAT->get_ref_val(d, n0 + 1), FEAT->get_ref_val(d, n1 + 1), FEAT->get_ref_val(d, n2 + 1)); + _targetdata[index].push_back(targint); + } +} - for (int k=1;k<=_sourcerel.Ncols();k++){ +//====================================================================================================================// +//================================Multivariate Non Linear SURFACE CLASS===========================================================================// + +void MultivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + NonLinearSRegDiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); + _sourcedata.clear(); + _sourcedata.resize(_SOURCE.nvertices(), vector()); + _sourceinrange.clear(); + _sourceinrange.resize(_CPgrid.nvertices(), vector()); + _targetdata.clear(); + _targetdata.resize(_SOURCE.nvertices(), vector()); + _weights.clear(); + _weights.resize(_SOURCE.nvertices(), vector()); +} +void MultivariateNonLinearSRegDiscreteCostFunction::get_source_data() +{ + // get source data + double distance, weight; + int ind = 0; + for (unsigned int i = 0; i < _sourcedata.size(); i++) + _sourcedata[i].clear(); + + for (int k = 0; k < _SOURCE.nvertices(); k++) { + + for (int j = 1; j <= _controlrel->Nrows(k + 1); j++) { + ind = (*_controlrel)(j, k + 1); + if (within_controlpt_range(ind - 1, k, distance)) { + _sourceinrange[ind - 1].push_back(k + 1); + } + } + + for (int d = 1; d <= FEAT->get_dim(); d++) { + _sourcedata[k].push_back(FEAT->get_input_val(d, k + 1)); + + if (_HIGHREScfweight.Nrows() >= d) + weight = _HIGHREScfweight(d, k + 1); + else + weight = 1; + _weights[k].push_back(weight); + } + } - for(int i=1;i<=_sourcerel.Nrows(k);i++){ - sourceind=_sourcerel(i,k); + resample_weights(); +} +double MultivariateNonLinearSRegDiscreteCostFunction::computeUnaryCost(int node, int label) +{ + Matrix ROT; + Pt newpt, CP; + double cost = 0; - _sourceinrange[k-1].push_back(sourceind); + newpt = (*ROTATIONS)[node] * _labels[label]; // this rotates the label set over the control point + CP = _CPgrid.get_coord(node); + ROT = estimate_rotation_matrix(CP, newpt); // this Matrix will rotate control point k to the label + get_target_data(node + 1, ROT); - for(int d=1;d<=FEAT->get_dim();d++){ - _sourcedata[k-1].push_back(FEAT->get_input_val(d,sourceind)); + for (unsigned int i = 0; i < _sourceinrange[node].size(); i++) { - if(_HIGHREScfweight.Nrows()>=d) weight=_HIGHREScfweight(d,sourceind); else weight=1; + cost += sim.get_sim_for_min(_sourcedata[_sourceinrange[node][i] - 1], _targetdata[_sourceinrange[node][i] - 1], _weights[_sourceinrange[node][i] - 1]); // weights similarity by cost function weighting + } - _weights[k-1].push_back(weight); - } - } + if (_sourceinrange[node].size() > 0) + cost /= _sourceinrange[node].size(); - } + if (_simmeasure == 1 || _simmeasure == 2) + return AbsoluteWeights(node + 1) * cost; + else + return -AbsoluteWeights(node + 1) * cost; +} +void MultivariateNonLinearSRegDiscreteCostFunction::resample_target_data(const Pt& v0, const Pt& v1, const Pt& v2, const Pt& tmp, const int& n0, const int& n1, const int& n2, int& index) +{ + barycentric2(v0, v1, v2, tmp, n0 + 1, n1 + 1, n2 + 1, *FEAT->get_reference_data(), _targetdata[index]); +} - resample_weights(); - } +void HOUnivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + NonLinearSRegDiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); + _sourcedata.clear(); + _sourcedata.resize(_CPgrid.ntriangles(), vector()); + _sourceinrange.clear(); + _sourceinrange.resize(_CPgrid.ntriangles(), vector()); + _targetdata.clear(); + _targetdata.resize(_CPgrid.ntriangles(), vector()); + _weights.clear(); + _weights.resize(_CPgrid.ntriangles(), vector()); +} - double HOUnivariateNonLinearSRegDiscreteCostFunction::triplet_likelihood(const int &triplet,const int & CP_id0,const int & CP_id1,const int &CP_id2,const Pt & CP_def0,const Pt &CP_def1,const Pt &CP_def2){ - get_target_data(triplet+1,CP_def0,CP_def1,CP_def2); +void HOUnivariateNonLinearSRegDiscreteCostFunction::get_source_data() +{ //const RELATIONS &cpneighbours + // get source data + int sourceind; //index; + double weight; + R.set_method("ADAP_BARY"); - double cost=(1.0/3)*(AbsoluteWeights(CP_id0+1)+AbsoluteWeights(CP_id1+1)+AbsoluteWeights(CP_id2+1))*sim.get_sim_for_min(_sourcedata[triplet], _targetdata[triplet],_weights[triplet]);// weights similarity by cost function weighting + for (unsigned int i = 0; i < _sourcedata.size(); i++) + _sourcedata[i].clear(); + for (int k = 1; k <= _sourcerel.Ncols(); k++) { - if(_simmeasure==1 || _simmeasure==2) - return cost; - else - return -cost; + for (int i = 1; i <= _sourcerel.Nrows(k); i++) { + sourceind = _sourcerel(i, k); - } + _sourceinrange[k - 1].push_back(sourceind); + for (int d = 1; d <= FEAT->get_dim(); d++) { + _sourcedata[k - 1].push_back(FEAT->get_input_val(d, sourceind)); - void HOMultivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes,int numLabels, int numPairs, int numTriplets, int numQuartets) - { - NonLinearSRegDiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); - _sourcedata.clear(); _sourcedata.resize(_SOURCE.nvertices(), vector ()); - _sourceinrange.clear(); _sourceinrange.resize(_CPgrid.ntriangles(), vector ()); - _targetdata.clear(); _targetdata.resize(_SOURCE.nvertices(), vector ()); - _weights.clear(); _weights.resize(_SOURCE.nvertices(), vector ()); + if (_HIGHREScfweight.Nrows() >= d) + weight = _HIGHREScfweight(d, sourceind); + else + weight = 1; + _weights[k - 1].push_back(weight); + } + } } - void HOMultivariateNonLinearSRegDiscreteCostFunction::get_source_data(){ - // get source data - double weight; + resample_weights(); +} - for (unsigned int i=0;i<_sourcedata.size();i++) _sourcedata[i].clear(); +double HOUnivariateNonLinearSRegDiscreteCostFunction::triplet_likelihood(const int& triplet, const int& CP_id0, const int& CP_id1, const int& CP_id2, const Pt& CP_def0, const Pt& CP_def1, const Pt& CP_def2) +{ + get_target_data(triplet + 1, CP_def0, CP_def1, CP_def2); - for (int k=1;k<=_sourcerel.Ncols();k++){ - for(int i=1;i<=_sourcerel.Nrows(k);i++){ - int sourceind=_sourcerel(i,k); - _sourceinrange[k-1].push_back(sourceind); - } - } + double cost = (1.0 / 3) * (AbsoluteWeights(CP_id0 + 1) + AbsoluteWeights(CP_id1 + 1) + AbsoluteWeights(CP_id2 + 1)) * sim.get_sim_for_min(_sourcedata[triplet], _targetdata[triplet], _weights[triplet]); // weights similarity by cost function weighting + if (_simmeasure == 1 || _simmeasure == 2) + return cost; + else + return -cost; +} - for (int k=0;k<_SOURCE.nvertices();k++){ - for(int d=1;d<=FEAT->get_dim();d++){ - _sourcedata[k].push_back(FEAT->get_input_val(d,k+1)); +void HOMultivariateNonLinearSRegDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + NonLinearSRegDiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); + _sourcedata.clear(); + _sourcedata.resize(_SOURCE.nvertices(), vector()); + _sourceinrange.clear(); + _sourceinrange.resize(_CPgrid.ntriangles(), vector()); + _targetdata.clear(); + _targetdata.resize(_SOURCE.nvertices(), vector()); + _weights.clear(); + _weights.resize(_SOURCE.nvertices(), vector()); +} - if(_HIGHREScfweight.Nrows()>=d) weight=_HIGHREScfweight(d,k+1); else weight=1; - _weights[k].push_back(weight); - } - } +void HOMultivariateNonLinearSRegDiscreteCostFunction::get_source_data() +{ + // get source data + double weight; - resample_weights(); + for (unsigned int i = 0; i < _sourcedata.size(); i++) + _sourcedata[i].clear(); + for (int k = 1; k <= _sourcerel.Ncols(); k++) { + for (int i = 1; i <= _sourcerel.Nrows(k); i++) { + int sourceind = _sourcerel(i, k); + _sourceinrange[k - 1].push_back(sourceind); + } } - double HOMultivariateNonLinearSRegDiscreteCostFunction::triplet_likelihood(const int &triplet,const int & CP_id0,const int & CP_id1,const int &CP_id2,const Pt & CP_def0,const Pt &CP_def1,const Pt &CP_def2){ - get_target_data(triplet+1,CP_def0,CP_def1,CP_def2); - double cost=0; + for (int k = 0; k < _SOURCE.nvertices(); k++) { + for (int d = 1; d <= FEAT->get_dim(); d++) { + _sourcedata[k].push_back(FEAT->get_input_val(d, k + 1)); - for (unsigned int i=0;i< _sourceinrange[triplet].size();i++){ - - cost+=sim.get_sim_for_min(_sourcedata[_sourceinrange[triplet][i]-1], _targetdata[_sourceinrange[triplet][i]-1],_weights[_sourceinrange[triplet][i]-1]); - } - if(_sourceinrange[triplet].size()>0) cost/=_sourceinrange[triplet].size(); - if(_simmeasure==1 || _simmeasure==2) - return (1.0/3)*(AbsoluteWeights(CP_id0+1)+AbsoluteWeights(CP_id1+1)+AbsoluteWeights(CP_id2+1))*(cost); - else - return -(1.0/3)*(AbsoluteWeights(CP_id0+1)+AbsoluteWeights(CP_id1+1)+AbsoluteWeights(CP_id2+1))*(cost); - - return cost; - } - - - RegularisationDiscreteCostFunction::RegularisationDiscreteCostFunction(double shear, double bulk, double exp) - { _rexp=exp; _mu=shear; _kappa=bulk;} - - void RegularisationDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) - { - DiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); - } - - double RegularisationDiscreteCostFunction::computeTripletRegularisation(int triplet, int labelA, int labelB, int labelC){ - vector id; - Pt normal; - vector v(_CPgrid.nvertices(), Pt()); - Pt v0,v1,v2; - double W; + if (_HIGHREScfweight.Nrows() >= d) + weight = _HIGHREScfweight(d, k + 1); + else + weight = 1; + _weights[k].push_back(weight); + } + } + resample_weights(); +} +double HOMultivariateNonLinearSRegDiscreteCostFunction::triplet_likelihood(const int& triplet, const int& CP_id0, const int& CP_id1, const int& CP_id2, const Pt& CP_def0, const Pt& CP_def1, const Pt& CP_def2) +{ + get_target_data(triplet + 1, CP_def0, CP_def1, CP_def2); + double cost = 0; + for (unsigned int i = 0; i < _sourceinrange[triplet].size(); i++) { - boost::shared_ptr strains; /// for debugging - //if(triplet==0){ sumlikelihood=0; sumregcost=0;} + cost += sim.get_sim_for_min(_sourcedata[_sourceinrange[triplet][i] - 1], _targetdata[_sourceinrange[triplet][i] - 1], _weights[_sourceinrange[triplet][i] - 1]); + } + if (_sourceinrange[triplet].size() > 0) + cost /= _sourceinrange[triplet].size(); + if (_simmeasure == 1 || _simmeasure == 2) + return (1.0 / 3) * (AbsoluteWeights(CP_id0 + 1) + AbsoluteWeights(CP_id1 + 1) + AbsoluteWeights(CP_id2 + 1)) * (cost); + else + return -(1.0 / 3) * (AbsoluteWeights(CP_id0 + 1) + AbsoluteWeights(CP_id1 + 1) + AbsoluteWeights(CP_id2 + 1)) * (cost); + + return cost; +} - if(_debug) strains=boost::shared_ptr(new ColumnVector (2)); - v0=_CPgrid.get_triangle_vertex(triplet,0); - v1=_CPgrid.get_triangle_vertex(triplet,1); - v2=_CPgrid.get_triangle_vertex(triplet,2); +RegularisationDiscreteCostFunction::RegularisationDiscreteCostFunction(double shear, double bulk, double exp) +{ + _rexp = exp; + _mu = shear; + _kappa = bulk; +} - id.push_back(_CPgrid.get_triangle_vertexID(triplet,0)); - id.push_back(_CPgrid.get_triangle_vertexID(triplet,1)); - id.push_back(_CPgrid.get_triangle_vertexID(triplet,2)); +void RegularisationDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ + DiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); +} +double RegularisationDiscreteCostFunction::computeTripletRegularisation(int triplet, int labelA, int labelB, int labelC) +{ + vector id; + Pt normal; + vector v(_CPgrid.nvertices(), Pt()); + Pt v0, v1, v2; + double W; - v[id[0]]=(*ROTATIONS)[id[0]]*_labels[labelA]; - v[id[1]]=(*ROTATIONS)[id[1]]*_labels[labelB]; - v[id[2]]=(*ROTATIONS)[id[2]]*_labels[labelC]; + boost::shared_ptr strains; /// for debugging + //if(triplet==0){ sumlikelihood=0; sumregcost=0;} - _SOURCE.set_coord(id[0],v[id[0]]); - _SOURCE.set_coord(id[1],v[id[1]]); - _SOURCE.set_coord(id[2],v[id[2]]); + if (_debug) + strains = boost::shared_ptr(new ColumnVector(2)); + v0 = _CPgrid.get_triangle_vertex(triplet, 0); + v1 = _CPgrid.get_triangle_vertex(triplet, 1); + v2 = _CPgrid.get_triangle_vertex(triplet, 2); - //cost=calculate_triangular_strain(TRI_ORIG, TRI, _mu, _kappa, boost::shared_ptr(), _k_exp); + id.push_back(_CPgrid.get_triangle_vertexID(triplet, 0)); + id.push_back(_CPgrid.get_triangle_vertexID(triplet, 1)); + id.push_back(_CPgrid.get_triangle_vertexID(triplet, 2)); - W=calculate_triangular_strain(triplet,_SOURCE,_CPgrid,_mu,_kappa,strains); -//W=calculate_triangular_strain(triplet,_ANAT,_SPHERE,_mu,_kappa,strains); - W=MISCMATHS::pow(W,_rexp); + v[id[0]] = (*ROTATIONS)[id[0]] * _labels[labelA]; + v[id[1]] = (*ROTATIONS)[id[1]] * _labels[labelB]; + v[id[2]] = (*ROTATIONS)[id[2]] * _labels[labelC]; + _SOURCE.set_coord(id[0], v[id[0]]); + _SOURCE.set_coord(id[1], v[id[1]]); + _SOURCE.set_coord(id[2], v[id[2]]); - _CPgrid.set_coord(id[0],v0); - _CPgrid.set_coord(id[1],v1); - _CPgrid.set_coord(id[2],v2); + //cost=calculate_triangular_strain(TRI_ORIG, TRI, _mu, _kappa, boost::shared_ptr(), _k_exp); + W = calculate_triangular_strain(triplet, _SOURCE, _CPgrid, _mu, _kappa, strains); + //W=calculate_triangular_strain(triplet,_ANAT,_SPHERE,_mu,_kappa,strains); + W = MISCMATHS::pow(W, _rexp); + _CPgrid.set_coord(id[0], v0); + _CPgrid.set_coord(id[1], v1); + _CPgrid.set_coord(id[2], v2); - //sumregcost+=W; + //sumregcost+=W; - return W; // normalise to try and ensure equivalent lambda for each resolution level - } + return W; // normalise to try and ensure equivalent lambda for each resolution level +} } diff --git a/src/DiscreteOpt/DiscreteGroupCostFunction.cpp b/src/DiscreteOpt/DiscreteGroupCostFunction.cpp index 7f6b19e..259371a 100644 --- a/src/DiscreteOpt/DiscreteGroupCostFunction.cpp +++ b/src/DiscreteOpt/DiscreteGroupCostFunction.cpp @@ -8,25 +8,32 @@ #include "DiscreteGroupCostFunction.h" #include -namespace DISCRETEOPTHOCR{ - - //====================================================================================================================// - //================================GroupSURFACE CLASS===========================================================================// - GroupDiscreteCostFunction::GroupDiscreteCostFunction() //: L1data(0) - { - _rexp=2; - _mu=0.1; _kappa=10; - _reglambda=0; _debug=false; _MEANANGLE=0; _verbosity=false; _outdir=""; _concat=false; - _lambdapairs=1; - VERTICES_PER_SUBJ=0; TRIPLETS_PER_SUBJ=0; +namespace DISCRETEOPTHOCR { + +//====================================================================================================================// +//================================GroupSURFACE CLASS===========================================================================// +GroupDiscreteCostFunction::GroupDiscreteCostFunction() //: L1data(0) +{ + _rexp = 2; + _mu = 0.1; + _kappa = 10; + _reglambda = 0; + _debug = false; + _MEANANGLE = 0; + _verbosity = false; + _outdir = ""; + _concat = false; + _lambdapairs = 1; + VERTICES_PER_SUBJ = 0; + TRIPLETS_PER_SUBJ = 0; /* if (!(eng = engOpen("matlab -nodisplay -nodesktop -nojvm"))){ cout << " eng not open " << endl; throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: Can't start MATLAB engine"); engSetVisible(eng, 0); } */ - } - /* +} +/* GroupDiscreteCostFunction::~GroupDiscreteCostFunction() { @@ -44,66 +51,82 @@ namespace DISCRETEOPTHOCR{ } */ - - void GroupDiscreteCostFunction::set_parameters(myparam & ALLPARAMS){ + +void GroupDiscreteCostFunction::set_parameters(myparam& ALLPARAMS) +{ myparam::iterator it; - - it=ALLPARAMS.find("lambda");_reglambda=boost::get(it->second); - it=ALLPARAMS.find("lambda_pairs");_lambdapairs=boost::get(it->second); - it=ALLPARAMS.find("set_lambda_pairs");_setpairs=boost::get(it->second); - it=ALLPARAMS.find("CPres");_RES=boost::get(it->second); - it=ALLPARAMS.find("simmeasure");_simmeasure=boost::get(it->second); sim.set_simval(_simmeasure); - it=ALLPARAMS.find("verbosity");_verbosity=boost::get(it->second); - it=ALLPARAMS.find("outdir");_outdir=boost::get(it->second); - it=ALLPARAMS.find("shearmodulus");_mu=boost::get(it->second); - it=ALLPARAMS.find("bulkmodulus");_kappa=boost::get(it->second); - it=ALLPARAMS.find("sigma_in");_sigma=boost::get(it->second); - it=ALLPARAMS.find("quartet");_quadcost=boost::get(it->second); + it = ALLPARAMS.find("lambda"); + _reglambda = boost::get(it->second); + it = ALLPARAMS.find("lambda_pairs"); + _lambdapairs = boost::get(it->second); + it = ALLPARAMS.find("set_lambda_pairs"); + _setpairs = boost::get(it->second); + it = ALLPARAMS.find("CPres"); + _RES = boost::get(it->second); + it = ALLPARAMS.find("simmeasure"); + _simmeasure = boost::get(it->second); + sim.set_simval(_simmeasure); + it = ALLPARAMS.find("verbosity"); + _verbosity = boost::get(it->second); + it = ALLPARAMS.find("outdir"); + _outdir = boost::get(it->second); + it = ALLPARAMS.find("shearmodulus"); + _mu = boost::get(it->second); + it = ALLPARAMS.find("bulkmodulus"); + _kappa = boost::get(it->second); + it = ALLPARAMS.find("sigma_in"); + _sigma = boost::get(it->second); + it = ALLPARAMS.find("quartet"); + _quadcost = boost::get(it->second); cout << " _reglambd " << _reglambda << " _lambdapairs " << _lambdapairs << " setpair " << _setpairs << endl; - } +} - void GroupDiscreteCostFunction::set_relations(const boost::shared_ptr &CONTROL,const boost::shared_ptr &TARG){ - _controlrel=CONTROL; _targetrel=TARG; - _sourcerel=_controlrel->invert_relationsTR( _CONTROLMESHES[0],_DATAMESHES[0]); - } +void GroupDiscreteCostFunction::set_relations(const boost::shared_ptr& CONTROL, const boost::shared_ptr& TARG) +{ + _controlrel = CONTROL; + _targetrel = TARG; + _sourcerel = _controlrel->invert_relationsTR(_CONTROLMESHES[0], _DATAMESHES[0]); +} - void GroupDiscreteCostFunction::get_spacings(){ +void GroupDiscreteCostFunction::get_spacings() +{ Pt CP; double dist; ColumnVector vMAXmvd(_CONTROLMESHES[0].nvertices()); SPACINGS.clear(); - for(int n=0; n::const_iterator it=_CONTROLMESHES[n].nbegin(k);it !=_CONTROLMESHES[n].nend(k);it++){ + for (int n = 0; n < num_subjects; n++) { + vMAXmvd = 0; + for (int k = 0; k < _CONTROLMESHES[n].nvertices(); k++) { - dist= 2*RAD*asin((CP-_CONTROLMESHES[n].get_coord(*it)).norm()/(2*RAD)); - + CP = _CONTROLMESHES[n].get_coord(k); + for (vector::const_iterator it = _CONTROLMESHES[n].nbegin(k); it != _CONTROLMESHES[n].nend(k); it++) { - if(dist > vMAXmvd(k+1)) - vMAXmvd(k+1)=dist; - - } - } - SPACINGS.push_back(vMAXmvd); - } + dist = 2 * RAD * asin((CP - _CONTROLMESHES[n].get_coord(*it)).norm() / (2 * RAD)); - } + if (dist > vMAXmvd(k + 1)) + vMAXmvd(k + 1) = dist; + } + } + SPACINGS.push_back(vMAXmvd); + } +} - void GroupDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets,int numQuartets) - { +void GroupDiscreteCostFunction::initialize(int numNodes, int numLabels, int numPairs, int numTriplets, int numQuartets) +{ cout << " GroupDiscreteCostFunction::initialize" << numQuartets << endl; - DiscreteCostFunction::initialize(numNodes,numLabels,numPairs,numTriplets,numQuartets); + DiscreteCostFunction::initialize(numNodes, numLabels, numPairs, numTriplets, numQuartets); ///////////////////// identify TEMPLATE grid cell that must be sampled from for each point ////////// - if(!_targetrel.get()) {throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must initialise RELATIONS in MODEL before running this function");} - if(_CONTROLMESHES.size()==0){throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must initialise meshes before running this function");} + if (!_targetrel.get()) { + throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must initialise RELATIONS in MODEL before running this function"); + } + if (_CONTROLMESHES.size() == 0) { + throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must initialise meshes before running this function"); + } define_template_patches(); resample_to_template(); @@ -111,53 +134,55 @@ namespace DISCRETEOPTHOCR{ resample_patches(); // L1data=0; - if(_quadcost==true && _setpairs==false){ _lambdapairs=(float)m_num_quartets/(float)m_num_pairs; cout << m_num_quartets << " true " << m_num_pairs << " " << (float)m_num_quartets/(float)m_num_pairs << endl;} - cout << " INIT " << _reglambda << " _lambdapairs " << _lambdapairs << " setpair " << _setpairs << endl; - - } - - void GroupDiscreteCostFunction::define_template_patches(){ /// make patches cover overlap with all between subject neighbours - int ind,mesh_ID,num; - vector > TOTALCELLS(m_num_nodes,vector ()); - vector > TEMPLATE_CELLS; + if (_quadcost == true && _setpairs == false) { + _lambdapairs = (float)m_num_quartets / (float)m_num_pairs; + cout << m_num_quartets << " true " << m_num_pairs << " " << (float)m_num_quartets / (float)m_num_pairs << endl; + } + cout << " INIT " << _reglambda << " _lambdapairs " << _lambdapairs << " setpair " << _setpairs << endl; +} + +void GroupDiscreteCostFunction::define_template_patches() +{ /// make patches cover overlap with all between subject neighbours + int ind, mesh_ID, num; + vector> TOTALCELLS(m_num_nodes, vector()); + vector> TEMPLATE_CELLS; vector PTS; char filename[1000]; TEMPLATEPTS.clear(); - cout <<" define_template_patches() " << endl; - if(!_pairs) {throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must set pairs before function");} - - for (int n=0;nreturn_cell_group(p,1.75*asin(MVD_LR/RAD))); - TEMPLATEPTS.push_back(vector()); - //cout << TEMPLATEPTS.size() << " " << TEMPLATEPTS[n].size() << endl; + cout << " define_template_patches() " << endl; + if (!_pairs) { + throw DISCRETEOPTHOCRException(" GroupDiscreteCostFunction::initialize must set pairs before function"); + } + for (int n = 0; n < m_num_nodes; n++) { //(int n=53;n<=53;n++){// + mesh_ID = floor(n / VERTICES_PER_SUBJ); + ind = n - mesh_ID * VERTICES_PER_SUBJ; + Pt p = _CONTROLMESHES[mesh_ID].get_coord(ind); + // cout << n << " mesh_ID " << mesh_ID << " *MVD_LR " << MVD_LR << " p.X " << p.X <<" p.Y " << p.Y <<" p.Z " << p.Z << endl; + TEMPLATE_CELLS.push_back(_targetrel->return_cell_group(p, 1.75 * asin(MVD_LR / RAD))); + TEMPLATEPTS.push_back(vector()); + //cout << TEMPLATEPTS.size() << " " << TEMPLATEPTS[n].size() << endl; } // exit(1); /////////////// make patch constant across all node pairs - for(int pair=0;pairget_cell_members(TOTALCELLS[n][i]); - TEMPLATEPTS[n].insert(TEMPLATEPTS[n].end(),PTS.begin(),PTS.end()); - // cout << i << " " << n << "PTS.size " << PTS.size() << "TEMPLATEPTS.size() " << TEMPLATEPTS.size() <get_cell_members(TOTALCELLS[n][i]); + TEMPLATEPTS[n].insert(TEMPLATEPTS[n].end(), PTS.begin(), PTS.end()); + // cout << i << " " << n << "PTS.size " << PTS.size() << "TEMPLATEPTS.size() " << TEMPLATEPTS.size() <update_RELATIONS(_DATAMESHES[n]); - RESAMPLEDDATA.push_back(FEAT->get_data_matrix(n)); - R.resampledata(_DATAMESHES[n],_TEMPLATE,RESAMPLEDDATA[n],0.0,_targetrel); - //sprintf(filename,"dataresampledtotemplate-%d-res%d-iter%d.func.gii",n,_RES,_iter); - //_TEMPLATE.set_pvalues(RESAMPLEDDATA[n]);_TEMPLATE.save(filename); - // sprintf(filename,"DATAMESHES-n%d-res%d-iter%d.surf.gii",n,_RES,_iter);_DATAMESHES[n].save(filename); + for (int n = 0; n < num_subjects; n++) { + _targetrel->update_RELATIONS(_DATAMESHES[n]); + RESAMPLEDDATA.push_back(FEAT->get_data_matrix(n)); + R.resampledata(_DATAMESHES[n], _TEMPLATE, RESAMPLEDDATA[n], 0.0, _targetrel); + //sprintf(filename,"dataresampledtotemplate-%d-res%d-iter%d.func.gii",n,_RES,_iter); + //_TEMPLATE.set_pvalues(RESAMPLEDDATA[n]);_TEMPLATE.save(filename); + // sprintf(filename,"DATAMESHES-n%d-res%d-iter%d.surf.gii",n,_RES,_iter);_DATAMESHES[n].save(filename); } - - } +} - //rpca version - /* double GroupDiscreteCostFunction::computeQuartetCost(int quartet, int labelA, int labelB, int labelC,int labelD){ +//rpca version +/* double GroupDiscreteCostFunction::computeQuartetCost(int quartet, int labelA, int labelB, int labelC,int labelD){ double cost=0; vector indices(4,0); vector rows; @@ -267,95 +287,99 @@ namespace DISCRETEOPTHOCR{ } */ - // pca version - double GroupDiscreteCostFunction::computeQuartetCost(int quartet, int labelA, int labelB, int labelC,int labelD){ - double cost=0; - vector indices(4,0); +// pca version +double GroupDiscreteCostFunction::computeQuartetCost(int quartet, int labelA, int labelB, int labelC, int labelD) +{ + double cost = 0; + vector indices(4, 0); vector rows; - int mesh_ID, index=0; - map testsubjects; + int mesh_ID, index = 0; + map testsubjects; // ofstream out; out.open("rows.txt"); bool found; - indices[0]=labelA+_quartets[4*quartet]*_labels.size(); - indices[1]=labelB+_quartets[4*quartet+1]*_labels.size(); - indices[2]=labelC+_quartets[4*quartet+2]*_labels.size(); - indices[3]=labelD+_quartets[4*quartet+3]*_labels.size(); + indices[0] = labelA + _quartets[4 * quartet] * _labels.size(); + indices[1] = labelB + _quartets[4 * quartet + 1] * _labels.size(); + indices[2] = labelC + _quartets[4 * quartet + 2] * _labels.size(); + indices[3] = labelD + _quartets[4 * quartet + 3] * _labels.size(); // if(quartet%10==0) cout << quartet << " computeQuartetCost " << labelA << " " << labelB << " " << labelC << " " << labelD << " num_quartets/num_pairs " << ((float)m_num_quartets/(float)m_num_pairs) << endl; - for(int i=0;i<4;i++){ - mesh_ID=floor(_quartets[4*quartet+i]/VERTICES_PER_SUBJ); - testsubjects[mesh_ID]=indices[i]; - // cout << i << " meshID "<< mesh_ID << " index " << indices[i] << " patch size " << PATCHDATA[indices[i]].size() << endl; + for (int i = 0; i < 4; i++) { + mesh_ID = floor(_quartets[4 * quartet + i] / VERTICES_PER_SUBJ); + testsubjects[mesh_ID] = indices[i]; + // cout << i << " meshID "<< mesh_ID << " index " << indices[i] << " patch size " << PATCHDATA[indices[i]].size() << endl; } - for (map::const_iterator iter = PATCHDATA[indices[0]].begin(); iter != PATCHDATA[indices[0]].end(); ++iter){ - found=true; - for(int i=1;i<4;i++){ - if(PATCHDATA[indices[i]].find(iter->first) == PATCHDATA[indices[i]].end()){ - found=false; - } - } - if(found){ rows.push_back(iter->first); - // out << iter->first << endl; - } + for (map::const_iterator iter = PATCHDATA[indices[0]].begin(); iter != PATCHDATA[indices[0]].end(); ++iter) { + found = true; + for (int i = 1; i < 4; i++) { + if (PATCHDATA[indices[i]].find(iter->first) == PATCHDATA[indices[i]].end()) { + found = false; + } + } + if (found) { + rows.push_back(iter->first); + // out << iter->first << endl; + } } - - Matrix Groupdata(rows.size(),num_subjects); Groupdata=0; + + Matrix Groupdata(rows.size(), num_subjects); + Groupdata = 0; // L1data = new double[num_subjects]; // cout << " estimate PCA " << rows.size() << endl; - if(rows.size()>0){ - for(int n=0;nsecond << endl; - Groupdata(r+1,n+1)=PATCHDATA[testsubjects[n]].find(rows[r])->second; - }else{ - Groupdata(r+1,n+1)=RESAMPLEDDATA[n](1,rows[r]+1); - } - // outdata(r+1,n+1)=L1data[n][r] ; - } - - } - - DiagonalMatrix eigenvals; - SVD(Groupdata,eigenvals); - - for(int i=1;i<=eigenvals.Nrows(); i++){ - cost+=eigenvals(i); - //if(quartet%10==0 && labelA==0 && labelB==0 && labelC==0 && labelD==0) cout << quartet << " i " << i << " eigenvals(i) " << eigenvals(i) << " " << cost << " rows.size() " << rows.size() << endl; - } - //cost/=rows.size(); - }else cost=MAXSIM; - return _lambdapairs*cost; - } - double GroupDiscreteCostFunction::computeTripletCost(int triplet, int labelA, int labelB, int labelC){ - double cost,weight=1; + if (rows.size() > 0) { + for (int n = 0; n < num_subjects; n++) { + + for (int r = 0; r < rows.size(); r++) { + //// first add all the test subjects then add remaining subjects? + if (testsubjects.find(n) != testsubjects.end()) { + // if(r==0) cout <second << endl; + Groupdata(r + 1, n + 1) = PATCHDATA[testsubjects[n]].find(rows[r])->second; + } else { + Groupdata(r + 1, n + 1) = RESAMPLEDDATA[n](1, rows[r] + 1); + } + // outdata(r+1,n+1)=L1data[n][r] ; + } + } + + DiagonalMatrix eigenvals; + SVD(Groupdata, eigenvals); + + for (int i = 1; i <= eigenvals.Nrows(); i++) { + cost += eigenvals(i); + //if(quartet%10==0 && labelA==0 && labelB==0 && labelC==0 && labelD==0) cout << quartet << " i " << i << " eigenvals(i) " << eigenvals(i) << " " << cost << " rows.size() " << rows.size() << endl; + } + //cost/=rows.size(); + } else + cost = MAXSIM; + return _lambdapairs * cost; +} +double GroupDiscreteCostFunction::computeTripletCost(int triplet, int labelA, int labelB, int labelC) +{ + double cost, weight = 1; int meshID; - Pt v0,v1,v2; - Pt n_v0,n_v1,n_v2; + Pt v0, v1, v2; + Pt n_v0, n_v1, n_v2; vector id; - Pt o_v0,o_v1,o_v2; - int m0,m1,m2; + Pt o_v0, o_v1, o_v2; + int m0, m1, m2; // cout << triplet << " in compute triplet " << TRIPLETS_PER_SUBJ << endl; /////////// GET VERTICES AND INDICES FOR THIS MESH - meshID=floor(triplet/TRIPLETS_PER_SUBJ); - m0=_triplets[3*triplet]-meshID*VERTICES_PER_SUBJ; - m1=_triplets[3*triplet+1]-meshID*VERTICES_PER_SUBJ; - m2=_triplets[3*triplet+2]-meshID*VERTICES_PER_SUBJ; + meshID = floor(triplet / TRIPLETS_PER_SUBJ); + m0 = _triplets[3 * triplet] - meshID * VERTICES_PER_SUBJ; + m1 = _triplets[3 * triplet + 1] - meshID * VERTICES_PER_SUBJ; + m2 = _triplets[3 * triplet + 2] - meshID * VERTICES_PER_SUBJ; // cout << m0 << " " << m1 << " " << m2 << " num_triplets " << m_num_triplets << " meshID " << meshID << " triplet 1 " << _triplets[3*triplet] << " " << _triplets[3*triplet+1] << " " << _triplets[3*triplet+2] << " labelA " << labelA << " " << labelB << " " << labelC << "_labels.szie() " << _labels.size() << endl; - v0=_CONTROLMESHES[meshID].get_coord(m0); - v1=_CONTROLMESHES[meshID].get_coord(m1); - v2=_CONTROLMESHES[meshID].get_coord(m2); - - o_v0=_ORIG.get_coord(m0); - o_v1=_ORIG.get_coord(m1); - o_v2=_ORIG.get_coord(m2); - + v0 = _CONTROLMESHES[meshID].get_coord(m0); + v1 = _CONTROLMESHES[meshID].get_coord(m1); + v2 = _CONTROLMESHES[meshID].get_coord(m2); + + o_v0 = _ORIG.get_coord(m0); + o_v1 = _ORIG.get_coord(m1); + o_v2 = _ORIG.get_coord(m2); + //id.push_back(_triplets[3*triplet]); //id.push_back(_triplets[3*triplet+1]); //id.push_back(_triplets[3*triplet+2]); @@ -363,61 +387,60 @@ namespace DISCRETEOPTHOCR{ //cout << "v0.X " << v0.X << " " << v0.Y << " " << v0.Z << " " << "v1.X " << v1.X << " " << v1.Y << " " << v1.Z << " " << "v0.X " << v2.X << " " << v2.Y << " " << v2.Z << " " << endl; //cout << "o_v0.X " << o_v0.X << " " << o_v0.Y << " " << o_v0.Z << " " <<"o_v1.X " << o_v1.X << " " << o_v1.Y << " " << o_v1.Z << " " <<"o_v2.X " << o_v2.X << " " << o_v2.Y << " " << o_v2.Z << " " << endl; - n_v0=(*ROTATIONS)[_triplets[3*triplet]]*_labels[labelA]; - n_v1=(*ROTATIONS)[_triplets[3*triplet+1]]*_labels[labelB]; - n_v2=(*ROTATIONS)[_triplets[3*triplet+2]]*_labels[labelC]; + n_v0 = (*ROTATIONS)[_triplets[3 * triplet]] * _labels[labelA]; + n_v1 = (*ROTATIONS)[_triplets[3 * triplet + 1]] * _labels[labelB]; + n_v2 = (*ROTATIONS)[_triplets[3 * triplet + 2]] * _labels[labelC]; // cout << " n_v0.X " << n_v0.X << " " << n_v0.Y << " " << n_v0.Z << " " << n_v1.X << " " << n_v1.Y << " " << n_v1.Z << " " << n_v2.X << " " <size() << endl; - + //cout << (*ROTATIONS)[_triplets[3*triplet]] << endl; //cout << (*ROTATIONS)[_triplets[3*triplet+1]] << endl; //cout << (*ROTATIONS)[_triplets[3*triplet+2]] << endl; //////////ESTIMATE STRAIN REGULARISATION ///////////// - Triangle TRI(n_v0,n_v1,n_v2,0); - Triangle TRI_ORIG(o_v0,o_v1,o_v2,0); - Triangle TRI_noDEF(v0,v1,v2,0); + Triangle TRI(n_v0, n_v1, n_v2, 0); + Triangle TRI_ORIG(o_v0, o_v1, o_v2, 0); + Triangle TRI_noDEF(v0, v1, v2, 0); - NEWMESH::Pt norm_new= TRI.normal(); + NEWMESH::Pt norm_new = TRI.normal(); NEWMESH::Pt norm_old = TRI_noDEF.normal(); - - if((norm_new|norm_old) < 0){ weight+=1e6 ; } + if ((norm_new | norm_old) < 0) { + weight += 1e6; + } - cost=weight*_reglambda*MISCMATHS::pow(calculate_triangular_strain(TRI_ORIG,TRI,_mu,_kappa),_rexp); + cost = weight * _reglambda * MISCMATHS::pow(calculate_triangular_strain(TRI_ORIG, TRI, _mu, _kappa), _rexp); // cout << weight << " cost " << cost << " mu " << _mu << " kappa " << _kappa <<" labelA " << labelA << " " << labelB << " " << labelC << "_labels.szie() " << endl; - - return cost; // normalise to try and ensure equivalent lambda for each resolution level - } + return cost; // normalise to try and ensure equivalent lambda for each resolution level +} - double GroupDiscreteCostFunction::computePairwiseCost(int pair, int labelA, int labelB){ +double GroupDiscreteCostFunction::computePairwiseCost(int pair, int labelA, int labelB) +{ ///// first set template sample grid to be within fixed range or p and q double cost; - int index1,index2; - Pt newpt,CP; + int index1, index2; + Pt newpt, CP; - cost=MAXSIM; + cost = MAXSIM; ////////////// Get template patch - - int ind1=0, ind2=162; - - index1=labelA+_pairs[2*pair]*_labels.size(); - index2=labelB +_pairs[2*pair+1]*_labels.size(); - - - if(PATCHDATA[index1].size()>0 && PATCHDATA[index1].size()>0){ - cost=sim.corr(PATCHDATA[index1],PATCHDATA[index2]); + + int ind1 = 0, ind2 = 162; + + index1 = labelA + _pairs[2 * pair] * _labels.size(); + index2 = labelB + _pairs[2 * pair + 1] * _labels.size(); + + if (PATCHDATA[index1].size() > 0 && PATCHDATA[index1].size() > 0) { + cost = sim.corr(PATCHDATA[index1], PATCHDATA[index2]); } - - if(cost==MAXSIM || cost!=cost){ - cout << " pairwise cost " << cost << " MAXSIM " << MAXSIM << " PATCHDATA[index1].size( " << PATCHDATA[index1].size() << " " << PATCHDATA[index2].size() << " pair " << pair << " labelA " << labelA << " " << labelB << " _pairs[2*pair] " << _pairs[2*pair] << " " << _pairs[2*pair+1] << " index1 " << index1 << " index2 " << index2 << endl; + if (cost == MAXSIM || cost != cost) { + cout << " pairwise cost " << cost << " MAXSIM " << MAXSIM << " PATCHDATA[index1].size( " << PATCHDATA[index1].size() << " " << PATCHDATA[index2].size() << " pair " << pair << " labelA " << labelA << " " << labelB << " _pairs[2*pair] " << _pairs[2 * pair] << " " << _pairs[2 * pair + 1] << " index1 " << index1 << " index2 " << index2 << endl; } - + /* if(pair<10){ // sprintf(filename,"sourceresampled-%d.surf.gii",ID); //newsource.save(filename); @@ -438,163 +461,165 @@ namespace DISCRETEOPTHOCR{ } */ return cost; - } +} - void GroupDiscreteCostFunction::resample_patches(){ +void GroupDiscreteCostFunction::resample_patches() +{ ///// first set template sample grid to be within fixed range or p and q double cost; int mesh_ID; int node; double dist; - map nodedata; + map nodedata; int labnum; int num; - vector withinCPrange(m_num_nodes*_labels.size(),false); - - cost=MAXSIM; + vector withinCPrange(m_num_nodes * _labels.size(), false); + + cost = MAXSIM; PATCHDATA.clear(); - + ////////////// Get template patch - - - for (int n=0;n()); - - dist=(_labels[lab]-_labels[0]).norm(); - if(dist <= 0.5*SPACINGS[mesh_ID](node+1)) - withinCPrange[lab+n*_labels.size()]=true; - } + for (int n = 0; n < m_num_nodes; n++) { + mesh_ID = floor(n / VERTICES_PER_SUBJ); + node = n - mesh_ID * VERTICES_PER_SUBJ; + for (int lab = 0; lab < _labels.size(); lab++) { + PATCHDATA.push_back(map()); + + dist = (_labels[lab] - _labels[0]).norm(); + if (dist <= 0.5 * SPACINGS[mesh_ID](node + 1)) + withinCPrange[lab + n * _labels.size()] = true; + } } // boost::thread_group group; //for (int i = 0; i <_threads; ++i) // group.create_thread(boost::bind(&GroupDiscreteCostFunction::resampler_worker_function, this,0,m_num_nodes*_labels.size(),withinCPrange)); - resampler_worker_function(0,m_num_nodes*_labels.size(),withinCPrange); - - } + resampler_worker_function(0, m_num_nodes * _labels.size(), withinCPrange); +} - void GroupDiscreteCostFunction::resampler_worker_function(const int &begin, const int &end,const vector &INrange){ +void GroupDiscreteCostFunction::resampler_worker_function(const int& begin, const int& end, const vector& INrange) +{ int mesh_ID; - int node,num; + int node, num; int labnum; Pt CP, newpt; - for (int n=begin;n 0.5*SPACINGS[meshID](node+1) " << endl; } - if(n%1000==0) cout << " resample patch: " << n << " " << labnum << " " << PATCHDATA[labnum+num*_labels.size()].size() << endl; + CP = _CONTROLMESHES[mesh_ID].get_coord(node); + newpt = (*ROTATIONS)[num] * _labels[labnum]; // this rotates the label set over the control point - } - } + if (INrange[labnum + num * _labels.size()] == true) { - map GroupDiscreteCostFunction::resample_onto_template(const int &node,const int &ID, const Pt &newCP,const vector &PTS){//, const RELATIONS - map sampledata; - map weights; - double g_weight,dist; - int sourceind, id0,id1,id2; - Pt tmp,SP; - Pt CP0,CP1,CP2; - Pt newCP0,newCP1,newCP2; - - char filename[1000]; - int trind=0; - bool _print=false; + //// move source mesh according to label rotation and resample on template - - for(int i=0;i< PTS.size();i++){ - sampledata[PTS[i]]=0; - weights[PTS[i]]=0; - } + cout << " lab+num*_labels.size() " << labnum + num * _labels.size() << " PATCHDATA size " << PATCHDATA.size() << endl; + PATCHDATA[labnum + num * _labels.size()] = resample_onto_template(node, mesh_ID, newpt, TEMPLATEPTS[num]); - - //cout << node << "_sourcerel " << _sourcerel.Ncols()<< " CP norm " << newCP.norm() << endl; + } else { + cout << " (newpt-CP).norm() > 0.5*SPACINGS[meshID](node+1) " << endl; + } + if (n % 1000 == 0) + cout << " resample patch: " << n << " " << labnum << " " << PATCHDATA[labnum + num * _labels.size()].size() << endl; + } +} + +map GroupDiscreteCostFunction::resample_onto_template(const int& node, const int& ID, const Pt& newCP, const vector& PTS) +{ //, const RELATIONS + map sampledata; + map weights; + double g_weight, dist; + int sourceind, id0, id1, id2; + Pt tmp, SP; + Pt CP0, CP1, CP2; + Pt newCP0, newCP1, newCP2; - for (vector::const_iterator j =_CONTROLMESHES[ID].tIDbegin(node); j!=_CONTROLMESHES[ID].tIDend(node); j++){ - trind++; - NEWMESH::Triangle tri=_CONTROLMESHES[ID].get_triangle(*j); - CP0 = tri.get_vertex_coord(0); CP1 = tri.get_vertex_coord(1); CP2 = tri.get_vertex_coord(2); - id0=tri.get_vertex_no(0); id1=tri.get_vertex_no(1); id2=tri.get_vertex_no(2); - - if(id0==node){ - newCP0=newCP; newCP1=CP1;newCP2=CP2; - } - else if(id1==node){ - newCP0=CP0; newCP1=newCP;newCP2=CP2; + char filename[1000]; + int trind = 0; + bool _print = false; - }else if(id2==node){ - newCP0=CP0; newCP1=CP1;newCP2=newCP; + for (int i = 0; i < PTS.size(); i++) { + sampledata[PTS[i]] = 0; + weights[PTS[i]] = 0; + } - }else{cout << node << " triangle node not found " << " id0" << id0 << " " << id1 << " " << id2 << endl; exit(1);} - - for(int i=1;i<=_sourcerel.Nrows(*j+1);i++){ - sourceind=_sourcerel(i,*j+1); - ///// move source using barycentric interpolation - SP=_DATAMESHES[ID].get_coord(sourceind-1); - projectPoint(CP0,CP1,CP2,SP); - tmp= barycentric(CP0,CP1,CP2,SP,newCP0,newCP1,newCP2); - - tmp.normalize(); ////////// ASSUMING SPHERE"S ORIGIN IS 0,0,0 (which we can project from the face to the surface of the sphere this way - tmp=tmp*RAD; - + //cout << node << "_sourcerel " << _sourcerel.Ncols()<< " CP norm " << newCP.norm() << endl; - /*if(_debug && _print){ + for (vector::const_iterator j = _CONTROLMESHES[ID].tIDbegin(node); j != _CONTROLMESHES[ID].tIDend(node); j++) { + trind++; + NEWMESH::Triangle tri = _CONTROLMESHES[ID].get_triangle(*j); + CP0 = tri.get_vertex_coord(0); + CP1 = tri.get_vertex_coord(1); + CP2 = tri.get_vertex_coord(2); + id0 = tri.get_vertex_no(0); + id1 = tri.get_vertex_no(1); + id2 = tri.get_vertex_no(2); + + if (id0 == node) { + newCP0 = newCP; + newCP1 = CP1; + newCP2 = CP2; + } else if (id1 == node) { + newCP0 = CP0; + newCP1 = newCP; + newCP2 = CP2; + + } else if (id2 == node) { + newCP0 = CP0; + newCP1 = CP1; + newCP2 = newCP; + + } else { + cout << node << " triangle node not found " + << " id0" << id0 << " " << id1 << " " << id2 << endl; + exit(1); + } + + for (int i = 1; i <= _sourcerel.Nrows(*j + 1); i++) { + sourceind = _sourcerel(i, *j + 1); + ///// move source using barycentric interpolation + SP = _DATAMESHES[ID].get_coord(sourceind - 1); + projectPoint(CP0, CP1, CP2, SP); + tmp = barycentric(CP0, CP1, CP2, SP, newCP0, newCP1, newCP2); + + tmp.normalize(); ////////// ASSUMING SPHERE"S ORIGIN IS 0,0,0 (which we can project from the face to the surface of the sphere this way + tmp = tmp * RAD; + + /*if(_debug && _print){ if(ID==0 && trind==1 && i==1 ){ // || i%10 ==0 cout << node << " " << i << " ID " << ID << " _sourcerel.Nrows(k) " << _sourcerel.Nrows(*j+1) << "sourcept.X " < > NEIGHBOURS=_targetrel->update_RELATIONS_for_ind(tmp); - // if(_RES==2 && node==0) cout << " neighbours.size() " << NEIGHBOURS.size() << " " << _sigma << endl; - for (int s=0;sget_data_val(1,sourceind,ID); - weights[NEIGHBOURS[s].second]+=g_weight; - } - } + ////////////// resample onto template using gaussian + vector> NEIGHBOURS = _targetrel->update_RELATIONS_for_ind(tmp); + // if(_RES==2 && node==0) cout << " neighbours.size() " << NEIGHBOURS.size() << " " << _sigma << endl; + for (int s = 0; s < NEIGHBOURS.size(); s++) { + dist = (tmp - _TEMPLATE.get_coord(NEIGHBOURS[s].second)).norm(); + g_weight = exp(-(dist * dist) / (2 * _sigma * _sigma)); + // if(_RES==3 && s<5 && node==0) cout << node << " ID " << ID << " g_weight " << g_weight << " dist " << dist << endl; + + sampledata[NEIGHBOURS[s].second] += g_weight * FEAT->get_data_val(1, sourceind, ID); + weights[NEIGHBOURS[s].second] += g_weight; + } + } } - for(int i=0;i #include +namespace DISCRETEOPTHOCR { + +///////////// BETWEEN MESH SIMILARITY IS EITHER PAIRIWISE (simple model) OR QUADS + +void GroupDiscreteModel::initialize_pairs() +{ + + m_num_pairs = 0; + for (int n = 0; n < m_num_subjects; n++) { + for (int i = 0; i < m_CONTROLMESHES[n].nvertices(); i++) { + for (int n2 = 0; n2 < m_num_subjects; n2++) { + if (n2 > n) { + m_num_pairs++; + } + } + } + } +} -namespace DISCRETEOPTHOCR{ - - - ///////////// BETWEEN MESH SIMILARITY IS EITHER PAIRIWISE (simple model) OR QUADS +void GroupDiscreteModel::initialize_quartets() +{ - void GroupDiscreteModel::initialize_pairs(){ - - m_num_pairs=0; - for(int n=0;nn){ - m_num_pairs++; - } - } - } - } + m_num_quartets = 0; /// number of combinations *nvertices + subjects.clear(); + int k = 4; - + for (int i = 0; i < m_num_subjects; i++) ////m_num_subjects + subjects.push_back(i); - } + cout << " initialise combinations " << subjects.size() << endl; - void GroupDiscreteModel::initialize_quartets(){ + if (k > m_num_subjects) + throw DISCRETEOPTHOCRException("GroupDiscreteModel::initialize_quartets() not enough examples!"); + for (int i = 0; i < m_CONTROLMESHES[0].nvertices(); i++) { - m_num_quartets=0; /// number of combinations *nvertices - subjects.clear(); - int k=4; - - for (int i = 0; i < m_num_subjects; i++) ////m_num_subjects - subjects.push_back(i); - - cout << " initialise combinations " << subjects.size() << endl; - - - if(k>m_num_subjects) throw DISCRETEOPTHOCRException("GroupDiscreteModel::initialize_quartets() not enough examples!"); - for(int i=0;in){ - int node_ids[2] = { i+n*control_grid_size, BETWEEN_SUBJECT_PAIRS[n][n2][i]}; - // cout << " node_ids[0] " << node_ids[0] << " " << node_ids[1] << endl; - if(2*pair+1> m_num_pairs*2) { cout <<2*pair+1 << " m_num_pairs " << m_num_pairs << " " << m_num_pairs*2 << endl; throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() index exceeds array size!");} - if((node_ids[1] >= (n-1)*m_CONTROLMESHES[n].nvertices()) && (node_ids[1] < n*m_CONTROLMESHES[n].nvertices())){throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() between mesh index pairs are from the same mesh!");} - if((node_ids[0] > m_num_subjects*control_grid_size) || (node_ids[1] > m_num_subjects*control_grid_size)){throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() indices exceed the total number of control points!");} - sort_nodeids(node_ids,2); - pairs[2*pair]=node_ids[0]; - pairs[2*pair+1]=node_ids[1]; - // cout << " pair " << pair << " " << node_ids[0] << " " << node_ids[1] << endl; - pair++; - } - } - - } + for (int n = 0; n < m_num_subjects; n++) { + for (int i = 0; i < m_CONTROLMESHES[n].nvertices(); i++) { + for (int n2 = 0; n2 < m_num_subjects; n2++) { + if (n2 > n) { + int node_ids[2] = { i + n * control_grid_size, BETWEEN_SUBJECT_PAIRS[n][n2][i] }; + // cout << " node_ids[0] " << node_ids[0] << " " << node_ids[1] << endl; + if (2 * pair + 1 > m_num_pairs * 2) { + cout << 2 * pair + 1 << " m_num_pairs " << m_num_pairs << " " << m_num_pairs * 2 << endl; + throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() index exceeds array size!"); + } + if ((node_ids[1] >= (n - 1) * m_CONTROLMESHES[n].nvertices()) && (node_ids[1] < n * m_CONTROLMESHES[n].nvertices())) { + throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() between mesh index pairs are from the same mesh!"); + } + if ((node_ids[0] > m_num_subjects * control_grid_size) || (node_ids[1] > m_num_subjects * control_grid_size)) { + throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_pairs() indices exceed the total number of control points!"); + } + sort_nodeids(node_ids, 2); + pairs[2 * pair] = node_ids[0]; + pairs[2 * pair + 1] = node_ids[1]; + // cout << " pair " << pair << " " << node_ids[0] << " " << node_ids[1] << endl; + pair++; + } + } + } } - +} - } +void GroupDiscreteModel::estimate_quartets() +{ - void GroupDiscreteModel::estimate_quartets(){ - - quartets = new int [m_num_quartets*4]; + quartets = new int[m_num_quartets * 4]; cout << " estimate quartets " << endl; - estimate_combinations(4,quartets); - - } - - void GroupDiscreteModel::estimate_combinations(int k, int *combinations){ - - int ind=0; - - for(int i=0;i node_ids; - node_ids.push_back(i+subjects[0]*control_grid_size); - for (int n = 1; n < k; ++n) - { - node_ids.push_back(BETWEEN_SUBJECT_PAIRS[subjects[0]][subjects[n]][i]); - - } - std::sort(node_ids.begin(), node_ids.end()); - std::cout << i << " " ; - for (int n = 0; n < k; ++n){ - combinations[k*ind+n]=node_ids[n]; - std::cout << node_ids[n] << " " ; - } - std::cout << "\n"; - ind++; - } - while(next_combination(subjects.begin(),subjects.begin() + k,subjects.end())); + estimate_combinations(4, quartets); +} + +void GroupDiscreteModel::estimate_combinations(int k, int* combinations) +{ + + int ind = 0; + + for (int i = 0; i < m_CONTROLMESHES[0].nvertices(); i++) { + + do { + vector node_ids; + node_ids.push_back(i + subjects[0] * control_grid_size); + for (int n = 1; n < k; ++n) { + node_ids.push_back(BETWEEN_SUBJECT_PAIRS[subjects[0]][subjects[n]][i]); + } + std::sort(node_ids.begin(), node_ids.end()); + std::cout << i << " "; + for (int n = 0; n < k; ++n) { + combinations[k * ind + n] = node_ids[n]; + std::cout << node_ids[n] << " "; + } + std::cout << "\n"; + ind++; + } while (next_combination(subjects.begin(), subjects.begin() + k, subjects.end())); } - cout << " ind " << ind << " " << m_num_quartets << endl; - } - - - void GroupDiscreteModel::estimate_triplets(){ ////// for regularisation - - m_num_triplets=m_num_subjects*m_CONTROLMESHES[0].ntriangles(); - - triplets = new int [m_num_triplets*3]; + cout << " ind " << ind << " " << m_num_quartets << endl; +} + +void GroupDiscreteModel::estimate_triplets() +{ ////// for regularisation + + m_num_triplets = m_num_subjects * m_CONTROLMESHES[0].ntriangles(); + + triplets = new int[m_num_triplets * 3]; cout << " in estimate triplets " << m_num_triplets << endl; - for(int n=0;n m_num_triplets*3 ) {throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_triplets index exceeds array size");} - if((node_ids[0] >= m_num_subjects*m_CONTROLMESHES[n].nvertices() ) || (node_ids[1] >= m_num_subjects*m_CONTROLMESHES[n].nvertices() )|| (node_ids[2] >= m_num_subjects*m_CONTROLMESHES[n].nvertices() )) {throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_triplets node index exceeds mesh size");} - //cout < m_num_triplets * 3) { + throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_triplets index exceeds array size"); + } + if ((node_ids[0] >= m_num_subjects * m_CONTROLMESHES[n].nvertices()) || (node_ids[1] >= m_num_subjects * m_CONTROLMESHES[n].nvertices()) || (node_ids[2] >= m_num_subjects * m_CONTROLMESHES[n].nvertices())) { + throw DISCRETEOPTHOCRException("GroupDiscreteModel::estimate_triplets node index exceeds mesh size"); + } + //cout < > ALLPOINTS=m_CONTROLMESHES[0].get_points(); - int ind,mesh_ID; - int found=0; - vector indices(control_grid_size,-1); //// Between subjects pairs is a per subject matrix of subjectsxvertex indicators of closest vertices for each node - double ang=2*asin(MVD/RAD),angtmp; + vector> ALLPOINTS = m_CONTROLMESHES[0].get_points(); + int ind, mesh_ID; + int found = 0; + vector indices(control_grid_size, -1); //// Between subjects pairs is a per subject matrix of subjectsxvertex indicators of closest vertices for each node + double ang = 2 * asin(MVD / RAD), angtmp; BETWEEN_SUBJECT_PAIRS.clear(); cout << BETWEEN_SUBJECT_PAIRS.size() << endl; - for(int n=0; n > mat(m_num_subjects,indices); - BETWEEN_SUBJECT_PAIRS.push_back(mat); + for (int n = 0; n < m_num_subjects; n++) { + vector> mat(m_num_subjects, indices); + BETWEEN_SUBJECT_PAIRS.push_back(mat); } - //////// create one giant mesh for all subject control grids - for (int n=1;n > tmppoints=m_CONTROLMESHES[n].get_points(); - ALLPOINTS.insert(ALLPOINTS.end(),tmppoints.begin(),tmppoints.end()); + //////// create one giant mesh for all subject control grids + for (int n = 1; n < m_num_subjects; n++) { + vector> tmppoints = m_CONTROLMESHES[n].get_points(); + ALLPOINTS.insert(ALLPOINTS.end(), tmppoints.begin(), tmppoints.end()); } cout << " ALLPOINTSsize " << ALLPOINTS.size() << " " << m_TEMPLATE_LR.nvertices() << endl; - - m_TEMPLATE_LR_ALL_RELATIONS=boost::shared_ptr(new RELATIONS (m_TEMPLATE_LR,ALLPOINTS,ang)); - - //// for all subjects and all vertices find the closest between mesh neighbours - for(int n=0;nupdate_RELATIONS_for_ind(i,m_CONTROLMESHES[n], angtmp); - // cout << i << " m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i) " << m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i) << " " << m_TEMPLATE_LR_ALL_RELATIONS->Ncols() << endl; - for (int r=1;r<=m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i);r++){ - ind=(*m_TEMPLATE_LR_ALL_RELATIONS)(r,i)-1; - mesh_ID=floor(ind/control_grid_size); - if(mesh_ID!=n && BETWEEN_SUBJECT_PAIRS[n][mesh_ID][i-1]==-1) { BETWEEN_SUBJECT_PAIRS[n][mesh_ID][i-1]=ind; - found++; - // cout << r << " " << ind << " mesh ID " << mesh_ID << " " << n << " " << ALLPOINTS.size() << " found " << found <<" m_num_subjects-1 " << m_num_subjects-1 << endl; - - if(found==m_num_subjects-1) break; - } - - - } - if(found!=m_num_subjects-1){ angtmp=2*ang; //// check that neighbours have been found between all other meshes - cout << " GroupDiscreteModel::get_between_subject_pairs() not between subjects neighbour pairs found for subject " << n << endl; break;} - else {i++;} - } - + + m_TEMPLATE_LR_ALL_RELATIONS = boost::shared_ptr(new RELATIONS(m_TEMPLATE_LR, ALLPOINTS, ang)); + + //// for all subjects and all vertices find the closest between mesh neighbours + for (int n = 0; n < m_num_subjects; n++) { + angtmp = ang; + int i = 1; + while (i <= control_grid_size) { + found = 0; + m_TEMPLATE_LR_ALL_RELATIONS->update_RELATIONS_for_ind(i, m_CONTROLMESHES[n], angtmp); + // cout << i << " m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i) " << m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i) << " " << m_TEMPLATE_LR_ALL_RELATIONS->Ncols() << endl; + for (int r = 1; r <= m_TEMPLATE_LR_ALL_RELATIONS->Nrows(i); r++) { + ind = (*m_TEMPLATE_LR_ALL_RELATIONS)(r, i) - 1; + mesh_ID = floor(ind / control_grid_size); + if (mesh_ID != n && BETWEEN_SUBJECT_PAIRS[n][mesh_ID][i - 1] == -1) { + BETWEEN_SUBJECT_PAIRS[n][mesh_ID][i - 1] = ind; + found++; + // cout << r << " " << ind << " mesh ID " << mesh_ID << " " << n << " " << ALLPOINTS.size() << " found " << found <<" m_num_subjects-1 " << m_num_subjects-1 << endl; + + if (found == m_num_subjects - 1) + break; + } + } + if (found != m_num_subjects - 1) { + angtmp = 2 * ang; //// check that neighbours have been found between all other meshes + cout << " GroupDiscreteModel::get_between_subject_pairs() not between subjects neighbour pairs found for subject " << n << endl; + break; + } else { + i++; + } + } } - // exit(1); - } - - void GroupDiscreteModel::get_rotations(vector &ROT){ /// rotates sampling grid to each control point - Matrix R,R2,R_n,R_n2,R_diff; - Pt ci,CP,CP_n; - ROT.clear(); - ci=m_samplinggrid.get_coord(m_centroid); +} +void GroupDiscreteModel::get_rotations(vector& ROT) +{ /// rotates sampling grid to each control point + Matrix R, R2, R_n, R_n2, R_diff; + Pt ci, CP, CP_n; + ROT.clear(); + ci = m_samplinggrid.get_coord(m_centroid); - for (int n=0;n=4) initialize_quartets(); + if (_estquartet && m_num_subjects >= 4) + initialize_quartets(); estimate_triplets(); - - + /////////////////// CALCULATE FIXED GRID SPACINGS//////// - MVD=Calculate_MVD(CONTROLGRID); - m_maxs_dist=0.4*Calculate_MaxVD(CONTROLGRID); + MVD = Calculate_MVD(CONTROLGRID); + m_maxs_dist = 0.4 * Calculate_MaxVD(CONTROLGRID); /// INITIALIAZE LABEL GRID///////// initLabeling(); - Initialize_sampling_grid(); + Initialize_sampling_grid(); //////////// INITIALIZE NEIGHBOURHOODS //////////////// - m_cp_neighbourhood=boost::shared_ptr(new RELATIONS (m_DATAMESHES[0],CONTROLGRID,2*asin(MVD/RAD))); /// as source mesh moves with control grid the relationships are constant for all meshes - m_inputrel=boost::shared_ptr(new RELATIONS (m_DATAMESHES[0],m_TEMPLATE,2*asin(MVD/RAD))); + m_cp_neighbourhood = boost::shared_ptr(new RELATIONS(m_DATAMESHES[0], CONTROLGRID, 2 * asin(MVD / RAD))); /// as source mesh moves with control grid the relationships are constant for all meshes + m_inputrel = boost::shared_ptr(new RELATIONS(m_DATAMESHES[0], m_TEMPLATE, 2 * asin(MVD / RAD))); // sprintf(filename,"%sSOURCE1-%d.surf",m_outdir.c_str(),m_iter); m_SOURCE.save(filename); - + cout << " update control RELATIONS " << endl; m_cp_neighbourhood->update_RELATIONS(m_DATAMESHES[0]); cout << " set meshes cf " << endl; - if(costfct.get()){ - costfct->set_meshes(m_TEMPLATE,m_DATAMESHES[0],CONTROLGRID,m_DATAMESHES.size()); + if (costfct.get()) { + costfct->set_meshes(m_TEMPLATE, m_DATAMESHES[0], CONTROLGRID, m_DATAMESHES.size()); - costfct->set_relations(m_cp_neighbourhood,m_inputrel); + costfct->set_relations(m_cp_neighbourhood, m_inputrel); } - m_iter=1; - - } - + m_iter = 1; +} - - void GroupDiscreteModel::setupCostFunction() - { +void GroupDiscreteModel::setupCostFunction() +{ char filename[1000]; cout << " GroupDiscreteModel::setupCostFunction " << endl; resetLabeling(); // initialise label array to zero ////// use geodesic distances //////// - for(int n=0;nreset_CPgrid(m_CONTROLMESHES[n],n); - // sprintf(filename,"Controlgrid_set_up_it%d_res%d_num%d.surf.gii",m_iter, m_CPres,n); - //m_CONTROLMESHES[n].save(filename); + for (int n = 0; n < m_num_subjects; n++) { + costfct->reset_CPgrid(m_CONTROLMESHES[n], n); + // sprintf(filename,"Controlgrid_set_up_it%d_res%d_num%d.surf.gii",m_iter, m_CPres,n); + //m_CONTROLMESHES[n].save(filename); } costfct->set_iter(m_iter); //////////////////////// GET BETWEEN MESH GROUPINGS ////////////// get_between_subject_pairs(); - - estimate_pairs(); - if(_estquartet) estimate_quartets(); + + estimate_pairs(); + if (_estquartet) + estimate_quartets(); ////////////////// GET LABEL SPACE ////////// - get_rotations(m_ROT); - if(m_iter%2==0) m_labels=m_samples; - else m_labels=m_barycentres; + get_rotations(m_ROT); + if (m_iter % 2 == 0) + m_labels = m_samples; + else + m_labels = m_barycentres; - m_num_labels=m_labels.size(); + m_num_labels = m_labels.size(); - costfct->set_labels(m_labels,m_ROT); + costfct->set_labels(m_labels, m_ROT); ///////////////// INIT //////// - if(m_verbosity)cout << " initialize cost function 2" << m_iter << " m_num_triplets " << m_num_triplets << endl; + if (m_verbosity) + cout << " initialize cost function 2" << m_iter << " m_num_triplets " << m_num_triplets << endl; costfct->setPairs(pairs); costfct->setTriplets(triplets); - if(_estquartet) costfct->setQuartets(quartets); - - costfct->initialize(m_num_nodes,m_num_labels,m_num_pairs,m_num_triplets,m_num_quartets); - - - - - - - if(m_verbosity) cout << " numpoints " << m_num_nodes << " m_num_labels " << m_num_labels << " m_num_pairs " << m_num_pairs << endl; - m_iter++; - } + if (_estquartet) + costfct->setQuartets(quartets); + costfct->initialize(m_num_nodes, m_num_labels, m_num_pairs, m_num_triplets, m_num_quartets); - void GroupDiscreteModel::applyLabeling(int *dlabels){ + if (m_verbosity) + cout << " numpoints " << m_num_nodes << " m_num_labels " << m_num_labels << " m_num_pairs " << m_num_pairs << endl; + m_iter++; +} + +void GroupDiscreteModel::applyLabeling(int* dlabels) +{ cout << " GroupDiscreteModel applylabelling " << endl; - if(dlabels){ - for (int n=0;n #include +namespace DISCRETEOPT { -namespace DISCRETEOPT{ - - void sort_nodeids(int *nodes, int length){ - std::vector myvector (nodes, nodes+length); - std::sort(myvector.begin(), myvector.begin()+length); - - for(unsigned int i=0;i(it->second); - it=PAR.find("CPres");m_CPres=boost::get(it->second); - it=PAR.find("SGres");m_SGres=boost::get(it->second); - it=PAR.find("simmeasure");m_simmeasure=boost::get(it->second); - it=PAR.find("regularisermode");m_regoption=boost::get(it->second); - it=PAR.find("multivariate");m_multivariate=boost::get(it->second); - it=PAR.find("verbosity");m_verbosity=boost::get(it->second); - it=PAR.find("outdir");m_outdir=boost::get(it->second); - it=PAR.find("TriLikelihood");m_triclique=boost::get(it->second); - it=PAR.find("rescalelabels");m_rescalelabels=boost::get(it->second); - it=PAR.find("numthreads");_numthreads=boost::get(it->second); - it=PAR.find("quartet");_estquartet=boost::get(it->second); - - if(m_regoption==1) _pairwise=true; - - - - - } - - void SRegDiscreteModel::Initialize(const newmesh &CONTROLGRID){ - ColumnVector vMAXmvd; - double MVDmax=0.0; - MVD=0; - double tot=0; - double dist=0; - Pt CP; - m_CPgrid=CONTROLGRID; - - /////////////// SET LOW RES DEFORMATION GRID & INITIALISE ASSOCIATED MRF PARAMS ///////////////////////// - m_num_nodes=m_CPgrid.nvertices(); m_num_pairs=0; - initLabeling(); - - //////////////////////// CALCULATE (MEAN) VERTEX SEPARATIONS FOR EACH VERTEX - vMAXmvd.ReSize(m_CPgrid.nvertices()); vMAXmvd=0; - for (int k=0;k::const_iterator it=m_CPgrid.nbegin(k);it !=m_CPgrid.nend(k);it++){ - - dist= 2*RAD*asin((CP-m_CPgrid.get_coord(*it)).norm()/(2*RAD)); - MVD+=(CP-m_CPgrid.get_coord(*it)).norm(); - tot++; - - if(dist > vMAXmvd(k+1)) - vMAXmvd(k+1)=dist; - if(vMAXmvd(k+1)>MVDmax) MVDmax=vMAXmvd(k+1); - } - } - MVD/=tot; - - m_maxs_dist=0.5*Calculate_MaxVD(m_CPgrid); - ////////////////// INITIALIZE COSTFCT /////////////////// - - if(costfct.get()){ - costfct->set_meshes(m_TARGET,m_SOURCE,m_CPgrid); - vector > orig_angles=m_CPgrid.get_face_angles(); - - costfct->set_initial_angles(orig_angles); - costfct->set_spacings(vMAXmvd,MVDmax); - } - else {throw DISCRETEOPTHOCRException("Discrete Model:: You have not initialised the discrete costfunction before initialising the model");} - - - m_iter=1; - - - - } - - void SRegDiscreteModel::initialize_cost_function(const bool &MV, const int & sim, myparam &P){ - //////////////////////// CREATE COST FUNCTION ////////////////////// - if(MV){ - - if(m_triclique) - costfct=boost::shared_ptr(new HOMultivariateNonLinearSRegDiscreteCostFunction()); - else - costfct=boost::shared_ptr(new MultivariateNonLinearSRegDiscreteCostFunction()); // choose CF based on choice of method of calculation of the data term - - } - else if (sim==4) {throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: alpha MI not in this version of MSM yet");} //costfct=boost::shared_ptr(new alphaMINonLinearSRegDiscreteCostFunction()); - else{ - if(m_triclique) - costfct=boost::shared_ptr(new HOUnivariateNonLinearSRegDiscreteCostFunction()); - else - costfct=boost::shared_ptr(new UnivariateNonLinearSRegDiscreteCostFunction());} - - - costfct->set_parameters(P); - +void sort_nodeids(int* nodes, int length) +{ + std::vector myvector(nodes, nodes + length); + std::sort(myvector.begin(), myvector.begin() + length); + + for (unsigned int i = 0; i < myvector.size(); i++) + nodes[i] = myvector[i]; +} + +//=== +//====================================================================================================================// + +//====================================================================================================================// +void DiscreteModel::resetLabeling() +{ + if (labeling) + std::fill(labeling, labeling + m_num_nodes, 0); +} + +//====================================================================================================================// +void DiscreteModel::initLabeling() +{ + if (m_num_nodes) { + if (labeling) + delete[] labeling; + labeling = new int[m_num_nodes]; + resetLabeling(); + } +} + +//====================================================================================================================// +void DiscreteModel::printLabeling() +{ + std::cout << "Labeling: "; + for (int i = 0; i < m_num_nodes; ++i) + std::cout << labeling[i] << " "; + std::cout << std::endl; +} + +//====================================================================================================================// +void SRegDiscreteModel::set_parameters(myparam PAR) +{ + myparam::iterator it; + + it = PAR.find("lambda"); + m_lambda = boost::get(it->second); + it = PAR.find("CPres"); + m_CPres = boost::get(it->second); + it = PAR.find("SGres"); + m_SGres = boost::get(it->second); + it = PAR.find("simmeasure"); + m_simmeasure = boost::get(it->second); + it = PAR.find("regularisermode"); + m_regoption = boost::get(it->second); + it = PAR.find("multivariate"); + m_multivariate = boost::get(it->second); + it = PAR.find("verbosity"); + m_verbosity = boost::get(it->second); + it = PAR.find("outdir"); + m_outdir = boost::get(it->second); + it = PAR.find("TriLikelihood"); + m_triclique = boost::get(it->second); + it = PAR.find("rescalelabels"); + m_rescalelabels = boost::get(it->second); + it = PAR.find("numthreads"); + _numthreads = boost::get(it->second); + it = PAR.find("quartet"); + _estquartet = boost::get(it->second); + + if (m_regoption == 1) + _pairwise = true; +} + +void SRegDiscreteModel::Initialize(const newmesh& CONTROLGRID) +{ + ColumnVector vMAXmvd; + double MVDmax = 0.0; + MVD = 0; + double tot = 0; + double dist = 0; + Pt CP; + m_CPgrid = CONTROLGRID; + + /////////////// SET LOW RES DEFORMATION GRID & INITIALISE ASSOCIATED MRF PARAMS ///////////////////////// + m_num_nodes = m_CPgrid.nvertices(); + m_num_pairs = 0; + initLabeling(); + + //////////////////////// CALCULATE (MEAN) VERTEX SEPARATIONS FOR EACH VERTEX + vMAXmvd.ReSize(m_CPgrid.nvertices()); + vMAXmvd = 0; + for (int k = 0; k < m_CPgrid.nvertices(); k++) { + + CP = m_CPgrid.get_coord(k); + for (vector::const_iterator it = m_CPgrid.nbegin(k); it != m_CPgrid.nend(k); it++) { + + dist = 2 * RAD * asin((CP - m_CPgrid.get_coord(*it)).norm() / (2 * RAD)); + MVD += (CP - m_CPgrid.get_coord(*it)).norm(); + tot++; + + if (dist > vMAXmvd(k + 1)) + vMAXmvd(k + 1) = dist; + if (vMAXmvd(k + 1) > MVDmax) + MVDmax = vMAXmvd(k + 1); + } + } + MVD /= tot; + + m_maxs_dist = 0.5 * Calculate_MaxVD(m_CPgrid); + ////////////////// INITIALIZE COSTFCT /////////////////// + + if (costfct.get()) { + costfct->set_meshes(m_TARGET, m_SOURCE, m_CPgrid); + vector> orig_angles = m_CPgrid.get_face_angles(); + + costfct->set_initial_angles(orig_angles); + costfct->set_spacings(vMAXmvd, MVDmax); + } else { + throw DISCRETEOPTHOCRException("Discrete Model:: You have not initialised the discrete costfunction before initialising the model"); + } + + m_iter = 1; +} + +void SRegDiscreteModel::initialize_cost_function(const bool& MV, const int& sim, myparam& P) +{ + //////////////////////// CREATE COST FUNCTION ////////////////////// + if (MV) { + + if (m_triclique) + costfct = boost::shared_ptr(new HOMultivariateNonLinearSRegDiscreteCostFunction()); + else + costfct = boost::shared_ptr(new MultivariateNonLinearSRegDiscreteCostFunction()); // choose CF based on choice of method of calculation of the data term + + } else if (sim == 4) { + throw DISCRETEOPTHOCRException("DiscreteModel ERROR:: alpha MI not in this version of MSM yet"); + } //costfct=boost::shared_ptr(new alphaMINonLinearSRegDiscreteCostFunction()); + else { + if (m_triclique) + costfct = boost::shared_ptr(new HOUnivariateNonLinearSRegDiscreteCostFunction()); + else + costfct = boost::shared_ptr(new UnivariateNonLinearSRegDiscreteCostFunction()); } - void SRegDiscreteModel::Initialize_sampling_grid(){ + costfct->set_parameters(P); +} + +void SRegDiscreteModel::Initialize_sampling_grid() +{ //////////////////////// LABELS USING HIGHER RES GRID ////////////////////// - m_samplinggrid.make_mesh_from_icosa(m_SGres); true_rescale(m_samplinggrid,RAD); + m_samplinggrid.make_mesh_from_icosa(m_SGres); + true_rescale(m_samplinggrid, RAD); ////// find the first centroid with 6 neighbours - for(int i=0;i getneighbours; - vector newneighbours; - int label; - Pt sample; - ColumnVector found(Grid.nvertices()),found_tr(Grid.ntriangles()); - - centre=Grid.get_coord(centroid); - found=0;found_tr=0; - getneighbours.push_back(centroid); - m_samples.push_back(centre); - m_barycentres.push_back(centre); - label=1; - - //// searches for neighbours of the cnetroid that are within the max sampling distance - while(getneighbours.size()>0){ - for(unsigned int i=0;i< getneighbours.size();i++){ - for(vector::const_iterator j=Grid.nbegin(getneighbours[i]); j!=Grid.nend(getneighbours[i]);j++){ - sample=Grid.get_coord(*j); - if((sample-centre).norm()<=dist && (found(*j+1)==0) && *j!=centroid){ - m_samples.push_back(Grid.get_coord(*j)); /// pt-centroid equals deformation vector - newneighbours.push_back(*j); - found(*j+1)=1; - - } - } - for(vector::const_iterator j=Grid.tIDbegin(getneighbours[i]); j!=Grid.tIDend(getneighbours[i]);j++){ - NEWMESH::Pt v1 = Grid.get_triangle_vertex(*j,0), v2 = Grid.get_triangle_vertex(*j,1), v3 = Grid.get_triangle_vertex(*j,2); - Pt bary((v1.X+v2.X+v3.X)/3,(v1.Y+v2.Y+v3.Y)/3,(v1.Z+v2.Z+v3.Z)/3); - bary.normalize(); bary=bary*RAD; - - if((bary-centre).norm()<=dist && (bary-centre).norm()> 0 && found_tr(*j+1)==0){ - for(unsigned int k=0;k SRegDiscreteModel::rescale_sampling_grid(){ - vector newlabels; - vector< pair > neighbours; - Pt sample,newsample; - if(m_verbosity) cout << " resample labels " << m_scale << " length scale " << (centre-m_samples[1]).norm() << endl; - - if(m_scale>=0.25){ - for(unsigned int i=0;i()); - - for(int i=0;i::const_iterator j=m_CPgrid.nbegin(i); j!=m_CPgrid.nend(i);j++){ - if(*j>i){ - int node_ids[2] = { i, *j}; - - sort_nodeids(node_ids,2); - pairs[2*pair]=node_ids[0]; - pairs[2*pair+1]=node_ids[1]; - pair++; - } - } - - } - - - } - - void NonLinearSRegDiscreteModel::estimate_triplets(){ - m_num_triplets=m_CPgrid.ntriangles(); - - triplets = new int [m_num_triplets*3]; - - for(int i=0;i getneighbours; + vector newneighbours; + int label; + Pt sample; + ColumnVector found(Grid.nvertices()), found_tr(Grid.ntriangles()); + + centre = Grid.get_coord(centroid); + found = 0; + found_tr = 0; + getneighbours.push_back(centroid); + m_samples.push_back(centre); + m_barycentres.push_back(centre); + label = 1; + + //// searches for neighbours of the cnetroid that are within the max sampling distance + while (getneighbours.size() > 0) { + for (unsigned int i = 0; i < getneighbours.size(); i++) { + for (vector::const_iterator j = Grid.nbegin(getneighbours[i]); j != Grid.nend(getneighbours[i]); j++) { + sample = Grid.get_coord(*j); + if ((sample - centre).norm() <= dist && (found(*j + 1) == 0) && *j != centroid) { + m_samples.push_back(Grid.get_coord(*j)); /// pt-centroid equals deformation vector + newneighbours.push_back(*j); + found(*j + 1) = 1; + } + } + for (vector::const_iterator j = Grid.tIDbegin(getneighbours[i]); j != Grid.tIDend(getneighbours[i]); j++) { + NEWMESH::Pt v1 = Grid.get_triangle_vertex(*j, 0), v2 = Grid.get_triangle_vertex(*j, 1), v3 = Grid.get_triangle_vertex(*j, 2); + Pt bary((v1.X + v2.X + v3.X) / 3, (v1.Y + v2.Y + v3.Y) / 3, (v1.Z + v2.Z + v3.Z) / 3); + bary.normalize(); + bary = bary * RAD; + + if ((bary - centre).norm() <= dist && (bary - centre).norm() > 0 && found_tr(*j + 1) == 0) { + for (unsigned int k = 0; k < m_barycentres.size(); k++) { + if (abs(1 - (((bary - centre) | (m_barycentres[k] - centre)) / ((bary - centre).norm() * (m_barycentres[k] - centre).norm()))) < 1e-2) { + found_tr(*j + 1) = 1; + } + } + if (!found_tr(*j + 1)) { + m_barycentres.push_back(bary); + Grid.set_pvalue(Grid.get_triangle_vertexID(*j, 0), label); + label++; + } + found_tr(*j + 1) = 1; + } + } + } + + getneighbours = newneighbours; + newneighbours.clear(); } - - - } - - void NonLinearSRegDiscreteModel::Initialize(const newmesh &CONTROLGRID){ - - SRegDiscreteModel::Initialize(CONTROLGRID); - m_scale=1; - if(_pairwise){ - //////////////////////// GET PAIRS ////////////// - estimate_pairs(); - // costfct->set_pairtrIDs(pair_trIDs); +} + +vector SRegDiscreteModel::rescale_sampling_grid() +{ + vector newlabels; + vector> neighbours; + Pt sample, newsample; + if (m_verbosity) + cout << " resample labels " << m_scale << " length scale " << (centre - m_samples[1]).norm() << endl; + + if (m_scale >= 0.25) { + for (unsigned int i = 0; i < m_samples.size(); i++) { + sample = m_samples[i]; + newsample = centre + (centre - sample) * m_scale; + + newsample.normalize(); + newsample = newsample * 100; + newlabels.push_back(newsample); + } + + } else { + m_scale = 1; + newlabels = m_samples; } - else{ - /////////////////////////// INITIALIZE TRIPLETS ///////////////////// - estimate_triplets(); + + m_scale *= 0.8; + + return newlabels; +} + +void NonLinearSRegDiscreteModel::estimate_pairs() +{ + int pair = 0; + + for (int i = 0; i < m_CPgrid.nvertices(); i++) { /// estimate the total number of edge pairs //// + m_num_pairs += m_CPgrid.get_total_neighbours(i); } - + m_num_pairs /= 2; + pairs = new int[m_num_pairs * 2]; + // pair_trIDs.resize(m_num_pairs,map()); + + for (int i = 0; i < m_CPgrid.nvertices(); i++) { + for (vector::const_iterator j = m_CPgrid.nbegin(i); j != m_CPgrid.nend(i); j++) { + if (*j > i) { + int node_ids[2] = { i, *j }; + + sort_nodeids(node_ids, 2); + pairs[2 * pair] = node_ids[0]; + pairs[2 * pair + 1] = node_ids[1]; + pair++; + } + } + } +} + +void NonLinearSRegDiscreteModel::estimate_triplets() +{ + m_num_triplets = m_CPgrid.ntriangles(); + + triplets = new int[m_num_triplets * 3]; + + for (int i = 0; i < m_CPgrid.ntriangles(); i++) { + int node_ids[3] = { m_CPgrid.get_triangle_vertexID(i, 0), m_CPgrid.get_triangle_vertexID(i, 1), m_CPgrid.get_triangle_vertexID(i, 2) }; + sort_nodeids(node_ids, 3); + + triplets[3 * i] = node_ids[0]; + triplets[3 * i + 1] = node_ids[1]; + triplets[3 * i + 2] = node_ids[2]; + } +} + +void NonLinearSRegDiscreteModel::Initialize(const newmesh& CONTROLGRID) +{ + + SRegDiscreteModel::Initialize(CONTROLGRID); + m_scale = 1; + if (_pairwise) { + //////////////////////// GET PAIRS ////////////// + estimate_pairs(); + // costfct->set_pairtrIDs(pair_trIDs); + } else { + /////////////////////////// INITIALIZE TRIPLETS ///////////////////// + estimate_triplets(); + } + /////////////////// CALCULATE FIXED GRID SPACINGS//////// - - double MVDinput=Calculate_MVD(m_TARGET); /// estimate spacing of data grid from first vertex - + + double MVDinput = Calculate_MVD(m_TARGET); /// estimate spacing of data grid from first vertex + /// INITIALIAZE LABEL GRID///////// - Initialize_sampling_grid(); - get_rotations(m_ROT); /// enables rotation of sampling grid onto every CP + Initialize_sampling_grid(); + get_rotations(m_ROT); /// enables rotation of sampling grid onto every CP //////////// INITIALIZE NEIGHBOURHOODS //////////////// - m_inputrel=boost::shared_ptr(new RELATIONS (m_SOURCE,m_TARGET,1.5*asin(MVDinput/RAD))); - - } - + m_inputrel = boost::shared_ptr(new RELATIONS(m_SOURCE, m_TARGET, 1.5 * asin(MVDinput / RAD))); +} - - - void NonLinearSRegDiscreteModel::get_rotations(vector &ROT){ /// rotates sampling grid to each control point - Matrix R,R2,R_n,R_n2,R_diff; - Pt ci,CP,CP_n; +void NonLinearSRegDiscreteModel::get_rotations(vector& ROT) +{ /// rotates sampling grid to each control point + Matrix R, R2, R_n, R_n2, R_diff; + Pt ci, CP, CP_n; ROT.clear(); - ci=m_samplinggrid.get_coord(m_centroid); - - for (int k=0;kreset_CPgrid(m_CPgrid); - if(m_iter==1){ + if (m_iter == 1) { costfct->initialize_regulariser(); - m_cp_neighbourhood=boost::shared_ptr(new RELATIONS (m_SOURCE,m_CPgrid,3*asin(MVD/RAD))); - + m_cp_neighbourhood = boost::shared_ptr(new RELATIONS(m_SOURCE, m_CPgrid, 3 * asin(MVD / RAD))); m_cp_neighbourhood->update_RELATIONS(m_SOURCE); - costfct->set_relations(m_cp_neighbourhood,m_inputrel); + costfct->set_relations(m_cp_neighbourhood, m_inputrel); } - costfct->reset_anatomical(m_outdir,m_iter); - - get_rotations(m_ROT); /// instead of recalulating the source->CP neighbours, these are now constant (as source is moving with CPgrid) we we just need to recalculate the rotations of the label grid to the cp vertices - - - if(m_debug){ - char filename[1000]; - sprintf(filename,"%sSOURCE-%d.surf",m_outdir.c_str(),m_iter); m_SOURCE.save(filename); - sprintf(filename,"%sSOURCE-%d.func",m_outdir.c_str(),m_iter); m_SOURCE.save(filename); - - if(m_iter==1){sprintf(filename,"%sTARGET.surf",m_outdir.c_str()); m_TARGET.save(filename); } - sprintf(filename,"%sCPgrid-%d.surf",m_outdir.c_str(),m_iter); m_CPgrid.save(filename); - + costfct->reset_anatomical(m_outdir, m_iter); + + get_rotations(m_ROT); /// instead of recalulating the source->CP neighbours, these are now constant (as source is moving with CPgrid) we we just need to recalculate the rotations of the label grid to the cp vertices + + if (m_debug) { + char filename[1000]; + sprintf(filename, "%sSOURCE-%d.surf", m_outdir.c_str(), m_iter); + m_SOURCE.save(filename); + sprintf(filename, "%sSOURCE-%d.func", m_outdir.c_str(), m_iter); + m_SOURCE.save(filename); + + if (m_iter == 1) { + sprintf(filename, "%sTARGET.surf", m_outdir.c_str()); + m_TARGET.save(filename); + } + sprintf(filename, "%sCPgrid-%d.surf", m_outdir.c_str(), m_iter); + m_CPgrid.save(filename); } //////////// set samples (labels vary from iter to iter ) /////////////// - if(m_rescalelabels){ - m_labels=rescale_sampling_grid(); - }else{ - if(m_iter%2==0) m_labels=m_samples; - else m_labels=m_barycentres; + if (m_rescalelabels) { + m_labels = rescale_sampling_grid(); + } else { + if (m_iter % 2 == 0) + m_labels = m_samples; + else + m_labels = m_barycentres; } - m_num_labels=m_labels.size(); + m_num_labels = m_labels.size(); + + costfct->set_labels(m_labels, m_ROT); + if (m_verbosity) + cout << " initialize cost function " << m_iter << endl; + costfct->initialize(m_num_nodes, m_num_labels, m_num_pairs, m_num_triplets); - costfct->set_labels(m_labels,m_ROT); - if(m_verbosity)cout << " initialize cost function " << m_iter << endl; - costfct->initialize(m_num_nodes,m_num_labels,m_num_pairs,m_num_triplets); - costfct->get_source_data(); - - if(_pairwise) costfct->setPairs(pairs); - else costfct->setTriplets(triplets); + if (_pairwise) + costfct->setPairs(pairs); + else + costfct->setTriplets(triplets); - - m_iter++; - } - - - void NonLinearSRegDiscreteModel::applyLabeling(int *dlabels){ - - if(dlabels){ - for (int i=0;ireset_CPgrid(m_CPgrid); - - get_rotations(m_ROT); /// instead of recalulating the source->CP neighbours, these are now constant (as source is moving with CPgrid) we we just need to recalculate the rotations of the label grid to the cp vertices +void RegularisationDiscreteModel::Initialize(const newmesh& CONTROLGRID) +{ + m_CPgrid = CONTROLGRID; + + m_num_nodes = m_CPgrid.nvertices(); + m_maxs_dist = 0.4 * Calculate_MaxVD(m_CPgrid); + initLabeling(); + /////////////////////////// INITIALIZE TRIPLETS ///////////////////// + estimate_triplets(); + Initialize_sampling_grid(); + get_rotations(m_ROT); /// enables rotation of sampling grid onto every CP + m_iter = 1; +} - //////////// set samples (labels vary from iter to iter ) /////////////// - if(m_iter%2==0) m_labels=m_samples; - else m_labels=m_barycentres; +void RegularisationDiscreteModel::setupCostFunction() +{ + resetLabeling(); // initialise label array to zero - m_num_labels=m_labels.size(); + ////// use geodesic distances //////// + costfct->reset_CPgrid(m_CPgrid); + get_rotations(m_ROT); /// instead of recalulating the source->CP neighbours, these are now constant (as source is moving with CPgrid) we we just need to recalculate the rotations of the label grid to the cp vertices + //////////// set samples (labels vary from iter to iter ) /////////////// + if (m_iter % 2 == 0) + m_labels = m_samples; + else + m_labels = m_barycentres; - costfct->set_labels(m_labels,m_ROT); - if(m_verbosity)cout << " initialize cost function " << m_iter << endl; - costfct->initialize(m_num_nodes,m_num_labels,m_num_pairs,m_num_triplets); + m_num_labels = m_labels.size(); + costfct->set_labels(m_labels, m_ROT); + if (m_verbosity) + cout << " initialize cost function " << m_iter << endl; + costfct->initialize(m_num_nodes, m_num_labels, m_num_pairs, m_num_triplets); - m_iter++; - } + m_iter++; +} } diff --git a/src/MSMRegLib/Fusion.cpp b/src/MSMRegLib/Fusion.cpp index c198a58..0d5f7d0 100644 --- a/src/MSMRegLib/Fusion.cpp +++ b/src/MSMRegLib/Fusion.cpp @@ -16,7 +16,6 @@ #include #include - #define NUM_SWEEPS 2 #define MAX_IMPROVEMENTS 0 @@ -24,326 +23,298 @@ using namespace ELCReduce; namespace MESHREG { - - template void Fusion::reduce_and_convert(PBF& pbf, OPTIMIZER& MODEL, Reduction mode) - { - switch(mode) - { - case ELC_HOCR: - { +template +void Fusion::reduce_and_convert(PBF& pbf, OPTIMIZER& MODEL, Reduction mode) +{ + switch (mode) { + case ELC_HOCR: { PBF qpbf; pbf.reduceHigher(); - pbf.toQuadratic(qpbf, pbf.maxID()+1); // Reduce the remaining higher-order terms using HOCR adding auxiliary variables - qpbf.convert(MODEL, qpbf.maxID()+1); + pbf.toQuadratic(qpbf, pbf.maxID() + 1); // Reduce the remaining higher-order terms using HOCR adding auxiliary variables + qpbf.convert(MODEL, qpbf.maxID() + 1); pbf.clear(); qpbf.clear(); break; - } - case ELC_APPROX: - { + } + case ELC_APPROX: { //PBF qpbf; - //qpbf = pbf; - pbf.reduceHigherApprox(); + //qpbf = pbf; + pbf.reduceHigherApprox(); - pbf.convert(MODEL, pbf.maxID()+1); + pbf.convert(MODEL, pbf.maxID() + 1); pbf.clear(); break; - } - case HOCR: - { + } + case HOCR: { PBF qpbf; - pbf.toQuadratic(qpbf, pbf.maxID()+1); // Reduce to Quadratic pseudo-Boolean function using HOCR. - qpbf.convert(MODEL, qpbf.maxID()+1); + pbf.toQuadratic(qpbf, pbf.maxID() + 1); // Reduce to Quadratic pseudo-Boolean function using HOCR. + qpbf.convert(MODEL, qpbf.maxID() + 1); pbf.clear(); qpbf.clear(); break; - - } - - } } + } +} //====================================================================================================================// - double Fusion::optimize( boost::shared_ptr energy, Reduction reductionMode, bool verbose ) +double Fusion::optimize(boost::shared_ptr energy, Reduction reductionMode, bool verbose) { - const int numNodes = energy->getNumNodes(); - const int numPairs = energy->getNumPairs(); - const int numTriplets = energy->getNumTriplets(); - const int numQuartets = energy->getNumQuartets(); - //const int numthreads = energy->getNumthreads(); - const int *pairs = energy->getPairs(); - const int *triplets = energy->getTriplets(); - const int *quartets = energy->getQuartets(); - - //const int numGraphNodes = numNodes + numTriplets + 5 * numQuartets; - //const int numGraphEdges = numPairs + 3 * numTriplets + 17 * numQuartets; - // cout << " numNodes " << numNodes << " numPairs " << numPairs << " " << numTriplets << endl; - #ifdef HAS_QPBO - if(verbose) cout << " has QPBO " << endl; - QPBO qpbo(numGraphNodes,numGraphEdges) ; - #endif - boost::shared_ptr FPDMODEL=boost::shared_ptr(new DiscreteModelDummy()); - - //double avg_unlabeled_ratio = 0; - - const int numSweeps = NUM_SWEEPS; - const int numLabels = energy->getNumLabels(); - int *labeling = energy->getLabeling(); - - //energy->applytestLabeling(labeling,-1); - double initEnergy = energy->evaluateTotalCostSum(); - - double lastEnergy = initEnergy; - double unlabeledAvg = 0;//unlabeledMax = 0, - double sumlabeldiff=0; + const int numNodes = energy->getNumNodes(); + const int numPairs = energy->getNumPairs(); + const int numTriplets = energy->getNumTriplets(); + const int numQuartets = energy->getNumQuartets(); + //const int numthreads = energy->getNumthreads(); + const int* pairs = energy->getPairs(); + const int* triplets = energy->getTriplets(); + const int* quartets = energy->getQuartets(); + +//const int numGraphNodes = numNodes + numTriplets + 5 * numQuartets; +//const int numGraphEdges = numPairs + 3 * numTriplets + 17 * numQuartets; +// cout << " numNodes " << numNodes << " numPairs " << numPairs << " " << numTriplets << endl; +#ifdef HAS_QPBO + if (verbose) + cout << " has QPBO " << endl; + QPBO qpbo(numGraphNodes, numGraphEdges); +#endif + boost::shared_ptr FPDMODEL = boost::shared_ptr(new DiscreteModelDummy()); + //double avg_unlabeled_ratio = 0; - for(int sweep = 0; sweep < numSweeps; ++sweep) - { - for(int label = 0; label < numLabels; ++label) - { - //cout << "1" << label << endl; - sumlabeldiff=0; + const int numSweeps = NUM_SWEEPS; + const int numLabels = energy->getNumLabels(); + int* labeling = energy->getLabeling(); - PBF pbf; - int improveCounter = 0; + //energy->applytestLabeling(labeling,-1); + double initEnergy = energy->evaluateTotalCostSum(); - double ratioUnlabeled = 0; - int nodesChanged = 0; + double lastEnergy = initEnergy; + double unlabeledAvg = 0; //unlabeledMax = 0, + double sumlabeldiff = 0; + for (int sweep = 0; sweep < numSweeps; ++sweep) { + for (int label = 0; label < numLabels; ++label) { + //cout << "1" << label << endl; + sumlabeldiff = 0; + PBF pbf; + int improveCounter = 0; - std::vector unary_data(numNodes); + double ratioUnlabeled = 0; + int nodesChanged = 0; - for(int node = 0; node < numNodes; ++node) - { - unary_data[node].buffer[0] = energy->computeUnaryCost(node,labeling[node]); //0 - unary_data[node].buffer[1] = energy->computeUnaryCost(node,label); //1 + std::vector unary_data(numNodes); - sumlabeldiff+=abs(label-labeling[node]); - } + for (int node = 0; node < numNodes; ++node) { + unary_data[node].buffer[0] = energy->computeUnaryCost(node, labeling[node]); //0 + unary_data[node].buffer[1] = energy->computeUnaryCost(node, label); //1 - //cout << " 2 " << endl; - if(sumlabeldiff>0){ - for(int node = 0; node < numNodes; ++node) - { + sumlabeldiff += abs(label - labeling[node]); + } - pbf.AddUnaryTerm(node, unary_data[node].buffer[0], unary_data[node].buffer[1]); - } + //cout << " 2 " << endl; + if (sumlabeldiff > 0) { + for (int node = 0; node < numNodes; ++node) { + pbf.AddUnaryTerm(node, unary_data[node].buffer[0], unary_data[node].buffer[1]); + } - std::vector pair_data(numPairs); + std::vector pair_data(numPairs); - for(int pair = 0; pair < numPairs; ++pair) - { - const int nodeA = pairs[pair*2]; - const int nodeB = pairs[pair*2+1]; + for (int pair = 0; pair < numPairs; ++pair) { + const int nodeA = pairs[pair * 2]; + const int nodeB = pairs[pair * 2 + 1]; - pair_data[pair].buffer[0] = energy->computePairwiseCost(pair,labeling[nodeA],labeling[nodeB]); //00 - pair_data[pair].buffer[1] = energy->computePairwiseCost(pair,labeling[nodeA],label); //01 - pair_data[pair].buffer[2] = energy->computePairwiseCost(pair,label,labeling[nodeB]); //10 - pair_data[pair].buffer[3] = energy->computePairwiseCost(pair,label,label); - //11 - } + pair_data[pair].buffer[0] = energy->computePairwiseCost(pair, labeling[nodeA], labeling[nodeB]); //00 + pair_data[pair].buffer[1] = energy->computePairwiseCost(pair, labeling[nodeA], label); //01 + pair_data[pair].buffer[2] = energy->computePairwiseCost(pair, label, labeling[nodeB]); //10 + pair_data[pair].buffer[3] = energy->computePairwiseCost(pair, label, label); + //11 + } - for(int pair = 0; pair < numPairs; ++pair) - { - const int nodeA = pairs[pair*2]; - const int nodeB = pairs[pair*2+1]; - int node_ids[2] = { nodeA, nodeB}; + for (int pair = 0; pair < numPairs; ++pair) { + const int nodeA = pairs[pair * 2]; + const int nodeB = pairs[pair * 2 + 1]; + int node_ids[2] = { nodeA, nodeB }; - pbf.AddPairwiseTerm(node_ids[0], node_ids[1], pair_data[pair].buffer[0], pair_data[pair].buffer[1], pair_data[pair].buffer[2], pair_data[pair].buffer[3]); - } - //cout << " 3 " << endl; - std::vector triplet_data(numTriplets); - //std::vector triplet_data_par(numTriplets); + pbf.AddPairwiseTerm(node_ids[0], node_ids[1], pair_data[pair].buffer[0], pair_data[pair].buffer[1], pair_data[pair].buffer[2], pair_data[pair].buffer[3]); + } + //cout << " 3 " << endl; + std::vector triplet_data(numTriplets); + //std::vector triplet_data_par(numTriplets); #ifdef HAS_TBB - tbb::task_scheduler_init init(numthreads); - parallel_for( blocked_range(0,numTriplets), computeTripletCosts(energy,triplets,labeling,label,triplet_data) ); + tbb::task_scheduler_init init(numthreads); + parallel_for(blocked_range(0, numTriplets), computeTripletCosts(energy, triplets, labeling, label, triplet_data)); #else - for (int triplet = 0; triplet < numTriplets; ++triplet) - { - const int nodeA = triplets[triplet*3]; - const int nodeB = triplets[triplet*3+1]; - const int nodeC = triplets[triplet*3+2]; - - triplet_data[triplet].buffer[0] = energy->computeTripletCost(triplet,labeling[nodeA],labeling[nodeB],labeling[nodeC]); //000 - triplet_data[triplet].buffer[1] = energy->computeTripletCost(triplet,labeling[nodeA],labeling[nodeB],label); //001 - triplet_data[triplet].buffer[2] = energy->computeTripletCost(triplet,labeling[nodeA],label,labeling[nodeC]); //010 - triplet_data[triplet].buffer[3] = energy->computeTripletCost(triplet,labeling[nodeA],label,label); //011 - triplet_data[triplet].buffer[4] = energy->computeTripletCost(triplet,label,labeling[nodeB],labeling[nodeC]); //100 - triplet_data[triplet].buffer[5] = energy->computeTripletCost(triplet,label,labeling[nodeB],label); //101 - triplet_data[triplet].buffer[6] = energy->computeTripletCost(triplet,label,label,labeling[nodeC]); //110 - triplet_data[triplet].buffer[7] = energy->computeTripletCost(triplet,label,label,label); //111 - - } + for (int triplet = 0; triplet < numTriplets; ++triplet) { + const int nodeA = triplets[triplet * 3]; + const int nodeB = triplets[triplet * 3 + 1]; + const int nodeC = triplets[triplet * 3 + 2]; + + triplet_data[triplet].buffer[0] = energy->computeTripletCost(triplet, labeling[nodeA], labeling[nodeB], labeling[nodeC]); //000 + triplet_data[triplet].buffer[1] = energy->computeTripletCost(triplet, labeling[nodeA], labeling[nodeB], label); //001 + triplet_data[triplet].buffer[2] = energy->computeTripletCost(triplet, labeling[nodeA], label, labeling[nodeC]); //010 + triplet_data[triplet].buffer[3] = energy->computeTripletCost(triplet, labeling[nodeA], label, label); //011 + triplet_data[triplet].buffer[4] = energy->computeTripletCost(triplet, label, labeling[nodeB], labeling[nodeC]); //100 + triplet_data[triplet].buffer[5] = energy->computeTripletCost(triplet, label, labeling[nodeB], label); //101 + triplet_data[triplet].buffer[6] = energy->computeTripletCost(triplet, label, label, labeling[nodeC]); //110 + triplet_data[triplet].buffer[7] = energy->computeTripletCost(triplet, label, label, label); //111 + } #endif - //cout << " 4 " << endl; - for (int triplet = 0; triplet < numTriplets; ++triplet) - { - const int nodeA = triplets[triplet*3]; - const int nodeB = triplets[triplet*3+1]; - const int nodeC = triplets[triplet*3+2]; - int node_ids[3] = { nodeA, nodeB, nodeC }; - pbf.AddHigherTerm(3, node_ids, triplet_data[triplet].buffer); - - } - - - std::vector quartet_data(numQuartets); + //cout << " 4 " << endl; + for (int triplet = 0; triplet < numTriplets; ++triplet) { + const int nodeA = triplets[triplet * 3]; + const int nodeB = triplets[triplet * 3 + 1]; + const int nodeC = triplets[triplet * 3 + 2]; + int node_ids[3] = { nodeA, nodeB, nodeC }; + pbf.AddHigherTerm(3, node_ids, triplet_data[triplet].buffer); + } + + std::vector quartet_data(numQuartets); #ifdef HAS_TBB - parallel_for( blocked_range(0,numQuartets), computeQuartetCosts(energy,quartets,labeling,label,quartet_data) ); + parallel_for(blocked_range(0, numQuartets), computeQuartetCosts(energy, quartets, labeling, label, quartet_data)); #else - for (int quartet = 0; quartet < numQuartets; ++quartet) - { - const int nodeA = quartets[quartet*4]; - const int nodeB = quartets[quartet*4+1]; - const int nodeC = quartets[quartet*4+2]; - const int nodeD = quartets[quartet*4+3]; - if(! (label==labeling[nodeA] && label==labeling[nodeB] && label==labeling[nodeC] && label==labeling[nodeD])){ - - quartet_data[quartet].buffer[0] = energy->computeQuartetCost(quartet,labeling[nodeA],labeling[nodeB],labeling[nodeC],labeling[nodeD]); - quartet_data[quartet].buffer[1] = energy->computeQuartetCost(quartet,labeling[nodeA],labeling[nodeB],labeling[nodeC],label); - quartet_data[quartet].buffer[2] = energy->computeQuartetCost(quartet,labeling[nodeA],labeling[nodeB],label,labeling[nodeD]); - quartet_data[quartet].buffer[3] = energy->computeQuartetCost(quartet,labeling[nodeA],labeling[nodeB],label,label); - - quartet_data[quartet].buffer[4] = energy->computeQuartetCost(quartet,labeling[nodeA],label,labeling[nodeC],labeling[nodeD]); - quartet_data[quartet].buffer[5] = energy->computeQuartetCost(quartet,labeling[nodeA],label,labeling[nodeC],label); - quartet_data[quartet].buffer[6] = energy->computeQuartetCost(quartet,labeling[nodeA],label,label,labeling[nodeD]); - quartet_data[quartet].buffer[7] = energy->computeQuartetCost(quartet,labeling[nodeA],label,label,label); - quartet_data[quartet].buffer[8] = energy->computeQuartetCost(quartet,label,labeling[nodeB],labeling[nodeC],labeling[nodeD]); - quartet_data[quartet].buffer[9] = energy->computeQuartetCost(quartet,label,labeling[nodeB],labeling[nodeC],label); - quartet_data[quartet].buffer[10] = energy->computeQuartetCost(quartet,label,labeling[nodeB],label,labeling[nodeD]); - quartet_data[quartet].buffer[11] = energy->computeQuartetCost(quartet,label,labeling[nodeB],label,label); - quartet_data[quartet].buffer[12] = energy->computeQuartetCost(quartet,label,label,labeling[nodeC],labeling[nodeD]); - quartet_data[quartet].buffer[13] = energy->computeQuartetCost(quartet,label,label,labeling[nodeC],label); - quartet_data[quartet].buffer[14] = energy->computeQuartetCost(quartet,label,label,label,labeling[nodeD]); - quartet_data[quartet].buffer[15] = energy->computeQuartetCost(quartet,label,label,label,label); - } - } + for (int quartet = 0; quartet < numQuartets; ++quartet) { + const int nodeA = quartets[quartet * 4]; + const int nodeB = quartets[quartet * 4 + 1]; + const int nodeC = quartets[quartet * 4 + 2]; + const int nodeD = quartets[quartet * 4 + 3]; + if (!(label == labeling[nodeA] && label == labeling[nodeB] && label == labeling[nodeC] && label == labeling[nodeD])) { + + quartet_data[quartet].buffer[0] = energy->computeQuartetCost(quartet, labeling[nodeA], labeling[nodeB], labeling[nodeC], labeling[nodeD]); + quartet_data[quartet].buffer[1] = energy->computeQuartetCost(quartet, labeling[nodeA], labeling[nodeB], labeling[nodeC], label); + quartet_data[quartet].buffer[2] = energy->computeQuartetCost(quartet, labeling[nodeA], labeling[nodeB], label, labeling[nodeD]); + quartet_data[quartet].buffer[3] = energy->computeQuartetCost(quartet, labeling[nodeA], labeling[nodeB], label, label); + + quartet_data[quartet].buffer[4] = energy->computeQuartetCost(quartet, labeling[nodeA], label, labeling[nodeC], labeling[nodeD]); + quartet_data[quartet].buffer[5] = energy->computeQuartetCost(quartet, labeling[nodeA], label, labeling[nodeC], label); + quartet_data[quartet].buffer[6] = energy->computeQuartetCost(quartet, labeling[nodeA], label, label, labeling[nodeD]); + quartet_data[quartet].buffer[7] = energy->computeQuartetCost(quartet, labeling[nodeA], label, label, label); + quartet_data[quartet].buffer[8] = energy->computeQuartetCost(quartet, label, labeling[nodeB], labeling[nodeC], labeling[nodeD]); + quartet_data[quartet].buffer[9] = energy->computeQuartetCost(quartet, label, labeling[nodeB], labeling[nodeC], label); + quartet_data[quartet].buffer[10] = energy->computeQuartetCost(quartet, label, labeling[nodeB], label, labeling[nodeD]); + quartet_data[quartet].buffer[11] = energy->computeQuartetCost(quartet, label, labeling[nodeB], label, label); + quartet_data[quartet].buffer[12] = energy->computeQuartetCost(quartet, label, label, labeling[nodeC], labeling[nodeD]); + quartet_data[quartet].buffer[13] = energy->computeQuartetCost(quartet, label, label, labeling[nodeC], label); + quartet_data[quartet].buffer[14] = energy->computeQuartetCost(quartet, label, label, label, labeling[nodeD]); + quartet_data[quartet].buffer[15] = energy->computeQuartetCost(quartet, label, label, label, label); + } + } #endif - for (int quartet = 0; quartet < numQuartets; ++quartet) - { - const int nodeA = quartets[quartet*4]; - const int nodeB = quartets[quartet*4+1]; - const int nodeC = quartets[quartet*4+2]; - const int nodeD = quartets[quartet*4+3]; - if(! (label==labeling[nodeA] && label==labeling[nodeB] && label==labeling[nodeC] && label==labeling[nodeD])){ - - int node_ids[4] = { nodeA, nodeB, nodeC, nodeD }; - pbf.AddHigherTerm(4, node_ids, quartet_data[quartet].buffer); - } - } - double newEnergy; + for (int quartet = 0; quartet < numQuartets; ++quartet) { + const int nodeA = quartets[quartet * 4]; + const int nodeB = quartets[quartet * 4 + 1]; + const int nodeC = quartets[quartet * 4 + 2]; + const int nodeD = quartets[quartet * 4 + 3]; + if (!(label == labeling[nodeA] && label == labeling[nodeB] && label == labeling[nodeC] && label == labeling[nodeD])) { + + int node_ids[4] = { nodeA, nodeB, nodeC, nodeD }; + pbf.AddHigherTerm(4, node_ids, quartet_data[quartet].buffer); + } + } + double newEnergy; #ifdef HAS_QPBO - qpbo.Reset(); - reduce_and_convert(pbf, qpbo, reductionMode); - qpbo.MergeParallelEdges(); - qpbo.Solve(); - - for(int node = 0; node < numNodes; ++node) { - if(labeling[node] != label) - { - if(qpbo.GetLabel(node) < 0) unlabeledNodes++; - } - } - - //TRY QPBO-I to improve the solution - if(unlabeledNodes > 0) - { - srand ( static_cast(time(NULL)) ); - - int numTrials = MAX_IMPROVEMENTS; - const double ratioThresh = 0.3; - ratioUnlabeled = static_cast(unlabeledNodes) / static_cast(numNodes); - if (ratioUnlabeled < ratioThresh) numTrials = static_cast(0.5+ratioUnlabeled*numTrials/ratioThresh); - - if(MAX_IMPROVEMENTS > 0) - { - for(int i = 0; i < numTrials; ++i) - { - if(qpbo.Improve()) improveCounter++; - } - } - - if(ratioUnlabeled > unlabeledMax) unlabeledMax = ratioUnlabeled; - unlabeledAvg += ratioUnlabeled; - } - - - - - - for(int node = 0; node < numNodes; ++node) - { - if(labeling[node] != label) - { - if(qpbo.GetLabel(node) == 1) { labeling[node] = label; nodesChanged++; } - } - } - - if(verbose){//energy->applytestLabeling(labeling,label); - newEnergy = energy->evaluateTotalCostSum(); -} + qpbo.Reset(); + reduce_and_convert(pbf, qpbo, reductionMode); + qpbo.MergeParallelEdges(); + qpbo.Solve(); + + for (int node = 0; node < numNodes; ++node) { + if (labeling[node] != label) { + if (qpbo.GetLabel(node) < 0) + unlabeledNodes++; + } + } + + //TRY QPBO-I to improve the solution + if (unlabeledNodes > 0) { + srand(static_cast(time(NULL))); + + int numTrials = MAX_IMPROVEMENTS; + const double ratioThresh = 0.3; + ratioUnlabeled = static_cast(unlabeledNodes) / static_cast(numNodes); + if (ratioUnlabeled < ratioThresh) + numTrials = static_cast(0.5 + ratioUnlabeled * numTrials / ratioThresh); + + if (MAX_IMPROVEMENTS > 0) { + for (int i = 0; i < numTrials; ++i) { + if (qpbo.Improve()) + improveCounter++; + } + } + + if (ratioUnlabeled > unlabeledMax) + unlabeledMax = ratioUnlabeled; + unlabeledAvg += ratioUnlabeled; + } + + for (int node = 0; node < numNodes; ++node) { + if (labeling[node] != label) { + if (qpbo.GetLabel(node) == 1) { + labeling[node] = label; + nodesChanged++; + } + } + } + + if (verbose) { //energy->applytestLabeling(labeling,label); + newEnergy = energy->evaluateTotalCostSum(); + } #else - FPDMODEL->reset(); - // cout << "HOCR fastPD " << endl; - reduce_and_convert(pbf,*FPDMODEL, reductionMode); - // exit(1); - FPDMODEL->initialise(); - int *Labels=FPDMODEL->getLabeling(); - FPD::FastPD opt(FPDMODEL, 100 ); - newEnergy = opt.run(); - opt.getLabeling(Labels); - - for(int node = 0; node < numNodes; ++node) - { - // cout << node << " labeling[node] " << labeling[node] << endl; - if(labeling[node] != label) - { - // cout << "Labels[node] " << Labels[node] << endl; - if(Labels[node] == 1) { labeling[node] = label; nodesChanged++; } - } - } + FPDMODEL->reset(); + // cout << "HOCR fastPD " << endl; + reduce_and_convert(pbf, *FPDMODEL, reductionMode); + // exit(1); + FPDMODEL->initialise(); + int* Labels = FPDMODEL->getLabeling(); + FPD::FastPD opt(FPDMODEL, 100); + newEnergy = opt.run(); + opt.getLabeling(Labels); + + for (int node = 0; node < numNodes; ++node) { + // cout << node << " labeling[node] " << labeling[node] << endl; + if (labeling[node] != label) { + // cout << "Labels[node] " << Labels[node] << endl; + if (Labels[node] == 1) { + labeling[node] = label; + nodesChanged++; + } + } + } #endif + // - // - - if(verbose){ - - // - energy->report(); - std::cout << " LAB " << label << ":\t" << lastEnergy << " -> " << newEnergy << " / " << ratioUnlabeled * 100 << "% UNL / " << nodesChanged / static_cast(numNodes) * 100 << "% CHN / IMP: " << improveCounter << std::endl; - lastEnergy = newEnergy; - } + if (verbose) { + // + energy->report(); + std::cout << " LAB " << label << ":\t" << lastEnergy << " -> " << newEnergy << " / " << ratioUnlabeled * 100 << "% UNL / " << nodesChanged / static_cast(numNodes) * 100 << "% CHN / IMP: " << improveCounter << std::endl; + lastEnergy = newEnergy; + } - // exit(1); - } - - } + // exit(1); + } + } } - unlabeledAvg /= static_cast(numLabels*numSweeps); + unlabeledAvg /= static_cast(numLabels * numSweeps); #ifndef PRINT_ENERGY -//cout << " evaluateTotalCost " << endl; + //cout << " evaluateTotalCost " << endl; //energy->applytestLabeling(labeling,numLabels+1); lastEnergy = energy->evaluateTotalCostSum(); #endif return lastEnergy; - - } +} }