OpenWalnut  1.5.0dev
WMCalculateTensors.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 <memory>
26 #include <string>
27 #include <vector>
28 
29 #include "WMCalculateTensors.h"
30 #include "core/common/WLimits.h"
31 #include "core/common/math/WMatrix.h"
32 #include "core/common/math/WSymmetricSphericalHarmonic.h"
33 #include "core/common/math/linearAlgebra/WVectorFixed.h"
34 #include "core/kernel/WKernel.h"
35 
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 )
38 
40  WModule(),
41  m_SHToTensorMat( 1, 1 )
42 {
43 }
44 
46 {
47 }
48 
49 std::shared_ptr< WModule > WMCalculateTensors::factory() const
50 {
51  return std::shared_ptr< WModule >( new WMCalculateTensors() );
52 }
53 
54 const char** WMCalculateTensors::getXPMIcon() const
55 {
56  return NULL;
57 }
58 const std::string WMCalculateTensors::getName() const
59 {
60  return "Calculate Tensors";
61 }
62 
63 const std::string WMCalculateTensors::getDescription() const
64 {
65  return "Calculates diffusion tensors from an input sh dataset.";
66 }
67 
69 {
70  m_input = std::shared_ptr< WModuleInputData< WDataSetSphericalHarmonics > >(
71  new WModuleInputData< WDataSetSphericalHarmonics >( shared_from_this(),
72  "shInput", "A spherical harmonics dataset." )
73  );
74 
75  m_output = std::shared_ptr< WModuleOutputData< WDataSetDTI > >( new WModuleOutputData< WDataSetDTI >( shared_from_this(),
76  "dtiOutput", "The diffusion tensor image." )
77  );
78 
81 
82  // call WModules initialization
84 }
85 
87 {
88  m_exceptionCondition = std::shared_ptr< WCondition >( new WCondition() );
89 
91 }
92 
94 {
95  m_moduleState.setResetable( true, true );
96  m_moduleState.add( m_input->getDataChangedCondition() );
98 
99  // calc sh->tensor conversion matrix
100  std::vector< WUnitSphereCoordinates< double > > orientations;
101  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( 1.0, 0.0, 0.0 ) ) ) );
102  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( 0.6, -0.1, 0.2 ) ) ) );
103  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( 1.0, 1.0, 1.0 ) ) ) );
104  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( -0.1, -0.3, 0.5 ) ) ) );
105  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( -0.56347, 0.374, -0.676676 ) ) ) );
106  orientations.push_back( WUnitSphereCoordinates< double >( normalize( WVector3d( 0.0, 4.0, 1.0 ) ) ) );
107 
109 
110  ready();
111 
112  while( !m_shutdownFlag() )
113  {
114  debugLog() << "Waiting.";
116 
117  std::shared_ptr< WDataSetSphericalHarmonics > inData = m_input->getData();
118  bool dataChanged = ( m_dataSet != inData );
119 
120  if( dataChanged && inData )
121  {
122  m_dataSet = inData;
123 
124  // start computation
125  resetTensorPool();
126  if( m_tensorPool )
127  {
128  m_tensorPool->run();
129  }
130  debugLog() << "Running computation.";
131  }
132  else if( m_tensorPool && ( m_tensorPool->status() == W_THREADS_FINISHED || m_tensorPool->status() == W_THREADS_ABORTED ) )
133  {
134  debugLog() << "Computation finished.";
135  m_currentProgress->finish();
136  std::shared_ptr< WDataSetSingle > temp = m_tensorFunc->getResult();
137  m_result = std::shared_ptr< WDataSetDTI >( new WDataSetDTI( temp->getValueSet(), temp->getGrid() ) );
138  m_tensorPool = std::shared_ptr< TensorPoolType >();
139  m_tensorFunc = std::shared_ptr< TensorFuncType >();
140 
141  // forward result
142  m_output->updateData( m_result );
143  }
144  else if( m_lastException )
145  {
146  throw WException( *m_lastException );
147  }
148  }
149 
150  // module shutdown
151  debugLog() << "Shutting down module.";
152  if( m_tensorPool )
153  {
154  if( m_tensorPool->status() == W_THREADS_RUNNING || m_tensorPool->status() == W_THREADS_STOP_REQUESTED )
155  {
156  m_tensorPool->stop();
157  m_tensorPool->wait();
158  }
159  }
160 }
161 
163 {
164  if( m_tensorPool )
165  {
166  WThreadedFunctionStatus s = m_tensorPool->status();
167  if( s != W_THREADS_FINISHED && s != W_THREADS_ABORTED )
168  {
169  m_tensorPool->stop();
170  m_tensorPool->wait();
171  s = m_tensorPool->status();
172  WAssert( s == W_THREADS_FINISHED || s == W_THREADS_ABORTED, "" );
173  }
174  m_moduleState.remove( m_tensorPool->getThreadsDoneCondition() );
175  }
176  // the threadpool should have finished computing by now
177 
178  if( m_dataSet->getSphericalHarmonicAt( 0 ).getOrder() == 2 )
179  {
180  std::shared_ptr< WGridRegular3D > g = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
181  WAssert( g, "" );
182  resetProgress( g->getNbCoordsX() * g->getNbCoordsY() * g->getNbCoordsZ() );
183 
184  // create a new one
185  m_tensorFunc = std::shared_ptr< TensorFuncType >( new TensorFuncType( m_dataSet, boost::bind( &This::perVoxelTensorFunc,
186  this,
187  boost::placeholders::_1 ) ) );
188  m_tensorPool = std::shared_ptr< TensorPoolType >( new TensorPoolType( 0, m_tensorFunc ) );
189  m_tensorPool->subscribeExceptionSignal( boost::bind( &This::handleException, this, boost::placeholders::_1 ) );
190  m_moduleState.add( m_tensorPool->getThreadsDoneCondition() );
191  }
192  else
193  {
194  warnLog() << "SH dataset has order > 2";
195  }
196 }
197 
199 {
200  m_lastException = std::shared_ptr< WException >( new WException( e ) );
201  m_exceptionCondition->notify();
202 }
203 
204 void WMCalculateTensors::resetProgress( std::size_t todo )
205 {
206  if( m_currentProgress )
207  {
208  m_currentProgress->finish();
209  }
210  m_currentProgress = std::shared_ptr< WProgress >( new WProgress( "calculate tensors", todo ) );
211  m_progress->addSubProgress( m_currentProgress );
212 }
213 
215 {
217  boost::array< double, 6 > a;
218  WValue<double> v( 6 );
219 
220  // calculation
221  for( std::size_t k = 0; k < 6; ++k )
222  {
223  v[ k ] = s[ k ];
224  }
225 
226  v = m_SHToTensorMat * v;
227 
228  for( std::size_t k = 0; k < 6; ++k )
229  {
230  a[ k ] = v[ k ];
231  }
232 
233  return a;
234 }
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void remove(std::shared_ptr< WCondition > condition)
Removes the specified condition.
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
Represents a Diffusion-Tensor-Image dataset.
Definition: WDataSetDTI.h:40
Basic exception handler.
Definition: WException.h:39
A module that calculates tensors from the input SH dataset.
boost::array< double, 6 > perVoxelTensorFunc(WValueSet< double >::SubArray const &s)
A function that gets called for every voxel in the input SH-dataset.
std::shared_ptr< WException > m_lastException
The last exception thrown by any worker thread.
std::shared_ptr< WCondition > m_exceptionCondition
Condition indicating if any exception was thrown.
std::shared_ptr< WDataSetSphericalHarmonics > m_dataSet
A pointer to the input dataset.
virtual const std::string getName() const
Gives back the name of this module.
void resetTensorPool()
Reset the threaded functions.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual void moduleMain()
Entry point after loading the module.
WThreadedPerVoxelOperation< double, 6, double, 6 > TensorFuncType
the threaded function type for tensor computation, order 4 to 2
std::shared_ptr< WModuleOutputData< WDataSetDTI > > m_output
The output Connector.
std::shared_ptr< WModuleInputData< WDataSetSphericalHarmonics > > m_input
The input Connector for the SH data.
WMCalculateTensors()
Standard constructor.
WThreadedFunction< TensorFuncType > TensorPoolType
the threadpool
std::shared_ptr< TensorPoolType > m_tensorPool
The threadpool.
virtual ~WMCalculateTensors()
Destructor.
std::shared_ptr< WProgress > m_currentProgress
The object that keeps track of the current progress.
WMatrix< double > m_SHToTensorMat
The sh->tensor conversion.
virtual void properties()
Initialize the properties for this module.
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< TensorFuncType > m_tensorFunc
The threaded function object.
void handleException(WException const &e)
Handle an exception thrown by a worker thread.
std::shared_ptr< WDataSetDTI > m_result
The output dataset.
void resetProgress(std::size_t todo)
Reset the progress indicator in the ui.
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getDescription() const
Gives back a description of this module.
Class offering an instantiate-able data connection between modules.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
wlog::WStreamedLogger warnLog() const
Logger instance for comfortable warning- logs.
Definition: WModule.cpp:580
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
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Class managing progress inside of modules.
Definition: WProgress.h:42
static WMatrix< T > calcSHToTensorSymMatrix(std::size_t order)
Calculates a matrix that converts spherical harmonics to symmetric tensors of equal or lower order.
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
This class stores coordinates on the unit sphere.
A helper class granting safe access to a certain part of the valueset.
Definition: WValueSet.h:65
Base class for all higher level values like tensors, vectors, matrices and so on.
Definition: WValue.h:41