cmtkTemplateArray.h

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2011 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2752 $
00026 //
00027 //  $LastChangedDate: 2011-01-17 11:33:31 -0800 (Mon, 17 Jan 2011) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #ifndef __cmtkTemplateArray_h_included_
00034 #define __cmtkTemplateArray_h_included_
00035 
00036 #include <cmtkconfig.h>
00037 
00038 #include <Base/cmtkTypedArray.h>
00039 #include <Base/cmtkTypedArrayFunction.h>
00040 
00041 #include <System/cmtkConsole.h>
00042 
00043 namespace
00044 cmtk
00045 {
00046 
00049 
00055 template<class T>
00056 class TemplateArray : 
00058   public TypedArray
00059 {
00060 public:
00062   typedef TemplateArray<T> Self;
00063 
00065   typedef TypedArray Superclass;
00066 
00068   typedef SmartPointer<Self> SmartPtr;
00069 
00071   typedef DataTypeTraits<T> TypeTraits;
00072 
00074   static typename Self::SmartPtr Create( const size_t size )
00075   {
00076     return typename Self::SmartPtr( new Self( size ) );
00077   }
00078 
00080   const T* GetDataPtrConcrete() const { return this->Data; }
00081 
00083   T* GetDataPtrConcrete() { return this->Data; }
00084 
00086   void SetPaddingValueTemplate ( const T paddingData ) 
00087   {
00088     this->Padding = paddingData;
00089     this->PaddingFlag = true;
00090   }
00091   
00102   TemplateArray ( void *const data, const size_t datasize, const bool freeArray, const bool paddingflag, const void* paddingData ) 
00103   {
00104     m_DataType = TypeTraits::GetScalarDataType();
00105     Data = static_cast<T*>( data );
00106     DataSize = datasize;
00107     FreeArray = freeArray;
00108     PaddingFlag = paddingflag;
00109     if ( paddingData )
00110       Padding = *((T*)paddingData);
00111     else
00112       Padding = (T) 0;
00113   }
00114 
00118   TemplateArray ( const size_t datasize = 0 ) 
00119   {
00120     m_DataType = TypeTraits::GetScalarDataType();
00121     Data = NULL;
00122     this->Alloc( datasize ); 
00123   }
00124 
00128   virtual ~TemplateArray () 
00129   {    
00130     this->FreeData();
00131   }
00132   
00134   virtual void SetPaddingValue ( const Types::DataItem paddingData ) 
00135   {
00136     this->SetPaddingValueTemplate( TypeTraits::Convert( paddingData ) );
00137   }
00138 
00140   virtual void SetPaddingPtr ( const void* paddingData ) 
00141   {
00142     this->SetPaddingValueTemplate( *((T*) paddingData) );
00143   }
00144 
00146   virtual void ReplacePaddingData ( const Types::DataItem value = 0 ) 
00147   {
00148     if ( PaddingFlag ) 
00149       {
00150       T v = TypeTraits::Convert( value );
00151       for ( size_t i = 0; i < DataSize; ++i )
00152         if ( Data[i] == Padding ) 
00153           {
00154           Data[i] = v;
00155           }
00156       }
00157   }
00158   
00162   virtual bool IsPaddingAt( const size_t index ) const 
00163   {
00164     return PaddingFlag && (Data[index]==Padding);
00165   }
00166   
00169   virtual bool IsPaddingOrZeroAt( const size_t index ) const 
00170   {
00171     return (PaddingFlag && (Data[index]==Padding)) || Data[index] == (T)0;
00172   }
00173   
00174   virtual void SetPaddingAt ( const size_t index = 0 ) 
00175   {
00176     if ( !PaddingFlag ) 
00177       {
00178       Padding = TypeTraits::ChoosePaddingValue();
00179       PaddingFlag = true;
00180       }
00181     Data[index] = Padding;
00182   }
00183   
00185   virtual ScalarDataType GetType () const { return TypeTraits::GetScalarDataType(); }
00186 
00188   virtual size_t GetItemSize () const { return sizeof(T); }
00189 
00191   virtual void* GetDataPtr( const size_t offset = 0 ) 
00192   {
00193     return Data + offset; 
00194   }
00195 
00197   virtual const void* GetDataPtr( const size_t offset = 0 ) const 
00198   {
00199     return Data + offset; 
00200   }
00201   
00203   virtual T* GetDataPtrTemplate( const size_t offset = 0 ) 
00204   {
00205     return Data + offset; 
00206   }
00207   
00209   virtual const T* GetDataPtrTemplate( const size_t offset = 0 ) const 
00210   {
00211     return Data + offset; 
00212   }
00213   
00225   virtual Types::DataItem* GetSubArray( Types::DataItem *const toPtr, const size_t fromIdx , const size_t len, const Types::DataItem substPadding = 0 ) const 
00226   {
00227     int index = fromIdx;
00228     
00229     if ( PaddingFlag ) 
00230       {
00231       for ( size_t i = 0; i<len; ++i, ++index ) 
00232         {
00233         T value = Data[index];
00234         if (value == Padding)
00235           toPtr[i] = substPadding;
00236         else
00237           toPtr[i] = static_cast<Types::DataItem>( value );
00238         }
00239       } 
00240     else
00241       {
00242       for ( size_t i = 0; i<len; ++i, ++index )
00243         toPtr[i] = static_cast<Types::DataItem>( Data[index] );
00244       }
00245     return toPtr;
00246   }
00247 
00259   virtual Types::DataItem* GetSubArray( const size_t fromIdx, const size_t len, const Types::DataItem substPadding = 0 ) const 
00260   {
00261     Types::DataItem* buffer = Memory::AllocateArray<Types::DataItem>( len );
00262     return this->GetSubArray( buffer, fromIdx, len, substPadding );
00263   }
00264 
00273   virtual T ConvertItem ( const Types::DataItem value ) 
00274   {
00275     return TypeTraits::Convert( value, PaddingFlag, Padding );
00276   }
00277 
00280   virtual TypedArray::SmartPtr Convert(  const ScalarDataType dtype ) const;
00281 
00282 
00287   virtual void* ConvertSubArray( const ScalarDataType dtype, const size_t fromIdx, const size_t len ) const;
00288   
00291   virtual void ConvertSubArray( void *const destination, const ScalarDataType dtype, const size_t fromIdx, const size_t len ) 
00292     const;
00293 
00296   virtual void ChangeEndianness();
00297 
00305   virtual void Rescale( const Types::DataItem scale = 1, const Types::DataItem offset = 0 ) 
00306   {
00307 #pragma omp parallel for    
00308     for ( size_t i = 0; i < this->DataSize; ++i )
00309       if ( ! PaddingFlag || (Data[i] != Padding ) )
00310         Data[i] = TypeTraits::Convert( (scale * Data[i]) + offset );
00311   }
00312   
00317   virtual void RescaleAndShift( const Types::DataItem scale = 1, const Types::DataItem offset = 0, const size_t shiftBits = 0 ) 
00318   {
00319     const long int shiftMultiplier = (1<<shiftBits);
00320 #pragma omp parallel for    
00321     for ( size_t i = 0; i < this->DataSize; ++i )
00322       if ( ! PaddingFlag || (Data[i] != Padding ) )
00323         Data[i] = TypeTraits::Convert( ((scale * Data[i]) + offset) * shiftMultiplier );
00324   }
00325   
00339   virtual void Rescale( const Types::DataItem scale, const Types::DataItem offset, const Types::DataItem truncLo, const Types::DataItem truncHi = CMTK_ITEM_MAX ) 
00340   {
00341 #pragma omp parallel for    
00342     for ( size_t i = 0; i < this->DataSize; ++i )
00343       if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00344         {
00345         Data[i] = TypeTraits::Convert( (scale * Data[i]) + offset );
00346         if ( Data[i] < truncLo )
00347           Data[i] = TypeTraits::Convert( truncLo );
00348         else
00349           if ( Data[i] > truncHi )
00350             Data[i] = TypeTraits::Convert( truncHi );
00351         }
00352   }
00353 
00357   virtual void GammaCorrection( const Types::DataItem gamma );
00358 
00361   virtual void ApplyFunctionFloat( typename Self::FunctionTypeFloat f );
00362 
00365   virtual void ApplyFunctionDouble( typename Self::FunctionTypeDouble f );
00366 
00371   virtual void Threshold( const Types::DataItemRange& range ) 
00372   {
00373     const T lo = TypeTraits::Convert( range.m_LowerBound );
00374     const T hi = TypeTraits::Convert( range.m_UpperBound );
00375 #pragma omp parallel for    
00376     for ( size_t i = 0; i < this->DataSize; ++i )
00377       if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00378         {
00379         if ( Data[i] < lo )
00380           Data[i] = lo;
00381         else
00382           if ( Data[i] > hi )
00383             Data[i] = hi;
00384         }
00385   }
00386   
00391   virtual void ThresholdToPadding( const Types::DataItemRange& range ) 
00392   {
00393     const T lo = TypeTraits::Convert( range.m_LowerBound );
00394     const T hi = TypeTraits::Convert( range.m_UpperBound );
00395 #pragma omp parallel for    
00396     for ( size_t i = 0; i < this->DataSize; ++i )
00397       if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00398         {
00399         if ( (Data[i] < lo) || (Data[i] > hi) )
00400           Data[i] = this->Padding;
00401         }
00402   }
00403   
00408   virtual void Binarize( const Types::DataItem threshold = 0 ) 
00409   {
00410     T thresh = TypeTraits::Convert( threshold );
00411     
00412     T one = TypeTraits::Convert( 1.0 ), zero = TypeTraits::Convert( 0.0 );
00413 #pragma omp parallel for    
00414     for ( size_t i = 0; i < this->DataSize; ++i )
00415       if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00416         {
00417         if ( Data[i] > thresh )
00418           Data[i] = one;
00419         else
00420           Data[i] = zero;
00421         }
00422   }
00423   
00425   virtual void MakeAbsolute()
00426   {
00427 #pragma omp parallel for    
00428     for ( size_t i = 0; i < this->DataSize; ++i )
00429       if ( ! PaddingFlag || (Data[i] != Padding ) )
00430         Data[i] = TypeTraits::Abs( Data[i] );
00431   }
00432   
00442   virtual bool Get ( Types::DataItem& value, const size_t index ) const 
00443   {
00444     CheckBounds( index, DataSize );
00445     if (PaddingFlag && (Padding==Data[index])) 
00446       {
00447       value = 0;
00448       return false;
00449       }
00450     value = static_cast<Types::DataItem>( Data[index] );
00451     return true;
00452   }
00453 
00461   virtual void GetSequence ( Types::DataItem *const values, const size_t index, const size_t length ) const
00462   {
00463     CheckBounds( index+length-1, DataSize );
00464     for ( size_t i = 0; i < index+length; ++i )
00465       if (PaddingFlag && (Padding==Data[index]))
00466         values[i] = 0;
00467       else
00468         values[i] = static_cast<Types::DataItem>( Data[index] );
00469   }
00470 
00477   virtual void Set ( const Types::DataItem value, const size_t index ) 
00478   {
00479     CheckBounds( index, DataSize );
00480     Data[index] = this->ConvertItem( value );
00481   }
00482 
00493   virtual void* GetPaddingPtr () const { return (void*)&Padding; }
00494 
00497   virtual Types::DataItem GetPaddingValue() const { return static_cast<Types::DataItem>( Padding ); }
00498 
00500   virtual bool PaddingDataAt ( const size_t index ) const 
00501   {
00502     return PaddingFlag && (Data[index] == Padding);
00503   }
00504   
00511   virtual Types::DataItem* GetData () const 
00512   {
00513     Types::DataItem* Result = Memory::AllocateArray<Types::DataItem>( DataSize );
00514     if ( Result ) 
00515       {
00516       for ( size_t idx = 0; idx < DataSize; ++idx )
00517         Result[idx] = (Types::DataItem) Data[idx];
00518       }
00519     return Result;
00520   }
00521 
00529   virtual void SetData ( Types::DataItem *const data ) 
00530   {
00531 #pragma omp parallel for    
00532     for ( size_t idx = 0; idx < this->DataSize; ++idx )
00533       Data[idx] = this->ConvertItem( data[idx] );
00534   }
00535 
00541   virtual void ClearArray ( const bool usePaddingData = false ) 
00542   {
00543     if ( usePaddingData && PaddingFlag ) 
00544       {
00545       for ( size_t idx = 0; idx < DataSize; ++idx )
00546         Data[idx] = Padding;
00547       } 
00548     else
00549       {
00550       memset( Data, 0, sizeof( *Data ) * this->GetDataSize() );
00551       }
00552   }
00553 
00555   virtual const Types::DataItemRange GetRange() const;
00556 
00558   virtual const Types::Range<T> GetRangeTemplate() const;
00559 
00561   virtual double GetEntropy( const bool fractional = CMTK_HISTOGRAM_DISCRETE, const int numberOfBins = 128 ) const;
00562   
00563   virtual double GetEntropy( Histogram<unsigned int>& histogram ) const;
00564   virtual double GetEntropy( Histogram<double>& histogram, const bool fractional = CMTK_HISTOGRAM_DISCRETE ) const;
00565   virtual double GetEntropy( Histogram<double>& histogram, const double* kernel, const size_t kernelRadius ) const;
00566 
00572   virtual size_t GetStatistics ( Types::DataItem& mean, Types::DataItem& variance ) const;
00573 
00576   virtual void BlockSet( const Types::DataItem value, const size_t fromOffset, const size_t toOffset );
00577 
00582   virtual Histogram<unsigned int>::SmartPtr GetHistogram( const unsigned int numberOfBins ,
00583                                                           const bool centeredBins = false  ) const;
00584 
00585   virtual void ApplyFunctionObject( const TypedArrayFunction& f );
00586 
00587 protected:
00589   virtual Self* CloneVirtual() const
00590   {
00591     Self* clone = new Self( this->DataSize );
00592     memcpy( clone->Data, this->Data, this->DataSize * sizeof( T ) );
00593     clone->Padding = this->Padding;
00594     clone->PaddingFlag = this->PaddingFlag;
00595     clone->m_DataClass = this->m_DataClass;
00596     return clone;
00597   }
00598 
00599 private:
00601   T *Data;
00602 
00604   T Padding;
00605 
00609   virtual void Alloc ( const size_t datasize ) 
00610   {
00611     DataSize = datasize;
00612     if ( DataSize ) 
00613       {
00614       if ( Data ) 
00615         {
00616         Memory::DeleteArray( Data );
00617         }
00618       Data = Memory::AllocateArray<T>( DataSize );
00619       if ( Data == NULL ) 
00620         {
00621         this->DataSize = 0;
00622         }
00623       FreeArray = true;
00624       } 
00625     else
00626       {
00627       Data = NULL;
00628       FreeArray = false;
00629       }
00630   }
00631   
00636   virtual void FreeData() 
00637   {
00638     if ( Data && FreeArray ) 
00639       {
00640       Memory::DeleteArray( Data );
00641       } 
00642     Data = NULL;
00643   }
00644 };
00645 
00648 
00650 typedef TemplateArray<byte>   ByteArray;
00651 
00653 typedef TemplateArray<char>   CharArray;
00654 
00656 typedef TemplateArray<short>  ShortArray;
00657 
00659 typedef TemplateArray<unsigned short> UShortArray;
00660 
00662 typedef TemplateArray<int>    IntArray;
00663 
00665 typedef TemplateArray<float>  FloatArray;
00666 
00668 typedef TemplateArray<double> DoubleArray;
00669 
00671 
00673 
00674 } // namespace cmtk
00675 
00676 #include "cmtkTemplateArray.txx"
00677 #include "cmtkTemplateArray_Statistics.txx"
00678 
00679 #endif // #ifndef __cmtkTemplateArray_h_included_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines