OpenWalnut  1.5.0dev
WHtreeProcesser.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 //---------------------------------------------------------------------------
26 //
27 // Project: hClustering
28 //
29 // Whole-Brain Connectivity-Based Hierarchical Parcellation Project
30 // David Moreno-Dominguez
31 // d.mor.dom@gmail.com
32 // moreno@cbs.mpg.de
33 // www.cbs.mpg.de/~moreno//
34 // This file is also part of OpenWalnut ( http://www.openwalnut.org ).
35 //
36 // hClustering is free software: you can redistribute it and/or modify
37 // it under the terms of the GNU Lesser General Public License as published by
38 // the Free Software Foundation, either version 3 of the License, or
39 // (at your option) any later version.
40 // http://creativecommons.org/licenses/by-nc/3.0
41 //
42 // hClustering is distributed in the hope that it will be useful,
43 // but WITHOUT ANY WARRANTY; without even the implied warranty of
44 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 // GNU Lesser General Public License for more details.
46 //
47 //---------------------------------------------------------------------------
48 
49 #include <vector>
50 #include <list>
51 #include <string>
52 #include <utility>
53 #include <map>
54 
55 #include "core/common/WStringUtils.h"
56 
57 #include "WHtreeProcesser.h"
58 
59 
60 WHtreeProcesser::WHtreeProcesser( WHtree* const tree ) : m_tree( *tree )
61 {
62 }
63 
65 {
66  //Cleanup
67 }
68 
69 // === PUBLIC MEMBER FUNCTIONS ===
70 
71 
72 std::pair< size_t, size_t > WHtreeProcesser::pruneTree( float condition, size_t safeSize, const HTPROC_MODE pruneType )
73 {
74  if( safeSize == 0 )
75  {
76  safeSize = m_tree.getNumLeaves(); // any cluster no matter what size may be pruned if he meets the conditions
77  }
78 
79  if( pruneType == HTPR_SIZERATIO )
80  {
81  if( condition < 2 )
82  throw std::runtime_error( "ERROR @ WHtreeProcesser::pruneTree(): size pruning ratio must be equal or greater than 2" );
83  }
84  else if( pruneType == HTPR_JOINSIZE )
85  {
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" );
90  }
91  else if( pruneType == HTPR_JOINLEVEL )
92  {
93  if( condition <= 0 || condition >= 1 )
94  {
95  throw std::runtime_error( "ERROR @ WHtreeProcesser::pruneTree(): condition is out of boundaries" );
96  }
97  if( safeSize >= m_tree.getNumLeaves() )
98  {
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" );
101  }
102  }
103 
104  size_t prunedLeaves( 0 ), prunedNodes( 0 );
105 
106  // loop through all leaves and set them to prune if they match discardidng conditions
107  for( std::vector< WHnode >::iterator leavesIter( m_tree.m_leaves.begin() ); leavesIter != m_tree.m_leaves.end(); ++leavesIter )
108  {
109  size_t parentID( leavesIter->getParent().second );
110  size_t parentLevel( m_tree.getNode( parentID ).getDistLevel() );
111 
112  if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
113  {
114  leavesIter->setFlag( true );
115  }
116  else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
117  {
118  size_t biggerSize( 0 );
119  std::vector< nodeID_t > kids( m_tree.getNode( parentID ).getChildren() );
120  for( size_t i = 0; i < kids.size(); ++i )
121  {
122  size_t brotherSize( m_tree.getNode( kids[i] ).getSize() );
123  if( brotherSize > biggerSize )
124  {
125  biggerSize = brotherSize;
126  }
127  }
128  if( biggerSize > condition )
129  {
130  leavesIter->setFlag( true );
131  }
132  }
133  }
134 
135  // loop through all nodes and set them to prune if they match discarding conditions
136  for( std::vector< WHnode >::iterator nodesIter( m_tree.m_nodes.begin() ); nodesIter != m_tree.m_nodes.end() - 1; ++nodesIter )
137  { // dont check last node
138  size_t parentID( nodesIter->getParent().second );
139  size_t nodeSize( nodesIter->getSize() );
140  size_t parentLevel( m_tree.getNode( parentID ).getDistLevel() );
141  bool pruneBranch( false );
142 
143  if( nodeSize < safeSize )
144  {
145  if( ( pruneType == HTPR_JOINLEVEL ) && ( parentLevel > condition ) )
146  {
147  pruneBranch = true;
148  }
149  else if( ( pruneType == HTPR_SIZERATIO ) || ( pruneType == HTPR_JOINSIZE ) )
150  {
151  size_t biggerSize( 0 );
152  std::vector< nodeID_t > kids( m_tree.getNode( parentID ).getChildren() );
153  for( size_t i = 0; i < kids.size(); ++i )
154  {
155  if( kids[i] == nodesIter->getFullID() )
156  {
157  continue;
158  }
159  size_t brotherSize( m_tree.getNode( kids[i] ).getSize() );
160  if( brotherSize > biggerSize )
161  {
162  biggerSize = brotherSize;
163  }
164  }
165 
166  if( ( pruneType == HTPR_SIZERATIO ) && ( biggerSize > ( nodeSize * condition ) ) )
167  {
168  pruneBranch = true;
169  }
170 
171  if( ( pruneType == HTPR_JOINSIZE ) && ( biggerSize >= condition ) )
172  {
173  pruneBranch = true;
174  }
175  }
176  }
177 
178  if( pruneBranch )
179  {
180  std::list< nodeID_t > worklist;
181  worklist.push_back( nodesIter->getFullID() );
182  while( !worklist.empty() )
183  {
184  WHnode* currentNode( m_tree.fetchNode( worklist.front() ) );
185  worklist.pop_front();
186  // if current node has already been pruned we continue with the next iteration
187  if( currentNode->isFlagged() )
188  {
189  continue;
190  }
191  currentNode->setFlag( true );
192  std::vector< nodeID_t > currentKids( currentNode->getChildren() );
193  worklist.insert( worklist.end(), currentKids.begin(), currentKids.end() );
194  }
195  }
196  }
197 
198  // count total pruned leaves
199  for( std::vector< WHnode >::iterator leavesIter( m_tree.m_leaves.begin() ); leavesIter != m_tree.m_leaves.end(); ++leavesIter )
200  {
201  if( leavesIter->isFlagged() )
202  {
203  ++prunedLeaves;
204  }
205  }
206 
207  // count total pruned nodes
208  for( std::vector< WHnode >::iterator nodesIter( m_tree.m_nodes.begin() ); nodesIter != m_tree.m_nodes.end() - 1; ++nodesIter )
209  {
210  if( nodesIter->isFlagged() )
211  ++prunedNodes;
212  }
213 
214  if( pruneType == HTPR_SIZERATIO )
215  {
216  m_tree.m_treeName += ( "_prunedR" + string_utils::toString( safeSize ) + ":" + string_utils::toString( condition ) );
217  }
218  else if( pruneType == HTPR_JOINSIZE )
219  {
220  m_tree.m_treeName += ( "_prunedS" + string_utils::toString( condition ) + ":" + string_utils::toString( safeSize ) );
221  }
222  else if( pruneType == HTPR_JOINLEVEL )
223  {
224  m_tree.m_treeName += ( "_prunedL" + string_utils::toString( safeSize ) + ":" + string_utils::toString( condition ) );
225  }
226 
227  std::pair< size_t, size_t > pruned( m_tree.cleanup() );
228 
229  pruned.second += m_tree.debinarize();
230 
231  return pruned;
232 } // end "pruneTree()" -----------------------------------------------------------------
233 
234 
235 std::pair< size_t, size_t > WHtreeProcesser::pruneRandom( const size_t numberPruned, unsigned int seed )
236 {
237  if( numberPruned >= m_tree.getNumLeaves() )
238  {
239  throw std::runtime_error(
240  "ERROR @ WHtreeProcesser::pruneRandom(): too many seeds to be pruned! (more than leaves in the tree)" );
241  }
242 
243  std::vector< size_t > prunedIDs( m_tree.getNumLeaves(), 0 );
244  for( size_t i = 0; i < prunedIDs.size(); ++i )
245  {
246  prunedIDs[i] = i;
247  }
248  size_t prunedLeaves( 0 );
249 
250  while( prunedLeaves < numberPruned )
251  {
252  size_t prunedPosition = ( rand_r( &seed ) % prunedIDs.size() );
253  if( m_tree.fetchLeaf( prunedIDs[prunedPosition] )->isFlagged() )
254  {
255  continue;
256  }
257  m_tree.fetchLeaf( prunedIDs[prunedPosition] )->setFlag( true );
258  ++prunedLeaves;
259  prunedIDs.erase( prunedIDs.begin() + prunedPosition );
260  }
261  unsigned int perthousand( numberPruned * 1000. / m_tree.getNumLeaves() );
262  float perone( perthousand / 1000. );
263  m_tree.m_treeName += ( "_randpruned" + string_utils::toString( perone ) );
264 
265  std::pair< size_t, size_t > pruned( m_tree.cleanup() );
266 
267  pruned.second += m_tree.debinarize();
268 
269  return pruned;
270 } // end "pruneRandom()" -----------------------------------------------------------------
271 
272 
273 size_t WHtreeProcesser::collapseTree( const dist_t flatGap, const dist_t distLevelLimit, const bool keepBaseNodes )
274 {
275  if( flatGap >= 1 )
276  {
277  std::cerr << "ERROR @ WHtreeProcesser::collapseTree(): flattening interval must be smaller than 1" << std::endl;
278  return 0;
279  }
280 
281  if( flatGap == 0 )
282  {
284  }
285  else
286  {
287  // flatten all levels
288  for( int32_t i = m_tree.getRoot().getID(); i >= 0; --i )
289  {
290  if( m_tree.getNode( i ).getDistLevel() > distLevelLimit )
291  {
292  collapseNode( i, flatGap );
293  }
294  }
295  m_tree.m_treeName += ( "_flat" + str( boost::format( "%1.3f" ) % flatGap ) );
296  }
297 
298  size_t collapsed( m_tree.debinarize( keepBaseNodes ) );
299 
300  return collapsed;
301 } // end "collapseTree()" -----------------------------------------------------------------
302 
303 size_t WHtreeProcesser::collapseTreeLinear( const dist_t coefficient, const bool keepBaseNodes )
304 {
305  if( coefficient <= 0 || coefficient >= 1 )
306  {
307  std::cerr << "ERROR @ WHtreeProcesser::collapseTreeLinear(): coefficient must be in the range (0,1 )" << std::endl;
308  return 0;
309  }
310 
311  else
312  {
313  // flatten all levels
314  for( int32_t i = m_tree.getRoot().getID(); i >= 0; --i )
315  {
316  collapseNode( i, coefficient, HTPR_C_LINEAR );
317  }
318  m_tree.m_treeName += ( "_flatL" + str( boost::format( "%1.3f" ) % coefficient ) );
319  }
320 
321  size_t collapsed( m_tree.debinarize( keepBaseNodes ) );
322 
323  return collapsed;
324 } // end "collapseTreeLinear()" -----------------------------------------------------------------
325 
326 size_t WHtreeProcesser::collapseTreeSquare( const dist_t coefficient, const bool keepBaseNodes )
327 {
328  if( coefficient <= 0 || coefficient >= 1 )
329  {
330  std::cerr << "ERROR @ WHtreeProcesser::collapseTreeLinear(): coefficient must be in the range (0,1 )" << std::endl;
331  return 0;
332  }
333 
334  else
335  {
336  // flatten all levels
337  for( int32_t i = m_tree.getRoot().getID(); i >= 0; --i )
338  {
339  collapseNode( i, coefficient, HTPR_C_SQ );
340  }
341  m_tree.m_treeName += ( "_flatSQ" + str( boost::format( "%1.3f" ) % coefficient ) );
342  }
343 
344  size_t collapsed( m_tree.debinarize( keepBaseNodes ) );
345 
346  return collapsed;
347 } // end "collapseTreeSquare()" -----------------------------------------------------------------
348 
349 
350 size_t WHtreeProcesser::collapseBranch( const dist_t flatGap, const dist_t distLevelLimit, size_t root, const bool keepBaseNodes )
351 {
352  if( flatGap >= 1 )
353  {
354  std::cerr << "ERROR @ WHtreeProcesser::flattenTree(): flattening interval must be smaller than 1" << std::endl;
355  return 0;
356  }
357 
358  std::vector< size_t > branchNodes( m_tree.getBranchNodes( root ) );
359 
360  //put higher hierarchy first:
361  std::reverse( branchNodes.begin(), branchNodes.end() );
362  // flatten levels
363  for( std::vector< size_t >::iterator nodesIter( branchNodes.begin() ); nodesIter != branchNodes.end(); ++nodesIter )
364  {
365  if( m_tree.getNode( *nodesIter ).getDistLevel() > distLevelLimit )
366  {
367  collapseNode( *nodesIter, flatGap );
368  }
369  }
370 
371  size_t collapsed( m_tree.debinarize( keepBaseNodes ) );
372 
373  return collapsed;
374 } // end "collapseBranch()" -----------------------------------------------------------------
375 
376 
377 //std::pair< size_t, size_t > WHtreeProcesser::smoothTree( const size_t safeSize, const size_t smoothSize, const dist_t smoothGap )
378 //{
379 // std::pair< size_t, size_t > firstPruned, secondPruned, finalPruned;
380 // size_t firstCollapsed( 0 ), secondCollapsed( 0 ), biggestSize( 0 );
381 
382 // //1st stage: prune clusters smaller than safeSize that join clusters bigger than smoothSize
383 // firstPruned = pruneTree( smoothSize, safeSize, HTPR_JOINSIZE );
384 
385 // //2nd stage: find smooth clusters with gaps smaller than smoothGap and flatten them
386 // std::vector< nodeID_t > partition;
387 // m_tree.partitionSmooth( smoothGap, &partition, true, m_tree.getRoot().getID() );
388 // firstCollapsed = flattenSelection( partition, false );
389 
390 // //3rd stage: prune clusters smaller than half of smoothSize that join clusters bigger than double smoothSize
391 // secondPruned = pruneTree( ( 2 * smoothSize ), ( smoothSize / 2 ), HTPR_JOINSIZE );
392 
393 // //4th stage: find a partition of clusters not bigger than smoothSize (unless undivisible) and flatten them
394 // partition.clear();
395 // biggestSize = m_tree.partitionClassic( smoothSize, &partition, HTP_SIZE, HTC_VALUE, true, m_tree.getRoot().getID() );
396 // secondCollapsed = flattenSelection( partition, false );
397 
398 // // output value (eliminated leaves and nodes)
399 // finalPruned.first = firstPruned.first + firstCollapsed + secondPruned.first + secondCollapsed;
400 // finalPruned.second = firstPruned.second + secondPruned.second;
401 
402 // // change name
403 // m_tree.m_treeName += ( "_smooth" + string_utils::toString( safeSize ) + ":" + string_utils::toString(
404 // smoothSize ) + ":" + str( boost::format( "%1.3f" ) % smoothGap ) );
405 
406 // return finalPruned;
407 //} // end "smoothTree()" -----------------------------------------------------------------
408 
409 
410 void WHtreeProcesser::coarseTree( const unsigned int coarseRatio )
411 {
412  if( coarseRatio < 2 )
413  {
414  return;
415  }
416 
417  std::map< WHcoord, size_t > roimap;
418  size_t count( 0 );
419  //create a matrix with seed voxels positions
420  std::vector< std::vector< std::vector< bool > > > roimatrix;
421  roimatrix.resize( m_tree.m_datasetSize.m_x );
422  for( size_t i = 0; i < roimatrix.size(); ++i )
423  {
424  roimatrix[i].resize( m_tree.m_datasetSize.m_y );
425  for( size_t j = 0; j < roimatrix[i].size(); ++j )
426  {
427  roimatrix[i][j].resize( m_tree.m_datasetSize.m_z, false );
428  }
429  }
430 
431  for( std::vector< WHcoord >::const_iterator coordIter = m_tree.m_coordinates.begin(); coordIter != m_tree.m_coordinates.end(); ++coordIter )
432  {
433  //std::cout <<*coord_iter<< std::endl;
434  roimatrix[coordIter->m_x][coordIter->m_y][coordIter->m_z] = true;
435  roimap.insert( std::make_pair( *coordIter, count++ ) );
436  }
437 
438  // convert previously discarded elements to new grid
439  std::list< WHcoord > newDiscarded( m_tree.m_discarded );
440  for( std::list< WHcoord >::iterator iter( newDiscarded.begin() ); iter != newDiscarded.end(); ++iter )
441  {
442  iter->m_x = iter->m_x / coarseRatio;
443  iter->m_y = iter->m_y / coarseRatio;
444  iter->m_z = iter->m_z / coarseRatio;
445  }
446  newDiscarded.sort();
447  newDiscarded.unique();
448  WHcoord newDataSetSize( m_tree.m_datasetSize.m_x / coarseRatio, m_tree.m_datasetSize.m_y / coarseRatio,
449  m_tree.m_datasetSize.m_z / coarseRatio );
450 
451  //loop through coarser grid
452  for( coord_t k = 0; k < m_tree.m_datasetSize.m_z; k += coarseRatio )
453  {
454  for( coord_t j = 0; j < m_tree.m_datasetSize.m_y; j += coarseRatio )
455  {
456  for( coord_t i = 0; i < m_tree.m_datasetSize.m_x; i += coarseRatio )
457  {
458  //loop through finer grid
459  std::list< WHcoord > bigGridVoxel;
460 
461  for( unsigned int n = 0; n < coarseRatio; ++n )
462  {
463  for( unsigned int m = 0; m < coarseRatio; ++m )
464  {
465  for( unsigned int l = 0; l < coarseRatio; ++l )
466  {
467  if( roimatrix[i + l][j + m][k + n] )
468  {
469  WHcoord tempCoord( i + l, j + m, k + n );
470  bigGridVoxel.push_back( tempCoord );
471  }
472  }
473  }
474  }
475  if( !bigGridVoxel.empty() )
476  {
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 );
481  m_tree.m_coordinates[keptID] = newCoord;
482 
483  for( std::list< WHcoord >::iterator iter( bigGridVoxel.begin() ); iter != bigGridVoxel.end(); ++iter )
484  {
485  size_t decimatedID( roimap[*iter] );
486  m_tree.fetchLeaf( decimatedID )->setFlag( true );
487  WHcoord emptyCoord;
488  m_tree.m_coordinates[decimatedID] = emptyCoord;
489  }
490  }
491  }
492  }
493  }
494 
495  m_tree.cleanup();
496  m_tree.debinarize();
497  m_tree.m_discarded = newDiscarded;
498  m_tree.m_datasetSize = newDataSetSize;
499  m_tree.m_treeName += ( "_coarse" + string_utils::toString( coarseRatio ) );
500 
501  return;
502 } // end "coarseTree()" -----------------------------------------------------------------
503 
504 
506 {
507  if( !m_tree.testRootBaseNodes() )
508  {
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;
511  return m_tree.getNumLeaves();
512  }
513 
514  std::vector <size_t> bases( m_tree.getRootBaseNodes() );
515  for( size_t i = 0; i < bases.size(); ++i )
516  {
517  std::vector <size_t> leaves4node( m_tree.getLeaves4node( bases[i] ) );
518  // start in j=1 so that we always leave one leaf not pruned
519  for( size_t j = 1; j < leaves4node.size(); ++j )
520  {
521  WHnode* currentLeaf( m_tree.fetchLeaf( leaves4node[j] ) );
522  currentLeaf->setFlag( true );
523  }
524  }
525  m_tree.cleanup();
526  m_tree.m_treeName += ( "_bases" );
527 
528  return m_tree.getNumLeaves();
529 } // end "baseNodes2Leaves()" -----------------------------------------------------------------
530 
532 {
534  return;
535 }
536 
538 {
540  return;
541 }
542 
543 void WHtreeProcesser::forceMonotonicity( double errorMult )
544 {
545  m_tree.forceMonotonicity( errorMult );
546  return;
547 }
548 
549 size_t WHtreeProcesser::debinarize( const bool keepBaseNodes )
550 {
551  return m_tree.debinarize( keepBaseNodes );
552 }
553 
554 // === PRIVATE MEMBER FUNCTIONS ===
555 
556 
557 size_t WHtreeProcesser::flattenBranch( size_t root, const bool keepBaseNodes )
558 {
559  collapseNode( root, 1 );
560 
561  size_t collapsed( m_tree.debinarize( keepBaseNodes ) );
562 
563  return collapsed;
564 } // end "flattenBranch()" -----------------------------------------------------------------
565 
566 
567 size_t WHtreeProcesser::flattenSelection( std::list< size_t > selection, bool keepBaseNodes )
568 {
569  if( keepBaseNodes && !m_tree.testRootBaseNodes() )
570  {
571  std::cerr << "WARNING@ flattenSelection: base nodes have mixed nodes and leaves, flattening will be standard " << std::endl;
572  keepBaseNodes = false;
573  }
574  while( !selection.empty() )
575  {
576  size_t thisNode( selection.front() );
577  selection.pop_front();
578  std::vector< nodeID_t > kids( m_tree.getNode( thisNode ).getChildren() );
579  for( size_t i = 0; i < kids.size(); ++i )
580  {
581  if( kids[i].first )
582  {
583  if( keepBaseNodes && ( m_tree.getNode( kids[i] ).getHLevel() == 1 ) )
584  {
585  continue;
586  }
587  else
588  {
589  m_tree.fetchNode( kids[i].second )->setFlag( true );
590  selection.push_back( kids[i].second );
591  }
592  }
593  }
594  }
595 
596  std::pair< size_t, size_t > pruned( m_tree.cleanup() );
597 
598  return pruned.second;
599 } // end "flattenSelection()" -----------------------------------------------------------------
600 size_t WHtreeProcesser::flattenSelection( const std::vector< size_t > &selection, const bool keepBaseNodes )
601 {
602  std::list< size_t > worklist( selection.begin(), selection.end() );
603  return flattenSelection( worklist, keepBaseNodes );
604 } // end "flattenSelection()" -----------------------------------------------------------------
605 size_t WHtreeProcesser::flattenSelection( const std::vector< nodeID_t > &selection, const bool keepBaseNodes )
606 {
607  std::list< size_t > worklist;
608  for( std::vector< nodeID_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
609  {
610  if( iter->first )
611  {
612  worklist.push_back( iter->second );
613  }
614  }
615  return flattenSelection( worklist, keepBaseNodes );
616 } // end "flattenSelection()" -----------------------------------------------------------------
617 
618 
619 std::pair< size_t, size_t > WHtreeProcesser::pruneSelection( const std::vector< size_t > &selection )
620 {
621  flagSelection( selection );
622  std::pair< size_t, size_t > pruned( m_tree.cleanup() );
623  return pruned;
624 } // end "pruneSelection()" -----------------------------------------------------------------
625 std::pair< size_t, size_t > WHtreeProcesser::pruneSelection( const std::vector< nodeID_t > &selection )
626 {
627  flagSelection( selection );
628  std::pair< size_t, size_t > pruned( m_tree.cleanup() );
629  return pruned;
630 } // end "pruneSelection()" -----------------------------------------------------------------
631 
632 void WHtreeProcesser::flagSelection( const std::vector< size_t > &selection )
633 {
634  for( std::vector< size_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
635  {
636  std::vector< size_t > pruneLeaves( m_tree.getLeaves4node( *iter ) );
637  flagLeaves( pruneLeaves );
638  }
639  return;
640 } // end "flagSelection()" -----------------------------------------------------------------
641 void WHtreeProcesser::flagSelection( const std::vector< nodeID_t > &selection )
642 {
643  for( std::vector< nodeID_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
644  {
645  std::vector< size_t > pruneLeaves( m_tree.getLeaves4node( *iter ) );
646  flagLeaves( pruneLeaves );
647  }
648  return;
649 } // end "flagSelection()" -----------------------------------------------------------------
650 void WHtreeProcesser::flagLeaves( const std::vector< size_t > &selection )
651 {
652  for( std::vector< size_t >::const_iterator iter( selection.begin() ); iter != selection.end(); ++iter )
653  {
654  m_tree.fetchLeaf( *iter )->setFlag( true );
655  }
656  return;
657 } // end "flagSelection()" -----------------------------------------------------------------
658 
659 
660 
661 void WHtreeProcesser::collapseNode( const nodeID_t &thisNodeID, const dist_t coefficient, HTPROC_COLLAPSE collapseMode )
662 {
663  if( !thisNodeID.first )
664  {
665  return;
666  }
667  else
668  {
669  collapseNode( thisNodeID.second, coefficient, collapseMode );
670  }
671  return;
672 } // end collapseNode() -------------------------------------------------------------------------------------
673 
674 void WHtreeProcesser::collapseNode( const size_t thisNodeID, const dist_t coefficient, HTPROC_COLLAPSE collapseMode )
675 {
676  if( thisNodeID > m_tree.getRoot().getID() )
677  {
678  throw std::runtime_error( "ERROR @ collapseNode::flattenBranch(): nodeID is out of boundaries" );
679  }
680 
681  const WHnode& thisNode( m_tree.getNode( thisNodeID ) );
682  dist_t upperLevel( thisNode.getDistLevel() );
683  std::list< nodeID_t > worklist;
684  worklist.push_back( thisNode.getFullID() );
685  while( !worklist.empty() )
686  {
687  WHnode* currentNode( m_tree.fetchNode( worklist.front() ) );
688  worklist.pop_front();
689  std::vector< nodeID_t > currentKids( currentNode->getChildren() );
690  dist_t parentLevel( currentNode->getDistLevel() );
691  for( std::vector< nodeID_t >::iterator kidIter( currentKids.begin() ); kidIter != currentKids.end(); ++kidIter )
692  {
693  if( m_tree.getNode( *kidIter ).isNode() )
694  {
695  dist_t kidLevel( m_tree.getNode( *kidIter ).getDistLevel() );
696 
697  bool doCollapse( false );
698 
699  switch( collapseMode )
700  {
701  case HTPR_C_CONSTANT:
702  doCollapse = ( ( parentLevel - kidLevel ) < coefficient );
703  break;
704  case HTPR_C_LINEAR:
705  doCollapse = ( ( parentLevel - kidLevel ) < ( kidLevel * coefficient ) );
706  break;
707  case HTPR_C_SQ:
708  doCollapse = ( ( parentLevel - kidLevel ) < ( kidLevel * kidLevel * coefficient ) );
709  break;
710  default:
711  break;
712  }
713 
714  if( doCollapse )
715  {
716  worklist.push_back( *kidIter );
717  }
718  }
719  }
720  currentNode->setDistLevel( upperLevel );
721  }
722  return;
723 } // end collapseNodeLinear() -------------------------------------------------------------------------------------
this class to contain a seed voxel coordinate.
Definition: WHcoord.h:76
coord_t m_z
z coordinate
Definition: WHcoord.h:156
coord_t m_y
y coordinate
Definition: WHcoord.h:155
coord_t m_x
x coordinate
Definition: WHcoord.h:154
this class implements a hierarchical tree node with several relevant attributes
Definition: WHnode.h:69
size_t getSize() const
returns number of elements contained by the node
Definition: WHnode.h:257
bool isFlagged() const
returns true if object is flagged for pruning
Definition: WHnode.h:237
size_t getHLevel() const
returns maximum number of nodes between the node and a leaf element
Definition: WHnode.h:267
size_t getID() const
returns node/leaf ID
Definition: WHnode.h:242
void setFlag(const bool newFlag)
sets the prune flag to the indicated value
Definition: WHnode.cpp:112
dist_t getDistLevel() const
returns distance level at which the element was formed
Definition: WHnode.h:262
void setDistLevel(const dist_t newLevel)
sets the distance level field to the specified value
Definition: WHnode.cpp:102
bool isNode() const
returns true if object is a node
Definition: WHnode.h:227
nodeID_t getFullID() const
returns full ID
Definition: WHnode.h:247
std::vector< nodeID_t > getChildren() const
returns a vector with the ids of the children of that node
Definition: WHnode.h:272
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,...
Definition: WHtree.h:81
std::vector< size_t > getRootBaseNodes() const
returns a vector with all the nodes that have direct link to leaves from the main root
Definition: WHtree.cpp:706
const WHnode & getRoot() const
returns a const reference to the root node
Definition: WHtree.cpp:348
std::vector< WHcoord > m_coordinates
Stores the coordinates of the leaf voxels.
Definition: WHtree.h:649
std::vector< size_t > getLeaves4node(const size_t nodeID) const
Returns a vector with all the leaf IDs contained in that cluster.
Definition: WHtree.cpp:380
WHcoord m_datasetSize
Stores the size of the dataset this tree was built from.
Definition: WHtree.h:625
std::vector< WHnode > m_nodes
Stores all the nodes (non-leaves) of the tree.
Definition: WHtree.h:646
const WHnode & getNode(const nodeID_t &thisNode) const
returns a const pointer to the node indicated by the ID
Definition: WHtree.cpp:307
void forceMonotonicityDown()
eliminates non monotonic steps in the tree top-down, raising the level of parents involved in the non...
Definition: WHtree.cpp:2226
size_t debinarize(const bool keepBaseNodes=false)
merges nodes joining binary at the same level into non-binary structures
Definition: WHtree.cpp:1985
std::vector< WHnode > m_leaves
Stores all the leaves of the tree (represents a single voxel, for several purposes a leaf also counts...
Definition: WHtree.h:643
WHnode * fetchNode(const nodeID_t &thisNode)
returns a pointer to the node indicated by the ID
Definition: WHtree.cpp:1684
std::pair< size_t, size_t > cleanup(std::vector< size_t > *outLookup=0)
cleans leaves/nodes set to be pruned
Definition: WHtree.cpp:1716
void forceMonotonicity(double errorMult=1)
eliminates non monotonic steps in the tree while keeping as much information as possible.
Definition: WHtree.cpp:2247
std::string m_treeName
Stores the name of the tree file.
Definition: WHtree.h:640
bool testRootBaseNodes() const
tests if all base nodes have only leaf children
Definition: WHtree.cpp:712
std::vector< size_t > getBranchNodes(const size_t nodeID) const
Returns a vector with all the node IDs contained in that branch.
Definition: WHtree.cpp:434
WHnode * fetchLeaf(const size_t thisLeaf)
returns a pointer to the leaf indicated by the ID
Definition: WHtree.cpp:1697
size_t getNumLeaves() const
Returns the number of leaves of the tree.
Definition: WHtree.h:831
std::list< WHcoord > m_discarded
Stores the coordinates of the voxels that were discarded during the process of building the tree.
Definition: WHtree.h:655
void forceMonotonicityUp()
eliminates non monotonic steps in the tree bottom-up, lowering the level of children involved in the ...
Definition: WHtree.cpp:2205
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120