OpenWalnut  1.5.0dev
WMSpatialDerivative.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 "WMSpatialDerivative.h"
30 #include "WMSpatialDerivative.xpm"
31 #include "core/common/WPropertyHelper.h"
32 #include "core/dataHandler/WDataHandler.h"
33 #include "core/kernel/WKernel.h"
34 
35 // This line is needed by the module loader to actually find your module. You need to add this to your module too. Do NOT add a ";" here.
36 W_LOADABLE_MODULE( WMSpatialDerivative )
37 
39  WModule()
40 {
41 }
42 
44 {
45  // Cleanup!
46 }
47 
48 std::shared_ptr< WModule > WMSpatialDerivative::factory() const
49 {
50  return std::shared_ptr< WModule >( new WMSpatialDerivative() );
51 }
52 
53 const char** WMSpatialDerivative::getXPMIcon() const
54 {
55  return WMSpatialDerivative_xpm;
56 }
57 
58 const std::string WMSpatialDerivative::getName() const
59 {
60  return "Spatial Derivative";
61 }
62 
63 const std::string WMSpatialDerivative::getDescription() const
64 {
65  return "This module a scalar field and derives it spatially.";
66 }
67 
69 {
70  // the dataset to process. Only accept scalar data.
71  m_scalarIn = WModuleInputData< WDataSetScalar >::createAndAdd( shared_from_this(), "scalars", "The scalar dataset."
72  "Needs to be in the same grid as the mesh." );
73 
74  // output vector data
75  m_vectorOut = WModuleOutputData< WDataSetVector >::createAndAdd( shared_from_this(), "derived", "The vector dataset representing spatial"
76  " derivate of the input field." );
77 
78  // call WModule's initialization
80 }
81 
83 {
84  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
85 
86  // normalizing?
87  m_normalize = m_properties->addProperty( "Normalize", "If true, vectors get normalized.", true, m_propCondition );
88 
89  // call WModule's initialization
91 }
92 
94 {
95  // get notified about data changes
96  m_moduleState.setResetable( true, true );
97  m_moduleState.add( m_scalarIn->getDataChangedCondition() );
98  // Remember the condition provided to some properties in properties()? The condition can now be used with this condition set.
100 
101  ready();
102 
103  // main loop
104  while( !m_shutdownFlag() )
105  {
106  debugLog() << "Waiting ...";
108 
109  // woke up since the module is requested to finish?
110  if( m_shutdownFlag() )
111  {
112  break;
113  }
114 
115  // To query whether an input was updated, simply ask the input:
116  bool dataUpdated = m_scalarIn->handledUpdate() || m_normalize->changed();
117  std::shared_ptr< WDataSetScalar > dataSet = m_scalarIn->getData();
118 
119  bool dataValid = ( dataSet != NULL );
120 
121  // reset output if input was reset/disconnected
122  if( !dataValid )
123  {
124  debugLog() << "Resetting output.";
125  m_vectorOut->reset();
126  continue;
127  }
128  if( dataValid && !dataUpdated )
129  {
130  continue;
131  }
132 
133  // prepare progress indicators
134  std::shared_ptr< WProgress > progress( new WProgress( "Processing", 0 ) );
135  m_progress->addSubProgress( progress );
136 
137  // loop through each voxel
138  std::shared_ptr< WGridRegular3D > grid = std::dynamic_pointer_cast< WGridRegular3D >( dataSet->getGrid() );
139  if( !grid )
140  {
141  errorLog() << "Only regular 3D grids allowed.";
142  continue;
143  }
144 
145  switch( dataSet->getValueSet()->getDataType() )
146  {
147  case W_DT_UNSIGNED_CHAR:
148  {
149  std::shared_ptr<WValueSet<unsigned char> > vals;
150  vals = std::dynamic_pointer_cast<WValueSet<unsigned char> >( dataSet->getValueSet() );
151  WAssert( vals, "Data type and data type indicator must fit." );
152  derive( grid, vals );
153  break;
154  }
155  case W_DT_INT16:
156  {
157  std::shared_ptr<WValueSet<int16_t> > vals;
158  vals = std::dynamic_pointer_cast<WValueSet<int16_t> >( dataSet->getValueSet() );
159  WAssert( vals, "Data type and data type indicator must fit." );
160  derive( grid, vals );
161  break;
162  }
163  case W_DT_SIGNED_INT:
164  {
165  std::shared_ptr<WValueSet<int32_t> > vals;
166  vals = std::dynamic_pointer_cast<WValueSet<int32_t> >( dataSet->getValueSet() );
167  WAssert( vals, "Data type and data type indicator must fit." );
168  derive( grid, vals );
169  break;
170  }
171  case W_DT_FLOAT:
172  {
173  std::shared_ptr< WValueSet< float > > vals;
174  vals = std::dynamic_pointer_cast< WValueSet< float > >( dataSet->getValueSet() );
175  WAssert( vals, "Data type and data type indicator must fit." );
176  derive( grid, vals );
177  break;
178  }
179  case W_DT_DOUBLE:
180  {
181  std::shared_ptr< WValueSet< double > > vals;
182  vals = std::dynamic_pointer_cast< WValueSet< double > >( dataSet->getValueSet() );
183  WAssert( vals, "Data type and data type indicator must fit." );
184  derive( grid, vals );
185  break;
186  }
187  default:
188  WAssert( false, "Unknown data type in." );
189  }
190 
191  // work done
192  progress->finish();
193  m_progress->removeSubProgress( progress );
194 
195  debugLog() << "Done";
196  }
197 }
198 
199 size_t getId( size_t xDim, size_t yDim, size_t /*zDim*/, size_t x, size_t y, size_t z, size_t offset = 0, size_t elements = 1 )
200 {
201  return offset + ( elements * ( z * xDim * yDim + y * xDim + x ) );
202 }
203 
204 template< typename T >
205 void WMSpatialDerivative::derive( std::shared_ptr< WGridRegular3D > grid, std::shared_ptr< WValueSet< T > > values )
206 {
207  size_t nX = grid->getNbCoordsX();
208  size_t nY = grid->getNbCoordsY();
209  size_t nZ = grid->getNbCoordsZ();
210 
211  std::shared_ptr< std::vector< double > > vectors =
212  std::shared_ptr< std::vector< double > >( new std::vector< double >( 3 * nX * nY * nZ, 0.0 ) );
213 
214  // iterate field
215  for( size_t z = 1; z < nZ - 1; z++ )
216  {
217  for( size_t y = 1; y < nY - 1; y++ )
218  {
219  for( size_t x = 1; x < nX - 1; x++ )
220  {
221  // TODO(ebaum): improve performance
222  // this loop should be quite slow but it works for now. Sorry.
223  float xp = values->getScalar( getId( nX, nY, nZ, x + 1, y, z ) );
224  float xm = values->getScalar( getId( nX, nY, nZ, x - 1, y, z ) );
225  float yp = values->getScalar( getId( nX, nY, nZ, x, y + 1, z ) );
226  float ym = values->getScalar( getId( nX, nY, nZ, x, y - 1, z ) );
227  float zp = values->getScalar( getId( nX, nY, nZ, x, y, z + 1 ) );
228  float zm = values->getScalar( getId( nX, nY, nZ, x, y, z - 1 ) );
229 
230  float vx = ( xp - xm ) / 2.0;
231  float vy = ( yp - ym ) / 2.0;
232  float vz = ( zp - zm ) / 2.0;
233 
234  float sqsum = vx * vx + vy * vy + vz * vz;
235  float len = sqrt( sqsum );
236  float scal = m_normalize->get( true ) ? 1.0 / len : 1.0;
237  if( len == 0.0 )
238  scal = 0.0;
239 
240  ( *vectors )[ getId( nX, nY, nZ, x, y, z, 0, 3 ) ] = scal * vx;
241  ( *vectors )[ getId( nX, nY, nZ, x, y, z, 1, 3 ) ] = scal * vy;
242  ( *vectors )[ getId( nX, nY, nZ, x, y, z, 2, 3 ) ] = scal * vz;
243  }
244  }
245  }
246 
247  std::shared_ptr< WValueSet< double > > valueset = std::shared_ptr< WValueSet< double > >(
248  new WValueSet< double >( 1, 3, vectors, W_DT_DOUBLE )
249  );
250  // register new
251  m_vectorOut->updateData( std::shared_ptr< WDataSetVector >( new WDataSetVector( valueset, grid ) ) );
252 }
253 
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
This data set type contains vectors as values.
This modules takes a dataset and derives it spatially.
virtual const std::string getName() const
Gives back the name of this module.
std::shared_ptr< WModuleInputData< WDataSetScalar > > m_scalarIn
An input connector used to get datasets from other modules.
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...
WMSpatialDerivative()
Default constructor.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
virtual void connectors()
Initialize the connectors this module is using.
virtual void moduleMain()
Entry point after loading the module.
std::shared_ptr< WModuleOutputData< WDataSetVector > > m_vectorOut
The output connector used to provide the calculated data to other modules.
void derive(std::shared_ptr< WGridRegular3D > grid, std::shared_ptr< WValueSet< T > > values)
Derives the specified scalar data set spatially and creates a new vector value set.
virtual const std::string getDescription() const
Gives back a description of this module.
virtual ~WMSpatialDerivative()
Destructor.
virtual void properties()
Initialize the properties for this module.
WPropBool m_normalize
If true, the vectors get normalized.
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
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
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.
Base Class for all value set types.
Definition: WValueSet.h:47