OpenWalnut  1.5.0dev
WMImageExtractor.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 <algorithm>
26 #include <memory>
27 #include <sstream>
28 #include <string>
29 #include <vector>
30 
31 #include "WMImageExtractor.h"
32 #include "WMImageExtractor.xpm"
33 #include "core/common/WPropertyHelper.h"
34 #include "core/dataHandler/WDataHandler.h"
35 #include "core/dataHandler/WDataTexture3D.h"
36 #include "core/graphicsEngine/WGEColormapping.h"
37 #include "core/kernel/WKernel.h"
38 
39 // This line is needed by the module loader to actually find your module.
40 W_LOADABLE_MODULE( WMImageExtractor )
41 
43  WModule()
44 {
45 }
46 
48 {
49 }
50 
51 std::shared_ptr< WModule > WMImageExtractor::factory() const
52 {
53  return std::shared_ptr< WModule >( new WMImageExtractor() );
54 }
55 
56 const std::string WMImageExtractor::getName() const
57 {
58  return "Image Extractor";
59 }
60 
61 const std::string WMImageExtractor::getDescription() const
62 {
63  return "This module allows extracting of single images from a dataset.";
64 }
65 
66 const char** WMImageExtractor::getXPMIcon() const
67 {
68  return imageExtractor_xpm;
69 }
70 
72 {
73  m_input = std::shared_ptr< WModuleInputData < WDataSetSingle > >(
74  new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) );
76 
77  m_output = std::shared_ptr< WModuleOutputData < WDataSetScalar > >(
78  new WModuleOutputData< WDataSetScalar >( shared_from_this(), "out", "The extracted image." ) );
80 
82 }
83 
85 {
86  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
87 
88  m_selectedImage = m_properties->addProperty( "Image", "The image to be extracted.", 0, m_propCondition );
89  m_selectedImage->setMin( 0 );
90  m_selectedImage->setMax( 0 );
91 
92  m_minValuePct = m_properties->addProperty( "Min %", "The data value percent that maps to 0.0 in the texture.", 0.0, m_propCondition );
93  m_minValuePct->setMin( 0.0 );
94  m_minValuePct->setMax( 100.0 );
95 
96  m_maxValuePct = m_properties->addProperty( "Max %", "The data value percent that maps to 1.0 in the texture.", 100.0, m_propCondition );
97  m_maxValuePct->setMin( 0.0 );
98  m_maxValuePct->setMax( 100.0 );
99 
101 }
102 
104 {
105  if( m_outData )
106  {
107  m_outData->getTexture()->active()->set( m_active->get() );
108  }
110 }
111 
113 {
114  m_moduleState.setResetable( true, true );
115  m_moduleState.add( m_input->getDataChangedCondition() );
117 
118  ready();
119 
120  while( !m_shutdownFlag() )
121  {
123 
124  if( m_shutdownFlag() )
125  {
126  break;
127  }
128 
129  std::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
130  bool dataChanged = ( m_dataSet != newDataSet );
131  bool dataValid = ( newDataSet != NULL );
132 
133  if( dataValid )
134  {
135  if( dataChanged || m_selectedImage->changed() || m_minValuePct->changed() || m_maxValuePct->changed() )
136  {
137  m_dataSet = newDataSet;
138  WAssert( m_dataSet, "" );
139  WAssert( m_dataSet->getValueSet(), "" );
140 
141  if( dataChanged )
142  {
143  m_selectedImage->setMax( m_dataSet->getValueSet()->dimension() - 1 );
144  m_selectedImage->ensureValidity( 0 );
145  }
146 
147  // remove the old dataset's properties and de-register from colormapper
148  if( m_outData )
149  {
150  m_properties->removeProperty( m_outData->getTexture()->getProperties() );
151  m_infoProperties->removeProperty( m_outData->getTexture()->getInformationProperties() );
152  }
153 
154  std::size_t i = static_cast< std::size_t >( m_selectedImage->get( true ) );
155 
156  std::shared_ptr< WDataSetScalar > oldOut = m_outData;
157  m_outData = extract( i );
158 
159  if( m_outData )
160  {
161  setOutputProps();
162  m_outData->setFilename( makeImageName( i ) );
163  // provide the texture's properties as own properties
164  m_properties->addProperty( m_outData->getTexture()->getProperties() );
165  m_infoProperties->addProperty( m_outData->getTexture()->getInformationProperties() );
166  }
167 
168  // update colormapper
169  // 1: there was some texture and there is a new texture:
170  if( oldOut && m_outData )
171  {
172  // according to WGEColormapper::replaceTexture, an non-existing old texture causes the new one to be inserted at the end.
173  WGEColormapping::replaceTexture( oldOut->getTexture(), m_outData->getTexture(), makeImageName( i ) );
174  }
175  // 2: there is no new texture. Remove old one.
176  else if( oldOut )
177  {
178  // no new texture. Remove old one.
179  WGEColormapping::deregisterTexture( oldOut->getTexture() );
180  }
181  // 3: there was no texture. Add new one.
182  else if( m_outData )
183  {
184  // no new texture. Remove old one.
186  }
187 
188  m_output->updateData( m_outData );
189  }
190  else
191  {
192  if( m_outData )
193  {
194  setOutputProps();
195  }
196  }
197  }
198  else // case !dataValid
199  {
200  if( m_outData )
201  {
202  m_properties->removeProperty( m_outData->getTexture()->getProperties() );
203  m_infoProperties->removeProperty( m_outData->getTexture()->getInformationProperties() );
205  }
206  m_outData = std::shared_ptr< WDataSetScalar >();
207  m_output->updateData( m_outData );
208  }
209  }
210 
211  debugLog() << "Shutting down...";
212 
213  if( m_outData )
214  {
215  m_properties->removeProperty( m_outData->getTexture()->getProperties() );
216  m_infoProperties->removeProperty( m_outData->getTexture()->getInformationProperties() );
218  }
219 
220  debugLog() << "Finished! Good Bye!";
221 }
222 
223 std::shared_ptr< WDataSetScalar > WMImageExtractor::extract( std::size_t i ) const
224 {
225  WAssert( m_dataSet, "" );
226  WAssert( m_dataSet->getValueSet(), "" );
227  WAssert( m_dataSet->getGrid(), "" );
228 
229  if( m_dataSet->getValueSet()->order() > 1 || i >= m_dataSet->getValueSet()->dimension() )
230  {
231  return std::shared_ptr< WDataSetScalar >();
232  }
233 
234  std::shared_ptr< WGridRegular3D > grid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
235  WAssert( grid, "" );
236 
237  std::size_t dim = m_dataSet->getValueSet()->dimension();
238 
239  // TODO(reichenbach): use the new valueset function mechanism
240  switch( m_dataSet->getValueSet()->getDataType() )
241  {
242  case W_DT_FLOAT:
243  {
244  std::shared_ptr< std::vector< float > > values = std::shared_ptr< std::vector< float > >(
245  new std::vector< float >( m_dataSet->getGrid()->size() ) );
246  std::shared_ptr< WValueSet< float > > v = std::dynamic_pointer_cast< WValueSet< float > >( m_dataSet->getValueSet() );
247  WAssert( v, "" );
248  for( std::size_t k = 0; k < grid->size(); ++k )
249  {
250  ( *values )[k] = v->rawData()[ dim * k + i ];
251  }
252 
253  std::shared_ptr< WValueSet< float > > vs =
254  std::shared_ptr< WValueSet< float > >( new WValueSet< float >( 0, 1, values, W_DT_FLOAT ) );
255 
256  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
257  }
258  case W_DT_DOUBLE:
259  {
260  std::shared_ptr< std::vector< double > > values = std::shared_ptr< std::vector< double > >(
261  new std::vector< double >( m_dataSet->getGrid()->size() ) );
262  std::shared_ptr< WValueSet< double > > v = std::dynamic_pointer_cast< WValueSet< double > >( m_dataSet->getValueSet() );
263  WAssert( v, "" );
264  for( std::size_t k = 0; k < grid->size(); ++k )
265  {
266  ( *values )[k] = v->rawData()[ dim * k + i ];
267  }
268 
269  std::shared_ptr< WValueSet< double > > vs =
270  std::shared_ptr< WValueSet< double > >( new WValueSet< double >( 0, 1, values, W_DT_DOUBLE ) );
271 
272  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
273  }
274  case W_DT_UINT8:
275  {
276  std::shared_ptr< std::vector< uint8_t > > values = std::shared_ptr< std::vector< uint8_t > >(
277  new std::vector< uint8_t >( m_dataSet->getGrid()->size() ) );
278  std::shared_ptr< WValueSet< uint8_t > > v = std::dynamic_pointer_cast< WValueSet< uint8_t > >( m_dataSet->getValueSet() );
279  WAssert( v, "" );
280  for( std::size_t k = 0; k < grid->size(); ++k )
281  {
282  ( *values )[k] = v->rawData()[ dim * k + i ];
283  }
284 
285  std::shared_ptr< WValueSet< uint8_t > > vs =
286  std::shared_ptr< WValueSet< uint8_t > >( new WValueSet< uint8_t >( 0, 1, values, W_DT_UINT8 ) );
287 
288  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
289  }
290  case W_DT_UINT16:
291  {
292  std::shared_ptr< std::vector< uint16_t > > values = std::shared_ptr< std::vector< uint16_t > >(
293  new std::vector< uint16_t >( m_dataSet->getGrid()->size() ) );
294  std::shared_ptr< WValueSet< uint16_t > > v = std::dynamic_pointer_cast< WValueSet< uint16_t > >( m_dataSet->getValueSet() );
295  WAssert( v, "" );
296  for( std::size_t k = 0; k < grid->size(); ++k )
297  {
298  ( *values )[k] = v->rawData()[ dim * k + i ];
299  }
300 
301  std::shared_ptr< WValueSet< uint16_t > > vs =
302  std::shared_ptr< WValueSet< uint16_t > >( new WValueSet< uint16_t >( 0, 1, values, W_DT_UINT16 ) );
303 
304  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
305  }
306  case W_DT_UINT32:
307  {
308  std::shared_ptr< std::vector< uint32_t > > values = std::shared_ptr< std::vector< uint32_t > >(
309  new std::vector< uint32_t >( m_dataSet->getGrid()->size() ) );
310  std::shared_ptr< WValueSet< uint32_t > > v = std::dynamic_pointer_cast< WValueSet< uint32_t > >( m_dataSet->getValueSet() );
311  WAssert( v, "" );
312  for( std::size_t k = 0; k < grid->size(); ++k )
313  {
314  ( *values )[k] = v->rawData()[ dim * k + i ];
315  }
316 
317  std::shared_ptr< WValueSet< uint32_t > > vs =
318  std::shared_ptr< WValueSet< uint32_t > >( new WValueSet< uint32_t >( 0, 1, values, W_DT_UINT32 ) );
319 
320  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
321  }
322  case W_DT_INT8:
323  {
324  std::shared_ptr< std::vector< int8_t > > values = std::shared_ptr< std::vector< int8_t > >(
325  new std::vector< int8_t >( m_dataSet->getGrid()->size() ) );
326  std::shared_ptr< WValueSet< int8_t > > v = std::dynamic_pointer_cast< WValueSet< int8_t > >( m_dataSet->getValueSet() );
327  WAssert( v, "" );
328  for( std::size_t k = 0; k < grid->size(); ++k )
329  {
330  ( *values )[k] = v->rawData()[ dim * k + i ];
331  }
332 
333  std::shared_ptr< WValueSet< int8_t > > vs =
334  std::shared_ptr< WValueSet< int8_t > >( new WValueSet< int8_t >( 0, 1, values, W_DT_INT8 ) );
335 
336  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
337  }
338  case W_DT_INT16:
339  {
340  std::shared_ptr< std::vector< int16_t > > values = std::shared_ptr< std::vector< int16_t > >(
341  new std::vector< int16_t >( m_dataSet->getGrid()->size() ) );
342  std::shared_ptr< WValueSet< int16_t > > v = std::dynamic_pointer_cast< WValueSet< int16_t > >( m_dataSet->getValueSet() );
343  WAssert( v, "" );
344  for( std::size_t k = 0; k < grid->size(); ++k )
345  {
346  ( *values )[k] = v->rawData()[ dim * k + i ];
347  }
348 
349  std::shared_ptr< WValueSet< int16_t > > vs =
350  std::shared_ptr< WValueSet< int16_t > >( new WValueSet< int16_t >( 0, 1, values, W_DT_INT16 ) );
351 
352  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
353  }
354  case W_DT_SIGNED_INT:
355  {
356  std::shared_ptr< std::vector< int32_t > > values = std::shared_ptr< std::vector< int32_t > >(
357  new std::vector< int32_t >( m_dataSet->getGrid()->size() ) );
358  std::shared_ptr< WValueSet< int32_t > > v = std::dynamic_pointer_cast< WValueSet< int32_t > >( m_dataSet->getValueSet() );
359  WAssert( v, "" );
360  for( std::size_t k = 0; k < grid->size(); ++k )
361  {
362  ( *values )[k] = v->rawData()[ dim * k + i ];
363  }
364 
365  std::shared_ptr< WValueSet< int32_t > > vs =
366  std::shared_ptr< WValueSet< int32_t > >( new WValueSet< int32_t >( 0, 1, values, W_DT_SIGNED_INT ) );
367 
368  return std::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
369  }
370  default:
371  warnLog() << "Encountered unsupported data format in ImageExtractor!";
372  return std::shared_ptr< WDataSetScalar >();
373  }
374 }
375 
376 const std::string WMImageExtractor::makeImageName( std::size_t i )
377 {
378  std::stringstream s;
379  WAssert( m_dataSet, "" );
380  WAssert( m_dataSet->getValueSet(), "" );
381 
382  s << m_dataSet->getFilename() << " (" << i << " of " << m_dataSet->getValueSet()->dimension() << ")";
383  return s.str();
384 }
385 
387 {
388  if( m_outData )
389  {
390  double min = m_outData->getMin();
391  double max = m_outData->getMax();
392  float fmin = static_cast< float >( min + ( max - min ) * m_minValuePct->get( true ) * 0.01 );
393  float fmax = static_cast< float >( min + ( max - min ) * m_maxValuePct->get( true ) * 0.01 );
394 
395  m_outData->getTexture()->minimum()->set( fmin );
396  m_outData->getTexture()->scale()->set( std::max( fmax, fmin + 1.0f ) - fmin );
397  }
398 }
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 scalars as values.
static void replaceTexture(osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name="")
Replaces the specified texture with the given new one.
static void registerTexture(osg::ref_ptr< WGETexture3D > texture, std::string name="")
Register the specified texture to the colormapper.
static void deregisterTexture(osg::ref_ptr< WGETexture3D > texture)
De-register the specified texture to the colormapper.
This module extracts single images from a dataset.
void setOutputProps()
Write property values to output dataset.
virtual const char ** getXPMIcon() const
Return an icon for this module.
WPropDouble m_maxValuePct
The data value percent that maps to 1.0 in the texture.
std::shared_ptr< WModuleOutputData< WDataSetScalar > > m_output
An output connector for the output scalar dataset.
std::shared_ptr< WDataSetScalar > m_outData
This is a pointer to the current output.
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getName() const
Gives back the name of 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...
virtual const std::string getDescription() const
Gives back a description of this module.
WPropInt m_selectedImage
A property that allows selecting the number of the desired image.
WMImageExtractor()
Standard constructor.
virtual ~WMImageExtractor()
Destructor.
virtual void moduleMain()
Entry point after loading the module.
std::shared_ptr< WDataSetSingle > m_dataSet
This is a pointer to the dataset the module is currently working on.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
WPropDouble m_minValuePct
The data value percent that maps to 0.0 in the texture.
const std::string makeImageName(std::size_t i)
Create a name for the extracted image.
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_input
An input connector that accepts order 1 datasets.
virtual void activate()
Callback for m_active.
std::shared_ptr< WDataSetScalar > extract(std::size_t i) const
Extract the ith image from the dataset.
virtual void properties()
Initialize the properties for this module.
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
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
std::shared_ptr< WProperties > m_infoProperties
The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION".
Definition: WModule.h:647
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
virtual void activate()
Callback for m_active.
Definition: WModule.cpp:220
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Base Class for all value set types.
Definition: WValueSet.h:47