OpenWalnut  1.5.0dev
WMEffectiveConnectivityCluster.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 #include <cmath>
26 #include <fstream>
27 #include <iostream>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 #include <osg/Geode>
33 #include <osg/Geometry>
34 #include <osg/LightModel>
35 #include <osg/PolygonMode>
36 #include <osg/StateAttribute>
37 #include <osg/StateSet>
38 #include <osgDB/WriteFile>
39 #include <osgText/FadeText>
40 #include <osgText/Text>
41 
42 #include "WMEffectiveConnectivityCluster.h"
43 #include "WMEffectiveConnectivityCluster.xpm"
44 #include "core/common/WProgress.h"
45 #include "core/dataHandler/WGridRegular3D.h"
46 #include "core/dataHandler/WSubject.h"
47 #include "core/dataHandler/datastructures/WFiberCluster.h"
48 #include "core/graphicsEngine/WGEUtils.h"
49 #include "core/graphicsEngine/WGraphicsEngine.h"
50 #include "core/graphicsEngine/widgets/labeling/WGEBorderLayout.h"
51 #include "core/graphicsEngine/widgets/labeling/WGELabel.h"
52 #include "core/kernel/WKernel.h"
53 #include "core/kernel/WModuleFactory.h"
54 #include "core/kernel/WModuleOutputData.h"
55 
56 // This line is needed by the module loader to actually find your module.
57 W_LOADABLE_MODULE( WMEffectiveConnectivityCluster )
58 
60  WModuleContainer( "Effective Connectivity Cluster", "This module is able to visualize effective connectivity cluster." ),
61  m_labelActive( false ),
62  m_rootNode( new WGEGroupNode() )
63 {
64  // WARNING: initializing connectors inside the constructor will lead to an exception.
65  // NOTE: Do not use the module factory inside this constructor. This will cause a dead lock as the module factory is locked
66  // during construction of this instance and can then not be used to create another instance (Isosurface in this case). If you
67  // want to initialize some modules using the module factory BEFORE the moduleMain() call, overwrite WModule::initialize().
68 }
69 
71 {
72  // cleanup
74 }
75 
76 std::shared_ptr< WModule > WMEffectiveConnectivityCluster::factory() const
77 {
78  return std::shared_ptr< WModule >( new WMEffectiveConnectivityCluster() );
79 }
80 
82 {
83  return WMEffectiveConnectivityCluster_xpm;
84 }
85 
86 const std::string WMEffectiveConnectivityCluster::getName() const
87 {
89 }
90 
92 {
94 }
95 
96 void WMEffectiveConnectivityCluster::fiberDataChange( std::shared_ptr< WModuleConnector > /*input*/,
97  std::shared_ptr< WModuleConnector > output )
98 {
99  if( !output )
100  {
101  m_labelActive = false;
102  m_propCondition->notify();
103 
104  // if the connector gets reset -> ignore this case
105  return;
106  }
107 
108  // cast it to the target type
109  std::shared_ptr< WModuleOutputData < WFiberCluster > > o = std::static_pointer_cast< WModuleOutputData< WFiberCluster > >( output );
110  if( !o )
111  {
112  errorLog() << "New data is not a WFiberCluster? That should not happen!";
113  }
114 
115  // grab data
116  std::shared_ptr< WFiberCluster > fibs = o->getData();
117  std::shared_ptr< WFiber > lline = fibs->getLongestLine();
118 
119  // the first and the last point of the longest line are required:
120  m_labelPos2 = ( *lline )[ lline->size() - 2 ];
121  m_labelPos1 = ( *lline )[ 1 ];
122 
123  m_labelActive = true;
124 
125  m_propCondition->notify();
126 }
127 
129 {
130  //////////////////////////////////////////////////////////////////////////////////
131  // Fiber Selection
132  //////////////////////////////////////////////////////////////////////////////////
133 
134  // create an instance using the prototypes
135  m_fiberSelection = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Fiber Selection" ) );
136 
137  // add to container
139 
140  // now wait for it to be ready
141  m_fiberSelection->isReady().wait();
142 
143  // set some props
144  std::shared_ptr< WProperties > props = m_fiberSelection->getProperties();
145  props->getProperty( "VOI1 threshold" )->toPropDouble()->set( 50.0 );
146  props->getProperty( "VOI2 threshold" )->toPropDouble()->set( 50.0 );
147  props->getProperty( "Cut fibers" )->toPropBool()->set( true );
148  m_properties->addProperty( props->getProperty( "Cut fibers" ) );
149  props->getProperty( "Prefer shortest path" )->toPropBool()->set( false );
150  m_properties->addProperty( props->getProperty( "Prefer shortest path" ) );
151 
152  // as this module needs the centerline / longest line -> subscribe to the output connector DATA_CHANGE signal
153  m_fiberSelection->getOutputConnector( "cluster" )->subscribeSignal( DATA_CHANGED,
154  boost::bind( &WMEffectiveConnectivityCluster::fiberDataChange, this, boost::placeholders::_1, boost::placeholders::_2 )
155  );
156 
157  //////////////////////////////////////////////////////////////////////
158  // Voxelize
159  //////////////////////////////////////////////////////////////////////
160 
161  // create an instance using the prototypes
162  m_voxelizer = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Voxelizer" ) );
163 
164  // add to container
165  add( m_voxelizer );
166 
167  // now wait for it to be ready
168  m_voxelizer->isReady().wait();
169 
170  // set/forward some props
171  props = m_voxelizer->getProperties();
172  props->getProperty( "Center line" )->toPropBool()->set( false );
173  props->getProperty( "active" )->toPropBool()->set( false );
174  props->getProperty( "Fiber tracts" )->toPropBool()->set( false );
175  props->getProperty( "Display voxels" )->toPropBool()->set( false );
176  props->getProperty( "Lighting" )->toPropBool()->set( false );
177 
178  // set longest line based parameterization
179  props->getProperty( "Voxels per unit" )->toPropInt()->set( 2 );
181  idx.push_back( 1 );
182  props->getProperty( "Parameterization" )->toPropSelection()->set( props->getProperty( "Parameterization"
183  )->toPropSelection()->get().newSelector( idx ) );
184 
185  m_properties->addProperty( props->getProperty( "Voxels per unit" ) );
186 
187  //////////////////////////////////////////////////////////////////////
188  // Gauss Filter the voxel output
189  //////////////////////////////////////////////////////////////////////
190 
191  // create an instance using the prototypes
192  m_gauss = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Gauss Filtering" ) );
193 
194  // add to container
195  add( m_gauss );
196 
197  // now wait for it to be ready
198  m_gauss->isReady().wait();
199 
200  // set/forward some props
201  props = m_gauss->getProperties();
202  props->getProperty( "Iterations" )->toPropInt()->set( 2 );
203 
204  //////////////////////////////////////////////////////////////////////
205  // Animation
206  //////////////////////////////////////////////////////////////////////
207 
208  // create an instance using the prototypes
210  WModuleFactory::getModuleFactory()->getPrototypeByName( "Surface Parameter Animator" )
211  );
212 
213  // add to container
214  add( m_animation );
215 
216  // now wait for it to be ready
217  m_animation->isReady().wait();
218 
219  // set/forward some props
220  props = m_animation->getProperties();
221  props->getProperty( "Isovalue" )->toPropInt()->set( 32 );
222  m_properties->addProperty( props->getProperty( "Isovalue" ) );
223  props->getProperty( "Step count" )->toPropInt()->set( 500 );
224  m_properties->addProperty( props->getProperty( "Step count" ) );
225  props->getProperty( "Iso color" )->toPropColor()->set( WColor( 0.0, 0.5, 1.0, 1.0 ) );
226  m_properties->addProperty( props->getProperty( "Iso color" ) );
227  props->getProperty( "Opacity %" )->toPropInt()->set( 100 );
228  m_properties->addProperty( props->getProperty( "Opacity %" ) );
229  m_properties->addProperty( props->getProperty( "Saturation %" ) );
230  m_properties->addProperty( props->getProperty( "Beam1 size" ) );
231  m_properties->addProperty( props->getProperty( "Beam2 size" ) );
232  m_properties->addProperty( props->getProperty( "Beam1 speed" ) );
233  m_properties->addProperty( props->getProperty( "Beam2 speed" ) );
234  m_properties->addProperty( props->getProperty( "Parameter scale" ) );
235 
236 
237  //////////////////////////////////////////////////////////////////////////////////
238  // Hard wire the modules
239  //////////////////////////////////////////////////////////////////////////////////
240 
241  // Connect voxelizer input with the selected fibers
242  m_voxelizer->getInputConnector( "tractInput" )->connect( m_fiberSelection->getOutputConnector( "cluster" ) );
243 
244  // Connect voxelizer output with the Gauss filter
245  m_gauss->getInputConnector( "in" )->connect( m_voxelizer->getOutputConnector( "voxelOutput" ) );
246 
247  // Connect voxelizer output with the animation
248  m_animation->getInputConnector( "in" )->connect( m_gauss->getOutputConnector( "out" ) );
249  m_animation->getInputConnector( "traces" )->connect( m_voxelizer->getOutputConnector( "parameterizationOutput" ) );
250 
251  // Connect inputs
252  m_fiberInput->forward( m_fiberSelection->getInputConnector( "fibers" ) );
253  m_VOI1->forward( m_fiberSelection->getInputConnector( "VOI1" ) );
254  m_VOI2->forward( m_fiberSelection->getInputConnector( "VOI2" ) );
255 
256  // forward some results
257  m_paramOutput->forward( m_voxelizer->getOutputConnector( "parameterizationOutput" ) );
258  m_voxelOutput->forward( m_gauss->getOutputConnector( "out" ) );
259  m_fiberOutput->forward( m_fiberSelection->getOutputConnector( "out" ) );
260 
261  //////////////////////////////////////////////////////////////////////////////////
262  // Done!
263  //////////////////////////////////////////////////////////////////////////////////
264 
265  // signal ready state
266  ready();
267 
268  // wake up on property change
269  m_moduleState.setResetable( true, true );
271 
272  // Signal ready state.
273  ready();
274 
275  // add this module's group node
276  m_rootNode->setNodeMask( m_active->get() ? 0xFFFFFFFF : 0x0 );
277  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
278 
279  // Now wait for data
280  bool lastLabelActiveState = m_labelActive;
281  while( !m_shutdownFlag() )
282  {
284 
285  // woke up since the module is requested to finish
286  if( m_shutdownFlag() )
287  {
288  break;
289  }
290  // has one of the properties changed?
291  if( m_labelActive && (
292  ( lastLabelActiveState != m_labelActive ) || m_voi1Name->changed() || m_voi2Name->changed() || m_labelCharacterSize->changed() )
293  )
294  {
295  lastLabelActiveState = true;
296  osg::ref_ptr< WGEBorderLayout > layouter = new WGEBorderLayout();
297 
298  std::string voi1 = m_voi1Name->get( true );
299  std::string voi2 = m_voi2Name->get( true );
300  if( !voi1.empty() )
301  {
302  osg::ref_ptr< WGELabel > label1 = new WGELabel();
303  label1->setText( voi1 );
304  label1->setAnchor( m_labelPos1 ); // the position relative to the current world coordinate system
305  label1->setCharacterSize( m_labelCharacterSize->get( true ) );
306  layouter->addLayoutable( label1 );
307  }
308 
309  if( !voi2.empty() )
310  {
311  osg::ref_ptr< WGELabel > label2 = new WGELabel();
312  label2->setText( voi2 );
313  label2->setAnchor( m_labelPos2 ); // the position relative to the current world coordinate system
314  label2->setCharacterSize( m_labelCharacterSize->get( true ) );
315  layouter->addLayoutable( label2 );
316  }
317 
318  m_rootNode->clear();
319  m_rootNode->insert( layouter );
320  }
321 
322  // remove labels if no dataset is connected anymore
323  if( !m_labelActive )
324  {
325  m_rootNode->clear();
326  }
327  }
328 
329  // At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove
330  // allocated memory and remove all OSG nodes.
331  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
332 
333  // stop container and the contained modules.
334  stop();
335 }
336 
338 {
339  // this is the scalar field input
340  m_VOI1 = std::shared_ptr< WModuleInputForwardData< WDataSetSingle > >(
341  new WModuleInputForwardData< WDataSetSingle >( shared_from_this(),
342  "VOI1", "The first volume of interest." )
343  );
344 
345  // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected.
346  addConnector( m_VOI1 );
347 
348  // this is the scalar field input
349  m_VOI2 = std::shared_ptr< WModuleInputForwardData< WDataSetSingle > >(
350  new WModuleInputForwardData< WDataSetSingle >( shared_from_this(),
351  "VOI2", "The second volume of interest." )
352  );
353 
354  // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected.
355  addConnector( m_VOI2 );
356 
357  // this is the scalar field input
358  m_fiberInput = std::shared_ptr< WModuleInputForwardData< WDataSetFibers > >(
359  new WModuleInputForwardData< WDataSetFibers >( shared_from_this(),
360  "fibers", "The fiber dataset used to find connection path." )
361  );
362 
363  // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected.
365 
366  // forwarder for some results
367  // this is the parameter field
368  m_paramOutput = std::shared_ptr< WModuleOutputForwardData< WDataSetScalar > >(
369  new WModuleOutputForwardData< WDataSetScalar >( shared_from_this(),
370  "paramOut", "The voxelized fiber parameterization field." )
371  );
373 
374  // this is the voxel field
375  m_voxelOutput = std::shared_ptr< WModuleOutputForwardData< WDataSetScalar > >(
376  new WModuleOutputForwardData< WDataSetScalar >( shared_from_this(),
377  "voxelsOut", "The voxelized fibers." )
378  );
380 
381  // these are the fibers
382  m_fiberOutput = std::shared_ptr< WModuleOutputForwardData< WDataSetFibers > >(
383  new WModuleOutputForwardData< WDataSetFibers >( shared_from_this(),
384  "fibersOut", "The voxelized fibers." )
385  );
387 
388  // call WModules initialization
390 }
391 
393 {
394  // Initialize the properties
395  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
396 
397  m_voi1Name = m_properties->addProperty( "Name of VOI1", "The name of the VOI1.", std::string( "" ), m_propCondition );
398  m_voi2Name = m_properties->addProperty( "Name of VOI2", "The name of the VOI2.", std::string( "" ), m_propCondition );
399 
400  m_labelCharacterSize = m_properties->addProperty( "Font size", "The size of the label fonts.", 20, m_propCondition );
401 
403 }
404 
406 {
407  m_animation->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() );
408 }
409 
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
This class contains a label layout for positioning labels at the side of the screen.
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
Definition: WGEGroupNode.h:48
Label layout-item.
Definition: WGELabel.h:39
std::vector< size_t > IndexList
The type used for storing index lists.
Definition: WItemSelector.h:59
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
This module is able to visualize connectome data in the context of MRI data.
WPosition m_labelPos2
The position of the second label showing m_voi2Name.
void fiberDataChange(std::shared_ptr< WModuleConnector > input, std::shared_ptr< WModuleConnector > output)
This method is called whenever the data on the fiberSelection module output changes.
virtual void moduleMain()
Entry point after loading the module.
WPropString m_voi2Name
The name of the first region of interest.
WPropString m_voi1Name
The name of the first region of interest.
std::shared_ptr< WModuleOutputForwardData< WDataSetScalar > > m_voxelOutput
The voxelized fibers used.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual void properties()
Initialize the properties for this module.
bool m_labelActive
True if the labels should be drawn.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
std::shared_ptr< WModuleOutputForwardData< WDataSetScalar > > m_paramOutput
The parameter dataset used.
virtual const std::string getDescription() const
Gives back a description of this module.
WPropInt m_labelCharacterSize
Size of the label font.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
std::shared_ptr< WModule > m_voxelizer
The voxelizer module.
virtual void activate()
Callback for m_active.
std::shared_ptr< WModuleInputForwardData< WDataSetSingle > > m_VOI1
The volume of interest 1.
std::shared_ptr< WModule > m_fiberSelection
The fiber selection module.
WPosition m_labelPos1
The position of the first label showing m_voi1Name.
virtual const std::string getName() const
Gives back the name of this module.
virtual void connectors()
Initialize the connectors this module is using.
std::shared_ptr< WModule > m_animation
The final animation.
std::shared_ptr< WModule > m_gauss
The Gauss filter which filters the voxelized fibers.
std::shared_ptr< WModuleInputForwardData< WDataSetFibers > > m_fiberInput
The fiber dataset used.
osg::ref_ptr< WGEGroupNode > m_rootNode
The root node used for this modules graphics.
std::shared_ptr< WModuleInputForwardData< WDataSetSingle > > m_VOI2
The volume of interest 2.
std::shared_ptr< WModuleOutputForwardData< WDataSetFibers > > m_fiberOutput
The fibers used.
Class able to contain other modules.
virtual const std::string getName() const
Gives back the name of this module.
virtual const std::string getDescription() const
Gives back a description of this module.
virtual void stop()
Stops all modules inside this container.
virtual void add(std::shared_ptr< WModule > module, bool run=true)
Add a module to this container and start it.
static SPtr getModuleFactory()
Returns instance of the module factory to use to create modules.
This is a simple class which forwards input data to input data connectors.
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
void removeConnectors()
Removes all connectors properly.
Definition: WModule.cpp:194
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
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
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.