55 #include "core/common/WStringUtils.h"
57 #include "WHtreeProcesser.h"
79 if( pruneType == HTPR_SIZERATIO )
82 throw std::runtime_error(
"ERROR @ WHtreeProcesser::pruneTree(): size pruning ratio must be equal or greater than 2" );
84 else if( pruneType == HTPR_JOINSIZE )
86 condition = std::floor( condition );
87 if( condition < safeSize )
88 throw std::runtime_error(
89 "ERROR @ WHtreeProcesser::pruneTree(): size pruning lower boundary must be smaller than greater boundary" );
91 else if( pruneType == HTPR_JOINLEVEL )
93 if( condition <= 0 || condition >= 1 )
95 throw std::runtime_error(
"ERROR @ WHtreeProcesser::pruneTree(): condition is out of boundaries" );
99 throw std::runtime_error(
100 "ERROR @ WHtreeProcesser::pruneTree(): when pruning by distance level a safe size smaller than the roi size must be entered" );
104 size_t prunedLeaves( 0 ), prunedNodes( 0 );
109 size_t parentID( leavesIter->getParent().second );
112 if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
114 leavesIter->setFlag(
true );
116 else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
118 size_t biggerSize( 0 );
120 for(
size_t i = 0; i < kids.size(); ++i )
123 if( brotherSize > biggerSize )
125 biggerSize = brotherSize;
128 if( biggerSize > condition )
130 leavesIter->setFlag(
true );
136 for( std::vector< WHnode >::iterator nodesIter(
m_tree.
m_nodes.begin() ); nodesIter !=
m_tree.
m_nodes.end() - 1; ++nodesIter )
138 size_t parentID( nodesIter->getParent().second );
139 size_t nodeSize( nodesIter->getSize() );
141 bool pruneBranch(
false );
143 if( nodeSize < safeSize )
145 if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
149 else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
151 size_t biggerSize( 0 );
153 for(
size_t i = 0; i < kids.size(); ++i )
155 if( kids[i] == nodesIter->getFullID() )
160 if( brotherSize > biggerSize )
162 biggerSize = brotherSize;
166 if( ( pruneType == HTPR_SIZERATIO ) && ( biggerSize > ( nodeSize * condition ) ) )
171 if( ( pruneType == HTPR_JOINSIZE ) && ( biggerSize >= condition ) )
180 std::list< nodeID_t > worklist;
181 worklist.push_back( nodesIter->getFullID() );
182 while( !worklist.empty() )
185 worklist.pop_front();
192 std::vector< nodeID_t > currentKids( currentNode->
getChildren() );
193 worklist.insert( worklist.end(), currentKids.begin(), currentKids.end() );
201 if( leavesIter->isFlagged() )
208 for( std::vector< WHnode >::iterator nodesIter(
m_tree.
m_nodes.begin() ); nodesIter !=
m_tree.
m_nodes.end() - 1; ++nodesIter )
210 if( nodesIter->isFlagged() )
214 if( pruneType == HTPR_SIZERATIO )
218 else if( pruneType == HTPR_JOINSIZE )
222 else if( pruneType == HTPR_JOINLEVEL )
239 throw std::runtime_error(
240 "ERROR @ WHtreeProcesser::pruneRandom(): too many seeds to be pruned! (more than leaves in the tree)" );
244 for(
size_t i = 0; i < prunedIDs.size(); ++i )
248 size_t prunedLeaves( 0 );
250 while( prunedLeaves < numberPruned )
252 size_t prunedPosition = ( rand_r( &seed ) % prunedIDs.size() );
259 prunedIDs.erase( prunedIDs.begin() + prunedPosition );
262 float perone( perthousand / 1000. );
277 std::cerr <<
"ERROR @ WHtreeProcesser::collapseTree(): flattening interval must be smaller than 1" << std::endl;
295 m_tree.
m_treeName += (
"_flat" + str( boost::format(
"%1.3f" ) % flatGap ) );
305 if( coefficient <= 0 || coefficient >= 1 )
307 std::cerr <<
"ERROR @ WHtreeProcesser::collapseTreeLinear(): coefficient must be in the range (0,1 )" << std::endl;
318 m_tree.
m_treeName += (
"_flatL" + str( boost::format(
"%1.3f" ) % coefficient ) );
328 if( coefficient <= 0 || coefficient >= 1 )
330 std::cerr <<
"ERROR @ WHtreeProcesser::collapseTreeLinear(): coefficient must be in the range (0,1 )" << std::endl;
341 m_tree.
m_treeName += (
"_flatSQ" + str( boost::format(
"%1.3f" ) % coefficient ) );
354 std::cerr <<
"ERROR @ WHtreeProcesser::flattenTree(): flattening interval must be smaller than 1" << std::endl;
361 std::reverse( branchNodes.begin(), branchNodes.end() );
363 for( std::vector< size_t >::iterator nodesIter( branchNodes.begin() ); nodesIter != branchNodes.end(); ++nodesIter )
412 if( coarseRatio < 2 )
417 std::map< WHcoord, size_t > roimap;
420 std::vector< std::vector< std::vector< bool > > > roimatrix;
422 for(
size_t i = 0; i < roimatrix.size(); ++i )
425 for(
size_t j = 0; j < roimatrix[i].size(); ++j )
434 roimatrix[coordIter->m_x][coordIter->m_y][coordIter->m_z] =
true;
435 roimap.insert( std::make_pair( *coordIter, count++ ) );
440 for( std::list< WHcoord >::iterator iter( newDiscarded.begin() ); iter != newDiscarded.end(); ++iter )
442 iter->m_x = iter->m_x / coarseRatio;
443 iter->m_y = iter->m_y / coarseRatio;
444 iter->m_z = iter->m_z / coarseRatio;
447 newDiscarded.unique();
459 std::list< WHcoord > bigGridVoxel;
461 for(
unsigned int n = 0; n < coarseRatio; ++n )
463 for(
unsigned int m = 0; m < coarseRatio; ++m )
465 for(
unsigned int l = 0; l < coarseRatio; ++l )
467 if( roimatrix[i + l][j + m][k + n] )
469 WHcoord tempCoord( i + l, j + m, k + n );
470 bigGridVoxel.push_back( tempCoord );
475 if( !bigGridVoxel.empty() )
477 WHcoord keptCoord( bigGridVoxel.front() );
478 bigGridVoxel.pop_front();
479 size_t keptID( roimap[keptCoord] );
480 WHcoord newCoord( keptCoord.
m_x / coarseRatio, keptCoord.
m_y / coarseRatio, keptCoord.
m_z / coarseRatio );
483 for( std::list< WHcoord >::iterator iter( bigGridVoxel.begin() ); iter != bigGridVoxel.end(); ++iter )
485 size_t decimatedID( roimap[*iter] );
509 std::cerr <<
"ERROR @ WHtreeProcesser::baseNodes2Leaves(): base nodes have both leaves and other nodes as children,";
510 std::cerr <<
" tree wont be processed" << std::endl;
515 for(
size_t i = 0; i < bases.size(); ++i )
519 for(
size_t j = 1; j < leaves4node.size(); ++j )
571 std::cerr <<
"WARNING@ flattenSelection: base nodes have mixed nodes and leaves, flattening will be standard " << std::endl;
572 keepBaseNodes =
false;
574 while( !selection.empty() )
576 size_t thisNode( selection.front() );
577 selection.pop_front();
579 for(
size_t i = 0; i < kids.size(); ++i )
590 selection.push_back( kids[i].second );
598 return pruned.second;
602 std::list< size_t > worklist( selection.begin(), selection.end() );
607 std::list< size_t > worklist;
608 for( std::vector< nodeID_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
612 worklist.push_back( iter->second );
634 for( std::vector< size_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
643 for( std::vector< nodeID_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
652 for( std::vector< size_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
663 if( !thisNodeID.first )
669 collapseNode( thisNodeID.second, coefficient, collapseMode );
678 throw std::runtime_error(
"ERROR @ collapseNode::flattenBranch(): nodeID is out of boundaries" );
683 std::list< nodeID_t > worklist;
684 worklist.push_back( thisNode.
getFullID() );
685 while( !worklist.empty() )
688 worklist.pop_front();
689 std::vector< nodeID_t > currentKids( currentNode->
getChildren() );
691 for( std::vector< nodeID_t >::iterator kidIter( currentKids.begin() ); kidIter != currentKids.end(); ++kidIter )
697 bool doCollapse(
false );
699 switch( collapseMode )
701 case HTPR_C_CONSTANT:
702 doCollapse = ( ( parentLevel - kidLevel ) < coefficient );
705 doCollapse = ( ( parentLevel - kidLevel ) < ( kidLevel * coefficient ) );
708 doCollapse = ( ( parentLevel - kidLevel ) < ( kidLevel * kidLevel * coefficient ) );
716 worklist.push_back( *kidIter );
this class to contain a seed voxel coordinate.
this class implements a hierarchical tree node with several relevant attributes
size_t getSize() const
returns number of elements contained by the node
bool isFlagged() const
returns true if object is flagged for pruning
size_t getHLevel() const
returns maximum number of nodes between the node and a leaf element
size_t getID() const
returns node/leaf ID
void setFlag(const bool newFlag)
sets the prune flag to the indicated value
dist_t getDistLevel() const
returns distance level at which the element was formed
void setDistLevel(const dist_t newLevel)
sets the distance level field to the specified value
bool isNode() const
returns true if object is a node
nodeID_t getFullID() const
returns full ID
std::vector< nodeID_t > getChildren() const
returns a vector with the ids of the children of that node
std::pair< size_t, size_t > pruneRandom(const size_t numberPruned, unsigned int seed=0)
Prunes the tree from randomly chosen leaves.
WHtree & m_tree
tree object
void forceMonotonicityDown()
calls on private WHtree member to eliminate non monotonic steps in the tree top-down,...
size_t debinarize(const bool keepBaseNodes)
calls on private WHtree member to merge nodes joining binary at the same level into non-binary struct...
void flagSelection(const std::vector< size_t > &selection)
set flags for pruning all of the subtrees indicated (using only non-leaf node ID)
size_t collapseTreeLinear(const dist_t coefficient, const bool keepBaseNodes)
Collapses the nodes of the tree that have branch lenghts smoller than the distance level multiplied b...
size_t collapseTreeSquare(const dist_t coefficient, const bool keepBaseNodes)
Collapses the nodes of the tree that have branch lenghts smoller than the squared distance level mult...
size_t baseNodes2Leaves()
converts the base nodes into leaves, pruning out all excess leaves and information
size_t flattenSelection(const std::list< size_t > selection, const bool keepBaseNodes)
Collapses all the nodes of the subtrees indicated (using only non-leaf node ID)
size_t collapseBranch(const dist_t flatGap, const dist_t distLevelLimit, size_t root, const bool keepBaseNodes)
Collapses the nodes of the subtree that have branch lenghts equal or lower to the one indicated.
~WHtreeProcesser()
Destructor.
void flagLeaves(const std::vector< size_t > &selection)
set flags for pruning all of the leaves indicated
size_t collapseTree(const dist_t flatGap, const dist_t distLevelLimit, const bool keepBaseNodes)
Collapses the nodes of the tree that have branch lenghts equal or lower to the one indicated.
void forceMonotonicityUp()
calls on private WHtree member to eliminate non monotonic steps in the tree bottom-up,...
void coarseTree(const unsigned int coarseRatio)
Reduces the tree grid size by the ratio specified (as if it had been obtained from an image of lower ...
WHtreeProcesser(WHtree *const tree)
Constructor.
size_t flattenBranch(size_t root, const bool keepBaseNodes)
Collapses all the nodes of the subtree.
void collapseNode(const size_t thisNodeID, const dist_t coefficient, HTPROC_COLLAPSE collapseMode=HTPR_C_CONSTANT)
eliminates branchings in the tree, raising them to the parent level
std::pair< size_t, size_t > pruneSelection(const std::vector< size_t > &selection)
Prunes all of the subtrees indicated (using only non-leaf node ID)
std::pair< size_t, size_t > pruneTree(float condition, size_t safeSize, const HTPROC_MODE pruneType)
Prunes the tree according to the options specified.
void forceMonotonicity(double errorMult=1)
calls on private WHtree member to eliminate non monotonic steps in the tree while keeping as much inf...
this class implements a hierarchical tree and provides functions for creation, partitioning,...
std::vector< size_t > getRootBaseNodes() const
returns a vector with all the nodes that have direct link to leaves from the main root
const WHnode & getRoot() const
returns a const reference to the root node
std::vector< WHcoord > m_coordinates
Stores the coordinates of the leaf voxels.
std::vector< size_t > getLeaves4node(const size_t nodeID) const
Returns a vector with all the leaf IDs contained in that cluster.
WHcoord m_datasetSize
Stores the size of the dataset this tree was built from.
std::vector< WHnode > m_nodes
Stores all the nodes (non-leaves) of the tree.
const WHnode & getNode(const nodeID_t &thisNode) const
returns a const pointer to the node indicated by the ID
void forceMonotonicityDown()
eliminates non monotonic steps in the tree top-down, raising the level of parents involved in the non...
size_t debinarize(const bool keepBaseNodes=false)
merges nodes joining binary at the same level into non-binary structures
std::vector< WHnode > m_leaves
Stores all the leaves of the tree (represents a single voxel, for several purposes a leaf also counts...
WHnode * fetchNode(const nodeID_t &thisNode)
returns a pointer to the node indicated by the ID
std::pair< size_t, size_t > cleanup(std::vector< size_t > *outLookup=0)
cleans leaves/nodes set to be pruned
void forceMonotonicity(double errorMult=1)
eliminates non monotonic steps in the tree while keeping as much information as possible.
std::string m_treeName
Stores the name of the tree file.
bool testRootBaseNodes() const
tests if all base nodes have only leaf children
std::vector< size_t > getBranchNodes(const size_t nodeID) const
Returns a vector with all the node IDs contained in that branch.
WHnode * fetchLeaf(const size_t thisLeaf)
returns a pointer to the leaf indicated by the ID
size_t getNumLeaves() const
Returns the number of leaves of the tree.
std::list< WHcoord > m_discarded
Stores the coordinates of the voxels that were discarded during the process of building the tree.
void forceMonotonicityUp()
eliminates non monotonic steps in the tree bottom-up, lowering the level of children involved in the ...
std::string toString(const T &value)
Convert a given value to a string.