cmtkTemplateArray.txx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 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: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <algorithm>
00034 
00035 #ifdef HAVE_IEEEFP_H
00036 #  include <ieeefp.h>
00037 #endif
00038 
00039 #include <Base/cmtkTypedArrayFunctionHistogramMatching.h>
00040 
00041 namespace
00042 cmtk
00043 {
00044 
00047 
00048 template<class T>
00049 double
00050 TemplateArray<T>
00051 ::GetEntropy( const bool fractional, const int numberOfBins ) const 
00052 {
00053   double entropy = 0;
00054   if ( fractional ) 
00055     {
00056     Histogram<double> histogram( numberOfBins );
00057     histogram.SetRange( this->GetRange() );
00058     
00059     for ( size_t idx = 0; idx < DataSize; ++idx )
00060       if ( !PaddingFlag || (Data[idx] != Padding) )
00061         histogram.IncrementFractional( histogram.ValueToBinFractional( Data[idx] ) );
00062     entropy = histogram.GetEntropy();
00063     } 
00064   else 
00065     {
00066     Histogram<unsigned int> histogram( numberOfBins );
00067     histogram.SetRange( this->GetRange() );
00068     
00069     for ( size_t idx = 0; idx < DataSize; ++idx )
00070       if ( !PaddingFlag || (Data[idx] != Padding) )
00071         histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00072     entropy = histogram.GetEntropy();
00073     }
00074   return entropy;
00075 }
00076 
00077 template<class T> 
00078 double
00079 TemplateArray<T>
00080 ::GetEntropy( Histogram<unsigned int>& histogram ) const 
00081 {
00082   histogram.Reset();
00083   for ( size_t idx = 0; idx < DataSize; ++idx )
00084     if ( !PaddingFlag || (Data[idx] != Padding) )
00085       histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00086   return histogram.GetEntropy();
00087 }
00088 
00089 template<class T> double
00090 TemplateArray<T>
00091 ::GetEntropy( Histogram<double>& histogram, const bool fractional ) const 
00092 {
00093   histogram.Reset();
00094   if ( fractional ) 
00095     {
00096     for ( size_t idx = 0; idx < DataSize; ++idx )
00097       if ( !PaddingFlag || (Data[idx] != Padding) )
00098         histogram.IncrementFractional( histogram.ValueToBinFractional( Data[idx] ) );
00099     } 
00100   else
00101     {
00102     for ( size_t idx = 0; idx < DataSize; ++idx )
00103       if ( !PaddingFlag || (Data[idx] != Padding) )
00104         histogram.Increment( histogram.ValueToBin( Data[idx] ) );
00105     }
00106   return histogram.GetEntropy();
00107 }
00108 
00109 template<class T> double
00110 TemplateArray<T>
00111 ::GetEntropy( Histogram<double>& histogram, const double* kernel, const size_t kernelRadius  ) const 
00112 {
00113   histogram.Reset();
00114   for ( size_t idx = 0; idx < DataSize; ++idx )
00115     if ( !PaddingFlag || (Data[idx] != Padding) )
00116       histogram.AddWeightedSymmetricKernelFractional( histogram.ValueToBinFractional( Data[idx] ), kernelRadius, kernel );
00117   return histogram.GetEntropy();
00118 }
00119 
00120 template<class T>
00121 const Types::DataItemRange
00122 TemplateArray<T>
00123 ::GetRange() const 
00124 {
00125   return Types::DataItemRange( this->GetRangeTemplate() );
00126 }
00127 
00128 template<class T> 
00129 const Types::Range<T>
00130 TemplateArray<T>
00131 ::GetRangeTemplate() 
00132   const 
00133 {
00134   Types::Range<T> range( 0, 0 );
00135   
00136   // find first finite and non-Padding element
00137   size_t idx = 0;
00138   if ( PaddingFlag )
00139     {
00140     while ( (idx < DataSize) && ((Data[idx] == Padding) || !finite(Data[idx])) ) 
00141       ++idx;
00142     }
00143   else
00144     {
00145     while ( (idx < DataSize) && !finite(Data[idx]) ) 
00146       ++idx;
00147     }
00148   
00149   // didn't find any? return with error flag.
00150   if ( idx < DataSize) 
00151     {
00152     // otherwise: search for min/max from here
00153     range.m_LowerBound = range.m_UpperBound = Data[idx];
00154 
00155     if ( PaddingFlag ) 
00156       {
00157       for ( ; idx < DataSize; ++idx ) 
00158         {
00159         if ( (Data[idx] != Padding) && finite(Data[idx]) ) 
00160           {
00161           if (Data[idx] > range.m_UpperBound) 
00162             range.m_UpperBound = Data[idx];
00163           if (Data[idx] < range.m_LowerBound) 
00164             range.m_LowerBound = Data[idx];
00165           }
00166         }
00167       } 
00168     else
00169       {
00170       for ( ; idx < DataSize; ++idx ) 
00171         {
00172         if ( finite(Data[idx]) )
00173           {
00174           if (Data[idx] > range.m_UpperBound) 
00175             range.m_UpperBound = Data[idx];
00176           if (Data[idx] < range.m_LowerBound) 
00177             range.m_LowerBound = Data[idx];
00178           }
00179         }
00180       }
00181     }
00182 
00183   return range;
00184 }
00185 
00189 template<class T>
00190 TypedArray::SmartPtr
00191 TemplateArray<T>
00192 ::Convert( const ScalarDataType dtype ) const 
00193 {
00194   void* data = this->ConvertArray( dtype );
00195   return TypedArray::Create( dtype, data, DataSize, true /* freeArray */ );
00196 }
00197 
00198 template<class T>
00199 void*
00200 TemplateArray<T>
00201 ::ConvertSubArray 
00202 ( const ScalarDataType dtype, const size_t fromIdx, const size_t len ) const 
00203 {
00204   void* data = Memory::AllocateArray<char>( len * TypeItemSize( dtype ) );
00205   this->ConvertSubArray( data, dtype, fromIdx, len );
00206   return data;
00207 }
00208 
00209 template<class T>
00210 void
00211 TemplateArray<T>
00212 ::GammaCorrection( const Types::DataItem gamma )
00213 {
00214   if ( gamma > 0 ) 
00215     {
00216     Types::Range<T> range = this->GetRangeTemplate();
00217     
00218     const T diff = range.m_UpperBound - range.m_LowerBound;
00219     const double scale = 1.0 / diff;
00220     
00221 #pragma omp parallel for if (DataSize>1e5)
00222     for ( size_t i = 0; i < DataSize; ++i )
00223       if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00224         {
00225         if ( Data[i] > range.m_LowerBound ) 
00226           {
00227           Data[i] = range.m_LowerBound + TypeTraits::Convert( diff * exp( log( scale * (Data[i]-range.m_LowerBound) ) / gamma ) );
00228           }
00229         }
00230     }
00231 }
00232 
00233 template<class T>
00234 void
00235 TemplateArray<T>
00236 ::ApplyFunctionFloat( typename Self::FunctionTypeFloat f )
00237 {
00238 #pragma omp parallel for if (DataSize>1e5)
00239   for ( size_t i = 0; i < DataSize; ++i )
00240     if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00241       {
00242       Data[i] = TypeTraits::Convert( f( (float)Data[i] ) );
00243       }
00244 }
00245 
00246 template<class T>
00247 void
00248 TemplateArray<T>
00249 ::ApplyFunctionDouble( typename Self::FunctionTypeDouble f )
00250 {
00251 #pragma omp parallel for if (DataSize>1e5)
00252   for ( size_t i = 0; i < DataSize; ++i )
00253     if ( ! PaddingFlag || (Data[i] != Padding ) ) 
00254       {
00255       Data[i] = TypeTraits::Convert( f( (double)Data[i] ) );
00256       }
00257 }
00258 
00259 template<class T>
00260 void TemplateArray<T>
00261 ::ConvertSubArray 
00262 ( void *const destination, const ScalarDataType dtype, const size_t fromIdx, const size_t len ) const 
00263 {
00264   if ( dtype == this->GetType() )
00265     memcpy( destination, Data + fromIdx, len * this->GetItemSize() );
00266   else 
00267     {
00268     switch ( dtype ) 
00269       {
00270       case TYPE_BYTE:
00271 #pragma omp parallel for if (len>1e5)
00272         for ( size_t idx = 0; idx < len; ++idx )
00273           ((byte*)destination)[idx] = DataTypeTraits<byte>::Convert( Data[ idx + fromIdx ] );
00274         break;
00275       case TYPE_CHAR:
00276 #pragma omp parallel for if (len>1e5)
00277         for ( size_t idx = 0; idx < len; ++idx )
00278           ((char*)destination)[idx] = DataTypeTraits<char>::Convert( Data[ idx + fromIdx ] );
00279         break;
00280       case TYPE_USHORT:
00281 #pragma omp parallel for if (len>1e5)
00282         for ( size_t idx = 0; idx < len; ++idx )
00283           ((unsigned short*)destination)[idx] = DataTypeTraits<unsigned short>::Convert( Data[ idx + fromIdx ] );
00284         break;
00285       case TYPE_SHORT:
00286 #pragma omp parallel for if (len>1e5)
00287         for ( size_t idx = 0; idx < len; ++idx )
00288           ((short*)destination)[idx] = DataTypeTraits<short>::Convert( Data[ idx + fromIdx ] );
00289         break;
00290       case TYPE_INT:
00291 #pragma omp parallel for if (len>1e5)
00292         for ( size_t idx = 0; idx < len; ++idx )
00293           ((int*)destination)[idx] = DataTypeTraits<int>::Convert( Data[ idx + fromIdx ] );
00294         break;
00295       case TYPE_FLOAT:
00296 #pragma omp parallel for if (len>1e5)
00297         for ( size_t idx = 0; idx < len; ++idx )
00298           ((float*)destination)[idx] = DataTypeTraits<float>::Convert( Data[ idx + fromIdx ] );
00299         break;
00300       case TYPE_DOUBLE:
00301 #pragma omp parallel for if (len>1e5)
00302         for ( size_t idx = 0; idx < len; ++idx )
00303           ((double*)destination)[idx] = DataTypeTraits<double>::Convert( Data[ idx + fromIdx ] );
00304         break;
00305       default:
00306         // unsupported / unknown data type. do nothing.
00307         break;
00308       }
00309     }
00310 }
00311 
00312 template<class T>
00313 void
00314 TemplateArray<T>
00315 ::ChangeEndianness() 
00316 {
00317   size_t itemSize = this->GetItemSize();
00318   if ( itemSize < 2 ) return;
00319   size_t dataBytes = DataSize * itemSize;
00320 
00321   // f is the index of the FIRST byte of the current data item, l is the
00322   // index of that items LAST byte.
00323   size_t f, l;
00324   for ( f=0, l=itemSize-1; f<dataBytes; f+=itemSize,l+=itemSize )
00325     for ( size_t j=0; j<itemSize/2; ++j ) 
00326       {
00327       char d = ((char*)Data)[l-j];
00328       ((char*)Data)[l-j] = ((char*)Data)[f+j];
00329       ((char*)Data)[f+j] = d;
00330       }
00331 }
00332 
00333 template<class T>
00334 void
00335 TemplateArray<T>
00336 ::ApplyFunctionObject( const TypedArrayFunction& f )
00337 {
00338 #pragma omp parallel for
00339   for ( size_t i = 0; i < this->DataSize; ++i )
00340     {
00341     if ( !this->PaddingFlag || (this->Data[i] != this->Padding) )
00342       this->Data[i] = static_cast<T>( f( this->Data[i] ) );
00343     }
00344 }
00345 
00346 template<class T>
00347 void 
00348 TemplateArray<T>
00349 ::BlockSet
00350 ( const Types::DataItem value, const size_t fromOffset, const size_t toOffset )
00351 {
00352   T valueT = TypeTraits::Convert( value );
00353 
00354 #pragma omp parallel for    
00355   for ( size_t i = fromOffset; i < toOffset; ++i )
00356     Data[i] = valueT;
00357 }
00358 
00359 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines