OpenWalnut  1.5.0dev
WMHierchClustDisplay.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 <algorithm>
50 #include <list>
51 #include <map>
52 #include <memory>
53 #include <queue>
54 #include <random>
55 #include <string>
56 #include <utility>
57 #include <vector>
58 
59 #include <boost/regex.hpp>
60 #include <osg/LightModel>
61 #include <osgGA/GUIEventAdapter>
62 #include <osgGA/GUIEventHandler>
63 #include <osgGA/StateSetManipulator>
64 #include <osgGA/TrackballManipulator>
65 #include <osgViewer/ViewerEventHandlers>
66 #include <osgWidget/Util> //NOLINT
67 #include <osgWidget/ViewerEventHandlers> //NOLINT
68 #include <osgWidget/WindowManager> //NOLINT
69 
70 #include "WMHierchClustDisplay.h"
71 #include "core/common/WPathHelper.h"
72 #include "core/common/WPropertyHelper.h"
73 #include "core/common/WStringUtils.h"
74 #include "core/common/algorithms/WMarchingLegoAlgorithm.h"
75 #include "core/graphicsEngine/WGEColormapping.h"
76 #include "core/graphicsEngine/WGEUtils.h"
77 #include "core/kernel/WKernel.h"
78 #include "core/kernel/WROIManager.h"
79 #include "core/kernel/WSelectionManager.h"
80 
81 bool WMHierchClustDisplay::MainViewEventHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& /* aa */ )
82 {
83 // wlog::debug( "WMHierchClustDisplay::MainViewEventHandler" ) << "handle";
84  if( ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON )
85  {
86  return ( true == m_signalLeftButtonPush( WVector2f( ea.getX(), ea.getY() ) ) );
87  }
88  if( ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
89  {
90  return ( true == m_signalRightButtonPush( WVector2f( ea.getX(), ea.getY() ) ) );
91  }
92  return false;
93 }
94 
95 void WMHierchClustDisplay::MainViewEventHandler::subscribeLeftButtonPush( mouseClickSignalType::slot_type slot )
96 {
97  m_signalLeftButtonPush.connect( slot );
98 }
99 
101 {
102  m_signalRightButtonPush.connect( slot );
103 }
104 
106  WModule(),
107  m_moduleNode( new WGEGroupNode() ),
109  m_meshNode( new WGEGroupNode() ),
110  m_treeDirty( false )
111 {
112 }
113 
115 {
116  // Cleanup!
117 }
118 
119 std::shared_ptr< WModule > WMHierchClustDisplay::factory() const
120 {
121  // See "src/modules/template/" for an extensively documented example.
122  return std::shared_ptr< WModule >( new WMHierchClustDisplay() );
123 }
124 
125 const std::string WMHierchClustDisplay::getName() const
126 {
127  // Specify your module name here. This name must be UNIQUE!
128  return "Hierarchical Clustering Display";
129 }
130 
131 const std::string WMHierchClustDisplay::getDescription() const
132 {
133  // Specify your module description here. Be detailed. This text is read by the user.
134  // See "src/modules/template/" for an extensively documented example.
135  return "Visualizes hierarchical clustering in dendrogram tree, texture and 3D seed voxels view";
136 }
137 
139 {
140  // the input dataset is just used as source for resolurtion and transformation matrix
141  m_input = std::shared_ptr< WModuleInputData < WDataSetSingle > >(
142  new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) );
144 
145  m_output = std::shared_ptr< WModuleOutputData < WDataSetVector > >(
146  new WModuleOutputData< WDataSetVector >( shared_from_this(), "colors out", "The extracted image." ) );
148 
149  m_output2 = std::shared_ptr< WModuleOutputData < WDataSetScalar > >(
150  new WModuleOutputData< WDataSetScalar >( shared_from_this(), "coords out", "The coordinate vector." ) );
152 
154 } // end connectors()
155 
157 {
158  m_propTriggerChange = std::shared_ptr< WCondition >( new WCondition() );
159 
160  // Info properties
161  m_groupInfoSelected = m_infoProperties->addPropertyGroup( "Selected cluster", "" ); //NOLINT
162  m_infoSelectedID = m_groupInfoSelected->addProperty( "ID: ", "", 0 );
163  m_infoSelectedSize = m_groupInfoSelected->addProperty( "Size: ", "", 0 );
164  m_infoSelectedDistance = m_groupInfoSelected->addProperty( "Distance: ", "", 0 );
165  m_groupInfoPartition = m_infoProperties->addPropertyGroup( "Partition", "" ); //NOLINT
166  m_infoPartNumber = m_groupInfoPartition->addProperty( "Partition clusters: ", "", 0 );
167  m_infoPartActive = m_groupInfoPartition->addProperty( "Partition active nodes: ", "", 0 );
168  m_infoPartLeaves = m_groupInfoPartition->addProperty( "Partition leaves: ", "", 0 );
169  m_infoCutValue = m_groupInfoPartition->addProperty( "Cut value: ", "", 0.0 );
170  m_groupInfoTree = m_infoProperties->addPropertyGroup( "Tree", "" ); //NOLINT
171  m_infoTreeName = m_groupInfoTree->addProperty( "Current Tree: ", "", std::string() );
172  m_infoCountLeaves = m_groupInfoTree->addProperty( "Total Leaves: ", "", 0 );
173  m_infoCountNodes = m_groupInfoTree->addProperty( "Total Nodes: ", "", 0 );
174  m_infoCountDiscarded = m_groupInfoTree->addProperty( "Total Discarded: ", "", 0 );
175  m_infoMaxLevel = m_groupInfoTree->addProperty( "Max Hierarch. Level: ", "", 0 );
176  m_infoCpcc = m_groupInfoTree->addProperty( "CPCC: ", "", 0.0 );
177  m_groupInfoMessage = m_infoProperties->addPropertyGroup( "Operation Messages", "" );
178  m_infoPartMessage = m_groupInfoMessage->addProperty( "Part", "", std::string() );
179 
180  // Group Read
181  m_groupRead = m_properties->addPropertyGroup( "Read file", "Groups the tree loading options" ); //NOLINT
182  m_propReadFilename = m_groupRead->addProperty( "Tree file", "", boost::filesystem::path( "" ) );
183  m_propReadTreeTrigger = m_groupRead->addProperty( "Load tree", "Load tree", WPVBaseTypes::PV_TRIGGER_READY, m_propTriggerChange );
184 
185  // Group Dendrogram
186  m_groupDendrogram = m_properties->addPropertyGroup( "Dendrogram", "Properties only related to the dendrogram." );
187  m_propShowDendrogram = m_groupDendrogram->addProperty( "Show dendrogram", "", true, m_propTriggerChange );
188  m_propDendroPlotByLevel = m_groupDendrogram->addProperty( "Height by hierarchical level", "", false, m_propTriggerChange );
189  m_propTriangleLeaves = m_groupDendrogram->addProperty( "\"Triangle\" leaves", "", false, m_propTriggerChange );
190 
193  m_propDendroSideList = std::shared_ptr< WItemSelection >( new WItemSelection() );
194  m_propDendroSideList->addItem( "Fill", "" );
195  m_propDendroSideList->addItem( "Left", "" );
196  m_propDendroSideList->addItem( "Right", "" );
197  m_propDendroSideList->addItem( "Manual", "" );
198  m_propDendroSideSelector = m_groupDendrogram->addProperty( "Position",
199  "selection",
200  m_propDendroSideList->getSelectorFirst(),
203 
204  m_groupDendroManual = m_groupDendrogram->addPropertyGroup( "Manual size", "manual resizing of the dendrogram." );
205  m_propDendroSizeX = m_groupDendroManual->addProperty( "Width", "", 100, m_propTriggerChange );
206  m_propDendroSizeX->setMin( 0 );
207  m_propDendroSizeY = m_groupDendroManual->addProperty( "Height", "", 100, m_propTriggerChange );
208  m_propDendroSizeY->setMin( 0 );
209  m_propDendroOffsetX = m_groupDendroManual->addProperty( "X-offset", "", 100, m_propTriggerChange );
210  m_propDendroOffsetY = m_groupDendroManual->addProperty( "Y-offset", "", 100, m_propTriggerChange );
211  m_groupDendrogram->setHidden( true );
212 
213  // Group Partition
214  m_groupPartition = m_properties->addPropertyGroup( "Cluster selections", "Groups the different cluster selection methods" ); //NOLINT
215  m_propPartRoot = m_groupPartition->addProperty( "Select tree root", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propTriggerChange );
216  m_propSourceCluster = m_groupPartition->addProperty( "Partition root",
217  "Selects an intermediate node as partition root.",
218  0,
220  m_propSourceCluster->setMin( 0 );
221  m_propPartitionSelectionList = std::shared_ptr< WItemSelection >( new WItemSelection() );
222  m_propPartitionSelectionList->addItem( "Classic: Horizontal", "Use horizonztal cut" );
223  m_propPartitionSelectionList->addItem( "Classic: Hierarch value", "Cut by hierarchical value" );
224  m_propPartitionSelectionList->addItem( "Search: min Cluster size diff", "Search for the partition with minimal cluster size difference" );
225  m_propPartitionSelectionList->addItem( "Search: Spread-Separation", "Search for the partition with best Spread-Separation value" );
226  m_propPartitionSelectionList->addItem( "Branch length", "Select clusters with branches higher than a definded value" );
227  m_propPartitionSelectionList->addItem( "Predefined partitions", "Select partitions previously saved in the tree file" );
228  //UNUSED m_propPartitionSelectionList->addItem( "Classic: Size Restrict.", "" );
229  //UNUSED m_propPartitionSelectionList->addItem( "Search: min Intra-Clust Dist", "" );
230  //UNUSED m_propPartitionSelectionList->addItem( "Search: min w-Intra-Clust Dist", "" );
231  //UNUSED m_propPartitionSelectionList->addItem( "Search: Max Inter-Clust Dist", "" );
232  //UNUSED m_propPartitionSelectionList->addItem( "Search: Max w-Inter-Clust Dist", "" );
233  //UNUSED m_propPartitionSelectionList->addItem( "Branch lenght normalized", "" );
234  m_propPartitionSelector = m_groupPartition->addProperty( "Selection method", "selection",
235  m_propPartitionSelectionList->getSelectorFirst(), m_propTriggerChange );
237 
238  m_propConditionSelectionsList = std::shared_ptr< WItemSelection >( new WItemSelection() );
239  m_propConditionSelectionsList->addItem( "Cluster #", "find partition with # clusters" );
240  m_propConditionSelectionsList->addItem( "Cut level", "find partition thresholding the method-related absolute value" );
241  m_propConditionSelectionsList->addItem( "Cut level (%)", "find partition thresholding the method-related relative value to its maximum" );
242  m_propConditionSelector = m_groupPartition->addProperty( "Selection condition", "condition",
243  m_propConditionSelectionsList->getSelectorFirst(), m_propTriggerChange );
245 
246 
247  m_propPartNumClusters = m_groupPartition->addProperty( "# of clusters", "", 5, m_propTriggerChange );
248  m_propPartNumClusters->setMin( 1 );
249  m_propPartSizeValue = m_groupPartition->addProperty( "Cluster size", "", 500, m_propTriggerChange );
250  m_propPartSizeValue->setMin( 1 );
251  m_propPartRelativeValue = m_groupPartition->addProperty( "% value", "", 10.0, m_propTriggerChange );
252  m_propPartRelativeValue->setMin( 0.0 );
253  m_propPartRelativeValue->setMax( 100.0 );
254  m_propPartHlevelValue = m_groupPartition->addProperty( "H.level cut value", "", 2, m_propTriggerChange );
255  m_propPartHlevelValue->setMin( 1 );
256  m_propPartDistanceValue = m_groupPartition->addProperty( "Distance value", "", 1.0, m_propTriggerChange );
257  m_propPartDistanceValue->setMin( 0.0001 );
258  m_propPartDistanceValue->setMax( 1.0 );
259  m_propPartSearchDepthValue = m_groupPartition->addProperty( "Search depth", "", 1, m_propTriggerChange );
260  m_propPartSearchDepthValue->setMin( 1 );
261  m_propPartSearchDepthValue->setMax( 10 );
262  m_propPreloadPartitionNr = m_groupPartition->addProperty( "partition to load", "", 0, m_propTriggerChange );
263  m_propPreloadPartitionNr->setMin( 0 );
264 
265 
266  m_propPartExcludeLeaves = m_groupPartition->addProperty( "Exclude leaves",
267  "Base nodes only containing single leaves will not be subdivided",
268  true,
270  m_propDoPartition = m_groupPartition->addProperty( "Find Partition", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propTriggerChange );
271  m_groupPartition->setHidden( true );
272 
273  // Group Visualization
274  m_groupVisualization = m_properties->addPropertyGroup( "Visualization", "Groups the visualization options" ); //NOLINT
275  m_propSubselectedCluster = m_groupVisualization->addProperty( "Selected cluster", "", 0, m_propTriggerChange );
276  m_propSubselectedcolor = m_groupVisualization->addProperty( "Selected color",
277  "Selected cluster colors",
278  WColor( 1.0, 1.0, 1.0, 1.0 ),
280  m_propColorSchemeList = std::shared_ptr< WItemSelection >( new WItemSelection() );
281  m_propColorSchemeList->addItem( "Custom", "Use custom color values, default is hierarchical tree coloring, can be modified" );
282  m_propColorSchemeList->addItem( "Partition", "Disregard custom value and assign color values to selected partition" );
283  m_propColorSchemeSelector= m_groupVisualization->addProperty( "Color Scheme",
284  "",
285  m_propColorSchemeList->getSelectorFirst(),
288  m_propColorActionList = std::shared_ptr< WItemSelection >( new WItemSelection() );
289  m_propColorActionList->addItem( "Shuffle partition", "" );
290  m_propColorActionList->addItem( "Redo: Size", "" );
291  m_propColorActionList->addItem( "Redo: Hierch.Dist", "" );
292  m_propColorActionList->addItem( "Apply: single selected", "" );
293  m_propColorActionList->addItem( "Apply: hierarchical selected", "" );
294  m_propColorActionList->addItem( "Apply: single partition", "" );
295  m_propColorActionList->addItem( "Apply: hierarchical partition", "" );
296  m_propColorActionSelector= m_groupVisualization->addProperty( "Color Action",
297  "",
298  m_propColorActionList->getSelectorFirst(),
302  m_propShowLabels = m_groupVisualization->addProperty( "Show cluster labels",
303  "Shows the an info label per selected cluster",
304  false,
306  m_propLabelList = std::shared_ptr< WItemSelection >( new WItemSelection() );
307  m_propLabelList->addItem( "Node-ID", "" );
308  m_propLabelList->addItem( "Size", "" );
309  m_propLabelList->addItem( "Distance", "" );
310  m_propLabelList->addItem( "H. Level", "" );
311  m_propLabelInfoSelector= m_groupVisualization->addProperty( "Label Info", "selection", m_propLabelList->getSelectorFirst(), m_propTriggerChange );
313  m_propShowDiscarded = m_groupVisualization->addProperty( "Show discarded voxels",
314  "( mesh triangulation is re-done )",
315  false, m_propTriggerChange );
316  m_propBoundaries = m_groupVisualization->addProperty( "Just boundaries", "Only show boundary colors", false, m_propTriggerChange );
317  m_propShowCubeMesh = m_groupVisualization->addProperty( "Render seed voxels",
318  "Shows the seed voxel cube triangulation",
319  false, m_propTriggerChange );
320  m_propDiscardedColor = m_groupVisualization->addProperty( "Discarded color", "", WColor( 0.0, 0.0, 0.0, 1.0 ), m_propTriggerChange );
321  m_propBoundaryColor = m_groupVisualization->addProperty( "Boundary color", "", WColor( 0.4, 0.4, 0.4, 1.0 ), m_propTriggerChange );
322  m_propInactiveColor = m_groupVisualization->addProperty( "Inactive color", "", WColor( 0.4, 0.4, 0.4, 1.0 ), m_propTriggerChange );
323  m_groupVisualization->setHidden( true );
324 
325  // Group Tree Processing
326  m_groupTreeProcess = m_properties->addPropertyGroup( "Tree Processing", "Grouping the different tree processing methods" ); //NOLINT
327  m_propProcessSelectionsList = std::shared_ptr< WItemSelection >( new WItemSelection() );
328  m_propProcessSelectionsList->addItem( "Prune by size ratio",
329  "Clusters smaller than SafeSize that join clusters bigger than SizeRatio times its size will be pruned" );
330  m_propProcessSelectionsList->addItem( "Prune by joining size",
331  "Clusters smaller than SafeSize that join clusters bigger than JoinSize will be pruned" );
332  m_propProcessSelectionsList->addItem( "Prune by joining level",
333  "Clusters smaller than SafeSize that join at a distance level higher than DistanceGap will be pruned" );
334  m_propProcessSelectionsList->addItem( "Prune randomly", "Pruned Number leaves randomly chosen will be pruned" );
335  m_propProcessSelectionsList->addItem( "Collapse nodes, linear", "Nodes with branches shorter than DistanceGap * nodeLevel will be collapsed" );
336  m_propProcessSelectionsList->addItem( "Flatten selection", "All inner nodes within the currently selected clusters will be collapsed" );
337  m_propProcessSelectionsList->addItem( "Prune selection", "currently selected clusters will be eliminated (including contained leaves)" );
338  m_propProcessSelector = m_groupTreeProcess->addProperty( "Processing method", "processing",
339  m_propProcessSelectionsList->getSelectorFirst(),
342  m_propSafeSize = m_groupTreeProcess->addProperty( "Safe Size", "Maximum size to be pruned", 1, m_propTriggerChange );
343  m_propSafeSize->setMin( 1 );
344  m_propSafeSize->setMax( 500 );
345  m_propPruneJoinSize= m_groupTreeProcess->addProperty( "Join Size", "", 500, m_propTriggerChange );
346  m_propPruneJoinSize->setMin( 1 );
347  m_propPruneJoinSize->setMax( 500 );
348  m_propPruneSizeRatio= m_groupTreeProcess->addProperty( "Size Ratio", "", 100.0, m_propTriggerChange );
349  m_propPruneSizeRatio->setMin( 2.0 );
350  m_propPruneSizeRatio->setMax( 1000.0 );
351  m_propDistanceGap= m_groupTreeProcess->addProperty( "Distance Gap", "", 0.1, m_propTriggerChange );
352  m_propDistanceGap->setMin( 0.0 );
353  m_propDistanceGap->setMax( 1 );
354  m_propDistanceGap->setMax( 0.5 );
355  m_propFlatLimit= m_groupTreeProcess->addProperty( "Flatten limit", "", 0.3, m_propTriggerChange );
356  m_propFlatLimit->setMin( 0.0 );
357  m_propDistanceGap->setMax( 1 );
358  m_propDistanceGap->setMax( 0.7 );
359  m_propPrunedNumber= m_groupTreeProcess->addProperty( "Pruned number", "Number of leaves to prune", 500, m_propTriggerChange );
360  m_propPrunedNumber->setMin( 1 );
361  m_propPrunedNumber->setMax( 500 );
362  m_propPrunedSeed= m_groupTreeProcess->addProperty( "Pruned seed", "Seed for the random generator", 0, m_propTriggerChange );
363  m_propPrunedSeed->setMin( 0 );
364  m_propPrunedSeed->setMax( 500 );
365  m_propKeepBases= m_groupTreeProcess->addProperty( "keep base nodes", "", false, m_propTriggerChange );
367  m_groupTreeProcess->setHidden( true );
368 
369 
370  // Group Partition
371  m_groupSavedPartition = m_properties->addPropertyGroup( "Add selected partitions", "Groups the tree partition options" ); //NOLINT
372  m_propAddPartTrigger = m_groupSavedPartition->addProperty( "Add partition", "Add partition",
375  m_propRecolorPartTrigger = m_groupSavedPartition->addProperty( "Recolor partition",
376  "Recolor partition",
379  m_propClearPartsTrigger = m_groupSavedPartition->addProperty( "Clear partitions",
380  "Clear partitions",
383  m_groupSavedPartition->setHidden( true );
384 
385  // Group Write
386  m_groupWrite = m_properties->addPropertyGroup( "Write Files", "Groups the file writing options" ); //NOLINT
387  m_propWriteTreeFilename = m_groupWrite->addProperty( "Output Tree file", "", boost::filesystem::path( "" ) );
389  m_propPartitionFile = m_groupWrite->addProperty( "Output Partition file", "", boost::filesystem::path( "" ) );
390 // WPropertyHelper::PC_PATHEXISTS::addTo( dirname );
391 // WPropertyHelper::PC_ISDIRECTORY::addTo( dirname );
392  m_propPartitionsTrigger = m_groupWrite->addProperty( "Write Partition", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propTriggerChange );
393  m_groupWrite->setHidden( true );
394 
396 } // end properties()
397 
399 {
400  osg::ref_ptr<osgViewer::View> viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView();
401  int height = viewer->getCamera()->getViewport()->height();
402  int width = viewer->getCamera()->getViewport()->width();
403 
404  m_oldViewHeight = height;
405  m_oldViewWidth = width;
406 
407  // create shader
408  m_shader = osg::ref_ptr< WGEShader >( new WGEShader( "WMHierchClustDisplay", m_localPath ) );
409 
410  m_moduleNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
411  m_dendrogramNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
412  m_meshNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
413  m_moduleNode->insert( m_dendrogramNode );
414  m_shader->apply( m_meshNode );
415  m_moduleNode->insert( m_meshNode );
416 
417  m_wm = new osgWidget::WindowManager( viewer, 0.0f, 0.0f, MASK_2D );
418 
419  m_camera = new osg::Camera();
420  m_camera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF );
421 
422  m_camera->setProjectionMatrix( osg::Matrix::ortho2D( 0.0, width, 0.0f, height ) );
423  m_camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
424  m_camera->setViewMatrix( osg::Matrix::identity() );
425  m_camera->setClearMask( GL_DEPTH_BUFFER_BIT );
426  m_camera->setRenderOrder( osg::Camera::POST_RENDER );
427 
428  m_dendrogramNode->addChild( m_camera );
429  m_camera->addChild( m_wm );
430 
431  viewer->addEventHandler( new osgWidget::MouseHandler( m_wm ) );
432  viewer->addEventHandler( new osgWidget::KeyboardHandler( m_wm ) );
433  viewer->addEventHandler( new osgWidget::ResizeHandler( m_wm, m_camera ) );
434  viewer->addEventHandler( new osgWidget::CameraSwitchHandler( m_wm, m_camera ) );
435  viewer->addEventHandler( new osgViewer::StatsHandler() );
436  viewer->addEventHandler( new osgViewer::WindowSizeHandler() );
437  viewer->addEventHandler( new osgGA::StateSetManipulator( viewer->getCamera()->getOrCreateStateSet() ) );
438 
439  m_wm->resizeAllWindows();
440 
441  m_moduleNode->addUpdateCallback( new WGEFunctorCallback< osg::Node >( boost::bind( &WMHierchClustDisplay::updateWidgets, this ) ) );
442  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_moduleNode );
443 } // end initWidgets()
444 
445 
446 
448 {
449  infoLog() << "Init properties...";
450 
451  infoLog() << m_tree.getName();
452 
453  // init gui appearance
454  m_groupRead->setHidden( false );
455  m_groupDendrogram->setHidden( false );
456  m_propTriangleLeaves->setHidden( false );
457  m_groupPartition->setHidden( false );
458  m_propPartNumClusters->setHidden( false );
459  m_propPartDistanceValue->setHidden( true );
460  m_propPartSizeValue->setHidden( true );
461  m_propPartSearchDepthValue->setHidden( true );
462  m_propPartRelativeValue->setHidden( true );
463  m_propPartHlevelValue->setHidden( true );
464  m_propPreloadPartitionNr->setHidden( true );
465  m_groupDendroManual->setHidden( true );
466  m_groupVisualization->setHidden( false );
467  m_propDiscardedColor->setHidden( true );
468  m_propBoundaryColor->setHidden( true );
469  m_propInactiveColor->setHidden( true );
470  m_propLabelInfoSelector->setHidden( true );
471  m_groupWrite->setHidden( false );
472  m_groupTreeProcess->setHidden( false );
473  m_propSafeSize->setHidden( false );
474  m_propPruneSizeRatio->setHidden( false );
475  m_propPruneJoinSize->setHidden( true );
476  m_propDistanceGap->setHidden( true );
477  m_propPrunedNumber->setHidden( true );
478  m_propPrunedSeed->setHidden( true );
479  m_propFlatLimit->setHidden( true );
480  m_propKeepBases->setHidden( true );
481  m_groupSavedPartition->setHidden( false );
482 
483  // set boundaries
484  const WHnode& root( m_tree.getRoot() );
485  infoLog() << root.printAllData();
486  m_propSubselectedCluster->removeConstraint( PC_MAX );
487  m_propSubselectedCluster->setMax( root.getID() );
488  m_propSourceCluster->removeConstraint( PC_MAX );
489  m_propSourceCluster->setMax( root.getID() );
490  m_propPartNumClusters->removeConstraint( PC_MAX );
491  m_propPartNumClusters->setMax( root.getSize() );
492  m_propPartDistanceValue->removeConstraint( PC_MAX );
493  m_propPartDistanceValue->setMax( root.getDistLevel() );
494  m_propPartHlevelValue->removeConstraint( PC_MAX );
495  m_propPartHlevelValue->setMax( root.getHLevel() );
496  m_propPartSizeValue->removeConstraint( PC_MAX );
497  m_propPartSizeValue->setMax( root.getSize() );
498  std::vector<size_t> baseNodes( m_tree.getRootBaseNodes() );
499  m_tree.sortBySize( &baseNodes );
500  m_propPartSizeValue->removeConstraint( PC_MIN );
501  m_propPartSizeValue->setMin( m_tree.getNode( baseNodes.front() ).getSize() );
502  m_propPartRelativeValue->removeConstraint( PC_MIN );
503  m_propPartRelativeValue->setMin( m_tree.getNode( baseNodes.front() ).getSize()*100/( ( double )m_tree.getNumLeaves() ) );
504  m_propPrunedNumber->removeConstraint( PC_MAX );
505  m_propPrunedNumber->setMax( root.getSize() );
506  m_propPruneJoinSize->removeConstraint( PC_MAX );
507  m_propPruneJoinSize->setMax( root.getSize()/3 );
508  m_propSafeSize->removeConstraint( PC_MAX );
509  m_propSafeSize->setMax( root.getSize()/3 );
510  m_propPreloadPartitionNr->removeConstraint( PC_MAX );
512  m_propPreloadPartitionNr->removeConstraint( PC_MIN );
513  if( m_tree.getSelectedValues().size() > 0 )
514  {
515  m_propPreloadPartitionNr->setMin( 1 );
516  m_propPreloadPartitionNr->set( 1 );
517  }
518  else
519  {
520  m_propPreloadPartitionNr->setMin( 0 );
521  m_propPreloadPartitionNr->set( 0 );
522  }
523 
524 
525 
526  // init properties
527  m_propSourceCluster->set( root.getID() );
528  m_propSourceCluster->changed( true );
529  m_propPartNumClusters->set( 1 );
530  m_propPartNumClusters->changed( true );
531  m_propPreloadPartitionNr->changed( true );
532  m_propShowDendrogram->set( true );
533  m_propShowDendrogram->changed( true );
534  m_propDendroPlotByLevel->set( false );
535  m_propDendroPlotByLevel->changed( true );
536  m_propTriangleLeaves->set( true );
537  m_propTriangleLeaves->changed( true );
538  m_propDendroSideSelector->set( m_propDendroSideList->getSelectorFirst() );
539  m_propDendroSideSelector->changed( true );
540  m_propShowDiscarded->set( false );
541  m_propShowDiscarded->changed( true );
542  m_propBoundaries->set( false );
543  m_propBoundaries->changed( true );
544  m_propShowCubeMesh->set( false );
545  m_propShowCubeMesh->changed( true );
546  m_propPartSizeValue->set( root.getSize() );
547  m_propPartSizeValue->changed( true );
548  m_propPartHlevelValue->set( root.getHLevel() );
549  m_propPartHlevelValue->changed( true );
550  m_propPartitionSelector->set( m_propPartitionSelectionList->getSelectorFirst() );
551  m_propPartitionSelector->changed( true );
552  m_propConditionSelector->set( m_propConditionSelectionsList->getSelectorFirst() );
553  m_propConditionSelector->changed( true );
554  m_propPartExcludeLeaves->set( true );
555  m_propPartExcludeLeaves->changed( true );
556  m_propLabelInfoSelector->set( m_propLabelList->getSelectorFirst() );
557  m_propLabelInfoSelector->changed( true );
558  m_propColorSchemeSelector->set( m_propColorSchemeList->getSelectorFirst() );
559  m_propColorSchemeSelector->changed( true );
560  m_propColorActionSelector->set( m_propColorActionList->getSelectorFirst() );
561  m_propColorActionSelector->changed( true );
562  m_propProcessSelector->set( m_propProcessSelectionsList->getSelectorFirst() );
563  m_propProcessSelector->changed( true );
564  m_propShowLabels->set( false );
565  m_propShowLabels->changed( true );
566  m_propKeepBases->set( false );
567  m_propKeepBases->changed( true );
568 
569 
570  // init variables
571  m_treeZoomRoot = root.getID();
572  m_selectionClusters.clear();
573  m_selectionClusters.push_back( m_propSourceCluster->get( true ) );
574  m_selectionColors.clear();
575  m_selectionColorsBackup.clear();
576  m_selectionLeaves.clear();
577  m_treeDirty = false;
578  m_labelsDirty = false;
579  m_horizontalLine = 0;
580  m_treeDisplayColors.clear();
581 
582 
583  // init info properties
584  m_infoSelectedID->set( root.getID() );
585  m_infoSelectedSize->set( root.getSize() );
586  m_infoPartNumber->set( 1 );
587  m_infoPartActive->set( 1 );
588  m_infoPartLeaves->set( 0 );
589  m_infoCutValue->set( root.getDistLevel() );
590  m_infoTreeName->set( m_tree.getName() );
594  m_infoMaxLevel->set( root.getHLevel() );
595  m_infoCpcc->set( m_tree.getCpcc() );
596  m_infoPartMessage->set( "" );
597 
598  infoLog() << "End Init properties...";
599 
600  return;
601 } // end initProperties()
602 
604 {
605  infoLog() << "Init tree data...";
606 
607  std::shared_ptr< WProgress > progressInitTreeData = std::shared_ptr< WProgress >( new WProgress( "Initializing tree data..." ) );
608  m_progress->addSubProgress( progressInitTreeData );
609 
610  // change to nifti coordinates if necessary
611  if( m_tree.convert2grid( HC_NIFTI ) )
612  {
613  infoLog() << "Tree was converted to nifti coordinates";
614  }
615 
616  // initialize colors for each cluster, assign new color to biggest cluster
618  m_treeDisplayColors.clear();
620 
621  //save a vector of seed voxel indices for each cluster
622  m_clusterVoxels.clear();
623  m_clusterVoxels.resize( m_tree.getNumNodes() );
624  for( size_t i = 0; i < m_clusterVoxels.size(); ++i )
625  {
626  std::vector<WHcoord> clusterCoords( m_tree.getCoordinates4node( i ) );
627  m_clusterVoxels[i].reserve( clusterCoords.size() );
628  for( size_t j = 0; j < clusterCoords.size(); ++j )
629  {
630  size_t voxelID( m_grid->getVoxelNum( clusterCoords[j].m_x, clusterCoords[j].m_y, clusterCoords[j].m_z ) );
631  m_clusterVoxels[i].push_back( voxelID );
632  }
633  }
634  m_discardedVoxels.clear();
635  std::list<WHcoord> discarded( m_tree.getDiscarded() );
636  for( std::list<WHcoord>::iterator listIter( discarded.begin() ); listIter != discarded.end(); ++listIter )
637  {
638  m_discardedVoxels.push_back( m_grid->getVoxelNum( listIter->m_x, listIter->m_y, listIter->m_z ) );
639  }
640 
641 
642  // create mesh for seed voxel triangulation
643  {
644  std::vector< size_t > seedVoxelMask;
645  seedVoxelMask.resize( m_grid->size(), 0 );
646  for( std::vector<size_t>::iterator iter( m_clusterVoxels.back().begin() ); iter != m_clusterVoxels.back().end(); ++iter )
647  {
648  seedVoxelMask[*iter] = 1;
649  }
650  WMarchingLegoAlgorithm mlAlgo;
651  m_cubeMesh = mlAlgo.genSurfaceOneValue( m_grid->getNbCoordsX(),
652  m_grid->getNbCoordsY(),
653  m_grid->getNbCoordsZ(),
654  m_grid->getTransformationMatrix(),
655  &seedVoxelMask, 1 );
656  }
657  // create mesh for discarded voxels
658  {
659  std::vector< size_t > discardedMask;
660  discardedMask.resize( m_grid->size(), 0 );
661  for( std::vector<size_t>::iterator iter( m_discardedVoxels.begin() ); iter != m_discardedVoxels.end(); ++iter )
662  {
663  discardedMask[*iter] = 1;
664  }
665  WMarchingLegoAlgorithm mlAlgo;
666  m_discardedMesh = mlAlgo.genSurfaceOneValue( m_grid->getNbCoordsX(),
667  m_grid->getNbCoordsY(),
668  m_grid->getNbCoordsZ(),
669  m_grid->getTransformationMatrix(),
670  &discardedMask, 1 );
671  }
672 
673  progressInitTreeData->finish();
674 
675  // update seed coordinates output
676  updateOutput2();
677 
678  return;
679 } // end initTreeData()
680 
681 
682 void WMHierchClustDisplay::assignColorHierch( const size_t thisID, const WColor thisColor )
683 {
684  // color up the tree
685  size_t currentID( thisID );
686  while( currentID != 0 )
687  {
688  if( m_tree.getNode( currentID ).isRoot() )
689  {
690  break;
691  }
692  size_t parentID = m_tree.getNode( currentID ).getParent().second;
693  std::vector<nodeID_t> kids( m_tree.getNode( parentID ).getChildren() );
694  m_tree.sortBySize( &kids );
695  if( kids.back().second == currentID )
696  {
697  m_nodeColorsCustom[parentID] = thisColor;
698  currentID = parentID;
699  }
700  else
701  {
702  break;
703  }
704  }
705 
706  // color down the tree
707  currentID = thisID;
708  m_nodeColorsCustom[currentID] = thisColor;
709  // give same color to all the biggest clusters in lower divisions.
710  while( true )
711  {
712  std::vector<nodeID_t> kids( m_tree.getNode( currentID ).getChildren() );
713  m_tree.sortBySize( &kids );
714  // if bigger son is a leaf ( should not happen) stop
715  if( !kids.back().first )
716  break;
717  currentID = kids.back().second;
718  m_nodeColorsCustom[currentID] = thisColor;
719  if( m_tree.getNode( currentID ).getHLevel() == 1 )
720  break;
721  }
722 } // end assignColorHierch()
723 
724 
726 {
727  // initialize colors for each cluster, assign new color to highest cluster in the tree
728  size_t colorIndex( 0 );
729  m_nodeColorsCustom.clear();
731  std::list<size_t> worklist;
732  for( size_t i = 0; i < m_tree.getNumNodes(); ++i )
733  {
734  worklist.push_front( i );
735  }
736  while( !worklist.empty() )
737  {
738  size_t currentID( worklist.front() );
739  worklist.pop_front();
740  m_nodeColorsCustom[currentID] = wge::getNthHSVColor( colorIndex );
741  if( m_tree.getNode( currentID ).getHLevel() == 1 )
742  continue;
743  // give same color to all the biggest clusters in lower divisions.
744  while( true )
745  {
746  std::vector<nodeID_t> kids( m_tree.getNode( currentID ).getChildren() );
747  m_tree.sortBySize( &kids );
748  // if bigger son is a leaf ( should not happen) stop
749  if( !kids.back().first )
750  break;
751  currentID = kids.back().second;
752  m_nodeColorsCustom[currentID] = wge::getNthHSVColor( colorIndex );
753  worklist.remove( currentID );
754  if( m_tree.getNode( currentID ).getHLevel() == 1 )
755  break;
756  }
757  // next cluster will ahve a different color
758  ++colorIndex;
759  }
760 } // end assignColorsHdist()
761 
762 
764 {
765  // initialize colors for each cluster, assign new color to biggest cluster
766  size_t colorIndex( 0 );
767  std::list<size_t> worklist;
768  m_nodeColorsCustom.clear();
770  {
771  std::vector<size_t> initOrder;
772  initOrder.reserve( m_tree.getNumNodes() );
773  for( size_t i = 0; i < m_tree.getNumNodes(); ++i )
774  {
775  initOrder.push_back( i );
776  }
777  m_tree.sortBySize( &initOrder );
778  for( size_t i = 0; i < initOrder.size(); ++i )
779  {
780  worklist.push_front( initOrder[i] );
781  }
782  }
783 
784  while( !worklist.empty() )
785  {
786  size_t currentID( worklist.front() );
787  worklist.pop_front();
788  m_nodeColorsCustom[currentID] = wge::getNthHSVColor( colorIndex );
789  if( m_tree.getNode( currentID ).getHLevel() == 1 )
790  continue;
791  // give same color to all the biggest clusters in lower divisions.
792  while( true )
793  {
794  std::vector<nodeID_t> kids( m_tree.getNode( currentID ).getChildren() );
795  m_tree.sortBySize( &kids );
796  // if bigger son is a leaf ( should not happen) stop
797  if( !kids.back().first )
798  break;
799  currentID = kids.back().second;
800  m_nodeColorsCustom[currentID] = wge::getNthHSVColor( colorIndex );
801  worklist.remove( currentID );
802  if( m_tree.getNode( currentID ).getHLevel() == 1 )
803  break;
804  }
805  // next cluster will ahve a different color
806  ++colorIndex;
807  }
808 } // end assignColorsSize()
809 
811 {
812  infoLog() << "Init texture";
813  std::shared_ptr< WProgress > progressInitTexture = std::shared_ptr< WProgress >( new WProgress( "Initializing output texture..." ) );
814  m_progress->addSubProgress( progressInitTexture );
815 
816  osg::ref_ptr< osg::Image > ima = new osg::Image;
817  ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_RGB, GL_UNSIGNED_BYTE );
818  unsigned char* data = ima->data();
819  m_textureLabels.clear();
820  m_textureLabels.resize( m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ(), 0 );
821 
822  for( unsigned int i = 0; i < m_grid->size() * 3; ++i )
823  {
824  data[i] = 0.0;
825  }
826 
827  m_texture = osg::ref_ptr<osg::Texture3D>( new osg::Texture3D );
828  m_texture->setFilter( osg::Texture3D::MIN_FILTER, osg::Texture3D::LINEAR );
829  m_texture->setFilter( osg::Texture3D::MAG_FILTER, osg::Texture3D::LINEAR );
830  m_texture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER );
831  m_texture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER );
832  m_texture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER );
833  m_texture->setImage( ima );
834  m_texture->setResizeNonPowerOfTwoHint( false );
835 
837  WKernel::getRunningKernel()->getSelectionManager()->setShader( 0 );
838  WKernel::getRunningKernel()->getSelectionManager()->setUseTexture( true );
839 
840  WDataHandler::getDefaultSubject()->getChangeCondition()->notify();
841 
842  progressInitTexture->finish();
843 
844  infoLog() << "End Init texture";
845 
846  return;
847 } // end initTexture()
848 
849 
851 {
852 // DEPRECATED boost::signals2::connection con = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getPickHandler()->getPickSignal()->
853 // DEPRECATED connect( boost::bind( &WMHierchClustDisplay::dendrogramClick, this, boost::placeholders::_1 ) );
854 
855  osg::ref_ptr< MainViewEventHandler > eh( new MainViewEventHandler );
856  eh->subscribeLeftButtonPush( boost::bind( &WMHierchClustDisplay::dendrogramClick, this, boost::placeholders::_1 ) );
857 
858  eh->subscribeRightButtonPush( boost::bind( &WMHierchClustDisplay::dendrogramClickRight, this, boost::placeholders::_1 ) );
859 
860  WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView()->addEventHandler( eh );
861 
862 
863  m_moduleState.setResetable( true, true );
864  m_moduleState.add( m_input->getDataChangedCondition() );
866  m_moduleState.add( m_active->getUpdateCondition() );
867 
868  ready();
869 
870  // wait for a dataset to be connected, most likely an anatomy dataset
871  while( !m_shutdownFlag() )
872  {
874  if( m_shutdownFlag() )
875  {
876  break;
877  }
878  std::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
879  bool dataChanged = ( m_anatomy != newDataSet );
880  bool dataValid = ( newDataSet != NULL );
881  if( dataValid )
882  {
883  if( dataChanged )
884  {
885  m_anatomy = newDataSet;
886  m_grid = std::dynamic_pointer_cast< WGridRegular3D >( m_anatomy->getGrid() );
887  break;
888  }
889  }
890  }
891 
892  // wait for a tree file to be loaded
893  while( !m_shutdownFlag() )
894  {
896  if( m_shutdownFlag() )
897  {
898  break;
899  }
901  {
902  infoLog() << "Loading tree file";
903 
904  boost::filesystem::path fileName = m_propReadFilename->get();
905 
906  if( m_tree.readTree( fileName.string() ) )
907  {
909  break;
910  }
911  else
912  {
913  infoLog() << "Invalid tree file";
915  continue;
916  }
917  }
918  }
919 
920  // initialize
921  if( !m_shutdownFlag() )
922  {
923  initWidgets();
924  initTreeData();
925  initProperties();
926  initTexture();
927  updateSelection();
928  }
929 
930  // === MAIN MODULE LOOP ===
931 
932 
933  // main loop, respond to controls
934  while( !m_shutdownFlag() )
935  {
937 
938  // if close signal is received, finish
939  if( m_shutdownFlag() )
940  break;
941 
942  // === READ TREE OPTIONS ===
943 
944  // if another tree is loaded, reinitialize
946  {
947  infoLog() << "Loading tree file";
948 
949  std::shared_ptr< WProgress > progressLoadTree = std::shared_ptr< WProgress >( new WProgress( "Loading tree from file..." ) );
950  m_progress->addSubProgress( progressLoadTree );
951 
952  boost::filesystem::path fileName = m_propReadFilename->get();
953 
954  if( !m_tree.readTree( fileName.string() ) )
955  {
956  infoLog() << "Invalid tree file";
957  progressLoadTree->finish();
959  continue;
960  }
961  progressLoadTree->finish();
962 
963  std::string message( "Tree \""+ m_tree.getName()+"\" loaded. " +
964  string_utils::toString( m_tree.getNumLeaves() )+" leaves and " +
965  string_utils::toString( m_tree.getNumNodes() )+" nodes" );
966  m_infoPartMessage->set( message );
967 
968  initTreeData();
969  initProperties();
970  updateSelection();
972  }
973 
974  // === DENDROGRAM OPTIONS ===
975 
976 
977  // if an action that changes the on screen tree is triggered, set tree to redraw
978  if( m_propTriangleLeaves->changed( true ) || m_propShowDendrogram->changed( true ) )
979  {
980  m_treeDirty = true;
981  }
982  if( m_propDendroSizeX->changed( true ) ||
983  m_propDendroSizeY->changed( true ) ||
984  m_propDendroOffsetX->changed( true ) ||
985  m_propDendroOffsetY->changed( true )
986  )
987  {
988  m_treeDirty = true;
989  m_labelsDirty = true;
990  }
991 
992  // only show triangle leaves option if tree is being plotted by distance level
993  if( m_propDendroPlotByLevel->changed( true ) )
994  {
995  m_treeDirty = true;
996 
997  if( m_propDendroPlotByLevel->get( true ) )
998  {
999  m_propTriangleLeaves->setHidden( true );
1000  }
1001  else
1002  {
1003  m_propTriangleLeaves->setHidden( false );
1004  }
1005  }
1006 
1007  // if zoom controls are changed, make changes and redraw
1009  {
1010  m_treeZoomRoot = m_propSourceCluster->get( true );
1012  m_treeDirty = true;
1013  }
1015  {
1018  m_treeDirty = true;
1019  }
1020 
1021  // if auto resize option is changed, set to redraw and hide or extend the manual settings
1022  if( m_propDendroSideSelector->changed( true ) )
1023  {
1024  m_labelsDirty = true;
1025  m_treeDirty = true;
1026 
1027  if( m_propDendroSideSelector->get( true ).getItemIndexOfSelected( 0 ) == 3 )
1028  {
1029  m_groupDendroManual->setHidden( false );
1030  }
1031  else
1032  {
1033  m_groupDendroManual->setHidden( true );
1034  }
1035  }
1036 
1037 
1038  // === CLUSTER SELECTION OPTIONS ===
1039 
1040 
1041  // if root button is pressed update
1043  {
1045  m_selectionClusters.clear();
1046  m_selectionClusters.push_back( m_propSourceCluster->get( true ) );
1047  m_horizontalLine = 0;
1048 
1049 
1051  std::string message( "Single cluster at distance: " +
1053  m_infoPartMessage->set( message );
1054  m_infoPartNumber->set( 1 );
1055  m_infoPartActive->set( 1 );
1056  m_infoPartLeaves->set( 0 );
1058 
1059  updateSelection();
1060  m_propSubselectedCluster->set( m_propSourceCluster->get( true ) );
1061  m_propSubselectedcolor->set( m_selectionColors.begin()->second );
1062  }
1063 
1064  // if root cluster bas changed
1065  if( m_propSourceCluster->changed( true ) )
1066  {
1067  m_selectionClusters.clear();
1068  m_horizontalLine = 0;
1069  m_selectionClusters.push_back( m_propSourceCluster->get( true ) );
1070  m_propPartNumClusters->removeConstraint( PC_MAX );
1071  m_propPartNumClusters->setMax( m_tree.getNode( m_propSourceCluster->get( true ) ).getSize() );
1072  m_propPartDistanceValue->removeConstraint( PC_MAX );
1074  m_propPartHlevelValue->removeConstraint( PC_MAX );
1075  m_propPartHlevelValue->setMax( m_tree.getNode( m_propSourceCluster->get( true ) ).getHLevel() );
1076  m_propPartSizeValue->removeConstraint( PC_MAX );
1077  m_propPartSizeValue->setMax( m_tree.getNode( m_propSourceCluster->get( true ) ).getSize() );
1078 
1079  std::string message( "Single cluster at distance: " +
1081  m_infoPartMessage->set( message );
1082  m_infoPartNumber->set( 1 );
1083  m_infoPartActive->set( 1 );
1084  m_infoPartLeaves->set( 0 );
1085  m_infoCutValue->set( m_tree.getNode( m_propSourceCluster->get( true ) ).getDistLevel() );
1086 
1087  updateSelection();
1088  m_propSubselectedCluster->set( m_propSourceCluster->get( true ) );
1089  m_propSubselectedcolor->set( m_selectionColors.begin()->second );
1090  }
1091 
1092  // if cluster selection has changed
1093  if( m_propPartitionSelector->changed( true ) )
1094  {
1095  m_propConditionSelector->setHidden( true );
1096  m_propPartNumClusters->setHidden( true );
1097  m_propPartDistanceValue->setHidden( true );
1098  m_propPartSizeValue->setHidden( true );
1099  m_propPartSearchDepthValue->setHidden( true );
1100  m_propPartRelativeValue->setHidden( true );
1101  m_propPartHlevelValue->setHidden( true );
1102  m_propPreloadPartitionNr->setHidden( true );
1103  m_horizontalLine = 0;
1104  switch( m_propPartitionSelector->get( true ).getItemIndexOfSelected( 0 ) )
1105  {
1106  case 0:
1107  case 1:
1108  m_propConditionSelector->setHidden( false );
1109  m_propPartNumClusters->setHidden( false );
1110  m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 0 ) );
1111  break;
1112  case 2:
1113  case 3:
1114  m_propConditionSelector->setHidden( false );
1115  m_propPartNumClusters->setHidden( false );
1116  m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 0 ) );
1117  m_propPartSearchDepthValue->setHidden( false );
1118  break;
1119  case 4:
1120  m_propPartDistanceValue->setHidden( false );
1121  m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 1 ) );
1122  break;
1123  case 5:
1124  m_propPreloadPartitionNr->setHidden( false );
1125  break;
1126 //UNUSED case 6:
1127 //UNUSED m_propConditionSelector->setHidden( false );
1128 //UNUSED m_propPartNumClusters->setHidden( false );
1129 //UNUSED m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 0 ) );
1130 //UNUSED break;
1131 //UNUSED case 7:
1132 //UNUSED case 8:
1133 //UNUSED case 9:
1134 //UNUSED case 10:
1135 //UNUSED m_propConditionSelector->setHidden( false );
1136 //UNUSED m_propPartNumClusters->setHidden( false );
1137 //UNUSED m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 0 ) );
1138 //UNUSED m_propPartSearchDepthValue->setHidden( false );
1139 //UNUSED break;
1140 //UNUSED case 11:
1141 //UNUSED m_propPartDistanceValue->setHidden( false );
1142 //UNUSED m_propConditionSelector->set( m_propConditionSelectionsList->getSelector( 1 ) );
1143 //UNUSED break;
1144  default:
1145  break;
1146  }
1147  }
1148 
1149  // if condition selection has changed
1150  if( m_propConditionSelector->changed( true ) )
1151  {
1152  m_propPartNumClusters->setHidden( true );
1153  m_propPartDistanceValue->setHidden( true );
1154  m_propPartSizeValue->setHidden( true );
1155  m_propPartRelativeValue->setHidden( true );
1156  m_propPartHlevelValue->setHidden( true );
1157  m_propPreloadPartitionNr->setHidden( true );
1158  switch( m_propConditionSelector->get( true ).getItemIndexOfSelected( 0 ) )
1159  {
1160  case 0:
1161  m_propPartNumClusters->setHidden( false );
1162  break;
1163  case 1:
1164 
1165  switch( m_propPartitionSelector->get( true ).getItemIndexOfSelected( 0 ) )
1166  {
1167  case 0:
1168  m_propPartDistanceValue->setHidden( false );
1169  break;
1170  case 1:
1171  m_propPartHlevelValue->setHidden( false );
1172  break;
1173  case 2:
1174  m_propPartSizeValue->setHidden( false );
1175  break;
1176  case 3:
1177  case 4:
1178  m_propPartDistanceValue->setHidden( false );
1179  break;
1180  case 5:
1181  break;
1182 //UNUSED case 6:
1183 //UNUSED m_propPartSizeValue->setHidden( false );
1184 //UNUSED break;
1185 //UNUSED case 7:
1186 //UNUSED case 8:
1187 //UNUSED case 9:
1188 //UNUSED case 10:
1189 //UNUSED m_propPartDistanceValue->setHidden( false );
1190 //UNUSED break;
1191  default:
1192  break;
1193  }
1194  break;
1195  case 2:
1196  m_propPartRelativeValue->setHidden( false );
1197  break;
1198  default:
1199  break;
1200  }
1201  }
1202 
1203 
1204 
1205  // if cluster selection has been triggered
1207  {
1208  clusterSelection();
1209  }
1210 
1211 
1212  // === VISUALIZATION OPTIONS ===
1213 
1214 
1215  // if coloring pattern has changed
1216  if( m_propColorSchemeSelector->changed( true ) )
1217  {
1218  updateSelection();
1219  }
1220 
1221  // if color actionhas been activated
1223  {
1224  colorAction();
1225  }
1226 
1227  // if show label option has changed
1228  if( m_propShowLabels->changed( true ) )
1229  {
1230  m_labelsDirty = true;
1231  m_treeDirty = true;
1232  if( m_propShowLabels->get( true ) )
1233  {
1234  m_propLabelInfoSelector->setHidden( false );
1235  }
1236  else
1237  {
1238  m_propLabelInfoSelector->setHidden( true );
1239  }
1240  }
1241 
1242  // if labeling scheme has changed
1243  if( m_propLabelInfoSelector->changed( true ) )
1244  {
1245  m_labelsDirty = true;
1246  }
1247 
1248  // if showing discarded voxels has changed
1249  if( m_propShowDiscarded->changed( true ) )
1250  {
1251  if( m_propShowDiscarded->get( true ) )
1252  {
1253  m_propDiscardedColor->setHidden( false );
1254  }
1255  else
1256  {
1257  m_propDiscardedColor->setHidden( true );
1258  }
1259  updateColors();
1260  updateOutput2();
1261  }
1262 
1263 
1264  // if showing just boundaries has changed
1265  if( m_propBoundaries->changed( true ) )
1266  {
1267  if( m_propBoundaries->get( true ) )
1268  {
1269  m_propBoundaryColor->set( WColor( 1, 0, 0, 1 ) );
1270  m_propBoundaryColor->setHidden( false );
1271  }
1272  else
1273  {
1274  m_propBoundaryColor->setHidden( true );
1275  }
1276  updateColors();
1277  }
1278 
1279 
1280  // if discarded, inactive, or boundary color has changed
1281  if( m_propDiscardedColor->changed( true ) || m_propInactiveColor->changed( true ) || m_propBoundaryColor->changed( true ) )
1282  {
1283  updateColors();
1284  }
1285 
1286  // if showing rendered cube voxels has changed
1287  if( m_propShowCubeMesh->changed( true ) )
1288  {
1289  if( m_propShowCubeMesh->get( true ) )
1290  {
1291  m_propInactiveColor->setHidden( false );
1292  }
1293  else
1294  {
1295  m_propInactiveColor->setHidden( true );
1296  }
1297  renderCubeMesh();
1298  }
1299 
1300 
1301 
1302 
1303 
1304  // === TREE PROCESSING OPTIONS ===
1305 
1306 
1307  // if processing method has changed
1308  if( m_propProcessSelector->changed( true ) )
1309  {
1310  m_propSafeSize->setHidden( true );
1311  m_propPruneJoinSize->setHidden( true );
1312  m_propPruneSizeRatio->setHidden( true );
1313  m_propDistanceGap->setHidden( true );
1314  m_propPrunedNumber->setHidden( true );
1315  m_propPrunedSeed->setHidden( true );
1316  m_propFlatLimit->setHidden( true );
1317  m_propKeepBases->setHidden( true );
1318 
1319 
1320  switch( m_propProcessSelector->get( true ).getItemIndexOfSelected( 0 ) )
1321  {
1322  case 0:
1323  m_propSafeSize->setHidden( false );
1324  m_propPruneSizeRatio->setHidden( false );
1325  break;
1326  case 1:
1327  m_propSafeSize->setHidden( false );
1328  m_propPruneJoinSize->setHidden( false );
1329  break;
1330  case 2:
1331  m_propSafeSize->setHidden( false );
1332  m_propDistanceGap->setHidden( false );
1333  break;
1334  case 3:
1335  m_propPrunedNumber->setHidden( false );
1336  m_propPrunedSeed->setHidden( false );
1337  break;
1338  case 4:
1339  m_propDistanceGap->setHidden( false );
1340  m_propKeepBases->setHidden( false );
1341  break;
1342  case 5:
1343  m_propKeepBases->setHidden( false );
1344  break;
1345  case 6:
1346  break;
1347  default:
1348  break;
1349  }
1350  }
1351 
1352  // if processing has been triggered
1354  {
1355  std::shared_ptr< WProgress > progressProcessing = std::shared_ptr< WProgress >( new WProgress( "Processing tree..." ) );
1356  m_progress->addSubProgress( progressProcessing );
1357 
1358  std::pair<size_t, size_t> prunedElements( 0, 0 );
1359  WHtreeProcesser processer( &m_tree );
1360  std::string message;
1361 
1362  switch( m_propProcessSelector->get( true ).getItemIndexOfSelected( 0 ) )
1363  {
1364  case 0:
1365  prunedElements = processer.pruneTree( m_propPruneSizeRatio->get( true ), m_propSafeSize->get( true ), HTPR_SIZERATIO );
1366  message = "Pruning by ratio: ";
1367  break;
1368  case 1:
1369  prunedElements = processer.pruneTree( m_propPruneJoinSize->get( true ), m_propSafeSize->get( true ), HTPR_JOINSIZE );
1370  message = "Pruning by join size: ";
1371  break;
1372  case 2:
1373  prunedElements = processer.pruneTree( m_propDistanceGap->get( true ), m_propSafeSize->get( true ), HTPR_JOINLEVEL );
1374  message = "Pruning by join level: ";
1375  break;
1376  case 3:
1377  prunedElements = processer.pruneRandom( m_propPrunedNumber->get( true ), m_propPrunedSeed->get( true ) );
1378  message = "Random Pruning: ";
1379  break;
1380  case 4:
1381  prunedElements.first = processer.collapseTreeLinear( m_propDistanceGap->get( true ), m_propKeepBases->get( true ) );
1382  message = "Node Collapsing, linear: ";
1383  break;
1384  case 5:
1385  prunedElements.first = processer.flattenSelection( m_selectionClusters, m_propKeepBases->get( true ) );
1386  message = "Selection Flattened: ";
1387  break;
1388  case 6:
1389  prunedElements = processer.pruneSelection( m_selectionClusters );
1390  message = "Selection Pruned: ";
1391  break;
1392  default:
1393  break;
1394  }
1395 
1396  progressProcessing->finish();
1397 
1398  initTreeData();
1399  initProperties();
1400  updateSelection();
1401 
1402  if( m_propProcessSelector->get( true ).getItemIndexOfSelected( 0 ) != 8 )
1403  {
1404  message+= ( string_utils::toString( prunedElements.first ) +
1405  " leaves and "+ string_utils::toString( prunedElements.second )+ " nodes eliminated" );
1406  }
1407  m_infoPartMessage->set( message );
1408 
1410  }
1411 
1412  // === PARTITION TREE OPTIONS ===
1413 
1414  // add partitions
1416  {
1417  addPartitions();
1418  }
1419 
1420  // recolor partitions
1422  {
1424  }
1425 
1427  {
1428  infoLog() << "Clearing partitions";
1430  m_propPreloadPartitionNr->removeConstraint( PC_MAX );
1431  m_propPreloadPartitionNr->setMax( 0 );
1432  m_propPreloadPartitionNr->removeConstraint( PC_MIN );
1433  m_propPreloadPartitionNr->setMin( 0 );
1434  m_propPreloadPartitionNr->set( 0 );
1436  }
1437 
1438 
1439  // === WRITE TREE OPTIONS ===
1440 
1441  // write tree file
1443  {
1444  infoLog() << "Writing tree file";
1445  boost::filesystem::path fileName = m_propWriteTreeFilename->get();
1446  m_tree.writeTree( fileName.string() );
1448  }
1449 
1450  // write partition file
1452  {
1453  infoLog() << "Writing partition files";
1454  writePartition();
1456  }
1457  }
1458 // DEPRECATED con.disconnect();
1459 
1460  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_moduleNode );
1461 } // end moduleMain()
1462 
1463 /*
1464  This function aims to display and color a lego-like surface of the non-zero voxels in the grid, that has been previously calculated and stored in m_cubeMesh,
1465  and give the vertices corresponding to each "cube" of this surface a color defined by the value of the voxel
1466  (as it is just the outer surface the number of vertices corresponding to each cube will vary depending of thesurrounding geometry)
1467  */
1469 {
1470  // if mesh doesnt need to be rendered, finish
1471  if( !m_propShowCubeMesh->get( true ) )
1472  {
1473  m_meshNode->clear(); //this will make the m_meschCube surface not to be shown in screen
1474  return;
1475  }
1476 
1477  std::shared_ptr< WProgress > progressRenderCubes = std::shared_ptr< WProgress >( new WProgress( "Rendering seed voxels..." ) );
1478  m_progress->addSubProgress( progressRenderCubes );
1479 
1480  {
1481  osg::Geometry* surfaceGeometry = new osg::Geometry();
1482  osg::ref_ptr< osg::Geode >outputGeode = osg::ref_ptr< osg::Geode >( new osg::Geode );
1483 
1484  outputGeode->setName( std::string( "seed voxels" ) );
1485  surfaceGeometry->setVertexArray( m_cubeMesh->getVertexArray() );
1486 
1487  // ------------------------------------------------
1488  // normals
1489  // NOTE: this was done using bind_per_primitive. This is not available anymore.
1490  surfaceGeometry->setNormalArray( m_cubeMesh->getVertexNormalArray( true ) );
1491  surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
1492 
1493  // ------------------------------------------------
1494  // colors
1495 
1496 
1497  std::vector<WHcoord> searchCoords; // here we simply a vector of coordinates that constitutes the direct nehborhood in positive space,
1498  // 000 001 100 010 101 and so on... till 111
1499  searchCoords.reserve( 8 );
1500  for( int cz = 0; cz < 2; ++cz )
1501  {
1502  for( int cy = 0; cy < 2; ++cy )
1503  {
1504  for( int cx = 0; cx < 2; ++cx )
1505  {
1506  searchCoords.push_back( WHcoord( cx, cy, cz ) );
1507  }
1508  }
1509  }
1510 
1511  // this is a table that maps a label value (the value ofa voxel in the grid)
1512  std::vector<std::map<size_t, WColor>::const_reverse_iterator> colorTable;
1513  colorTable.reserve( m_selectionColors.size() );
1514  for( std::map< size_t, WColor >::const_reverse_iterator colorIter( m_selectionColors.rbegin() );
1515  colorIter != m_selectionColors.rend();
1516  ++colorIter )
1517  {
1518  colorTable.push_back( colorIter );
1519  }
1520 
1521  osg::Vec4Array* cubeMeshColors = new osg::Vec4Array; //this will keep the colors for each vertex
1522 
1523  for( size_t i = 0; i < m_cubeMesh->getVertexArray()->getNumElements(); ++i ) // loop over all vertices of cube mesh
1524  {
1525  // decide to which voxel centre (cube centre) a vertex is going to be linked to in order to color it according to the value of that voxel
1526  unsigned int vX( m_cubeMesh->getVertex( i ).x() );
1527  if( vX >= m_grid->getNbCoordsX() )
1528  {
1529  vX = m_grid->getNbCoordsX()-1;
1530  }
1531  unsigned int vY( m_cubeMesh->getVertex( i ).y() );
1532  if( vY >= m_grid->getNbCoordsY() )
1533  {
1534  vY = m_grid->getNbCoordsY()-1;
1535  }
1536  unsigned int vZ( m_cubeMesh->getVertex( i ).z() );
1537  if( vZ >= m_grid->getNbCoordsZ() )
1538  {
1539  vZ = m_grid->getNbCoordsZ()-1;
1540  }
1541 
1542  size_t colorLabel( 0 );
1543  for( size_t j = 0; j < searchCoords.size(); ++j ) // assing color to the vertex
1544  {
1545  if( ( ( static_cast<int>( vX ) )-searchCoords[j].m_x ) < 0 ||
1546  ( ( static_cast<int>( vY ) )-searchCoords[j].m_y ) < 0 ||
1547  ( ( static_cast<int>( vZ ) )-searchCoords[j].m_z ) < 0 )
1548  {
1549  continue;
1550  }
1551  // m_texture labels, keeps a value for each voxel of the grid, that will define the color
1552  colorLabel = m_textureLabels[m_grid->getVoxelNum( vX-searchCoords[j].m_x, vY-searchCoords[j].m_y, vZ-searchCoords[j].m_z )];
1553  // if the label is 0 or is equal to m_tree.getNumNodes()+1 we dont want to recolor it
1554  if( colorLabel != 0 && colorLabel != m_tree.getNumNodes() + 1 )
1555  {
1556  break;
1557  }
1558  }
1559 
1560  if( colorLabel == m_tree.getNumNodes()+2 ) //depending on the colorLabel value, we give it a different color vector value
1561  {
1562  cubeMeshColors->push_back( m_propBoundaryColor->get( true ) );
1563  }
1564  else if( colorLabel == 0 || colorLabel == m_tree.getNumNodes()+1 )
1565  {
1566  cubeMeshColors->push_back( m_propInactiveColor->get( true ) );
1567  }
1568  else
1569  {
1570  cubeMeshColors->push_back( colorTable[colorLabel-1]->second );
1571  }
1572  }
1573 
1574  surfaceGeometry->setColorArray( cubeMeshColors ); // assing the array of colors per vertex to the geometry
1575  surfaceGeometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
1576 
1577 
1578  osg::DrawElementsUInt* surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
1579 
1580  std::vector< size_t >tris = m_cubeMesh->getTriangles();
1581  surfaceElement->reserve( tris.size() );
1582 
1583  for( unsigned int vertId = 0; vertId < tris.size(); ++vertId )
1584  {
1585  surfaceElement->push_back( tris[vertId] );
1586  }
1587  surfaceGeometry->addPrimitiveSet( surfaceElement );
1588  outputGeode->addDrawable( surfaceGeometry );
1589 
1590  osg::StateSet* state = outputGeode->getOrCreateStateSet();
1591  osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
1592  lightModel->setTwoSided( true );
1593  state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
1594  state->setMode( GL_BLEND, osg::StateAttribute::ON );
1595 
1596  m_meshNode->clear();
1597  m_meshNode->insert( outputGeode );
1598  }
1599 
1600  if( m_propShowDiscarded->get() )
1601  {
1602  osg::Geometry* surfaceGeometry = new osg::Geometry();
1603  osg::ref_ptr< osg::Geode >outputGeode = osg::ref_ptr< osg::Geode >( new osg::Geode );
1604 
1605  outputGeode->setName( ( std::string( "non active" ) ).c_str() );
1606 
1607  surfaceGeometry->setVertexArray( m_discardedMesh->getVertexArray() );
1608 
1609  // ------------------------------------------------
1610  // normals
1611  // NOTE: this was done using bind_per_primitive. This is not available anymore.
1612  surfaceGeometry->setNormalArray( m_discardedMesh->getVertexNormalArray( true ) );
1613  surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
1614 
1615  // ------------------------------------------------
1616  // colors
1617  osg::Vec4Array* discardedColor = new osg::Vec4Array;
1618  discardedColor->push_back( m_propDiscardedColor->get( true ) );
1619  surfaceGeometry->setColorArray( discardedColor );
1620  surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL );
1621 
1622  osg::DrawElementsUInt* surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
1623 
1624  std::vector< size_t >tris = m_discardedMesh->getTriangles();
1625  surfaceElement->reserve( tris.size() );
1626 
1627  for( unsigned int vertId = 0; vertId < tris.size(); ++vertId )
1628  {
1629  surfaceElement->push_back( tris[vertId] );
1630  }
1631  surfaceGeometry->addPrimitiveSet( surfaceElement );
1632  outputGeode->addDrawable( surfaceGeometry );
1633 
1634  osg::StateSet* state = outputGeode->getOrCreateStateSet();
1635  osg::ref_ptr<osg::LightModel> lightModel = new osg::LightModel();
1636  lightModel->setTwoSided( true );
1637  state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
1638  state->setMode( GL_BLEND, osg::StateAttribute::ON );
1639 
1640  m_meshNode->insert( outputGeode );
1641  }
1642  progressRenderCubes->finish();
1643  return;
1644 } // end renderCubeMesh()
1645 
1646 
1647 
1649 {
1650  osg::ref_ptr<osgViewer::View> viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView();
1651  int totalHeight = viewer->getCamera()->getViewport()->height();
1652  int totalWidth = viewer->getCamera()->getViewport()->width();
1653 
1654  const unsigned int labelHeight = 20;
1655  const unsigned int labelWidth = 100;
1656  int labelRows = ( totalHeight - 20 ) / labelHeight;
1657 
1658  if( ( totalHeight != m_oldViewHeight ) || totalWidth != m_oldViewWidth )
1659  {
1660  m_oldViewHeight = totalHeight;
1661  m_oldViewWidth = totalWidth;
1662  m_treeDirty = true;
1663  m_labelsDirty = true;
1664  }
1665 
1666  bool buttonClicked( false );
1667 
1668  for( size_t i = 0; i < m_selectionLabels.size(); ++i )
1669  {
1670  if( m_selectionLabels[i]->clicked() )
1671  {
1672  if( m_selectionLabels[i]->pushed() )
1673  {
1674  m_selectionColors[m_selectionLabels[i]->getId()] = WColor( 0.9, 0.9, 0.9, 1 );
1675  }
1676  else
1677  {
1679  }
1680  m_selectionLabels[i]->setBackgroundColor( m_selectionColors[m_selectionLabels[i]->getId()] );
1681  m_propSubselectedCluster->set( m_selectionLabels[i]->getId() );
1683  buttonClicked = true;
1684  updateColors();
1685  }
1686  }
1687 
1688  if( !buttonClicked && !m_treeDirty && !m_labelsDirty )
1689  {
1690  return;
1691  }
1692 
1693  std::shared_ptr< WProgress > progressUpdateWidgets = std::shared_ptr< WProgress >( new WProgress( "Updating widgets..." ) );
1694  m_progress->addSubProgress( progressUpdateWidgets );
1695 
1696  int usedXoffset( 0 );
1697  int usedWidth( totalWidth );
1698  int usedHeight( totalHeight/2 );
1699  int usedYoffset( 0 );
1700 
1701  switch( m_propDendroSideSelector->get( true ).getItemIndexOfSelected( 0 ) )
1702  {
1703  case 0:
1704  usedWidth -= 20;
1705  usedXoffset += 10;
1706  break;
1707  case 1:
1708  usedWidth = ( usedWidth-30 )/2;
1709  usedXoffset += 10;
1710  break;
1711  case 2:
1712  usedXoffset += ( usedWidth/2 ) + 5;
1713  usedWidth = ( usedWidth-30 )/2;
1714  break;
1715  case 3:
1716  usedWidth = m_propDendroSizeX->get( true );
1717  usedHeight = m_propDendroSizeY->get( true );
1718  usedXoffset = m_propDendroOffsetX->get( true );
1719  usedYoffset = m_propDendroOffsetY->get( true );
1720  break;
1721  default:
1722  break;
1723  }
1724 
1725 
1726  if( m_labelsDirty )
1727  {
1728  // redo labels
1729  for( size_t i = 0; i < m_selectionLabels.size(); ++i )
1730  {
1731  m_wm->removeChild( m_selectionLabels[i] );
1732  }
1733  m_selectionLabels.clear();
1734 
1735  if( m_propShowLabels->get( true ) )
1736  {
1737  std::vector<std::pair<float, size_t> > labelPairs;
1738  labelPairs.reserve( m_selectionColors.size() );
1739  for( std::map<size_t, WColor>::iterator cIter( m_selectionColors.begin() ); cIter != m_selectionColors.end(); ++cIter )
1740  {
1741  const WHnode& thisCluster( m_tree.getNode( cIter->first ) );
1742  float value( 0 );
1743  switch( m_propLabelInfoSelector->get( true ).getItemIndexOfSelected( 0 ) )
1744  {
1745  case 0:
1746  value = thisCluster.getID();
1747  break;
1748  case 1:
1749  value = thisCluster.getSize();
1750  break;
1751  case 2:
1752  value = thisCluster.getDistLevel();
1753  break;
1754  case 3:
1755  value = thisCluster.getHLevel();
1756  break;
1757  default:
1758  break;
1759  }
1760  labelPairs.push_back( std::make_pair( value, thisCluster.getID() ) );
1761  }
1762 
1763  std::sort( labelPairs.begin(), labelPairs.end() );
1764  for( size_t i = 0; i < labelPairs.size(); ++i )
1765  {
1766  std::string labelString;
1767  if( labelPairs[i].first<1 && labelPairs[i].first>0 )
1768  {
1769  labelString = ( str( boost::format( "%.05f" ) % labelPairs[i].first ) );
1770  }
1771  else
1772  {
1773  labelString = ( str( boost::format( "%-6d" ) % labelPairs[i].first ) );
1774  }
1775 
1776  osg::ref_ptr<WOSGButton> newButton = osg::ref_ptr<WOSGButton>( new WOSGButton( labelString, osgWidget::Box::VERTICAL, true, true ) );
1777  newButton->setPosition( osg::Vec3( ( i / labelRows ) * labelWidth + usedXoffset, ( i % labelRows ) * 20.f, 0 ) );
1778  newButton->setId( labelPairs[i].second );
1779  newButton->setBackgroundColor( m_selectionColors[labelPairs[i].second] );
1780  newButton->managed( m_wm );
1781  m_wm->addChild( newButton );
1782  m_selectionLabels.push_back( newButton );
1783  }
1784  }
1785  m_labelsDirty = false;
1786  }
1787 
1788  if( m_propShowLabels->get( true ) )
1789  {
1790  usedXoffset += ( ( m_selectionColors.size() / labelRows ) + 1 ) * labelWidth;
1791  usedWidth -= ( ( m_selectionColors.size() / labelRows ) + 1 ) * labelWidth;
1792  }
1793 
1794  if( m_treeDirty )
1795  {
1796  m_wm->resizeAllWindows();
1797 
1798  m_camera->removeChild( m_dendrogramGeode );
1799 
1800  if( m_propShowDendrogram->get( true ) )
1801  {
1802  m_dendrogramGeode = new WNonBinDendroGeode( m_tree, m_treeDisplayColors, m_treeZoomRoot, usedWidth , usedHeight , usedXoffset,
1803  usedYoffset, m_propDendroPlotByLevel->get( true ), m_propTriangleLeaves->get( true ), m_horizontalLine );
1804 
1805  m_camera->addChild( m_dendrogramGeode );
1806  }
1807  m_treeDirty = false;
1808  }
1809  progressUpdateWidgets->finish();
1810 
1811  return;
1812 } // end updateWidgets()
1813 
1814 
1815 
1816  //DEPRECATED void WMHierchClustDisplay::dendrogramClick( WPickInfo pickInfo )
1818 {
1819  //DEPRECATED if( !m_propShowDendrogram->get() || !( pickInfo.getName() == "nothing" ) )
1820  if( m_tree.isLoaded() && m_propShowDendrogram->get( true ) )
1821  {
1822  int x = pos[0];
1823  int y = pos[1];
1824  if( m_dendrogramGeode->inDendrogramArea( x, y ) )
1825  {
1826  size_t cluster = m_dendrogramGeode->getClickedCluster( x, y );
1827  if( cluster != m_treeZoomRoot+1 )
1828  {
1829  m_propSourceCluster->set( cluster );
1830  }
1831  return true;
1832  }
1833  }
1834 
1835  //DEPRECATED int x = pickInfo.getPickPixel().x();
1836  //DEPRECATED int y = pickInfo.getPickPixel().y();
1837  //DEPRECATED size_t cluster = m_dendrogramGeode->getClickedCluster( x, y );
1838  //DEPRECATED m_buttonExecuteSelection->set( WPVBaseTypes::PV_TRIGGER_TRIGGERED );} // end dendrogramClick()
1839 
1840  return false;
1841 } // end dendrogramClick()
1842 
1843 
1845 {
1846  if( m_tree.isLoaded() && m_propShowDendrogram->get( true ) )
1847  {
1848  int x = pos[0];
1849  int y = pos[1];
1850  if( m_dendrogramGeode->inDendrogramArea( x, y ) )
1851  {
1852  size_t cluster = m_dendrogramGeode->getClickedCluster( x, y );
1853 
1854  if( cluster != m_treeZoomRoot+1 )
1855  {
1856  std::vector< size_t >::const_iterator findIter( std::find( m_selectionClusters.begin(), m_selectionClusters.end(), cluster ) );
1857  if( findIter != m_selectionClusters.end() )
1858  {
1859  //size_t sel_pos=findIter-m_selectionClusters.begin();
1860  //std::cout<<"cluster pos "<<sel_pos<<std::endl;
1861  m_propSubselectedCluster->set( cluster );
1862 
1863  if( m_selectionColors[cluster] == WColor( 0.9, 0.9, 0.9, 1 ) )
1864  {
1865  m_selectionColors[cluster]=m_selectionColorsBackup[cluster];
1866  }
1867  else
1868  {
1869  m_selectionColors[cluster] = WColor( 0.9, 0.9, 0.9, 1 );
1870  }
1872  m_labelsDirty = true;
1873  updateColors();
1874  }
1875  }
1876  return true;
1877  }
1878  }
1879  return false;
1880 }
1881 
1882 void WMHierchClustDisplay::colorBranch( const size_t &thisNode, const WColor &color )
1883 {
1884  const WHnode& current( m_tree.getNode( thisNode ) );
1885  m_treeDisplayColors[thisNode] = color;
1886 
1887  // if the children are anly leaves stop
1888  if( current.getHLevel() == 1 )
1889  return;
1890 
1891  std::vector<nodeID_t> kids( current.getChildren() );
1892  for( unsigned int i = 0; i < kids.size(); ++i )
1893  {
1894  if( kids[i].first )
1895  {
1896  //if its a node
1897  colorBranch( kids[i].second, color );
1898  }
1899  }
1900  return;
1901 }
1902 
1903 void WMHierchClustDisplay::colorBranchCustom( const size_t &thisNode, const WColor &color )
1904 {
1905  const WHnode& current( m_tree.getNode( thisNode ) );
1906  m_nodeColorsCustom[thisNode] = color;
1907 
1908  // if the children are only leaves stop
1909  if( current.getHLevel() == 1 )
1910  return;
1911 
1912  std::vector<nodeID_t> kids( current.getChildren() );
1913  for( unsigned int i = 0; i < kids.size(); ++i )
1914  {
1915  if( kids[i].first )
1916  {
1917  //if its a node
1918  colorBranchCustom( kids[i].second, color );
1919  }
1920  }
1921  return;
1922 }
1923 
1924 
1925 void WMHierchClustDisplay::updateSelection( const std::vector< WColor > &preloadedColors )
1926 {
1927  std::shared_ptr< WProgress > progressUpdateSelection = std::shared_ptr< WProgress >( new WProgress( "Updating selection..." ) );
1928  m_progress->addSubProgress( progressUpdateSelection );
1929 
1930  // get a color for each of the clusters currently selected
1931  m_selectionColors.clear();
1932  m_selectionColorsBackup.clear();
1933 
1934  if( preloadedColors.empty() || preloadedColors.size() != m_selectionClusters.size() )
1935  {
1936  // sorting before color assignment
1937  switch( m_propColorSchemeSelector->get( true ).getItemIndexOfSelected( 0 ) )
1938  {
1939  case 0:
1940  break;
1941  case 1:
1942 //UNUSED case 2:
1944  std::reverse( m_selectionClusters.begin(), m_selectionClusters.end() );
1945  break;
1946  default:
1947  infoLog() << "Error at color assignment";
1948  break;
1949  }
1950 
1951 //UNUSED unsigned int seed( 0 );
1952  for( size_t k = 0; k < m_selectionClusters.size(); ++k )
1953  {
1954  switch( m_propColorSchemeSelector->get( true ).getItemIndexOfSelected( 0 ) )
1955  {
1956  case 0:
1958  break;
1959  case 1:
1960  m_selectionColors.insert( std::make_pair( m_selectionClusters[k], wge::getNthHSVColor( k ) ) );
1961  break;
1962 //UNUSED case 2:
1963 //UNUSED m_selectionColors.insert( std::make_pair( m_selectionClusters[k], wge::getNthHSVColor( rand_r( &seed ) ) ) );
1964 //UNUSED break;
1965  default:
1966  infoLog() << "Error at color assignment";
1967  break;
1968  }
1969  }
1970  }
1971  else
1972  {
1973  infoLog() << "Preloaded colors";
1974  for( size_t k = 0; k < m_selectionClusters.size(); ++k )
1975  {
1976  m_selectionColors.insert( std::make_pair( m_selectionClusters[k], preloadedColors[k] ) );
1977  }
1978  }
1979  // after assigning colors we need to order in decreasing hierarchical order for cluster and dendrogram coloring to work
1980  std::sort( m_selectionClusters.begin(), m_selectionClusters.end() );
1981  std::reverse( m_selectionClusters.begin(), m_selectionClusters.end() );
1982 
1984 
1985  m_labelsDirty = true;
1986 
1987  progressUpdateSelection->finish();
1988 
1989  updateColors();
1990 
1991  return;
1992 } // end updateSelection()
1993 
1994 
1996 {
1997  const size_t filteredLabel( m_tree.getNumNodes()+2 );
1998  const size_t discardedLabel( m_tree.getNumNodes()+1 );
1999 
2000 
2001  // recolor clusters for shown tree
2002  std::shared_ptr< WProgress > progressUpdateColors = std::shared_ptr< WProgress >( new WProgress( "Updating colors..." ) );
2003  m_progress->addSubProgress( progressUpdateColors );
2004 
2005 
2006  // set colors for cluster in the tree
2007 
2008  colorBranch( m_tree.getRoot().getID(), WColor( 0.3, 0.3, 0.3, 1 ) );
2009 
2010  for( std::map< size_t, WColor >::reverse_iterator revIter( m_selectionColors.rbegin() ); revIter != m_selectionColors.rend(); ++revIter )
2011  {
2012  colorBranch( revIter->first, revIter->second );
2013  }
2014 
2015 
2016  // reassing texture labels
2017  m_textureLabels.clear();
2018  m_textureLabels.resize( m_grid->size(), 0 );
2019  if( m_propShowDiscarded->get( true ) )
2020  {
2021  for( std::vector<size_t>::iterator discardedIter( m_discardedVoxels.begin() ); discardedIter != m_discardedVoxels.end(); ++discardedIter )
2022  {
2023  m_textureLabels[*discardedIter] = discardedLabel;
2024  }
2025  }
2026 
2027 
2028  std::vector<std::map<size_t, WColor>::const_reverse_iterator> colorTable;
2029  colorTable.reserve( m_selectionColors.size() );
2030  {
2031  size_t thisLabel = 1;
2032  for( std::map< size_t, WColor >::const_reverse_iterator revIter( m_selectionColors.rbegin() );
2033  revIter != m_selectionColors.rend();
2034  ++revIter )
2035  {
2036  for( size_t k = 0; k < m_clusterVoxels[revIter->first].size(); ++k )
2037  {
2038  m_textureLabels[m_clusterVoxels[revIter->first][k]] = thisLabel;
2039  }
2040  ++thisLabel;
2041  colorTable.push_back( revIter );
2042  }
2043  }
2044 
2045  // reassing labels to show only boundaries if set
2046  if( m_propBoundaries->get( true ) )
2047  {
2048  const size_t inactiveLabel( m_tree.getNumNodes()+3 );
2049  size_t rootID( m_tree.getRoot().getID() );
2050  for( size_t i = 0; i < m_clusterVoxels[rootID].size(); ++i )
2051  {
2052  if( m_textureLabels[m_clusterVoxels[rootID][i]] == 0 )
2053  {
2054  m_textureLabels[m_clusterVoxels[rootID][i]] = inactiveLabel;
2055  }
2056  }
2057 
2058  for( size_t i = 0; i < m_grid->size(); ++i )
2059  {
2060  if( m_textureLabels[i] == discardedLabel || m_textureLabels[i] == 0 )
2061  {
2062  continue;
2063  }
2064 
2065  size_t thisLabel( m_textureLabels[i] );
2066  std::vector<size_t> nbors( m_grid->getNeighbours27( i ) );
2067 
2068 
2069  for( size_t j = 0; j < nbors.size(); ++j )
2070  {
2071  size_t nbID( nbors[j] );
2072  size_t nbLabel( m_textureLabels[nbID] );
2073  if( nbLabel == discardedLabel || nbLabel == 0 || nbLabel == filteredLabel || nbLabel== thisLabel )
2074  {
2075  continue;
2076  }
2077  else
2078  {
2079  m_textureLabels[i] = filteredLabel;
2080  break;
2081  }
2082  }
2083  }
2084  for( size_t i = 0; i < m_textureLabels.size(); ++i )
2085  {
2086  if( m_textureLabels[i] == discardedLabel || m_textureLabels[i] == filteredLabel || m_textureLabels[i] == 0 )
2087  {
2088  continue;
2089  }
2090  else
2091  {
2092  m_textureLabels[i] = 0;
2093  }
2094  }
2095  }
2096 
2097 
2098  // redraw texture
2099  unsigned char* data = m_texture->getImage()->data();
2100  for( size_t i = 0; i < m_grid->size(); ++i )
2101  {
2102  WColor color( 0, 0, 0, 1 );
2103 
2104  if( m_textureLabels[i] == discardedLabel )
2105  {
2106  color = m_propDiscardedColor->get( true );
2107  }
2108  else if( m_textureLabels[i] == filteredLabel )
2109  {
2110  color = m_propBoundaryColor->get( true );
2111  }
2112  else if( m_textureLabels[i] != 0 )
2113  {
2114  color = colorTable[m_textureLabels[i]-1]->second;
2115  }
2116 
2117  data[i * 3 ] = color[0] * 255;
2118  data[i * 3 + 1] = color[1] * 255;
2119  data[i * 3 + 2] = color[2] * 255;
2120  }
2121  m_texture->dirtyTextureObject();
2122 
2123 
2124  // update output texture
2125  WAssert( m_anatomy, "" );
2126  WAssert( m_anatomy->getValueSet(), "" );
2127  WAssert( m_anatomy->getGrid(), "" );
2128 
2129  std::shared_ptr< std::vector< unsigned char > >ptr( new std::vector< unsigned char >( m_textureLabels.size() * 3 ) );
2130 
2131  for( size_t i = 0; i < m_textureLabels.size()*3; ++i )
2132  {
2133  ptr->at( i ) = data[i];
2134  }
2135 
2136  std::shared_ptr< WValueSet< unsigned char > > vs =
2137  std::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 1, 3, ptr, W_DT_UINT8 ) );
2138 
2139  std::shared_ptr< WGridRegular3D> grid =
2140  std::shared_ptr< WGridRegular3D>( new WGridRegular3D(
2141  m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), m_grid->getTransform() ) );
2142  m_outData = std::shared_ptr< WDataSetVector >( new WDataSetVector( vs, grid ) );
2143  m_output->updateData( m_outData );
2144 
2145  m_treeDirty = true;
2146 
2147  progressUpdateColors->finish();
2148 
2149  renderCubeMesh();
2150 
2151  return;
2152 } // end updateColors()
2153 
2154 
2156 {
2157  //update coordinates output
2158  std::shared_ptr< WProgress > progressUpdateOutput2 = std::shared_ptr< WProgress >( new WProgress( "Updating Output 2 ( coordinates )..." ) );
2159  m_progress->addSubProgress( progressUpdateOutput2 );
2160 
2161  std::shared_ptr< std::vector< int > >coordPtr( new std::vector< int >() );
2162  std::vector<WHcoord> coordinates( m_tree.getRoi() );
2163  for( std::vector<WHcoord>::iterator coordIter( coordinates.begin() ); coordIter != coordinates.end(); ++coordIter )
2164  {
2165  coordPtr->push_back( coordIter->m_x );
2166  coordPtr->push_back( coordIter->m_y );
2167  coordPtr->push_back( coordIter->m_z );
2168  }
2169  std::list<WHcoord> discarded( m_tree.getDiscarded() );
2170  if( m_propShowDiscarded->get( true ) )
2171  {
2172  for( std::list<WHcoord>::iterator discardedIter( discarded.begin() ); discardedIter != discarded.end(); ++discardedIter )
2173  {
2174  coordPtr->push_back( discardedIter->m_x );
2175  coordPtr->push_back( discardedIter->m_y );
2176  coordPtr->push_back( discardedIter->m_z );
2177  }
2178  }
2179  std::shared_ptr< WValueSet< int > > vs = std::shared_ptr< WValueSet< int > >( new WValueSet< int >( 0, 1, coordPtr, W_DT_INT16 ) );
2180  std::shared_ptr< WGridRegular3D> grid = std::shared_ptr< WGridRegular3D>(
2181  new WGridRegular3D( coordPtr->size(), 1, 1, m_grid->getTransform() ) );
2182 
2183  m_outData2 = std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
2184  m_output2->updateData( m_outData2 );
2185 
2186  progressUpdateOutput2->finish();
2187 
2188  return;
2189 } // end updateOutput2()
2190 
2191 
2193 {
2194  if( m_selectionClusters.empty() )
2195  {
2196  infoLog() << "Partition empty, partition file not written";
2197  return;
2198  }
2199  boost::filesystem::path partitionFilename = m_propPartitionFile->get();
2200 
2201  std::ofstream streamFile( partitionFilename.string() );
2202  if( !streamFile )
2203  {
2204  errorLog() << "ERROR: unable to open partition file: \"" << partitionFilename << "\"";
2205  }
2206  else
2207  {
2208  for( size_t i = 0; i < m_selectionClusters.size(); ++i )
2209  {
2210  const WHnode &thisNode( m_tree.getNode( m_selectionClusters[i] ) );
2211  size_t thisID( thisNode.getID() );
2212  std::vector< WHcoord > thisCoords = m_tree.getCoordinates4node( thisID );
2213  for( size_t j = 0; j < thisCoords.size(); ++j )
2214  {
2215  streamFile << thisCoords[j] << " " << thisID << std::endl;
2216  }
2217  }
2218  }
2219 } // end writePartition()
2220 
2222 {
2223  std::shared_ptr< WProgress > progressPartition = std::shared_ptr< WProgress >( new WProgress( "Finding partition..." ) );
2224  m_progress->addSubProgress( progressPartition );
2225 
2226  std::vector<nodeID_t> partition;
2227  std::vector< size_t > selectedPartition;
2228  std::vector< WHcoord > selectedColors;
2229  std::vector< WColor > partitionColors;
2230 
2231  float returnedCutValue( 0 );
2232  float conditionValue( 0 );
2233  float relativeCoefficient( 0 );
2234  HT_CONDITION conditionMode( HTC_CNUM );
2235  HT_PARTMODE partitionMode1( HTP_HOZ );
2236  HT_PARTMODE2 partitionMode2( HTP2_CSD );
2237 
2238  WHtreePartition partitioner( &m_tree );
2239 
2240  switch( m_propPartitionSelector->get( true ).getItemIndexOfSelected( 0 ) )
2241  {
2242  case 0:
2243  partitionMode1 = HTP_HOZ;
2244  conditionValue = m_propPartDistanceValue->get( true );
2245  relativeCoefficient = 0.01;
2246  break;
2247  case 1:
2248  partitionMode1 = HTP_HLEVEL;
2249  conditionValue = m_propPartHlevelValue->get( true );
2250  relativeCoefficient = m_tree.getNode( m_propSourceCluster->get( true ) ).getHLevel()/100.0;
2251  break;
2252  case 2:
2253  partitionMode2 = HTP2_CSD;
2254  conditionValue = m_propPartSizeValue->get( true );
2255  relativeCoefficient = m_tree.getNode( m_propSourceCluster->get( true ) ).getSize()/100.0;
2256  break;
2257  case 3:
2258  partitionMode2 = HTP2_OPT;
2259  break;
2260  case 4:
2261  conditionValue = m_propPartDistanceValue->get( true );
2262  break;
2263  case 5:
2264  break;
2265  default:
2266  break;
2267  }
2268 
2269  switch( m_propConditionSelector->get( true ).getItemIndexOfSelected( 0 ) )
2270  {
2271  case 0:
2272  conditionValue = m_propPartNumClusters->get( true );
2273  conditionMode = HTC_CNUM;
2274  break;
2275  case 1:
2276  conditionMode = HTC_VALUE;
2277  break;
2278  case 2:
2279  conditionValue = m_propPartRelativeValue->get( true )*relativeCoefficient;
2280  conditionMode = HTC_VALUE;
2281  break;
2282  default:
2283  break;
2284  }
2285 
2286  switch( m_propPartitionSelector->get( true ).getItemIndexOfSelected( 0 ) )
2287  {
2288  case 0:
2289  case 1:
2290  returnedCutValue = partitioner.partitionClassic( conditionValue,
2291  &partition,
2292  partitionMode1,
2293  conditionMode,
2294  m_propPartExcludeLeaves->get( true ),
2295  m_propSourceCluster->get( true ) );
2296  break;
2297  case 2:
2298  case 3:
2299  returnedCutValue = partitioner.partitionOptimized( conditionValue,
2300  &partition,
2301  partitionMode2,
2302  conditionMode,
2303  m_propPartExcludeLeaves->get( true ),
2304  m_propSourceCluster->get( true ),
2305  m_propPartSearchDepthValue->get( true ) );
2306  break;
2307  case 4:
2308  returnedCutValue = partitioner.partitionSharp( conditionValue,
2309  &partition,
2310  m_propPartExcludeLeaves->get( true ),
2311  m_propSourceCluster->get( true ), false );
2312  break;
2313  case 5:
2314  if( m_tree.getSelectedValues().empty() )
2315  {
2316  infoLog() << "tree has no partitions";
2317  break;
2318  }
2319  else
2320  {
2321  int partIndex = m_propPreloadPartitionNr->get( true ) -1;
2322  if( partIndex < 0 )
2323  {
2324  infoLog() << " Partition index is negative";
2325  break;
2326  }
2327 
2328  returnedCutValue = m_tree.getSelectedValues( partIndex );
2329  selectedPartition = m_tree.getSelectedPartitions( partIndex );
2330  selectedColors = m_tree.getSelectedColors( partIndex );
2331 
2332  partition.clear();
2333  partition.reserve( selectedPartition.size() );
2334 
2335  for( size_t i = 0; i < selectedPartition.size(); ++i )
2336  {
2337  partition.push_back( std::make_pair( true, selectedPartition[i] ) );
2338  }
2339  }
2340  break;
2341  default:
2342  break;
2343  }
2344 
2345  if( m_propPartitionSelector->get( true ).getItemIndexOfSelected( 0 ) == 0 )
2346  {
2347  m_horizontalLine = returnedCutValue;
2348  }
2349  size_t totalLeafClusterNum( 0 ), totalNodeClusterNum( 0 );
2350 
2351  {
2352  std::vector<size_t> empty1, empty2, empty3;
2353  m_selectionClusters.swap( empty1 );
2354  m_selectionLeaves.swap( empty3 );
2355  }
2356  partitionColors.clear();
2357  size_t addIndex( partition.size() );
2358 
2359  for( size_t i = 0; i < partition.size(); ++i )
2360  {
2361  if( partition[i].first )
2362  {
2363  m_selectionClusters.push_back( partition[i].second );
2364  ++totalNodeClusterNum;
2365 
2366  if( partition.size() == selectedColors.size() )
2367  {
2368  float Rcolor( selectedColors[i].m_x/ 255.0 );
2369  float Gcolor( selectedColors[i].m_y/ 255.0 );
2370  float Bcolor( selectedColors[i].m_z/ 255.0 );
2371  WColor thisColor( Rcolor, Gcolor, Bcolor, 1.0 );
2372 
2373  // if encoded color is black, select a new color
2374  if( thisColor == WColor( 0, 0, 0, 1 ) )
2375  {
2376  partitionColors.push_back( wge::getNthHSVColor( addIndex++ ) );
2377  }
2378  else
2379  {
2380  partitionColors.push_back( thisColor );
2381  }
2382  }
2383  }
2384  else
2385  {
2386  m_selectionLeaves.push_back( partition[i].second );
2387  ++totalLeafClusterNum;
2388  }
2389  }
2390  std::string message( "Total of " + string_utils::toString( partition.size() ) + " clusters" );
2391  message += ( " (" + string_utils::toString( totalNodeClusterNum ) + " nodes, " );
2392  message += ( string_utils::toString( totalLeafClusterNum )+ " single leaves)" );
2393  message += ( " at a cut level: "+ string_utils::toString( returnedCutValue ) );
2394  m_infoPartMessage->set( message );
2395 
2396  m_infoPartNumber->set( partition.size() );
2397  m_infoPartActive->set( totalNodeClusterNum );
2398  m_infoPartLeaves->set( totalLeafClusterNum );
2399  m_infoCutValue->set( returnedCutValue );
2400 
2401  std::sort( m_selectionLeaves.begin(), m_selectionLeaves.end() );
2402  std::reverse( m_selectionLeaves.begin(), m_selectionLeaves.end() );
2403 
2404  progressPartition->finish();
2405  updateSelection( partitionColors );
2407 }
2408 
2409 
2410 
2412 {
2413  std::random_device rd;
2414  std::mt19937 g( rd() );
2415 
2416  m_labelsDirty = true;
2417  bool doUpdateSelection( true );
2418  std::map<size_t, WColor >::iterator clustIter( m_selectionColors.find( m_propSubselectedCluster->get( true ) ) );
2419 
2420  switch( m_propColorActionSelector->get( true ).getItemIndexOfSelected( 0 ) )
2421  {
2422  case 0:
2423  {
2424  std::vector<WColor> shuffledColors;
2425  shuffledColors.reserve( m_selectionColorsBackup.size() );
2426  for( std::map<size_t, WColor>::const_iterator cIter( m_selectionColorsBackup.begin() );
2427  cIter != m_selectionColorsBackup.end();
2428  ++cIter )
2429  {
2430  shuffledColors.push_back( cIter->second );
2431  }
2432  std::shuffle( shuffledColors.begin(), shuffledColors.end(), g );
2433  size_t i( 0 );
2434  for( std::map<size_t, WColor>::iterator cIter( m_selectionColorsBackup.begin() ); cIter != m_selectionColorsBackup.end(); ++cIter )
2435  {
2436  cIter->second = shuffledColors[i++];
2437  }
2438  }
2440  doUpdateSelection = false;
2441  break;
2442  case 1:
2444  break;
2445  case 2:
2447  break;
2448  case 3:
2449  // change in color table
2451  //change in current screen
2452  if( clustIter != m_selectionColors.end() )
2453  {
2454  clustIter->second = m_propSubselectedcolor->get( true );
2455  m_selectionColorsBackup[clustIter->first] = m_propSubselectedcolor->get( true );
2456  }
2457  doUpdateSelection = false;
2458  break;
2459  case 4:
2460  //change in current screen
2461  if( clustIter != m_selectionColors.end() )
2462  {
2463  clustIter->second = m_propSubselectedcolor->get( true );
2464  m_selectionColorsBackup[clustIter->first] = m_propSubselectedcolor->get( true );
2465  }
2466  // change in color table
2468  doUpdateSelection = false;
2469  break;
2470  case 5:
2471  for( std::map<size_t, WColor>::iterator cIter( m_selectionColorsBackup.begin() ); cIter != m_selectionColorsBackup.end(); ++cIter )
2472  {
2473  m_nodeColorsCustom[ cIter->first ] = cIter->second;
2474  }
2475  break;
2476  case 6:
2477  for( std::map<size_t, WColor>::iterator cIter( m_selectionColorsBackup.begin() ); cIter != m_selectionColorsBackup.end(); ++cIter )
2478  {
2479  assignColorHierch( cIter->first, cIter->second );
2480  }
2481  break;
2482  default:
2483  break;
2484  }
2485 
2486  if( doUpdateSelection )
2487  {
2488  m_propColorSchemeSelector->set( m_propColorSchemeList->getSelectorFirst(), true );
2489  updateSelection();
2490  }
2491  else
2492  {
2493  updateColors();
2494  }
2496 }
2497 
2498 
2500 {
2501  if( m_selectionClusters.empty() )
2502  {
2503  infoLog() << "Selection is empty. Partition was not added";
2504  }
2505  else if( m_selectionClusters.size() == 1 && m_selectionClusters.front() == m_tree.getRoot().getID() )
2506  {
2507  infoLog() << "Selection is trivial. Partition was not added";
2508  }
2509  else
2510  {
2511  infoLog() << "Adding current partition to tree file";
2512  std::vector< float > partValues( m_tree.getSelectedValues() );
2513  std::vector< std::vector< size_t > > partSet( m_tree.getSelectedPartitions() );
2514  std::vector< std::vector< WHcoord > > partColors( m_tree.getSelectedColors() );
2515 
2516  partValues.push_back( m_horizontalLine );
2517  partSet.push_back( m_selectionClusters );
2518 
2519  std::vector< WHcoord > addedPartColor;
2520  addedPartColor.reserve( m_selectionColorsBackup.size() );
2521  for( size_t i = 0; i < m_selectionClusters.size(); ++i )
2522  {
2523  WColor thisColor( m_selectionColorsBackup[m_selectionClusters[i]] );
2524  WHcoord thisColorCoord( thisColor.r()*255, thisColor.g()*255, thisColor.b()*255 );
2525  addedPartColor.push_back( thisColorCoord );
2526  }
2527  partColors.push_back( addedPartColor );
2528  m_tree.insertPartitions( partSet, partValues, partColors );
2529 
2530  m_propPreloadPartitionNr->removeConstraint( PC_MAX );
2531  m_propPreloadPartitionNr->setMax( partValues.size() );
2532  m_propPreloadPartitionNr->removeConstraint( PC_MIN );
2533  m_propPreloadPartitionNr->setMin( 1 );
2534  m_propPreloadPartitionNr->set( 1 );
2535 
2536  std::cout << "Tree now has " << partValues.size() << " partitions saved of sizes: " << std::flush;
2537  for( size_t i = 0; i < partSet.size(); ++i )
2538  {
2539  std::cout << partSet[i].size() << "," << std::flush;
2540  }
2541  std::cout << std::endl;
2542  }
2544 }
2545 
2547 {
2548  if( m_tree.getSelectedValues().empty() )
2549  {
2550  infoLog() << "WARNING: Selection is empty. Nothing was done";
2551  }
2552  else
2553  {
2554  if( !m_tree.getSelectedColors().empty() )
2555  {
2556  infoLog() << "WARNING: Partitions already had assigned colors... they will be replaced";
2557  }
2558 
2559  std::vector< float > partValues( m_tree.getSelectedValues() );
2560  std::vector< std::vector< size_t > > partSet( m_tree.getSelectedPartitions() );
2561  std::vector< std::vector< WHcoord > > partColors;
2562  partColors.reserve( partValues.size() );
2563 
2564  for( size_t i = 0; i < partSet.size(); ++i )
2565  {
2566  std::vector< WHcoord > addedPartColor;
2567  addedPartColor.reserve( partSet[i].size() );
2568  for( size_t j = 0; j < partSet[i].size(); ++j )
2569  {
2570  WColor thisColor( m_nodeColorsCustom[partSet[i][j]] );
2571  WHcoord thisColorCoord( thisColor.r()*255, thisColor.g()*255, thisColor.b()*255 );
2572  addedPartColor.push_back( thisColorCoord );
2573  }
2574  partColors.push_back( addedPartColor );
2575  }
2576  m_tree.insertPartitions( partSet, partValues, partColors );
2577  }
2579 }
2580 
2581 
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
static std::shared_ptr< WSubject > getDefaultSubject()
Gets the subject with the ID SUBJECT_UNKNOWN.
This data set type contains scalars as values.
This data set type contains vectors as values.
This callback allows you a simple usage of callbacks in your module.
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
This class adds some convenience methods to WGEGroupNode.
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
A grid that has parallelepiped cells which all have the same proportion.
this class to contain a seed voxel coordinate.
Definition: WHcoord.h:76
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
size_t getHLevel() const
returns maximum number of nodes between the node and a leaf element
Definition: WHnode.h:267
bool isRoot() const
returns true if object is the root of the tree
Definition: WHnode.cpp:77
size_t getID() const
returns node/leaf ID
Definition: WHnode.h:242
std::string printAllData() const
prints out a string with the node data, in order to implement the operator <<
Definition: WHnode.cpp:117
dist_t getDistLevel() const
returns distance level at which the element was formed
Definition: WHnode.h:262
nodeID_t getParent() const
returns parent ID
Definition: WHnode.h:252
std::vector< nodeID_t > getChildren() const
returns a vector with the ids of the children of that node
Definition: WHnode.h:272
this class operates over the class WHtree to extract partitions and analyze partition quality it may ...
float partitionClassic(float compValue, std::vector< nodeID_t > *const partition, const HT_PARTMODE mode, const HT_CONDITION condition, const bool excludeLeaves, const size_t root) const
Gets a classic partition for the tree (those where clusters are further subdivided until a condition ...
float partitionSharp(const float compValue, std::vector< nodeID_t > *const partition, const bool excludeLeaves, const size_t root, const bool normalized) const
Finds clusters with sharp boundaries (long branches) the tree.
float partitionOptimized(float compValue, std::vector< nodeID_t > *const partition, const HT_PARTMODE2 mode, const HT_CONDITION condition, const bool excludeLeaves, const size_t root, const size_t levelDepth) const
Gets an optimized partition for the tree (those where a partition characteristic must be cosnidered f...
this class implements methods for dendrogram processing, such as pruning, node collapsing and decimat...
std::pair< size_t, size_t > pruneRandom(const size_t numberPruned, unsigned int seed=0)
Prunes the tree from randomly chosen leaves.
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 flattenSelection(const std::list< size_t > selection, const bool keepBaseNodes)
Collapses all the nodes of the subtrees indicated (using only non-leaf node ID)
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.
size_t getNumDiscarded() const
Returns the number of leaves of the tree.
Definition: WHtree.h:850
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
size_t getNumNodes() const
Returns the number of nodes of the tree.
Definition: WHtree.h:836
std::vector< WHcoord > getCoordinates4node(const size_t nodeID) const
Returns a vector with all the seed voxel coordinates contained in that cluster.
Definition: WHtree.cpp:480
void insertPartitions(const std::vector< std::vector< size_t > > &selectedPartitions, const std::vector< float > &selectedValues, const std::vector< std::vector< WHcoord > > &selectedColors=std::vector< std::vector< WHcoord > >())
insert a set of partitions into the tree data
Definition: WHtree.cpp:1473
const WHnode & getNode(const nodeID_t &thisNode) const
returns a const pointer to the node indicated by the ID
Definition: WHtree.cpp:307
std::vector< std::vector< size_t > > getSelectedPartitions() const
Returns the set of the selected partitions.
Definition: WHtree.h:902
std::list< WHcoord > getDiscarded() const
Returns the discarded list.
Definition: WHtree.h:880
void clearPartitions()
delete all data related to saved partitions
Definition: WHtree.cpp:1534
void sortBySize(std::vector< size_t > *const nodeVector) const
Reorders the nodes in the vector according to their size.
Definition: WHtree.cpp:755
bool isLoaded() const
Returns the loading status of the tree.
Definition: WHtree.h:826
std::vector< float > getSelectedValues() const
Returns the cutting values for the selected partitions.
Definition: WHtree.h:885
std::string getName() const
Returns the tree name.
Definition: WHtree.h:821
bool writeTree(const std::string &filename, const bool isNifti=true) const
writes the current tree data
Definition: WHtree.cpp:1233
bool convert2grid(const HC_GRID newGrid)
converts all the coordinates to the grid format indicated
Definition: WHtree.cpp:867
float getCpcc() const
Returns the cpcc value of the tree.
Definition: WHtree.h:865
bool readTree(const std::string &filename)
Reads the the tree data from a file and creates the structure, containing it in the leaves,...
Definition: WHtree.cpp:911
std::vector< std::vector< WHcoord > > getSelectedColors() const
Returns the set of the selected partition colors.
Definition: WHtree.h:919
size_t getNumLeaves() const
Returns the number of leaves of the tree.
Definition: WHtree.h:831
std::vector< WHcoord > getRoi() const
Returns the roi coordinate vector.
Definition: WHtree.h:870
A class containing a list of named items.
std::shared_ptr< WSelectionManager > getSelectionManager()
get for selection manager
Definition: WKernel.cpp:214
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
Small event handler class to catch left mouse buttons clicks in the main view.
void subscribeLeftButtonPush(mouseClickSignalType::slot_type slot)
Registers a function slot to LEFT BUTTON PUSH events.
bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &)
The OSG calls this function whenever a new event has occured.
mouseClickSignalType m_signalLeftButtonPush
Signal used for notification of the LEFT BUTTON PUSH event.
mouseClickSignalType m_signalRightButtonPush
Signal used for notification of the RIGHT BUTTON PUSH event.
void subscribeRightButtonPush(mouseClickSignalType::slot_type slot)
Registers a function slot to RIGHT BUTTON PUSH events.
WPropInt m_infoCountLeaves
Info property: number of leaves.
WPropTrigger m_propPartitionsTrigger
This property triggers the actual writing of the partition file.
osg::ref_ptr< WGEGroupNode > m_dendrogramNode
Pointer to the dendrogram group node.
void initializeColorsSize()
Assigns a default color to each node travelling the tree top-down based on dividing first the biggest...
WPropGroup m_groupSavedPartition
grouping the partition options
WPropGroup m_groupTreeProcess
grouping the different tree processing methods
std::vector< std::vector< size_t > > m_clusterVoxels
stores the contained seed voxel IDs for each cluster, increases speed for texture drawing
std::shared_ptr< WItemSelection > m_propProcessSelectionsList
A list of cluster selection methods.
WPropDouble m_propFlatLimit
distance gap for prunin process
virtual std::shared_ptr< WModule > factory() const
new instance of this module Due to the prototype design pattern used to build modules,...
WPropInt m_propPrunedSeed
rng seed for random pruning
void colorBranchCustom(const size_t &root, const WColor &color)
recursive function that fills the display colors for a whole branch with a custom color from a scheme...
int m_oldViewWidth
stores the old viewport resolution width to check whether a resize happened
WPropBool m_propBoundaries
visualize only parcel boundaries
WPropGroup m_groupInfoPartition
grouping the partition info
void renderCubeMesh()
renders the triangulated seed voxels
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_input
An input connector that accepts order 1 datasets.
std::shared_ptr< WModuleOutputData< WDataSetScalar > > m_output2
An output connector for the output coordinate vector.
WPropInt m_infoMaxLevel
Info property: maximum hierarchical level.
WNonBinDendroGeode * m_dendrogramGeode
stores the dendrogram geode
WPropInt m_propDendroOffsetY
controls the vertical origin of the dendrogram
WPropGroup m_groupWrite
grouping the tree writing
void updateSelection(const std::vector< WColor > &preloadedColors=std::vector< WColor >())
after the active cluster list has changed this function updates the texture, cubeMesh,...
void clusterSelection()
manages cluster selection action response
WPropGroup m_groupDendroManual
grouping the dendrogram manual resizing properties
WPropDouble m_propPartDistanceValue
distance cut value for the desired partition
osg::Camera * m_camera
stores the camera object
WPropColor m_propInactiveColor
color for inactive mesh voxels
std::shared_ptr< WDataSetVector > m_outData
This is a pointer to the current output1.
osgWidget::WindowManager * m_wm
stores a pointer to the window manager used for osg wdgets and overlay stuff
float m_horizontalLine
to draw a horizontal line when theres distance partition cutting
void updateColors()
updates the selection colors
std::vector< size_t > m_textureLabels
label vector for texture creation
WPropTrigger m_propRecolorPartTrigger
This property triggers the recoloring partition of the current partitions.
WPropSelection m_propColorActionSelector
selection of color schemes
WPropInt m_propDendroOffsetX
controls the horizontal origin of the dendrogram
WPropDouble m_infoCpcc
Info property: cpcc value.
std::map< size_t, WColor > m_selectionColorsBackup
stores a backup of m_selectionColors
WPropSelection m_propPartitionSelector
Selection property for clusters.
WPropGroup m_groupRead
grouping the tree loading
WPropBool m_propShowDiscarded
visualize also discarded voxels
bool dendrogramClickRight(const WVector2f &pos)
handles right clicks into the dendrogram
WPropGroup m_groupInfoMessage
grouping the message info
std::shared_ptr< WGridRegular3D > m_grid
stores a pointer to the grid we use;
WPropDouble m_propPruneSizeRatio
size ratio for pruning process
std::shared_ptr< WItemSelection > m_propColorActionList
List of color schemes.
WPropTrigger m_propClearPartsTrigger
This property triggers the clearing of current partitions in the tree.
bool dendrogramClick(const WVector2f &pos)
handles clicks into the dendrogram
int m_oldViewHeight
stores the old viewport resolution height to check whether a resize happened
WPropDouble m_propDistanceGap
distance gap for prunin process
WPropInt m_infoCountDiscarded
Info property: number of discarded voxels.
virtual void connectors()
Initialize the connectors this module is using.
virtual void moduleMain()
Entry point after loading the module. Runs in separate thread.
WPropTrigger m_propPartRoot
triggers the selection of root cluster
std::shared_ptr< WCondition > m_propTriggerChange
A condition used to notify about changes in several properties.
WPropTrigger m_propWriteTreeTrigger
This property triggers the actual writing of the tree file.
void addPartitions()
Adds partitions form current selections into the tree object.
void updateWidgets()
updates the graphical widgets in the 3d scene
std::shared_ptr< WItemSelection > m_propColorSchemeList
List of color schemes.
WPropBool m_propShowDendrogram
controls the display of the dendrogram overlay
void initWidgets()
inits the graphical widgets in the 3d scene
virtual const std::string getName() const
Gives back the name of this module.
WPropBool m_propShowLabels
show info labels for selected clusters
osg::ref_ptr< WGEShader > m_shader
The shader.
std::shared_ptr< WItemSelection > m_propPartitionSelectionList
A list of cluster selection methods.
std::shared_ptr< WModuleOutputData< WDataSetVector > > m_output
An output connector for the output scalar dsataset.
void assignColorHierch(const size_t thisID, const WColor thisColor)
Uses the provided node Id and color to update the current tree default coloring using hierarchical in...
size_t m_treeZoomRoot
control variable for tree zoom mode
std::vector< size_t > m_discardedVoxels
stores the contained seed voxel IDs for discarded elements
WPropGroup m_groupVisualization
grouping the different visualization options
std::shared_ptr< WDataSetSingle > m_anatomy
This is a pointer to the anatomy dataset the module is currently working on.
std::shared_ptr< WTriangleMesh > m_cubeMesh
Cube-like triangulation of the seed voxels.
WPropSelection m_propConditionSelector
Selection condition for clusters.
WPropInt m_propPrunedNumber
number of leaves to be pruned by random pruning
WPropFilename m_propWriteTreeFilename
The tree file will be written to this location.
bool m_treeDirty
true if the dendrogram needs redrawing
virtual void properties()
Initialize the properties for this module.
WPropDouble m_infoCutValue
Info property: cut value for current partition.
WPropColor m_propSubselectedcolor
color for subselected cluster
WPropFilename m_propPartitionFile
The partition file will be written to this location.
WPropSelection m_propColorSchemeSelector
selection of color schemes
WPropInt m_propSafeSize
maximum size to be pruned
void writePartition()
writes partition selection(s) in an ascii file
WPropInt m_propSourceCluster
the current subtree root cluster
void colorAction()
manages action after the trigger of the color section has been pressed
bool m_labelsDirty
true if the labels need redrawing
WPropTrigger m_propDendroZoomOut
zooms out, m_treeZoom = false, dendrogram shows the whole tree
void initProperties()
updates property min/max values after loading a clustering file
WPropInt m_infoSelectedID
Info property: clusters in current partition.
WPropTrigger m_propDoProcessing
triggers the tree processing
WPropGroup m_groupInfoSelected
grouping the selected info
std::shared_ptr< WItemSelection > m_propDendroSideList
A list of dendrogram positions.
WPropInt m_propPartSearchDepthValue
depth of search for optimized partitioning
std::shared_ptr< WTriangleMesh > m_discardedMesh
Cube-like triangulation of the discarded voxels.
WPropSelection m_propDendroSideSelector
Selection property for dendrogram positions.
WPropInt m_propPartNumClusters
number of clusters of the desired partition
WPropInt m_infoPartNumber
Info property: clusters in current partition.
void initializeColorsHdist()
Assigns a default color to each node travelling the tree top-down based on hierarchy where the bigges...
WPropBool m_propShowCubeMesh
visualize voxel cube triangulation
void initTexture()
creates a texture, assigning the colouring of the current partition to the respective seed voxels in ...
WPropGroup m_groupInfoTree
grouping the tree info
WPropTrigger m_propColorActionTrigger
shuffle current colors
WHtree m_tree
stores the tree object as loaded from file;
WPropTrigger m_propAddPartTrigger
This property triggers the inclusion in the tree of the current partition.
WPropString m_infoPartMessage
Info property: partition output message.
std::vector< WColor > m_treeDisplayColors
stores a the current colors each tree node should be displayed, given the current selection
WPropTrigger m_propReadTreeTrigger
This property triggers the actual reading of the tree file.
WPropInt m_propPruneJoinSize
join size for pruning process
WPropInt m_infoSelectedDistance
Info property: clusters in current partition.
WPropBool m_propTriangleLeaves
specifies a minimum size for a cluster so that too small cluster won't get an own color
std::vector< osg::ref_ptr< WOSGButton > > m_selectionLabels
list of buttons for the active cluster selection
WPropInt m_propDendroSizeY
controls the height of the dendrogram
WPropBool m_propDendroPlotByLevel
controls plotting the height of a join (1 plots the tree by hierarchical level, 0 by cluster distance...
WPropInt m_propPartHlevelValue
hierarchical level cut value for the desired partition
WPropDouble m_propPartRelativeValue
Relative size cut value for the desired partition.
std::shared_ptr< WItemSelection > m_propConditionSelectionsList
A list of condition selection methods.
osg::ref_ptr< WGEGroupNode > m_meshNode
Pointer to the cube mesh group node.
WPropGroup m_groupDendrogram
grouping the dendrogram manipulation properties
WPropTrigger m_propDendroZoomIn
zoom into tree, sets m_treeZoom true and m_zoomRoot to the currently selected cluster
WPropInt m_propPartSizeValue
size cut value for the desired partition
void recolorPartitions()
recolors added partitions from the tree object with current selection set of colors
WPropString m_infoTreeName
Info property: current tree name.
WPropColor m_propBoundaryColor
color for cluster boundaries
osg::ref_ptr< WGEGroupNode > m_moduleNode
Pointer to the modules group node.
std::shared_ptr< WItemSelection > m_propLabelList
List of label contents.
WPropInt m_infoPartActive
Info property: active clusters in current partition.
WPropColor m_propDiscardedColor
color for discarded voxels
std::shared_ptr< WDataSetScalar > m_outData2
This is a pointer to the current output2.
WPropTrigger m_propDoPartition
triggers the cluster selection update
WPropInt m_propSubselectedCluster
the currently selected cluster
osg::ref_ptr< osg::Texture3D > m_texture
stores a pointer to the texture we paint in (to overlay to anatomy)
std::map< size_t, WColor > m_selectionColors
stores a the current colors each cluster should be displayed, given the current selection
void updateOutput2()
updates the voxels coordinate output
WPropInt m_infoSelectedSize
Info property: clusters in current partition.
void initTreeData()
initializes properties depending on the specific tree structure loaded
virtual ~WMHierchClustDisplay()
Destructor.
void colorBranch(const size_t &root, const WColor &color)
recursive function that fills the display colors for a whole branch with a selected color
WPropSelection m_propProcessSelector
Selection property for processing.
WPropInt m_propPreloadPartitionNr
predefined partition to load
std::vector< size_t > m_selectionClusters
stores the currently activated clusters
virtual const std::string getDescription() const
Gives back a description of this module.
WPropGroup m_groupPartition
grouping the different selection methods
WPropBool m_propKeepBases
dont debinarize basenodes
std::vector< size_t > m_selectionLeaves
stores the leaves output by the selection
WPropFilename m_propReadFilename
The tree file will be loaded form this directory.
WPropBool m_propPartExcludeLeaves
defines if base nodes will be subdivided or not
std::vector< WColor > m_nodeColorsCustom
stores preset color for every tree node, so clusters keep same color through different selection
WPropSelection m_propLabelInfoSelector
selection of info on button labels
WPropInt m_propDendroSizeX
controls the width of the dendrogram
WPropInt m_infoPartLeaves
Info property: leaf clusters in current partition.
WPropInt m_infoCountNodes
Info property: number of nodes.
Creates a non interpolated triangulation of an isosurface.
std::shared_ptr< WTriangleMesh > genSurfaceOneValue(size_t nbCoordsX, size_t nbCoordsY, size_t nbCoordsZ, const WMatrix< double > &mat, const std::vector< size_t > *vals, size_t isoValue, std::shared_ptr< WProgressCombiner > progress=std::shared_ptr< WProgressCombiner >())
Generate the triangles for the surface on the given dataSet (inGrid, vals).
A fixed size matrix class.
Definition: WMatrixFixed.h:150
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
boost::filesystem::path m_localPath
The path where the module binary resides in.
Definition: WModule.h:734
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
std::shared_ptr< WProperties > m_infoProperties
The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION".
Definition: WModule.h:647
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
wlog::WStreamedLogger errorLog() const
Logger instance for comfortable error logging.
Definition: WModule.cpp:570
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
wlog::WStreamedLogger infoLog() const
Logger instance for comfortable info logging.
Definition: WModule.cpp:565
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Class creates a dendrogram from a hierarchical clustering, and allows to click and select specific no...
bool inDendrogramArea(int xClick, int yClick) const
calculates if the given position is within the view area of the dendrogram
size_t getClickedCluster(int xClick, int yClick)
calculate which cluster was clicked from given pixel coordinates
Class implements an osgWidget::Box with a label that can be used as a button in the 3D scene.
Definition: WOSGButton.h:42
Class managing progress inside of modules.
Definition: WProgress.h:42
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Base Class for all value set types.
Definition: WValueSet.h:47
@ PV_TRIGGER_TRIGGERED
Trigger property: got triggered.
@ PV_TRIGGER_READY
Trigger property: is ready to be triggered (again)
void addTo(WPropSelection prop)
Add the PC_SELECTONLYONE constraint to the property.
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120
WColor getNthHSVColor(int n)
creates the nth color of a partition of the hsv color circle
Definition: WGEUtils.cpp:168