ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/DataStorage/chunk.hpp

Go to the documentation of this file.
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