OpenWalnut  1.5.0dev
WMVectorScale.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 <stdint.h>
30 #include <string>
31 #include <vector>
32 
33 #include <boost/variant.hpp>
34 
35 #include "WMVectorScale.h"
36 #include "core/common/WAssert.h"
37 #include "core/common/WProgress.h"
38 #include "core/common/WStringUtils.h"
39 #include "core/common/WTypeTraits.h"
40 #include "core/common/exceptions/WTypeMismatch.h"
41 #include "core/dataHandler/WDataHandler.h"
42 #include "core/dataHandler/WDataHandlerEnums.h"
43 #include "core/dataHandler/WGridRegular3D.h"
44 #include "core/dataHandler/exceptions/WDHValueSetMismatch.h"
45 #include "core/kernel/WKernel.h"
46 
47 // This line is needed by the module loader to actually find your module.
48 W_LOADABLE_MODULE( WMVectorScale )
49 
51  WModule()
52 {
53  // initialize
54 }
55 
57 {
58  // cleanup
60 }
61 
62 std::shared_ptr< WModule > WMVectorScale::factory() const
63 {
64  return std::shared_ptr< WModule >( new WMVectorScale() );
65 }
66 
67 const std::string WMVectorScale::getName() const
68 {
69  return "Vector Scaling";
70 }
71 
72 const std::string WMVectorScale::getDescription() const
73 {
74  return "Scales the given vector field by the given scalar field.";
75 }
76 
78 {
79  m_inputA = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "operandA", "First operand of operation." );
80  m_inputB = WModuleInputData< WDataSetScalar >::createAndAdd( shared_from_this(), "operandB", "Second operand of operation." );
81 
82  m_output = WModuleOutputData< WDataSetVector >::createAndAdd( shared_from_this(), "result", "Result of voxel-wise operation." );
83 
84  // call WModules initialization
86 }
87 
89 {
90  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
92 }
93 
94 /**
95  * The second visitor which got applied to the second value set. It discriminates the integral type and applies the operator in a per value
96  * style.
97  *
98  * \tparam VSetAType The integral type of the first valueset.
99  */
100 template< typename VSetAType >
101 class VisitorVSetB: public boost::static_visitor< std::shared_ptr< WValueSetBase > >
102 {
103 public:
104  /**
105  * Creates visitor for the second level of cascading. Takes the first value set as parameter. This visitor applies the operation o to A and
106  * B: o(A,B).
107  *
108  * \param vsetA the first value set
109  */
110  explicit VisitorVSetB( const WValueSet< VSetAType >* const vsetA ):
111  boost::static_visitor< result_type >(),
112  m_vsetA( vsetA )
113  {
114  }
115 
116  /**
117  * Visitor on the second valueset. This applies the operation.
118  *
119  * \tparam VSetBType the integral type of the currently visited valueset.
120  * \param vsetB the valueset currently visited (B).
121  *
122  * \return the result of o(A,B)
123  */
124  template < typename VSetBType >
125  result_type operator()( const WValueSet< VSetBType >* const& vsetB ) const // NOLINT
126  {
127  // get best matching return scalar type
129 
131  std::vector< ResultT > data;
132  data.resize( m_vsetA->rawSize() );
133 
134  // discriminate the right operation with the correct type. It would be nicer to use some kind of strategy pattern here, but the template
135  // character of the operators forbids it as template methods can't be virtual. Besides this, at some point in the module main the
136  // selector needs to be queried and its index mapped to a pointer. This is what we do here.
137 
138  // apply op to each value
139  const VSetAType* a = m_vsetA->rawData();
140  const VSetBType* b = vsetB->rawData();
141  for( size_t i = 0; i < vsetB->rawSize(); ++i )
142  {
143  size_t vi = 3 * i;
144  data[ vi + 0 ] = static_cast< ResultT >( a[ vi + 0 ] ) * static_cast< ResultT >( b[ i ] );
145  data[ vi + 1 ] = static_cast< ResultT >( a[ vi + 1 ] ) * static_cast< ResultT >( b[ i ] );
146  data[ vi + 2 ] = static_cast< ResultT >( a[ vi + 2 ] ) * static_cast< ResultT >( b[ i ] );
147  }
148 
149  // create result value set
150  std::shared_ptr< WValueSet< ResultT > > result = std::shared_ptr< WValueSet< ResultT > >(
151  new WValueSet< ResultT >( 1,
152  3,
153  std::shared_ptr< std::vector< ResultT > >( new std::vector< ResultT >( data ) ),
154  type )
155  );
156  return result;
157  }
158 
159  /**
160  * The first valueset.
161  */
162  const WValueSet< VSetAType >* const m_vsetA;
163 };
164 
165 /**
166  * Visitor for discriminating the type of the first valueset. It simply creates a new instance of VisitorVSetB with the proper integral type of
167  * the first value set.
168  */
169 class VisitorVSetA: public boost::static_visitor< std::shared_ptr< WValueSetBase > >
170 {
171 public:
172  /**
173  * Create visitor instance. The specified valueset gets visited if the first one is visited using this visitor.
174  *
175  * \param vsetB The valueset to visit during this visit.
176  */
177  explicit VisitorVSetA( WValueSetBase* vsetB ):
178  boost::static_visitor< result_type >(),
179  m_vsetB( vsetB )
180  {
181  }
182 
183  /**
184  * Called by boost::varying during static visiting. Creates a new VisitorVSetB which finally applies the operation.
185  *
186  * \tparam T the real integral type of the first value set.
187  * \param vsetA the first valueset currently visited.
188  *
189  * \return the result from the operation with this and the second value set
190  */
191  template < typename T >
192  result_type operator()( const WValueSet< T >* const& vsetA ) const // NOLINT
193  {
194  // visit the second value set as we now know the type of the first one
195  VisitorVSetB< T > visitor( vsetA );
196  return m_vsetB->applyFunction( visitor );
197  }
198 
199  /**
200  * The valueset where to cascade.
201  */
203 };
204 
206 {
207  // let the main loop awake if the data changes or the properties changed.
208  m_moduleState.setResetable( true, true );
209  m_moduleState.add( m_inputA->getDataChangedCondition() );
210  m_moduleState.add( m_inputB->getDataChangedCondition() );
212 
213  // signal ready state
214  ready();
215 
216  // loop until the module container requests the module to quit
217  while( !m_shutdownFlag() )
218  {
219  // Now, the moduleState variable comes into play. The module can wait for the condition, which gets fired whenever the input receives data
220  // or an property changes. The main loop now waits until something happens.
221  debugLog() << "Waiting ...";
223 
224  // woke up since the module is requested to finish
225  if( m_shutdownFlag() )
226  {
227  break;
228  }
229 
230  // has the data changed?
231  if( m_inputA->handledUpdate() || m_inputB->handledUpdate() )
232  {
233  std::shared_ptr< WDataSetVector > dataSetA = m_inputA->getData();
234  std::shared_ptr< WDataSetScalar > dataSetB = m_inputB->getData();
235  if( !dataSetA || !dataSetB )
236  {
237  // reset output if input was reset/disconnected
238  debugLog() << "Resetting output.";
239  m_output->reset();
240  continue;
241  }
242 
243  // the first value-set is always needed -> grab it
244  std::shared_ptr< WValueSetBase > valueSetA = dataSetA->getValueSet();
245  std::shared_ptr< WValueSetBase > valueSetB = dataSetB->getValueSet();
246 
247  // use a custom progress combiner
248  std::shared_ptr< WProgress > prog = std::shared_ptr< WProgress >(
249  new WProgress( "Applying operator on data" ) );
250  m_progress->addSubProgress( prog );
251 
252  // apply the operation to each voxel
253  debugLog() << "Processing ...";
254 
255  // both value sets need to be the same
256  bool match = ( valueSetA->rawSize() == 3 * valueSetB->rawSize() );
257  if( !match )
258  {
259  errorLog() << "Rawsize Mismatch: " << valueSetA->rawSize() << " != 3 * " << valueSetB->rawSize();
260  throw WDHValueSetMismatch( std::string( "The both value sets are not of equal size." ) );
261  }
262 
263  // this keeps the result
264  std::shared_ptr< WValueSetBase > newValueSet;
265  VisitorVSetA visitor( valueSetB.get() ); // the visitor cascades to the second value set
266  newValueSet = valueSetA->applyFunction( visitor );
267 
268  // Create the new dataset and export it
269  m_output->updateData( std::shared_ptr<WDataSetVector>( new WDataSetVector( newValueSet, m_inputA->getData()->getGrid() ) ) );
270 
271  // done
272  prog->finish();
273  m_progress->removeSubProgress( prog );
274  }
275  }
276 }
277 
Visitor for discriminating the type of the first valueset.
VisitorVSetA(WValueSetBase *vsetB)
Create visitor instance.
result_type operator()(const WValueSet< T > *const &vsetA) const
Called by boost::varying during static visiting.
WValueSetBase * m_vsetB
The valueset where to cascade.
The second visitor which got applied to the second value set.
result_type operator()(const WValueSet< VSetBType > *const &vsetB) const
Visitor on the second valueset.
const WValueSet< VSetAType > *const m_vsetA
The first valueset.
VisitorVSetB(const WValueSet< VSetAType > *const vsetA)
Creates visitor for the second level of cascading.
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
An exception that should be used whenever two valuesets are used which need to be of same size,...
This data set type contains vectors as values.
Operators for processing a vector with a WDataSetScalar.
Definition: WMVectorScale.h:48
~WMVectorScale()
Destructor.
WMVectorScale()
Standard constructor.
virtual void moduleMain()
Entry point after loading the module.
virtual const std::string getDescription() const
Gives back a description of this module.
std::shared_ptr< WModuleInputData< WDataSetScalar > > m_inputB
Input connector required by this module.
virtual const std::string getName() const
Gives back the name of this module.
virtual void properties()
Initialize the properties for this module.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
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...
virtual void connectors()
Initialize the connectors this module is using.
std::shared_ptr< WModuleInputData< WDataSetVector > > m_inputA
Input connector required by this module.
std::shared_ptr< WModuleOutputData< WDataSetVector > > m_output
The only output of this filter module.
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this out data connector with proper type and add it to...
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 removeConnectors()
Removes all connectors properly.
Definition: WModule.cpp:194
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
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
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Class for checking the "better" type if two integral types are known.
Definition: WTypeTraits.h:46
Abstract base class to all WValueSets.
Definition: WValueSetBase.h:60
Func_T::result_type applyFunction(Func_T const &func)
Apply a function object to this valueset.
const T * rawData() const
Sometimes we need raw access to the data array, for e.g.
Definition: WValueSet.h:240
virtual size_t rawSize() const
Definition: WValueSet.h:184
dataType
Data types and number values taken from the nifti1.h, at this point it's unknown if it makes sense to...
An object that knows an appropriate dataType flag for the typename T.