Commit 792bf945 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[MERGE]

parents cfec9404 96dc3879
......@@ -53,14 +53,14 @@ public:
WColor( float red = 0.0, float green = 0.0, float blue = 0.0, float alpha = 1.0 );
/**
* Casts a color to an vector comfortably.
* Casts a color to a vector comfortably.
*
* \return vector instance
*/
inline operator osg::Vec4f() const;
/**
* Casts a color to an vector comfortably. As the returned vector is three-dimensional, the alpha value is omitted.
* Casts a color to a vector comfortably. As the returned vector is three-dimensional, the alpha value is omitted.
*
* \return vector instance
*/
......
......@@ -36,7 +36,9 @@
#include "WWorkerThread.h"
#include "WSharedObject.h"
//! an enum indicating the status of a multithreaded computation
/**
* An enum indicating the status of a multithreaded computation
*/
enum WThreadedFunctionStatus
{
W_THREADS_INITIALIZED, //! the status after constructing the function
......@@ -46,6 +48,15 @@ enum WThreadedFunctionStatus
W_THREADS_FINISHED //! all threads completed their work successfully
};
/**
* An enum indicating the number of threads used
*/
enum WThreadedFunctionNbThreads
{
W_AUTOMATIC_NB_THREADS = 0 //!< Use half the available cores as number of threads
};
/**
* \class WThreadedFunction
*
......@@ -201,7 +212,7 @@ WThreadedFunction< Function_T >::WThreadedFunction( std::size_t numThreads, boos
}
// find a suitable number of threads
if( m_numThreads == 0 )
if( m_numThreads == W_AUTOMATIC_NB_THREADS )
{
m_numThreads = 1;
while( m_numThreads < boost::thread::hardware_concurrency() / 2 && m_numThreads < 1024 )
......
......@@ -124,6 +124,24 @@ public:
TS_ASSERT_DELTA( ds.interpolate( wmath::WPosition( 0.5, 0.5, 0.5 ), &success )[2], 33.5, 1e-9 );
TS_ASSERT( success );
}
/**
* A test for ticket #313
*/
void testBoundary_ticket313( void )
{
boost::shared_ptr< WGridRegular3D > grid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D( 3, 4, 5, 1, 1, 1 ) );
bool success = false;
std::vector< double > data( grid->size() * 3 );
for( size_t i = 0; i < grid->size() * 3; ++i )
{
data[i] = i;
}
boost::shared_ptr< WValueSet< double > > valueSet( new WValueSet< double >( 1, 3, data, W_DT_DOUBLE ) );
WDataSetVector ds( valueSet, grid );
ds.interpolate( wmath::WPosition( 2.0, 3.0, 4.0 ), &success );
TS_ASSERT( !success );
}
};
#endif // WDATASETVECTOR_TEST_H
......@@ -34,7 +34,7 @@
#include "WExportWGE.h"
/**
* Class implementing an uniform which can be controlled by an property instance. This is mainly a convenience class for
* Class implementing a uniform which can be controlled by a property instance. This is mainly a convenience class for
* WGEPropertyUniformCallback (which is used here).
*
* \tparam the class used as controlling mechanism. The class needs to be a boost::shared_ptr to a type supporting get() method: T->get()
......
......@@ -69,14 +69,14 @@ const char** WMBermanTracking::getXPMIcon() const
const std::string WMBermanTracking::getName() const
{
// Specify your module name here. This name must be UNIQUE!
return "BermanTracking";
return "Berman Probabilistic Tracking";
}
const std::string WMBermanTracking::getDescription() const
{
// Specify your module description here. Be detailed. This text is read by the user.
// See "src/modules/template/" for an extensively documented example.
return "";
return "Implements the probabilistic tracking algorithm with residual bootstrapping by Berman et al.";
}
void WMBermanTracking::connectors()
......@@ -314,7 +314,7 @@ void WMBermanTracking::calcGFA()
resetProgress( m_dataSet->getGrid()->size() );
ThreadPool t( 0, gfafunc );
ThreadPool t( W_AUTOMATIC_NB_THREADS, gfafunc );
t.subscribeExceptionSignal( boost::bind( &This::handleException, this, _1 ) );
t.run();
t.wait();
......
......@@ -44,7 +44,7 @@
#include "../../dataHandler/WThreadedTrackingFunction.h"
#include "../../dataHandler/WFiberAccumulator.h"
#define WM_MORI_NUM_CORES 0
#define WM_MORI_NUM_CORES W_AUTOMATIC_NB_THREADS
/**
* \class WMDeterministicFTMori
......
......@@ -142,6 +142,11 @@ void WMTeemGlyphs::connectors()
new WModuleInputData< WDataSetSphericalHarmonics >( shared_from_this(), "in", "The input dataset." ) );
addConnector( m_input );
m_inputGFA = boost::shared_ptr< WModuleInputData< WDataSetScalar > >( new WModuleInputData< WDataSetScalar >( shared_from_this(),
"inGFA", "Generalized fractional anisotropy." )
);
addConnector( m_inputGFA );
// call WModules initialization
WModule::connectors();
......@@ -159,6 +164,14 @@ void WMTeemGlyphs::properties()
m_recompute );
WPropertyHelper::PC_SELECTONLYONE::addTo( m_sliceOrientationSelection );
m_GFAThresholdProp = m_properties->addProperty( "GFA threshold", "Show only glyphs at voxels above the given generalized fractional"
" anisotropy (GFA) threshold"
" (if GFA data is present at input connector).",
0.0,
m_recompute );
m_GFAThresholdProp->setMin( 0 );
m_GFAThresholdProp->setMax( 1. );
m_glyphSizeProp = m_properties->addProperty( "Glyph size", "Size of the displayed glyphs.", 0.5, m_recompute );
m_glyphSizeProp->setMin( 0 );
m_glyphSizeProp->setMax( 100. );
......@@ -217,12 +230,14 @@ void WMTeemGlyphs::renderSlice( size_t sliceId )
boost::shared_ptr< GlyphGeneration > generator;
generator = boost::shared_ptr< GlyphGeneration >(
new GlyphGeneration( boost::shared_dynamic_cast< WDataSetSphericalHarmonics >( m_input->getData() ),
boost::shared_dynamic_cast< WDataSetScalar >( m_inputGFA->getData() ),
m_GFAThresholdProp->get(),
sliceId,
sliceType,
m_usePolarPlotProp->get(),
m_glyphSizeProp->get(),
m_useNormalizationProp->get() ) );
WThreadedFunction< GlyphGeneration > generatorThreaded( 0, generator );
WThreadedFunction< GlyphGeneration > generatorThreaded( W_AUTOMATIC_NB_THREADS, generator );
generatorThreaded.run();
generatorThreaded.wait();
......@@ -304,13 +319,17 @@ void WMTeemGlyphs::GlyphGeneration::minMaxNormalization( limnPolyData *glyph, co
}
WMTeemGlyphs::GlyphGeneration::GlyphGeneration( boost::shared_ptr< WDataSetSphericalHarmonics > dataSet,
boost::shared_ptr< WDataSetScalar > dataGFA,
double thresholdGFA,
const size_t& sliceId,
const size_t& sliceType,
const bool& usePolar,
const float& scale,
const bool& useNormalization ) :
m_dataSet( dataSet ),
m_dataGFA( dataGFA ),
m_grid( boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() ) ),
m_thresholdGFA( thresholdGFA ),
m_sliceType( sliceType ),
m_usePolar( usePolar ),
m_scale( scale ),
......@@ -367,11 +386,14 @@ WMTeemGlyphs::GlyphGeneration::GlyphGeneration( boost::shared_ptr< WDataSetSpher
limnPolyDataIcoSphere( m_sphere, infoBitFlag, level );
size_t nbVerts = m_sphere->xyzwNum;
m_vertArray = new osg::Vec3Array( nbVerts * nbGlyphs );
m_normals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array( nbVerts * nbGlyphs ) );
m_colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array( nbVerts * nbGlyphs ) );
m_vertArray = new osg::Vec3Array();
m_normals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array() );
m_colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array() );
m_vertArray->resize( nbVerts * nbGlyphs );
m_normals->resize( nbVerts * nbGlyphs );
m_colors->resize( nbVerts * nbGlyphs, osg::Vec4( 0, 0, 0, 1.0 ) );
m_glyphElements = osg::ref_ptr< osg::DrawElementsUInt >( new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 ) );
m_glyphElements = osg::ref_ptr< osg::DrawElementsUInt >( new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES ) );
m_glyphElements->resize( m_sphere->indxNum * nbGlyphs );
}
......@@ -422,6 +444,8 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
for( size_t bId = 0; bId < m_nB; ++bId )
{
size_t glyphId = aId * m_nB + bId;
size_t vertsUpToCurrentIteration = glyphId * nbVerts;
size_t idsUpToCurrentIteration = glyphId * m_sphere->indxNum;
......@@ -439,6 +463,22 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
break;
}
//-------------------------------
// vertex indices
// We have to set them also if we do not darw the glyph becaus otherwise we would leave their
// to be zero. If many indices are zero, they block each other because of synchronized
// memory access to the same memory address.
for( unsigned int vertId = 0; vertId < localSphere->indxNum; ++vertId )
{
( *m_glyphElements )[idsUpToCurrentIteration+vertId] = ( vertsUpToCurrentIteration + localSphere->indx[vertId] );
}
// do not compute positions of vertices if GFA below threshold
if( m_dataGFA && boost::shared_static_cast< WDataSetSingle >( m_dataGFA )->getValueAt( posId ) < m_thresholdGFA )
{
continue;
}
wmath::WValue< double > coeffs = m_dataSet->getSphericalHarmonicAt( posId ).getCoefficients();
WAssert( coeffs.size() == 15,
"This module can handle only 4th order spherical harmonics."
......@@ -483,7 +523,7 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
if( m_useNormalization )
{
minMaxNormalization( glyph, nbVertCoords );
minMaxNormalization( glyph, nbVertCoords );
}
else
{
......@@ -493,13 +533,6 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
wmath::WPosition glyphPos = m_grid->getPosition( posId );
//-------------------------------
// vertex indices
for( unsigned int vertId = 0; vertId < glyph->indxNum; ++vertId )
{
( *m_glyphElements )[idsUpToCurrentIteration+vertId] = ( vertsUpToCurrentIteration + glyph->indx[vertId] );
}
for( unsigned int vertId = 0; vertId < glyph->xyzwNum; ++vertId )
{
......
......@@ -30,6 +30,7 @@
#include <osg/Geode>
#include "../../dataHandler/WDataSetSphericalHarmonics.h"
#include "../../dataHandler/WDataSetScalar.h"
#include "../../graphicsEngine/WShader.h"
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
......@@ -128,11 +129,13 @@ private:
*/
void renderSlice( size_t sliceId );
boost::shared_ptr< WModuleInputData< WDataSetScalar > > m_inputGFA; //!< The input for the GFA.
osg::ref_ptr< WShader > m_shader; //!< The shader used for the glyph surfaces
boost::shared_ptr< WItemSelection > m_sliceOrientations; //!< A list of the selectable slice orientations, i.e x, y and z.
WPropSelection m_sliceOrientationSelection; //!< To choose whether to x, y or z slice.
WPropBool m_usePolarPlotProp; //!< Property indicating whether to use polar plot instead of HOME glyph
WPropBool m_useNormalizationProp; //!< Indicates whether to us radius normalization.
WPropDouble m_GFAThresholdProp; //!< Property holding the threshold of GFA above which glyphs should be drawn.
WPropDouble m_glyphSizeProp; //!< Property holding the size of the displayed glyphs
WPropInt m_sliceIdProp; //!< Property holding the slice ID
......@@ -150,6 +153,8 @@ private:
* Constructor setting the data pointers and the properties from the module.
*
* \param dataSet Pointer to the treated data set.
* \param dataGFA GFA data for dataSet.
* \param thresholdGFA Threshold of GFA below which we will not draw the glyphs
* \param sliceId Rendered slice
* \param sliceType Slice direction (sagittal, coronal, axial )
* \param usePolar Use polar glyphs (HOME otherwise)
......@@ -157,6 +162,8 @@ private:
* \param useNormalization Scale minimum and maximum radius to [0,1].
*/
GlyphGeneration( boost::shared_ptr< WDataSetSphericalHarmonics > dataSet,
boost::shared_ptr< WDataSetScalar > dataGFA,
double thresholdGFA,
const size_t& sliceId,
const size_t& sliceType,
const bool& usePolar,
......@@ -196,6 +203,7 @@ private:
size_t m_nY; //!< Number of voxels in y direction.
size_t m_nZ; //!< Number of voxels in z direction.
boost::shared_ptr< WDataSetSphericalHarmonics > m_dataSet; //!< Pointer to the treated data set.
boost::shared_ptr< WDataSetScalar > m_dataGFA; //!< Pointer to possible GFA data set.
boost::shared_ptr< WGridRegular3D > m_grid; //!< Pointer to the grid of the treated data set.
osg::Geometry* m_glyphGeometry; //!< All glyphs.
osg::ref_ptr< osg::Geode > m_glyphsGeode; //!< The geode containing the glyphs.
......@@ -205,6 +213,7 @@ private:
osg::ref_ptr< osg::DrawElementsUInt > m_glyphElements; //!< Indices of the vertices of the triangles of the glyphs.
osg::ref_ptr< WGEGroupNode > m_generatorNode; //!< Pointer to the generators group node.
double m_thresholdGFA; //!< Stores the GFA threshold from the property.
size_t m_sliceId; //!< Stores option from property.
size_t m_sliceType; //!< Stores option from property.
bool m_usePolar; //!< Stores option from property.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment