1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-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
//---------------------------------------------------------------------------
25
#ifndef WTHREADEDPERVOXELOPERATION_H
26
#define WTHREADEDPERVOXELOPERATION_H
31
#include <boost/array.hpp>
32
#include <boost/shared_ptr.hpp>
33
#include <boost/function.hpp>
35
#include "../common/WException.h"
36
#include "../common/WThreadedJobs.h"
37
#include "../common/WSharedObject.h"
38
#include "../common/WSharedSequenceContainer.h"
39
#include "WDataSetSingle.h"
40
#include "WDataSetScalar.h"
41
#include "WValueSet.h"
42
#include "WDataHandlerEnums.h"
44
//! forward declaration for the test
45
class WThreadedPerVoxelOperationTest;
48
* \class WThreadedPerVoxelOperation
50
* A template that performs an operation on a per voxel basis. This
51
* template is intended to be used in combination with \see WThreadedFunction.
53
* The template parameters are the internal datatype of the input datasets valueset,
54
* the number of input data elements per voxel, the type of the output data and the number of
57
* Example: Suppose one wants to calculate the largest eigenvector of a symmetric tensor of order
58
* 2 per voxel, where the input tensors are stored als 6 floats. The output could be 3 double values.
59
* The corresponding template parameters would be float, 6, double, 3.
61
* A function that converts the input values to output values needs to be given via a boost::function
62
* object. The correct 'signature' is:
64
* boost::array< Output_T, numOutputs > func( WValueSet< Value_T >::SubArray const& );
66
* The subarray will have exactly numInputs entries.
68
template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
69
class WThreadedPerVoxelOperation : public WThreadedStripingJobs< WValueSet< Value_T >, std::size_t >
71
//! the test is a friend
72
friend class WThreadedPerVoxelOperationTest;
75
typedef WThreadedStripingJobs< WValueSet< Value_T >, std::size_t > BaseType;
78
//! the input valueset's type
79
typedef WValueSet< Value_T > ValueSetType;
81
//! the output valueset's type
82
typedef WValueSet< Output_T > OutValueSetType;
84
//! the input type for the per-voxel operation
85
typedef typename ValueSetType::SubArray const TransmitType;
87
//! the output type for the per-voxel operation
88
typedef boost::array< Output_T, numOutputs > OutTransmitType;
91
typedef boost::function< OutTransmitType const ( TransmitType const& ) > FunctionType;
94
* Construct a per-voxel operation.
96
* \param dataset The input dataset.
97
* \param func The function to be evaluated per voxel.
99
WThreadedPerVoxelOperation( boost::shared_ptr< WDataSetSingle const > dataset, FunctionType func );
104
virtual ~WThreadedPerVoxelOperation();
107
* Perform the computation for a specific voxel.
109
* \param input The input dataset.
110
* \param voxelNum The voxel number to operate on.
112
virtual void compute( boost::shared_ptr< ValueSetType const > input, std::size_t voxelNum );
115
* Get the output dataset.
117
* \return The oupput dataset.
119
boost::shared_ptr< WDataSetSingle > getResult();
122
using BaseType::m_input;
125
//! a threadsafe vector (container)
126
typedef boost::shared_ptr< std::vector< Output_T > > OutputVectorType;
128
//! stores the output of the per-voxel-operation
129
OutputVectorType m_output;
131
//! the function applied to every voxel
135
boost::shared_ptr< WGrid > m_grid;
138
template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
139
WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::WThreadedPerVoxelOperation(
140
boost::shared_ptr< WDataSetSingle const > dataset,
142
: BaseType( ( dataset ? boost::shared_dynamic_cast< ValueSetType >( dataset->getValueSet() )
143
: boost::shared_ptr< ValueSetType >() ) ) // NOLINT
147
throw WException( std::string( "No input dataset." ) );
149
if( !dataset->getValueSet() )
151
throw WException( std::string( "The input dataset has no valueset." ) );
153
if( !dataset->getGrid() )
155
throw WException( std::string( "The input dataset has no grid." ) );
157
if( dataset->getValueSet()->order() > 1 )
159
throw WException( std::string( "An order of 2 or more is currently not supported." ) );
161
if( dataset->getValueSet()->dimension() != numValues )
163
throw WException( std::string( "Invalid valueset dimension." ) );
167
throw WException( std::string( "No valid function provided." ) );
172
// allocate enough memory for the output data
173
m_output = OutputVectorType( new std::vector< Output_T >( m_input->size() * numOutputs ) );
175
catch( std::exception const& e )
177
throw WException( std::string( e.what() ) );
180
m_grid = dataset->getGrid();
183
template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
184
WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::~WThreadedPerVoxelOperation()
188
template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
189
void WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::compute( boost::shared_ptr< ValueSetType const > input,
190
std::size_t voxelNum )
192
TransmitType t = input->getSubArray( voxelNum * numValues, numValues );
193
OutTransmitType o = m_func( t );
194
for( std::size_t k = 0; k < numOutputs; ++k )
196
( *m_output )[ voxelNum * numOutputs + k ] = o[ k ];
200
template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
201
boost::shared_ptr< WDataSetSingle > WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::getResult()
203
boost::shared_ptr< OutValueSetType > values;
207
values = boost::shared_ptr< OutValueSetType >( new OutValueSetType( 0, 1, m_output,
208
DataType< Output_T >::type ) );
209
return boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( values, m_grid ) );
211
values = boost::shared_ptr< OutValueSetType >( new OutValueSetType( 1, numOutputs, m_output,
212
DataType< Output_T >::type ) );
213
return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( values, m_grid ) );
217
#endif // WTHREADEDPERVOXELOPERATION_H