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
00034
00035 #ifndef OPENMS_TRANSFORMATIONS_FEATUREFINDER_EGHTRACEFITTER_H
00036 #define OPENMS_TRANSFORMATIONS_FEATUREFINDER_EGHTRACEFITTER_H
00037
00038 #include <sstream>
00039 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmPickedHelperStructs.h>
00040 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/TraceFitter.h>
00041
00042 namespace OpenMS
00043 {
00044
00057 template <class PeakType>
00058 class EGHTraceFitter :
00059 public TraceFitter<PeakType>
00060 {
00061 public:
00062 EGHTraceFitter()
00063 {
00064
00065 }
00066
00067 EGHTraceFitter(const EGHTraceFitter & other) :
00068 TraceFitter<PeakType>(other)
00069 {
00070 this->height_ = other.height_;
00071 this->apex_rt_ = other.apex_rt_;
00072 this->sigma_square_ = other.sigma_square_;
00073 this->tau_ = other.tau_;
00074
00075 this->sigma_5_bound_ = other.sigma_5_bound_;
00076 this->fwhm_bound_ = other.fwhm_bound_;
00077
00078 updateMembers_();
00079 }
00080
00081 EGHTraceFitter & operator=(const EGHTraceFitter & source)
00082 {
00083 TraceFitter<PeakType>::operator=(source);
00084
00085 this->height_ = source.height_;
00086 this->apex_rt_ = source.apex_rt_;
00087 this->sigma_square_ = source.sigma_square_;
00088 this->tau_ = source.tau_;
00089
00090 this->sigma_5_bound_ = source.sigma_5_bound_;
00091 this->fwhm_bound_ = source.fwhm_bound_;
00092
00093 updateMembers_();
00094
00095 return *this;
00096 }
00097
00098 virtual ~EGHTraceFitter()
00099 {
00100 }
00101
00102
00103 void fit(FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> & traces)
00104 {
00105 setInitialParameters_(traces);
00106
00107 double x_init[NUM_PARAMS_] = {height_, apex_rt_, sigma_square_, tau_};
00108
00109 Size num_params = NUM_PARAMS_;
00110
00111 TraceFitter<PeakType>::optimize_(traces, num_params, x_init,
00112 &(EGHTraceFitter<PeakType>::residual_),
00113 &(EGHTraceFitter<PeakType>::jacobian_),
00114 &(EGHTraceFitter<PeakType>::evaluate_));
00115 }
00116
00117 DoubleReal getLowerRTBound() const
00118 {
00119 return sigma_5_bound_.first;
00120 }
00121
00122 DoubleReal getTau() const
00123 {
00124 return tau_;
00125 }
00126
00127 DoubleReal getUpperRTBound() const
00128 {
00129 return sigma_5_bound_.second;
00130 }
00131
00132 DoubleReal getHeight() const
00133 {
00134 return height_;
00135 }
00136
00137 DoubleReal getSigmaSquare() const
00138 {
00139 return sigma_square_;
00140 }
00141
00142 DoubleReal getCenter() const
00143 {
00144 return apex_rt_;
00145 }
00146
00147 bool checkMaximalRTSpan(const DoubleReal max_rt_span)
00148 {
00149 return (sigma_5_bound_.second - sigma_5_bound_.first) > max_rt_span * region_rt_span_;
00150 }
00151
00152 virtual bool checkMinimalRTSpan(const std::pair<DoubleReal, DoubleReal> & rt_bounds, const DoubleReal min_rt_span)
00153 {
00154 return (rt_bounds.second - rt_bounds.first) < min_rt_span * (sigma_5_bound_.second - sigma_5_bound_.first);
00155 }
00156
00157 DoubleReal computeTheoretical(const FeatureFinderAlgorithmPickedHelperStructs::MassTrace<PeakType> & trace, Size k)
00158 {
00159 double rt = trace.peaks[k].first;
00160 double t_diff, t_diff2, denominator = 0.0;
00161 double fegh = 0.0;
00162
00163 t_diff = rt - apex_rt_;
00164 t_diff2 = t_diff * t_diff;
00165
00166 denominator = 2 * sigma_square_ + tau_ * t_diff;
00167
00168 if (denominator > 0.0)
00169 {
00170 fegh = trace.theoretical_int * height_ * exp(-t_diff2 / denominator);
00171 }
00172
00173 return fegh;
00174 }
00175
00176 virtual DoubleReal getFeatureIntensityContribution()
00177 {
00178 return height_ * (fwhm_bound_.second - fwhm_bound_.first);
00179 }
00180
00181 DoubleReal getFWHM() const
00182 {
00183
00184 std::pair<DoubleReal, DoubleReal> bounds = getAlphaBoundaries_(0.5);
00185 return bounds.second - bounds.first;
00186 }
00187
00188 virtual String getGnuplotFormula(FeatureFinderAlgorithmPickedHelperStructs::MassTrace<PeakType> const & trace, const char function_name, const DoubleReal baseline, const DoubleReal rt_shift)
00189 {
00190 std::stringstream s;
00191 s << String(function_name) << "(x)= " << baseline << " + ";
00192 s << "(";
00193 s << "((" << 2 * sigma_square_ << " + " << tau_ << " * (x - " << (rt_shift + apex_rt_) << " )) > 0) ? ";
00194 s << (trace.theoretical_int * height_) << " * exp(-1 * (x - " << (rt_shift + apex_rt_) << ")**2 " <<
00195 "/" <<
00196 " ( " << 2 * sigma_square_ << " + " << tau_ << " * (x - " << (rt_shift + apex_rt_) << " )))";
00197 s << " : 0)";
00198 return String(s.str());
00199 }
00200
00201 protected:
00202 DoubleReal apex_rt_;
00203 DoubleReal height_;
00204
00205 DoubleReal sigma_square_;
00206 DoubleReal tau_;
00207
00208 std::pair<DoubleReal, DoubleReal> sigma_5_bound_;
00209 std::pair<DoubleReal, DoubleReal> fwhm_bound_;
00210
00211 DoubleReal region_rt_span_;
00212
00213 static const Size NUM_PARAMS_ = 4;
00214
00220 std::pair<DoubleReal, DoubleReal> getAlphaBoundaries_(const DoubleReal alpha) const
00221 {
00222 std::pair<DoubleReal, DoubleReal> bounds;
00223 DoubleReal L = log(alpha);
00224 DoubleReal s = sqrt(
00225 ((L * tau_) * (L * tau_) / 4) - 2 * L * sigma_square_
00226 );
00227
00228 DoubleReal s1, s2;
00229 s1 = (-1 * (L * tau_) / 2) + s;
00230 s2 = (-1 * (L * tau_) / 2) - s;
00231
00232
00233 bounds.first = apex_rt_ + std::min(s1, s2);
00234
00235 bounds.second = apex_rt_ + std::max(s1, s2);
00236
00237 return bounds;
00238 }
00239
00240 void getOptimizedParameters_(gsl_multifit_fdfsolver * fdfsolver)
00241 {
00242 height_ = gsl_vector_get(fdfsolver->x, 0);
00243 apex_rt_ = gsl_vector_get(fdfsolver->x, 1);
00244 sigma_square_ = gsl_vector_get(fdfsolver->x, 2);
00245 tau_ = gsl_vector_get(fdfsolver->x, 3);
00246
00247
00248
00249 sigma_5_bound_ = getAlphaBoundaries_(0.043937);
00250
00251 fwhm_bound_ = getAlphaBoundaries_(0.45783);
00252 }
00253
00254 static Int residual_(const gsl_vector * param, void * data, gsl_vector * f)
00255 {
00256 FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> * traces = static_cast<FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> *>(data);
00257
00258 double H = gsl_vector_get(param, 0);
00259 double tR = gsl_vector_get(param, 1);
00260 double sigma_square = gsl_vector_get(param, 2);
00261 double tau = gsl_vector_get(param, 3);
00262
00263 double t_diff, t_diff2, denominator = 0.0;
00264
00265 double fegh = 0.0;
00266
00267 UInt count = 0;
00268 for (Size t = 0; t < traces->size(); ++t)
00269 {
00270 FeatureFinderAlgorithmPickedHelperStructs::MassTrace<PeakType> & trace = traces->at(t);
00271 for (Size i = 0; i < trace.peaks.size(); ++i)
00272 {
00273 DoubleReal rt = trace.peaks[i].first;
00274
00275 t_diff = rt - tR;
00276 t_diff2 = t_diff * t_diff;
00277
00278 denominator = 2 * sigma_square + tau * t_diff;
00279
00280 if (denominator > 0.0)
00281 {
00282 fegh = traces->baseline + trace.theoretical_int * H * exp(-t_diff2 / denominator);
00283 }
00284 else
00285 {
00286 fegh = 0.0;
00287 }
00288
00289 gsl_vector_set(f, count, (fegh - trace.peaks[i].second->getIntensity()));
00290 ++count;
00291 }
00292 }
00293 return GSL_SUCCESS;
00294 }
00295
00296 static Int jacobian_(const gsl_vector * param, void * data, gsl_matrix * J)
00297 {
00298 FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> * traces = static_cast<FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> *>(data);
00299
00300 double H = gsl_vector_get(param, 0);
00301 double tR = gsl_vector_get(param, 1);
00302 double sigma_square = gsl_vector_get(param, 2);
00303 double tau = gsl_vector_get(param, 3);
00304
00305 double derivative_H, derivative_tR, derivative_sigma_square, derivative_tau = 0.0;
00306 double t_diff, t_diff2, exp1, denominator = 0.0;
00307
00308 UInt count = 0;
00309 for (Size t = 0; t < traces->size(); ++t)
00310 {
00311 FeatureFinderAlgorithmPickedHelperStructs::MassTrace<PeakType> & trace = traces->at(t);
00312 for (Size i = 0; i < trace.peaks.size(); ++i)
00313 {
00314 DoubleReal rt = trace.peaks[i].first;
00315
00316 t_diff = rt - tR;
00317 t_diff2 = t_diff * t_diff;
00318
00319 denominator = 2 * sigma_square + tau * t_diff;
00320
00321 if (denominator > 0)
00322 {
00323 exp1 = exp(-t_diff2 / denominator);
00324
00325
00326 derivative_H = trace.theoretical_int * exp1;
00327
00328
00329 derivative_tR = trace.theoretical_int * H * exp1 * (((4 * sigma_square + tau * t_diff) * t_diff) / (denominator * denominator));
00330
00331
00332 derivative_sigma_square = trace.theoretical_int * H * exp1 * ((2 * t_diff2) / (denominator * denominator));
00333
00334
00335 derivative_tau = trace.theoretical_int * H * exp1 * ((t_diff * t_diff2) / (denominator * denominator));
00336 }
00337 else
00338 {
00339 derivative_H = 0.0;
00340 derivative_tR = 0.0;
00341 derivative_sigma_square = 0.0;
00342 derivative_tau = 0.0;
00343 }
00344
00345
00346 gsl_matrix_set(J, count, 0, derivative_H);
00347 gsl_matrix_set(J, count, 1, derivative_tR);
00348 gsl_matrix_set(J, count, 2, derivative_sigma_square);
00349 gsl_matrix_set(J, count, 3, derivative_tau);
00350
00351 ++count;
00352 }
00353 }
00354 return GSL_SUCCESS;
00355 }
00356
00357 static Int evaluate_(const gsl_vector * param, void * data, gsl_vector * f, gsl_matrix * J)
00358 {
00359 residual_(param, data, f);
00360 jacobian_(param, data, J);
00361 return GSL_SUCCESS;
00362 }
00363
00364 void setInitialParameters_(FeatureFinderAlgorithmPickedHelperStructs::MassTraces<PeakType> & traces)
00365 {
00366 LOG_DEBUG << "EGHTraceFitter->setInitialParameters(..)" << std::endl;
00367 LOG_DEBUG << "Traces length: " << traces.size() << std::endl;
00368 LOG_DEBUG << "Max trace: " << traces.max_trace << std::endl;
00369
00370
00371 height_ = traces[traces.max_trace].max_peak->getIntensity() - traces.baseline;
00372 LOG_DEBUG << "height: " << height_ << std::endl;
00373 apex_rt_ = traces[traces.max_trace].max_rt;
00374 LOG_DEBUG << "apex_rt: " << apex_rt_ << std::endl;
00375 region_rt_span_ = traces[traces.max_trace].peaks.back().first - traces[traces.max_trace].peaks[0].first;
00376 LOG_DEBUG << "region_rt_span_: " << region_rt_span_ << std::endl;
00377
00378 const PeakType * max_peak = traces[traces.max_trace].peaks.begin()->second;
00379 Size max_pos = 0;
00380
00381 for (Size i = 1; i < traces[traces.max_trace].peaks.size(); ++i)
00382 {
00383 if (traces[traces.max_trace].peaks[i].second->getIntensity() > max_peak->getIntensity())
00384 {
00385 max_peak = traces[traces.max_trace].peaks[i].second;
00386 max_pos = i;
00387 }
00388 }
00389
00390 Size i = max_pos;
00391 LOG_DEBUG << "max_pos: " << max_pos << std::endl;
00392 if (traces[traces.max_trace].peaks.size() < 3)
00393 {
00394
00395
00396 }
00397
00398 Size filter_max_pos = traces[traces.max_trace].peaks.size() - 2;
00399
00400
00401
00402 DoubleReal smoothed_height;
00403 if ((max_pos < 2) || (max_pos + 2 >= traces[traces.max_trace].peaks.size()))
00404 {
00405
00406 smoothed_height = traces[traces.max_trace].peaks[max_pos].second->getIntensity();
00407
00408 }
00409 else
00410 {
00411 smoothed_height = (traces[traces.max_trace].peaks[max_pos - 2].second->getIntensity()
00412 + traces[traces.max_trace].peaks[max_pos - 1].second->getIntensity()
00413 + traces[traces.max_trace].peaks[max_pos].second->getIntensity()
00414 + traces[traces.max_trace].peaks[max_pos + 1].second->getIntensity()
00415 + traces[traces.max_trace].peaks[max_pos + 2].second->getIntensity()) / 5.0;
00416 }
00417
00418
00419
00420
00421 while (i > 2 && i < filter_max_pos)
00422 {
00423
00424 DoubleReal smoothed = (traces[traces.max_trace].peaks[i - 2].second->getIntensity()
00425 + traces[traces.max_trace].peaks[i - 1].second->getIntensity()
00426 + traces[traces.max_trace].peaks[i].second->getIntensity()
00427 + traces[traces.max_trace].peaks[i + 1].second->getIntensity()
00428 + traces[traces.max_trace].peaks[i + 2].second->getIntensity()) / 5.0;
00429
00430 if (smoothed / smoothed_height < 0.5) break;
00431 else --i;
00432 }
00433 LOG_DEBUG << "Left alpha at " << i << " with " << traces[traces.max_trace].peaks[i].first << std::endl;
00434 double A = apex_rt_ - traces[traces.max_trace].peaks[i].first;
00435
00436 i = max_pos;
00437 while (i < filter_max_pos && i > 2)
00438 {
00439 DoubleReal smoothed = (traces[traces.max_trace].peaks[i - 2].second->getIntensity()
00440 + traces[traces.max_trace].peaks[i - 1].second->getIntensity()
00441 + traces[traces.max_trace].peaks[i].second->getIntensity()
00442 + traces[traces.max_trace].peaks[i + 1].second->getIntensity()
00443 + traces[traces.max_trace].peaks[i + 2].second->getIntensity()) / 5.0;
00444
00445 if (smoothed / smoothed_height < 0.5) break;
00446 else ++i;
00447 }
00448 LOG_DEBUG << "Right alpha at " << i << " with " << traces[traces.max_trace].peaks[i].first << std::endl;
00449 double B = traces[traces.max_trace].peaks[i].first - apex_rt_;
00450
00451
00452
00453
00454
00455 double log_alpha = log(0.5);
00456
00457 tau_ = (-1 / log_alpha) * (B - A);
00458 LOG_DEBUG << "tau: " << tau_ << std::endl;
00459 sigma_square_ = (-1 / (2 * log_alpha)) * (B * A);
00460 LOG_DEBUG << "sigma_square: " << sigma_square_ << std::endl;
00461 }
00462
00463 virtual void updateMembers_()
00464 {
00465 TraceFitter<PeakType>::updateMembers_();
00466 }
00467
00468 void printState_(SignedSize iter, gsl_multifit_fdfsolver * s)
00469 {
00470 LOG_DEBUG << "iter: " << iter << " "
00471 << "height: " << gsl_vector_get(s->x, 0) << " "
00472 << "apex_rt: " << gsl_vector_get(s->x, 1) << " "
00473 << "sigma_square: " << gsl_vector_get(s->x, 2) << " "
00474 << "tau: " << gsl_vector_get(s->x, 3) << " "
00475 << "|f(x)| = " << gsl_blas_dnrm2(s->f) << std::endl;
00476 }
00477
00478 };
00479
00480 }
00481
00482 #endif // #ifndef OPENMS_TRANSFORMATIONS_FEATUREFINDER_FEATUREFINDERALGORITHMPICKEDTRACEFITTERGAUSS_H