00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 }
00675
00676 #include "cmtkTemplateArray.txx"
00677 #include "cmtkTemplateArray_Statistics.txx"
00678
00679 #endif // #ifndef __cmtkTemplateArray_h_included_