30 #include <boost/tuple/tuple.hpp>
33 #include <osg/Material>
34 #include <osg/ShapeDrawable>
35 #include <osg/StateAttribute>
37 #include "WMFiberSelection.h"
38 #include "WMFiberSelection.xpm"
39 #include "core/common/WColor.h"
40 #include "core/kernel/WKernel.h"
62 return fiberSelection_xpm;
68 return "Fiber Selection";
74 return "Select fibers in a given dataset using two additional datasets as volume of interest. The purpose of this module is to allow the user"
75 "to select a bunch of fibers which go through two regions defined by two scalar datasets. A fiber goes through both volumes of interest"
76 "if and only if at least one of the vertices of a fiber is inside a voxel of the scalar datasets with a value greater than a specified"
77 "threshold. Currently, this only works good for large regions and/or densely sampled fibers.";
83 m_fiberInput = std::shared_ptr< WModuleInputData < WDataSetFibers > >(
91 m_voi1Input = std::shared_ptr< WModuleInputData < WDataSetSingle > >(
99 m_voi2Input = std::shared_ptr< WModuleInputData < WDataSetSingle > >(
107 m_fiberOutput = std::shared_ptr< WModuleOutputData < WDataSetFibers > >(
109 "out",
"The fiber dataset only containing fibers which got through both volume of interest." )
116 m_clusterOutput = std::shared_ptr< WModuleOutputData < WFiberCluster > >(
118 "cluster",
"The cluster dataset only containing fibers which got through both volume of interest." )
134 m_voi1Threshold =
m_properties->addProperty(
"VOI1 threshold",
"The threshold uses for determining whether a fiber is inside the first VOI"
136 m_voi2Threshold =
m_properties->addProperty(
"VOI2 threshold",
"The threshold uses for determining whether a fiber is inside the second VOI"
141 "exit of a VOI. This should prevent the fibers from going deep into the VOI's.",
false,
m_propCondition );
189 std::shared_ptr< WDataSetFibers > newFibers =
m_fiberInput->getData();
190 std::shared_ptr< WDataSetSingle > newVoi1 =
m_voi1Input->getData();
191 std::shared_ptr< WDataSetSingle > newVoi2 =
m_voi2Input->getData();
194 bool dataValid = ( newFibers && newVoi1 && newVoi2 );
212 if( ( propChanged || dataChanged ) && dataValid )
214 debugLog() <<
"Data received. Recalculating.";
228 std::shared_ptr< std::vector< size_t > > fibStart =
m_fibers->getLineStartIndexes();
229 std::shared_ptr< std::vector< size_t > > fibLen =
m_fibers->getLineLengths();
230 std::shared_ptr< std::vector< float > > fibVerts =
m_fibers->getVertices();
234 std::shared_ptr< WGridRegular3D > grid1 = std::dynamic_pointer_cast< WGridRegular3D >(
m_voi1->getGrid() );
235 std::shared_ptr< WGridRegular3D > grid2 = std::dynamic_pointer_cast< WGridRegular3D >(
m_voi2->getGrid() );
238 std::vector< boost::tuple< size_t, size_t, size_t > > matches;
241 std::shared_ptr< WProgress > progress1(
new WProgress(
"Checking fibers against ", fibStart->size() ) );
249 debugLog() <<
"Iterating over all fibers.";
250 for(
size_t fidx = 0; fidx < fibStart->size() ; ++fidx )
255 size_t sidx = fibStart->at( fidx ) * 3;
258 size_t len = fibLen->at( fidx );
261 FibTrace current1 = { 0,
true,
false,
false };
262 FibTrace current2 = { 0,
false,
false,
false };
263 std::vector< FibTrace > hits1;
264 std::vector< FibTrace > hits2;
267 for(
size_t k = 0; k < len; ++k )
269 float x = fibVerts->at( ( 3 * k ) + sidx );
270 float y = fibVerts->at( ( 3 * k ) + sidx + 1 );
271 float z = fibVerts->at( ( 3 * k ) + sidx + 2 );
274 int voxel1 = grid1->getVoxelNum(
WPosition( x, y, z ) );
275 int voxel2 = grid2->getVoxelNum(
WPosition( x, y, z ) );
276 if( ( voxel1 < 0 ) || ( voxel2 < 0 ) )
278 warnLog() <<
"Fiber vertex (" << x <<
"," << y <<
"," << z <<
") not in VOI1 or VOI2 grid. Ignoring vertex.";
283 double value1 =
m_voi1->getSingleRawValue( voxel1 );
284 double value2 =
m_voi2->getSingleRawValue( voxel2 );
288 current1.wasInside = current1.isInside;
289 current1.isInside = ( value1 >= voi1Threshold );
291 current2.wasInside = current2.isInside;
292 current2.isInside = ( value2 >= voi2Threshold );
295 if( current1.wasInside ^ current1.isInside )
297 hits1.push_back( current1 );
300 if( current2.wasInside ^ current2.isInside )
302 hits2.push_back( current2 );
312 if( !preferShortestPath )
320 if( ( hits1.size() >= 1 ) && ( hits2.size() >= 1 ) )
322 debugLog() <<
"Fiber " << fidx <<
" inside VOI1 and VOI2.";
323 matches.push_back( boost::make_tuple( fidx, std::min( hits1[ 0 ].idx, hits2[ 0 ].idx ),
324 std::max( hits1[ hits1.size() - 1 ].idx, hits2[ hits2.size() - 1 ].idx ) ) );
336 if( ( hits1.size() >= 1 ) && ( hits2.size() >= 1 ) )
338 debugLog() <<
"Fiber " << fidx <<
" inside VOI1 and VOI2.";
339 matches.push_back( boost::make_tuple( fidx, std::min( hits1[ 0 ].idx, hits2[ hits2.size() - 1 ].idx ),
340 std::max( hits1[ hits1.size() - 1 ].idx, hits2[ 0 ].idx ) ) );
344 debugLog() <<
"Iterating over all fibers: done!";
348 infoLog() <<
"Found " << matches.size() <<
" fibers going through VOI1 and VOI2.";
352 std::shared_ptr< std::vector< float > > newFibVerts(
new std::vector< float >() );
353 std::shared_ptr< std::vector< size_t > > newFibStart(
new std::vector< size_t >() );
354 std::shared_ptr< std::vector< size_t > > newFibLen(
new std::vector< size_t >() );
355 std::shared_ptr< std::vector< size_t > > newFibVertsRev(
new std::vector< size_t >() );
357 progress1 = std::shared_ptr< WProgress >(
new WProgress(
"Creating Output Dataset.", matches.size() ) );
359 debugLog() <<
"Creating new Fiber Dataset and Cluster.";
362 std::shared_ptr< WFiberCluster > newFiberCluster(
new WFiberCluster() );
365 size_t curVertIdx = 0;
366 size_t curRealFibIdx = 0;
367 for(
size_t i = 0; i < matches.size(); ++i )
372 size_t sidx = fibStart->at( matches[ i ].get< 0 >() ) * 3;
373 size_t len = fibLen->at( matches[ i ].get< 0 >() );
378 sidx = sidx + ( matches[ i ].get< 1 >() * 3 );
379 len = matches[ i ].get< 2 >() - matches[ i ].get< 1 >();
389 newFibLen->push_back( len );
392 newFibStart->push_back( curVertIdx );
396 newFiberCluster->merge( a );
399 for(
size_t vi = 0; vi < len; ++vi )
403 newFibVerts->push_back( fibVerts->at( sidx + ( 3 * vi ) ) );
404 newFibVerts->push_back( fibVerts->at( sidx + ( 3 * vi ) + 1 ) );
405 newFibVerts->push_back( fibVerts->at( sidx + ( 3 * vi ) + 2 ) );
406 newFibVertsRev->push_back( curRealFibIdx );
407 newFibVertsRev->push_back( curRealFibIdx );
408 newFibVertsRev->push_back( curRealFibIdx );
416 std::shared_ptr< WDataSetFibers > newFibers(
new WDataSetFibers( newFibVerts, newFibStart, newFibLen, newFibVertsRev ) );
419 progress1 = std::shared_ptr< WProgress >(
new WProgress(
"Creating Output Vector Dataset." ) );
421 debugLog() <<
"Creating Fiber Vector Dataset.";
423 std::shared_ptr< WDataSetFiberVector > newFiberVector(
new WDataSetFiberVector( newFibers )
425 newFiberCluster->setDataSetReference( newFiberVector );
426 newFiberCluster->generateCenterLine();
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.
Represents a simple set of WFibers.
Represents a simple set of WFibers.
Represents a cluster of indices of a WDataSetFiberVector.
This module handles selection of fibers based on two volumes of interest.
virtual const std::string getDescription() const
Gives back a description of this module.
std::shared_ptr< WDataSetSingle > m_voi2
The VOI2 dataset (from m_voi2Input).
WPropDouble m_voi1Threshold
VOI1 threshold.
std::shared_ptr< WModuleOutputData< WFiberCluster > > m_clusterOutput
The cluster dataset created from m_fiberOutput.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
virtual ~WMFiberSelection()
Destructor.
std::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput
The fiber dataset which is going to be filtered.
WPropBool m_cutFibers
Cut the fibers when they are outside the VOI?
WPropDouble m_voi2Threshold
VOI2 threshold.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_voi1Input
The first VOI.
virtual const std::string getName() const
Gives back the name of this module.
virtual void connectors()
Initialize the connectors this module is using.
virtual void activate()
Callback for m_active.
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< WDataSetFibers > m_fibers
The fiber dataset (from m_fiberInput).
std::shared_ptr< WModuleOutputData< WDataSetFibers > > m_fiberOutput
The output connector used to provide the calculated data to other modules.
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_voi2Input
The second VOI.
virtual void properties()
Initialize the properties for this module.
std::shared_ptr< WDataSetSingle > m_voi1
The VOI1 dataset (from m_voi1Input).
WPropBool m_preferShortestPath
Should the fibers be cut to avoid having them inside the VOI.
virtual void moduleMain()
Entry point after loading the module.
WMFiberSelection()
Default constructor.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
virtual void properties()
Initialize properties in this function.
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
wlog::WStreamedLogger warnLog() const
Logger instance for comfortable warning- logs.
std::shared_ptr< WProperties > m_properties
The property object for the module.
void ready()
Call this whenever your module is ready and can react on property changes.
WConditionSet m_moduleState
The internal state of the module.
virtual void activate()
Callback for m_active.
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
wlog::WStreamedLogger infoLog() const
Logger instance for comfortable info logging.
virtual void connectors()
Initialize connectors in this function.
This only is a 3d double vector.
Class managing progress inside of modules.
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.