ISIS Core Library 0.7.2 (api 3.0.0)
|
00001 // 00002 // C++ Interface: chunk 00003 // 00004 // Description: 00005 // 00006 // 00007 // Author: Enrico Reimer<reimer@cbs.mpg.de>, (C) 2009 00008 // 00009 // Copyright: See COPYING file that comes with this distribution 00010 // 00011 // 00012 00013 #ifndef CHUNK_H 00014 #define CHUNK_H 00015 00016 #include "valuearray.hpp" 00017 #include "../CoreUtils/log.hpp" 00018 #include "../CoreUtils/propmap.hpp" 00019 #include "common.hpp" 00020 #include <string.h> 00021 #include <list> 00022 #include "ndimensional.hpp" 00023 #include "../CoreUtils/vector.hpp" 00024 00025 #include <boost/numeric/ublas/matrix.hpp> 00026 00027 namespace isis 00028 { 00029 namespace data 00030 { 00031 00032 class Chunk; 00033 00035 namespace _internal 00036 { 00037 class ChunkBase : public NDimensional<4>, public util::PropertyMap 00038 { 00039 protected: 00040 ChunkBase() {}; //do not use this 00041 public: 00042 // static const dimensions dimension[n_dims]={rowDim,columnDim,sliceDim,timeDim}; 00043 typedef isis::util::_internal::GenericReference<ChunkBase > Reference; 00044 00045 ChunkBase( size_t nrOfColumns, size_t nrOfRows, size_t nrOfSlices, size_t nrOfTimesteps ); 00046 virtual ~ChunkBase(); //needed to make it polymorphic 00047 static const char *neededProperties; 00048 }; 00049 } 00051 00053 template <typename TYPE> class VoxelOp: std::unary_function<bool, TYPE> 00054 { 00055 public: 00056 virtual bool operator()( TYPE &vox, const util::vector4<size_t> &pos ) = 0; 00057 virtual ~VoxelOp() {} 00058 }; 00059 00065 class Chunk : public _internal::ChunkBase, protected ValueArrayReference 00066 { 00067 friend class Image; 00068 friend class std::vector<Chunk>; 00069 protected: 00079 template<typename TYPE, typename D> Chunk( TYPE *src, D d, size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 ): 00080 _internal::ChunkBase( nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps ), ValueArrayReference( ValueArray<TYPE>( src, getVolume(), d ) ) {} 00081 00082 Chunk() {}; //do not use this 00083 public: 00084 00085 typedef ValueArrayBase::value_iterator iterator; 00086 typedef ValueArrayBase::const_value_iterator const_iterator; 00087 typedef iterator::reference reference; 00088 typedef const_iterator::reference const_reference; 00089 00090 Chunk( const isis::data::ValueArrayReference &src, size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1, bool fakeValid = false ); 00091 00097 template<typename TYPE> TYPE &voxel( size_t nrOfColumns, size_t nrOfRows = 0, size_t nrOfSlices = 0, size_t nrOfTimesteps = 0 ) { 00098 const size_t idx[] = {nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps}; 00099 LOG_IF( ! isInRange( idx ), Debug, isis::error ) 00100 << "Index " << util::vector4<size_t>( idx ) << " is out of range " << getSizeAsString(); 00101 ValueArray<TYPE> &ret = asValueArray<TYPE>(); 00102 return ret[getLinearIndex( idx )]; 00103 } 00104 00105 const util::ValueReference getVoxelValue( size_t nrOfColumns, size_t nrOfRows = 0, size_t nrOfSlices = 0, size_t nrOfTimesteps = 0 )const; 00106 void setVoxelValue( const util::ValueReference &val, size_t nrOfColumns, size_t nrOfRows = 0, size_t nrOfSlices = 0, size_t nrOfTimesteps = 0 ); 00107 00112 template<typename TYPE> const TYPE &voxel( size_t nrOfColumns, size_t nrOfRows = 0, size_t nrOfSlices = 0, size_t nrOfTimesteps = 0 )const { 00113 const size_t idx[] = {nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps}; 00114 00115 if ( !isInRange( idx ) ) { 00116 LOG( Debug, isis::error ) 00117 << "Index " << util::vector4<size_t>( idx ) << nrOfTimesteps 00118 << " is out of range (" << getSizeAsString() << ")"; 00119 } 00120 00121 const ValueArray<TYPE> &ret = const_cast<Chunk &>( *this ).asValueArray<TYPE>(); 00122 00123 return ret[getLinearIndex( idx )]; 00124 } 00125 00126 void copySlice( size_t thirdDimS, size_t fourthDimS, Chunk &dst, size_t thirdDimD, size_t fourthDimD ) const; 00127 00136 template <typename TYPE> size_t foreachVoxel( VoxelOp<TYPE> &op, util::vector4<size_t> offset ) { 00137 const util::vector4<size_t> imagesize = getSizeAsVector(); 00138 util::vector4<size_t> pos; 00139 TYPE *vox = &asValueArray<TYPE>()[0]; 00140 size_t ret = 0; 00141 00142 for( pos[timeDim] = 0; pos[timeDim] < imagesize[timeDim]; pos[timeDim]++ ) 00143 for( pos[sliceDim] = 0; pos[sliceDim] < imagesize[sliceDim]; pos[sliceDim]++ ) 00144 for( pos[columnDim] = 0; pos[columnDim] < imagesize[columnDim]; pos[columnDim]++ ) 00145 for( pos[rowDim] = 0; pos[rowDim] < imagesize[rowDim]; pos[rowDim]++ ) { 00146 if( op( *( vox++ ), pos + offset ) == false ) 00147 ++ret; 00148 } 00149 00150 return ret; 00151 } 00152 00158 template<typename TYPE> size_t foreachVoxel( VoxelOp<TYPE> &op ) { 00159 return foreachVoxel<TYPE>( op, util::vector4<size_t>() ); 00160 } 00161 00162 iterator begin(); 00163 iterator end(); 00164 const_iterator begin()const; 00165 const_iterator end()const; 00166 00167 ValueArrayBase &asValueArrayBase() {return operator*();} 00168 const ValueArrayBase &getValueArrayBase()const {return operator*();} 00169 00170 template<typename TYPE> ValueArray<TYPE> &asValueArray() {return asValueArrayBase().castToValueArray<TYPE>();} 00171 template<typename TYPE> const ValueArray<TYPE> getValueArray()const {return getValueArrayBase().castToValueArray<TYPE>();} 00172 00174 size_t useCount()const; 00175 00177 Chunk cloneToNew( size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 )const; 00178 00180 static Chunk createByID( short unsigned int ID, size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1, bool fakeValid = false ); 00181 00187 bool convertToType( short unsigned int ID, scaling_pair scaling = scaling_pair() ); 00188 00197 template<typename T> bool copyToMem( T *dst, size_t len, scaling_pair scaling = scaling_pair() )const { 00198 return getValueArrayBase().copyToMem<T>( dst, len, scaling ); // use copyToMem of ValueArrayBase 00199 } 00207 Chunk copyByID( unsigned short ID = 0, scaling_pair scaling = scaling_pair() )const; 00208 00210 scaling_pair getScalingTo( unsigned short typeID, autoscaleOption scaleopt = autoscale )const; 00211 scaling_pair getScalingTo( unsigned short typeID, const std::pair<util::ValueReference, util::ValueReference> &minmax, autoscaleOption scaleopt = autoscale )const; 00212 00213 size_t getBytesPerVoxel()const; 00214 std::string getTypeName()const; 00215 unsigned short getTypeID()const; 00216 template<typename T> bool is()const {return getValueArrayBase().is<T>();} 00217 00218 void copyRange( const size_t source_start[], const size_t source_end[], Chunk &dst, const size_t destination[] )const; 00219 00220 size_t compare( const Chunk &dst )const; 00221 size_t compareRange( const size_t source_start[], const size_t source_end[], const Chunk &dst, const size_t destination[] )const; 00222 00223 std::pair<util::ValueReference, util::ValueReference> getMinMax()const; 00224 00225 Chunk &operator=( const Chunk &ref ); 00226 00236 std::list<Chunk> autoSplice( uint32_t acquisitionNumberStride = 0 )const; 00237 00245 std::list<Chunk> splice( dimensions atDim )const; 00246 00259 bool transformCoords( boost::numeric::ublas::matrix<float> transform_matrix, bool transformCenterIsImageCenter = false ) { 00260 LOG_IF( !hasProperty( "rowVec" ) || !hasProperty( "columnVec" ) || !hasProperty( "sliceVec" ) 00261 || !hasProperty( "voxelSize" ) || !hasProperty( "indexOrigin" ), Debug, error ) 00262 << "Cannot do Chunk::transformCoords because of missing properties!"; 00263 00264 if( !isis::data::_internal::transformCoords( *this, getSizeAsVector(), transform_matrix, transformCenterIsImageCenter ) ) { 00265 LOG( Runtime, error ) << "Error during transforming the coords of the chunk."; 00266 return false; 00267 } 00268 00269 return true; 00270 } 00274 void swapAlong( const dimensions dim ) const; 00275 00281 util::PropertyValue &propertyValueAt( const util::PropertyMap::KeyType &key, size_t at ); 00283 const util::PropertyValue &propertyValueAt( const util::PropertyMap::KeyType &key, size_t at )const; 00284 }; 00285 00287 template<typename TYPE> class MemChunk : public Chunk 00288 { 00289 public: 00291 MemChunk( size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 ): 00292 Chunk( ValueArrayReference( ValueArray<TYPE>( nrOfColumns *nrOfRows *nrOfSlices *nrOfTimesteps ) ), nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps ) {} 00304 template<typename T> MemChunk( const T *const org, size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 ): 00305 Chunk( ValueArrayReference( ValueArray<TYPE>( nrOfColumns *nrOfRows *nrOfSlices *nrOfTimesteps ) ), nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps ) { 00306 util::checkType<T>(); 00307 asValueArrayBase().copyFromMem( org, getVolume() ); 00308 } 00310 MemChunk( const Chunk &ref ): Chunk( ref ) { 00311 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00312 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00313 } 00320 MemChunk( const Chunk &ref, const scaling_pair &scaling ): Chunk( ref ) { 00321 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00322 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID, scaling ) ); 00323 } 00324 MemChunk( const MemChunk<TYPE> &ref ): Chunk( ref ) { //this is needed, to prevent generation of default-copy constructor 00325 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00326 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00327 } 00329 MemChunk &operator=( const Chunk &ref ) { 00330 LOG_IF( useCount() > 1, Debug, warning ) 00331 << "Not overwriting current chunk memory (which is still used by " << useCount() - 1 << " other chunk(s))."; 00332 Chunk::operator=( ref ); //copy the chunk of ref 00333 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00334 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00335 return *this; 00336 } 00338 MemChunk &operator=( const MemChunk<TYPE> &ref ) { //this is needed, to prevent generation of default-copy operator 00339 return operator=( static_cast<const Chunk &>( ref ) ); 00340 } 00341 }; 00342 00343 00344 template<typename TYPE> class MemChunkNonDel : public Chunk 00345 { 00346 public: 00347 // 00349 MemChunkNonDel( size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 ): 00350 Chunk( 00351 ( TYPE * )calloc( nrOfTimesteps *nrOfSlices *nrOfRows *nrOfColumns, sizeof( TYPE ) ), 00352 typename ValueArray<TYPE>::NonDeleter(), 00353 nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps 00354 ) {} 00367 template<typename T> MemChunkNonDel( const T *const org, size_t nrOfColumns, size_t nrOfRows = 1, size_t nrOfSlices = 1, size_t nrOfTimesteps = 1 ): 00368 Chunk( 00369 ( TYPE * )malloc( sizeof( TYPE )*nrOfTimesteps *nrOfSlices *nrOfRows *nrOfColumns ), 00370 typename ValueArray<TYPE>::NonDeleter(), 00371 nrOfColumns, nrOfRows, nrOfSlices, nrOfTimesteps 00372 ) { 00373 util::checkType<T>(); 00374 asValueArrayBase().copyFromMem( org, getVolume() ); 00375 } 00377 MemChunkNonDel( const Chunk &ref ): Chunk( ref ) { 00378 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00379 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00380 } 00388 MemChunkNonDel( const Chunk &ref, const util::ValueBase &min, const util::ValueBase &max ): Chunk( ref ) { 00389 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00390 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID, min, max ) ); 00391 } 00392 MemChunkNonDel( const MemChunk<TYPE> &ref ): Chunk( ref ) { //this is needed, to prevent generation of default-copy constructor 00393 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00394 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00395 } 00397 MemChunkNonDel &operator=( const Chunk &ref ) { 00398 LOG_IF( useCount() > 1, Debug, warning ) 00399 << "Not overwriting current chunk memory (which is still used by " << useCount() - 1 << " other chunk(s))."; 00400 Chunk::operator=( ref ); //copy the chunk of ref 00401 //get rid of my ValueArray and make a new copying/converting the data of ref (use the reset-function of the scoped_ptr Chunk is made of) 00402 ValueArrayReference::operator=( ref.getValueArrayBase().copyByID( ValueArray<TYPE>::staticID ) ); 00403 return *this; 00404 } 00406 MemChunkNonDel &operator=( const MemChunkNonDel<TYPE> &ref ) { //this is needed, to prevent generation of default-copy operator 00407 return operator=( static_cast<const Chunk &>( ref ) ); 00408 } 00409 }; 00410 } 00411 } 00412 namespace std 00413 { 00415 template<typename charT, typename traits> 00416 basic_ostream<charT, traits>& operator<<( basic_ostream<charT, traits> &out, const isis::data::Chunk &s ) 00417 { 00418 return out << static_cast<const isis::util::PropertyMap &>( s ); 00419 } 00420 } 00421 #endif // CHUNK_H