OpenWalnut
1.4.0
|
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