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 #include "cmtkTypedArrayNoiseEstimatorBrummer.h"
00032
00033 namespace
00034 cmtk
00035 {
00036
00037
00038
00039
00040 TypedArrayNoiseEstimatorBrummer::TypedArrayNoiseEstimatorBrummer
00041 ( const TypedArray* data, const size_t histogramBins )
00042 {
00043 UNUSED(histogramBins);
00044
00045 const size_t histogramBinsActual = 255;
00046 Histogram<unsigned int>::SmartPtr histogram( data->GetHistogram( histogramBinsActual ) );
00047
00048
00049
00050 double sampleMean = 0;
00051 for ( size_t i = 0; i < histogramBinsActual; i++ )
00052 {
00053 sampleMean += (*histogram)[i] * histogram->BinToValue(i);
00054 }
00055 sampleMean /= histogram->SampleCount();
00056 std::cout << " sampleMean: " << sampleMean << std::endl;
00057 std::cout << " sampleCount: " << histogram->SampleCount() << std::endl;
00058 std::cout << " 1 / sampleCount: " << (1.0 / histogram->SampleCount()) << std::endl;
00059
00060 double sumSquaredSampleDiffs = 0;
00061 for ( size_t i = 0; i < histogramBinsActual; i++ )
00062 {
00063 sumSquaredSampleDiffs += (*histogram)[i] * pow( ( histogram->BinToValue(i) - sampleMean ), 2 );
00064 }
00065 std::cout << " sumSquaredSampleDiffs: " << sumSquaredSampleDiffs << std::endl;
00066
00067 const double sampleStdDev = sqrt( ( 1.0 / histogram->SampleCount() ) * sumSquaredSampleDiffs );
00068 std::cout << " sampleStdDev: " << sampleStdDev << std::endl;
00069 std::cout << " npow: " << pow( (double)histogram->SampleCount(), 1/5 ) << std::endl;
00070
00071
00072
00073
00074
00075 const double changH = 1.0 / ( 1.06 * sampleStdDev * pow( (double)histogram->SampleCount(), 1/5 ) );
00076 double changSigma = 0;
00077 double sigmaUpperBound = 100;
00078 double valueToMaximize = std::numeric_limits<double>::min();
00079 for ( double maybeChangSigma = 1.0; maybeChangSigma < sigmaUpperBound; maybeChangSigma += 1.5 )
00080 {
00081
00082 double changSum = 0;
00083 for ( size_t i = 0; i < histogramBinsActual; i++ )
00084 {
00085 const double valToAdd = ( (*histogram)[i]
00086 * ( 1.0 / sqrt(2.0 * M_PI) )
00087 * exp( ( -1.0 * log( pow( (double)( maybeChangSigma - histogram->BinToValue(i) ) / changH, 2 )
00088 / 2.0) ) ) );
00089 changSum += valToAdd;
00090
00091 }
00092
00093 std::cout << " changSum: " << changSum << std::endl;
00094
00095 double curValueToMaximize = ( 1.0 / ( histogram->SampleCount() * changH ) ) * changSum;
00096
00097 std::cout << " curValueToMaximize: " << curValueToMaximize << std::endl;
00098
00099 if ( curValueToMaximize > valueToMaximize )
00100 {
00101 valueToMaximize = curValueToMaximize;
00102 changSigma = maybeChangSigma;
00103 std::cout << "New max: " << curValueToMaximize << " New changSigma: " << changSigma << std::endl;
00104 }
00105
00106 }
00107
00108
00109
00110
00111 valueToMaximize = std::numeric_limits<double>::min();
00112 double sigma0 = changSigma;
00113
00114 double maxAmplitude = 2000;
00115 double brummerSigma = changSigma;
00116 for ( double maybeSigma = 0; maybeSigma < histogramBinsActual; maybeSigma += 1.0 )
00117 {
00118 for ( double maybeAmplitude = 0; maybeAmplitude < maxAmplitude; maybeAmplitude += 10.0 )
00119 {
00120 double brummerSum = 0;
00121 for ( int i = 0; i <= 2 * sigma0; i++ )
00122 {
00123 brummerSum += log( pow( (double)(*histogram)[i]
00124 - maybeAmplitude
00125 * ( histogram->BinToValue(i) / pow( maybeSigma, 2) )
00126 * exp( -1 * ( pow( (double)histogram->BinToValue(i),2) / (2 * pow( maybeSigma, 2 ) ) ) )
00127 , 2 ) );
00128 }
00129 std::cout << " sigma: " << maybeSigma << " K: " << maybeAmplitude << " brummerSum: " << brummerSum << std::endl;
00130 if ( brummerSum > valueToMaximize )
00131 {
00132 valueToMaximize = brummerSum;
00133 brummerSigma = maybeSigma;
00134 std::cout << "new valueToMaximize: " << valueToMaximize << std::endl;
00135 std::cout << "new brummerSigma: " << brummerSigma << std::endl;
00136 }
00137 }
00138 }
00139 std::cerr << brummerSigma << std::endl;
00140
00141
00142 this->m_NoiseLevelSigma = static_cast<Types::DataItem>( 0 );
00143 }
00144
00145 double
00146 TypedArrayNoiseEstimatorBrummer::SijbersBiasHat
00147 ( const Histogram<unsigned int>::SmartPtr histogram, const double sigmaHat, const int numBinsToUse )
00148 {
00149
00150 double K = numBinsToUse;
00151
00152
00153
00154
00155
00156 int partialHistCount = 0;
00157 for ( int i = 0; i < K; i++ )
00158 {
00159 partialHistCount += (*histogram)[i];
00160 }
00161
00162
00163
00164
00165 const double twoSigmaSquared = 2 * sigmaHat * sigmaHat;
00166 const double denom =
00167 exp( -1 * ( log( (double)pow( histogram->BinToValue( 0 ), 2 ) / twoSigmaSquared ) ) )
00168 - exp( -1 * ( log( (double)pow( histogram->BinToValue( K ), 2 ) / twoSigmaSquared ) ) ) ;
00169
00170 assert ( denom != 0 );
00171
00172
00173
00174
00175
00176
00177
00178 double lambdaStar = 0.0;
00179 for ( int i = 1; i < K; i++ )
00180 {
00181 const double quotient =
00182 ( exp( -1 * ( log( (double)pow( histogram->BinToValue(i-1), 2 ) ) ) / twoSigmaSquared )
00183 - exp( -1 * ( log( pow( (double)histogram->BinToValue( i ), 2 ) ) ) / twoSigmaSquared ) )
00184 / denom;
00185 const double f = partialHistCount * quotient;
00186 assert ( f != 0 );
00187 lambdaStar += pow( f - (*histogram)[i], 2 ) / f;
00188 }
00189
00190
00191
00192
00193 for ( size_t i = static_cast<size_t>( K ); i < histogram->GetNumBins(); i++ )
00194 {
00195 const double quotient =
00196 ( exp( -1 * ( log( pow( (double)histogram->BinToValue(i-1), 2 ) ) ) / twoSigmaSquared )
00197 - exp( -1 * ( log( pow( (double)histogram->BinToValue( i ), 2 ) ) ) / twoSigmaSquared ) )
00198 / denom;
00199 const double f = partialHistCount * quotient;
00200 double numerator = ( f - (*histogram)[i] );
00201 if ( numerator < 0 ) numerator = 0 ;
00202 assert ( f != 0 );
00203 lambdaStar += pow( numerator, 2 ) / f;
00204
00205 }
00206
00207
00208
00209
00210 int M = 0;
00211 for ( size_t i = static_cast<size_t>( K ); i < histogram->GetNumBins(); i++ )
00212 {
00213 const double quotient =
00214 ( exp( -1 * ( log( pow( (double)histogram->BinToValue(i-1), 2 ) ) / twoSigmaSquared ) )
00215 - exp( -1 * ( log( pow( (double)histogram->BinToValue( i ), 2 ) ) / twoSigmaSquared ) ) )
00216 / denom;
00217 const double f = partialHistCount * quotient;
00218 const double applyStepFilterTo = ( f - (*histogram)[i] );
00219 M += ( applyStepFilterTo >= 0 ) ? 1 : 0;
00220 }
00221
00222
00223
00224
00225
00226
00227 const double biasHat = ( lambdaStar - ( K - 2 + M ) )
00228 / sqrt( K - 2 + M );
00229 std::cout << "biasHat: " << biasHat << std::endl;
00230
00231
00232 return 0;
00233 }
00234
00235 double
00236 TypedArrayNoiseEstimatorBrummer::SijbersLogLikelihood
00237 ( const Histogram<unsigned int>::SmartPtr histogram, const double sigma, const int numBinsToUse )
00238 {
00239
00240 double s2 = 2 * sigma * sigma;
00241 int K = numBinsToUse;
00242
00243 double logLikelihood = 0.0;
00244 for ( int i = 0; i < K; i++ )
00245 {
00246 const double curCount = (*histogram)[i];
00247 const double quotient =
00248 ( exp( -1 * ( log( pow( (double)histogram->BinToValue(i-1), 2 ) ) / s2 ) )
00249 - exp( -1 * ( log( pow( (double)histogram->BinToValue( i ), 2 ) ) / s2 ) ) )
00250 /
00251 ( exp( -1 * ( log( pow( (double)histogram->BinToValue( 0 ), 2 ) ) / s2 ) )
00252 - exp( -1 * ( log( pow( (double)histogram->BinToValue( K ), 2 ) ) / s2 ) ) );
00253
00254 std::cout << exp( -1 * ( log( pow( histogram->BinToValue(i-1), 2 ) ) / s2 ) ) << std::endl;
00255 std::cout << exp( -1 * ( log( pow( histogram->BinToValue( i ), 2 ) ) / s2 ) ) << std::endl;
00256 std::cout << exp( -1 * ( log( pow( histogram->BinToValue( 0 ), 2 ) ) / s2 ) ) << std::endl;
00257 std::cout << exp( -1 * ( log( pow( histogram->BinToValue( K ), 2 ) ) / s2 ) ) << std::endl;
00258
00259 logLikelihood += curCount * quotient;
00260 }
00261 return logLikelihood;
00262 }
00263
00264 double
00265 TypedArrayNoiseEstimatorBrummer::SijbersVarHat
00266 ( const Histogram<unsigned int>::SmartPtr histogram, const double sigmaHat, const int numBinsToUse )
00267 {
00268
00269 double h = 0.01;
00270
00271 const double fXminusH = SijbersLogLikelihood( histogram, sigmaHat - h, numBinsToUse );
00272 const double fX = SijbersLogLikelihood( histogram, sigmaHat, numBinsToUse );
00273 const double fXplusH = SijbersLogLikelihood( histogram, sigmaHat + h, numBinsToUse );
00274
00275 std::cout << "fXminusH: " << fXminusH << std::endl;
00276 std::cout << "fX: " << fX << std::endl;
00277 std::cout << "fXplusH: " << fXplusH << std::endl;
00278
00279 const double secondDerivOfLogLikelihood = ( fXminusH - 2 * fX + fXplusH ) / ( h * h );
00280
00281 const double varHat = -1.0 * 1 / secondDerivOfLogLikelihood;
00282 std::cout << "varHat: " << varHat << std::endl;
00283
00284 return 0;
00285 }
00286
00287 double
00288 TypedArrayNoiseEstimatorBrummer::EstimateNumBinsToUse
00289 ( const TypedArray* data, const Histogram<unsigned int>::SmartPtr histogram, const double sigmaHat )
00290 {
00291 UNUSED(data);
00292
00293 double bestK = 0;
00294 double curKMinimizer;
00295 double minKMinimizer = std::numeric_limits<double>::max();
00296
00297 double maxK = histogram->GetNumBins() / 2;
00298
00299 for ( int curK = 1; curK < maxK; curK++ )
00300 {
00301 curKMinimizer = SijbersBiasHat( histogram, sigmaHat, curK )+ SijbersVarHat( histogram, sigmaHat, curK );
00302
00303
00304 if ( curKMinimizer < minKMinimizer )
00305 {
00306 minKMinimizer = curKMinimizer;
00307 bestK = curK;
00308 }
00309 }
00310
00311
00312
00313 return bestK;
00314 }
00315
00316 }