OpenWalnut  1.4.0
WThreadedPerVoxelOperation.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WTHREADEDPERVOXELOPERATION_H
00026 #define WTHREADEDPERVOXELOPERATION_H
00027 
00028 #include <vector>
00029 #include <string>
00030 
00031 #include <boost/array.hpp>
00032 #include <boost/shared_ptr.hpp>
00033 #include <boost/function.hpp>
00034 
00035 #include "../common/WException.h"
00036 #include "../common/WThreadedJobs.h"
00037 #include "../common/WSharedObject.h"
00038 #include "../common/WSharedSequenceContainer.h"
00039 #include "WDataSetSingle.h"
00040 #include "WDataSetScalar.h"
00041 #include "WValueSet.h"
00042 #include "WDataHandlerEnums.h"
00043 
00044 //! forward declaration for the test
00045 class WThreadedPerVoxelOperationTest;
00046 
00047 /**
00048  * \class WThreadedPerVoxelOperation
00049  *
00050  * A template that performs an operation on a per voxel basis. This
00051  * template is intended to be used in combination with \see WThreadedFunction.
00052  *
00053  * The template parameters are the internal datatype of the input datasets valueset,
00054  * the number of input data elements per voxel, the type of the output data and the number of
00055  * outputs per voxel.
00056  *
00057  * Example: Suppose one wants to calculate the largest eigenvector of a symmetric tensor of order
00058  * 2 per voxel, where the input tensors are stored als 6 floats. The output could be 3 double values.
00059  * The corresponding template parameters would be float, 6, double, 3.
00060  *
00061  * A function that converts the input values to output values needs to be given via a boost::function
00062  * object. The correct 'signature' is:
00063  *
00064  * boost::array< Output_T, numOutputs > func( WValueSet< Value_T >::SubArray const& );
00065  *
00066  * The subarray will have exactly numInputs entries.
00067  */
00068 template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
00069 class WThreadedPerVoxelOperation : public WThreadedStripingJobs< WValueSet< Value_T >, std::size_t >
00070 {
00071     //! the test is a friend
00072     friend class WThreadedPerVoxelOperationTest;
00073 
00074     //! the base class
00075     typedef WThreadedStripingJobs< WValueSet< Value_T >, std::size_t > BaseType;
00076 
00077 public:
00078     //! the input valueset's type
00079     typedef WValueSet< Value_T > ValueSetType;
00080 
00081     //! the output valueset's type
00082     typedef WValueSet< Output_T > OutValueSetType;
00083 
00084     //! the input type for the per-voxel operation
00085     typedef typename ValueSetType::SubArray const TransmitType;
00086 
00087     //! the output type for the per-voxel operation
00088     typedef boost::array< Output_T, numOutputs > OutTransmitType;
00089 
00090     //! the function type
00091     typedef boost::function< OutTransmitType const ( TransmitType const& ) > FunctionType;
00092 
00093     /**
00094      * Construct a per-voxel operation.
00095      *
00096      * \param dataset The input dataset.
00097      * \param func The function to be evaluated per voxel.
00098      */
00099     WThreadedPerVoxelOperation( boost::shared_ptr< WDataSetSingle const > dataset, FunctionType func );
00100 
00101     /**
00102      * Destructor.
00103      */
00104     virtual ~WThreadedPerVoxelOperation();
00105 
00106     /**
00107      * Perform the computation for a specific voxel.
00108      *
00109      * \param input The input dataset.
00110      * \param voxelNum The voxel number to operate on.
00111      */
00112     virtual void compute( boost::shared_ptr< ValueSetType const > input, std::size_t voxelNum );
00113 
00114     /**
00115      * Get the output dataset.
00116      *
00117      * \return The oupput dataset.
00118      */
00119     boost::shared_ptr< WDataSetSingle > getResult();
00120 
00121 protected:
00122     using BaseType::m_input;
00123 
00124 private:
00125     //! a threadsafe vector (container)
00126     typedef boost::shared_ptr< std::vector< Output_T > > OutputVectorType;
00127 
00128     //! stores the output of the per-voxel-operation
00129     OutputVectorType m_output;
00130 
00131     //! the function applied to every voxel
00132     FunctionType m_func;
00133 
00134     //! store the grid
00135     boost::shared_ptr< WGrid > m_grid;
00136 };
00137 
00138 template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
00139 WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::WThreadedPerVoxelOperation(
00140                                                         boost::shared_ptr< WDataSetSingle const > dataset,
00141                                                         FunctionType func )
00142     : BaseType( ( dataset ? boost::dynamic_pointer_cast< ValueSetType >( dataset->getValueSet() )
00143                           : boost::shared_ptr< ValueSetType >() ) ) // NOLINT
00144 {
00145     if( !dataset )
00146     {
00147         throw WException( std::string( "No input dataset." ) );
00148     }
00149     if( !dataset->getValueSet() )
00150     {
00151         throw WException( std::string( "The input dataset has no valueset." ) );
00152     }
00153     if( !dataset->getGrid() )
00154     {
00155         throw WException( std::string( "The input dataset has no grid." ) );
00156     }
00157     if( dataset->getValueSet()->order() > 1 )
00158     {
00159         throw WException( std::string( "An order of 2 or more is currently not supported." ) );
00160     }
00161     if( dataset->getValueSet()->dimension() != numValues )
00162     {
00163         throw WException( std::string( "Invalid valueset dimension." ) );
00164     }
00165     if( !func )
00166     {
00167         throw WException( std::string( "No valid function provided." ) );
00168     }
00169 
00170     try
00171     {
00172         // allocate enough memory for the output data
00173         m_output = OutputVectorType( new std::vector< Output_T >( m_input->size() * numOutputs ) );
00174     }
00175     catch( std::exception const& e )
00176     {
00177         throw WException( std::string( e.what() ) );
00178     }
00179     m_func = func;
00180     m_grid = dataset->getGrid();
00181 }
00182 
00183 template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
00184 WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::~WThreadedPerVoxelOperation()
00185 {
00186 }
00187 
00188 template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
00189 void WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::compute( boost::shared_ptr< ValueSetType const > input,
00190                                                                std::size_t voxelNum )
00191 {
00192     TransmitType t = input->getSubArray( voxelNum * numValues, numValues );
00193     OutTransmitType o = m_func( t );
00194     for( std::size_t k = 0; k < numOutputs; ++k )
00195     {
00196         ( *m_output )[ voxelNum * numOutputs + k ] = o[ k ];
00197     }
00198 }
00199 
00200 template< typename Value_T, std::size_t numValues, typename Output_T, std::size_t numOutputs >
00201 boost::shared_ptr< WDataSetSingle > WThreadedPerVoxelOperation< Value_T, numValues, Output_T, numOutputs >::getResult()
00202 {
00203     boost::shared_ptr< OutValueSetType > values;
00204     switch( numOutputs )
00205     {
00206     case 1:
00207         values = boost::shared_ptr< OutValueSetType >( new OutValueSetType( 0, 1, m_output,
00208                                                                             DataType< Output_T >::type ) );
00209         return boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( values, m_grid ) );
00210     default:
00211         values = boost::shared_ptr< OutValueSetType >( new OutValueSetType( 1, numOutputs, m_output,
00212                                                                             DataType< Output_T >::type ) );
00213         return boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( values, m_grid ) );
00214     }
00215 }
00216 
00217 #endif  // WTHREADEDPERVOXELOPERATION_H