1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
28
#include "core/common/math/WSymmetricSphericalHarmonic.h"
29
#include "core/common/math/WMatrix.h"
30
#include "core/common/math/linearAlgebra/WLinearAlgebra.h"
31
#include "core/common/WLimits.h"
32
#include "core/kernel/WKernel.h"
34
#include "WMCalculateTensors.h"
36
// This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here.
37
W_LOADABLE_MODULE( WMCalculateTensors )
39
WMCalculateTensors::WMCalculateTensors():
41
m_SHToTensorMat( 1, 1 )
45
WMCalculateTensors::~WMCalculateTensors()
49
boost::shared_ptr< WModule > WMCalculateTensors::factory() const
51
return boost::shared_ptr< WModule >( new WMCalculateTensors() );
54
const char** WMCalculateTensors::getXPMIcon() const
58
const std::string WMCalculateTensors::getName() const
60
return "Calculate Tensors";
63
const std::string WMCalculateTensors::getDescription() const
65
return "Calculates diffusion tensors from an input sh dataset.";
68
void WMCalculateTensors::connectors()
70
m_input = boost::shared_ptr< WModuleInputData< WDataSetSphericalHarmonics > >(
71
new WModuleInputData< WDataSetSphericalHarmonics >( shared_from_this(),
72
"shInput", "A spherical harmonics dataset." )
75
m_output = boost::shared_ptr< WModuleOutputData< WDataSetDTI > >( new WModuleOutputData< WDataSetDTI >( shared_from_this(),
76
"dtiOutput", "The diffusion tensor image." )
79
addConnector( m_input );
80
addConnector( m_output );
82
// call WModules initialization
83
WModule::connectors();
86
void WMCalculateTensors::properties()
88
m_exceptionCondition = boost::shared_ptr< WCondition >( new WCondition() );
90
WModule::properties();
93
void WMCalculateTensors::moduleMain()
95
m_moduleState.setResetable( true, true );
96
m_moduleState.add( m_input->getDataChangedCondition() );
97
m_moduleState.add( m_exceptionCondition );
99
// calc sh->tensor conversion matrix
100
std::vector< WUnitSphereCoordinates > orientations;
101
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( 1.0, 0.0, 0.0 ) ) ) );
102
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( 0.6, -0.1, 0.2 ) ) ) );
103
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( 1.0, 1.0, 1.0 ) ) ) );
104
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( -0.1, -0.3, 0.5 ) ) ) );
105
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( -0.56347, 0.374, -0.676676 ) ) ) );
106
orientations.push_back( WUnitSphereCoordinates( normalize( WVector3d( 0.0, 4.0, 1.0 ) ) ) );
108
m_SHToTensorMat = WSymmetricSphericalHarmonic::calcSHToTensorSymMatrix( 2, orientations );
112
while( !m_shutdownFlag() )
114
debugLog() << "Waiting.";
115
m_moduleState.wait();
117
boost::shared_ptr< WDataSetSphericalHarmonics > inData = m_input->getData();
118
bool dataChanged = ( m_dataSet != inData );
120
if( dataChanged && inData )
130
debugLog() << "Running computation.";
132
else if( m_tensorPool && ( m_tensorPool->status() == W_THREADS_FINISHED || m_tensorPool->status() == W_THREADS_ABORTED ) )
134
debugLog() << "Computation finished.";
135
m_currentProgress->finish();
136
boost::shared_ptr< WDataSetSingle > temp = m_tensorFunc->getResult();
137
m_result = boost::shared_ptr< WDataSetDTI >( new WDataSetDTI( temp->getValueSet(), temp->getGrid() ) );
138
m_tensorPool = boost::shared_ptr< TensorPoolType >();
139
m_tensorFunc = boost::shared_ptr< TensorFuncType >();
142
m_output->updateData( m_result );
144
else if( m_lastException )
146
throw WException( *m_lastException );
151
debugLog() << "Shutting down module.";
154
if( m_tensorPool->status() == W_THREADS_RUNNING || m_tensorPool->status() == W_THREADS_STOP_REQUESTED )
156
m_tensorPool->stop();
157
m_tensorPool->wait();
162
void WMCalculateTensors::resetTensorPool()
166
WThreadedFunctionStatus s = m_tensorPool->status();
167
if( s != W_THREADS_FINISHED && s != W_THREADS_ABORTED )
169
m_tensorPool->stop();
170
m_tensorPool->wait();
171
s = m_tensorPool->status();
172
WAssert( s == W_THREADS_FINISHED || s == W_THREADS_ABORTED, "" );
174
m_moduleState.remove( m_tensorPool->getThreadsDoneCondition() );
176
// the threadpool should have finished computing by now
178
if( m_dataSet->getSphericalHarmonicAt( 0 ).getOrder() == 2 )
180
boost::shared_ptr< WGridRegular3D > g = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
182
resetProgress( g->getNbCoordsX() * g->getNbCoordsY() * g->getNbCoordsZ() );
185
m_tensorFunc = boost::shared_ptr< TensorFuncType >( new TensorFuncType( m_dataSet, boost::bind( &This::perVoxelTensorFunc, this, _1 ) ) );
186
m_tensorPool = boost::shared_ptr< TensorPoolType >( new TensorPoolType( 0, m_tensorFunc ) );
187
m_tensorPool->subscribeExceptionSignal( boost::bind( &This::handleException, this, _1 ) );
188
m_moduleState.add( m_tensorPool->getThreadsDoneCondition() );
192
warnLog() << "SH dataset has order > 2";
196
void WMCalculateTensors::handleException( WException const& e )
198
m_lastException = boost::shared_ptr< WException >( new WException( e ) );
199
m_exceptionCondition->notify();
202
void WMCalculateTensors::resetProgress( std::size_t todo )
204
if( m_currentProgress )
206
m_currentProgress->finish();
208
m_currentProgress = boost::shared_ptr< WProgress >( new WProgress( "calculate tensors", todo ) );
209
m_progress->addSubProgress( m_currentProgress );
212
boost::array< double, 6 > WMCalculateTensors::perVoxelTensorFunc( WValueSet< double >::SubArray const& s )
214
++*m_currentProgress;
215
boost::array< double, 6 > a;
216
WValue<double> v( 6 );
219
for( std::size_t k = 0; k < 6; ++k )
224
v = m_SHToTensorMat * v;
226
for( std::size_t k = 0; k < 6; ++k )