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_FEATUREFINDERALGORITHMMRM_H
00036 #define OPENMS_TRANSFORMATIONS_FEATUREFINDER_FEATUREFINDERALGORITHMMRM_H
00037
00038 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithm.h>
00039 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/ProductModel.h>
00040 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/EmgFitter1D.h>
00041 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/EmgModel.h>
00042 #include <OpenMS/FILTERING/SMOOTHING/SavitzkyGolayFilter.h>
00043 #include <OpenMS/FILTERING/SMOOTHING/GaussFilter.h>
00044 #include <OpenMS/DATASTRUCTURES/Map.h>
00045 #include <OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMeanIterative.h>
00046 #include <OpenMS/FILTERING/TRANSFORMERS/LinearResampler.h>
00047 #include <OpenMS/KERNEL/StandardTypes.h>
00048
00049 #include <boost/math/special_functions/fpclassify.hpp>
00050
00051 #include <fstream>
00052 #include <limits>
00053
00054 namespace OpenMS
00055 {
00072 template <class PeakType, class FeatureType>
00073 class FeatureFinderAlgorithmMRM :
00074 public FeatureFinderAlgorithm<PeakType, FeatureType>,
00075 public FeatureFinderDefs
00076 {
00077 public:
00079
00080 typedef typename FeatureFinderAlgorithm<PeakType, FeatureType>::MapType MapType;
00081 typedef typename MapType::SpectrumType SpectrumType;
00082 typedef typename SpectrumType::FloatDataArrays FloatDataArrays;
00084
00085 using FeatureFinderAlgorithm<PeakType, FeatureType>::param_;
00086 using FeatureFinderAlgorithm<PeakType, FeatureType>::features_;
00087 using FeatureFinderAlgorithm<PeakType, FeatureType>::ff_;
00088 using FeatureFinderAlgorithm<PeakType, FeatureType>::defaults_;
00089 using FeatureFinderAlgorithm<PeakType, FeatureType>::map_;
00090
00091 public:
00092
00093 enum
00094 {
00095 RT = Peak2D::RT,
00096 MZ = Peak2D::MZ
00097 };
00098
00099
00101 FeatureFinderAlgorithmMRM() :
00102 FeatureFinderAlgorithm<PeakType, FeatureType>()
00103 {
00104 defaults_.setValue("min_rt_distance", 10.0, "Minimal distance of MRM features in seconds.");
00105 defaults_.setMinFloat("min_rt_distance", 0.0);
00106 defaults_.setValue("min_num_peaks_per_feature", 5, "Minimal number of peaks which are needed for a single feature", StringList::create("advanced"));
00107 defaults_.setMinInt("min_num_peaks_per_feature", 1);
00108 defaults_.setValue("min_signal_to_noise_ratio", 2.0, "Minimal S/N ratio a peak must have to be taken into account. Set to zero if the MRM-traces contains mostly signals, and no noise.");
00109 defaults_.setMinFloat("min_signal_to_noise_ratio", 0);
00110 defaults_.setValue("write_debug_files", "false", "If set to true, for each feature a plot will be created, in the subdirectory 'debug'", StringList::create("advanced"));
00111 defaults_.setValidStrings("write_debug_files", StringList::create("true,false"));
00112
00113 defaults_.setValue("resample_traces", "false", "If set to true, each trace, which is in this case a part of the MRM monitoring trace with signal is resampled, using the minimal distance of two data points in RT dimension", StringList::create("advanced"));
00114 defaults_.setValidStrings("resample_traces", StringList::create("true,false"));
00115
00116 defaults_.setValue("write_debuginfo", "false", "If set to true, debug messages are written, the output can be somewhat lengthy.", StringList::create("advanced"));
00117 defaults_.setValidStrings("write_debuginfo", StringList::create("true,false"));
00118
00119 this->defaultsToParam_();
00120 }
00121
00123 virtual void run()
00124 {
00125
00126
00127
00128
00129 Map<Size, Map<Size, std::vector<std::pair<DoubleReal, PeakType> > > > traces;
00130
00131 SignalToNoiseEstimatorMeanIterative<RichPeakSpectrum> sne;
00132 LinearResampler resampler;
00133
00134
00135 ff_->startProgress(0, traces.size(), "Finding features in traces.");
00136 Size counter(0);
00137
00138
00139 DoubleReal min_rt_distance(param_.getValue("min_rt_distance"));
00140 DoubleReal min_signal_to_noise_ratio(param_.getValue("min_signal_to_noise_ratio"));
00141 Size min_num_peaks_per_feature(param_.getValue("min_num_peaks_per_feature"));
00142 Size feature_id(0);
00143 bool write_debuginfo(param_.getValue("write_debuginfo").toBool());
00144 bool write_debug_files(param_.getValue("write_debug_files").toBool());
00145 bool resample_traces(param_.getValue("resample_traces").toBool());
00146
00147 if (write_debuginfo)
00148 {
00149 std::cerr << "Starting feature finding #chromatograms=" << map_->getChromatograms().size() << ", #spectra=" << map_->size() << std::endl;
00150 }
00151
00152 typename std::vector<MSChromatogram<ChromatogramPeak> >::const_iterator first_it = map_->getChromatograms().begin();
00153 for (; first_it != map_->getChromatograms().end(); ++first_it)
00154 {
00155
00156 RichPeakSpectrum chromatogram;
00157
00158 for (MSChromatogram<ChromatogramPeak>::const_iterator it = first_it->begin(); it != first_it->end(); ++it)
00159 {
00160 RichPeak1D peak;
00161 peak.setMZ(it->getRT());
00162 peak.setIntensity(it->getIntensity());
00163 chromatogram.push_back(peak);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 if (resample_traces)
00174 {
00175
00176 DoubleReal min_distance(std::numeric_limits<DoubleReal>::max()), old_rt(0);
00177 for (RichPeakSpectrum::ConstIterator it = chromatogram.begin(); it != chromatogram.end(); ++it)
00178 {
00179 if (write_debuginfo)
00180 {
00181 std::cerr << "CHROMATOGRAM: " << it->getMZ() << " " << it->getIntensity() << std::endl;
00182 }
00183 DoubleReal rt_diff = it->getMZ() - old_rt;
00184 if (rt_diff < min_distance && rt_diff > 0)
00185 {
00186 min_distance = rt_diff;
00187 }
00188 old_rt = it->getMZ();
00189 }
00190
00191 if (write_debuginfo)
00192 {
00193 std::cerr << "Min_distance=" << min_distance << std::endl;
00194 }
00195 if (min_distance > 50 || chromatogram.size() < min_num_peaks_per_feature)
00196 {
00197 continue;
00198 }
00199 Param resampler_param(resampler.getParameters());
00200 resampler_param.setValue("spacing", min_distance);
00201 resampler.setParameters(resampler_param);
00202 resampler.raster(chromatogram);
00203 }
00204
00205
00206 GaussFilter filter;
00207 Param filter_param(filter.getParameters());
00208 filter.setParameters(filter_param);
00209
00210
00211 RichPeakSpectrum sn_chrom;
00212 Param sne_param(sne.getParameters());
00213
00214 if (write_debuginfo)
00215 {
00216 std::cerr << "win_len m/z: " << (chromatogram.end() - 1)->getMZ() << " " << chromatogram.begin()->getMZ() << std::endl;
00217 }
00218 sne_param.setValue("win_len", (chromatogram.end() - 1)->getMZ() - chromatogram.begin()->getMZ());
00219
00220 if ((DoubleReal)sne_param.getValue("win_len") < 10e-4)
00221 {
00222 continue;
00223 }
00224 sne.setParameters(sne_param);
00225 sne.init(chromatogram.begin(), chromatogram.end());
00226
00227 if (write_debuginfo)
00228 {
00229 std::cerr << first_it->getPrecursor().getMZ() << " " << first_it->getProduct().getMZ() << " ";
00230 }
00231 for (RichPeakSpectrum::Iterator sit = chromatogram.begin(); sit != chromatogram.end(); ++sit)
00232 {
00233 DoubleReal sn(sne.getSignalToNoise(sit));
00234 sit->setMetaValue("SN", sn);
00235 if (write_debuginfo)
00236 {
00237 std::cerr << sit->getMZ() << " " << sit->getIntensity() << " " << sn << std::endl;
00238 }
00239 if (min_signal_to_noise_ratio == 0 || sn > min_signal_to_noise_ratio)
00240 {
00241 sn_chrom.push_back(*sit);
00242 }
00243 }
00244
00245
00246 DoubleReal last_rt(0), this_rt(0);
00247 std::vector<std::vector<DPosition<2> > > sections;
00248 for (RichPeakSpectrum::Iterator sit = sn_chrom.begin(); sit != sn_chrom.end(); ++sit)
00249 {
00250 if (write_debuginfo)
00251 {
00252 std::cerr << "SECTIONS: " << sit->getMZ() << " " << sit->getIntensity() << std::endl;
00253 }
00254 this_rt = sit->getMZ();
00255 if (sections.empty() || (this_rt - last_rt) > min_rt_distance)
00256 {
00257 if (write_debuginfo)
00258 {
00259 std::cerr << "Starting new section, sections.size()=" << sections.size() << ", rt_diff=" << this_rt - last_rt << std::endl;
00260 }
00261
00262 std::vector<DPosition<2> > section;
00263 section.push_back(DPosition<2>(this_rt, sit->getIntensity()));
00264 sections.push_back(section);
00265 }
00266 else
00267 {
00268 sections.back().push_back(DPosition<2>(this_rt, sit->getIntensity()));
00269 }
00270 last_rt = this_rt;
00271 }
00272
00273
00274
00275 for (Size i = 0; i != sections.size(); ++i)
00276 {
00277 if (sections[i].size() < min_num_peaks_per_feature)
00278 {
00279 continue;
00280 }
00281
00282 std::vector<DoubleReal> deltas(2, 0.0);
00283 DoubleReal last_int(sections[i][0].getY());
00284 for (Size j = 1; j < sections[i].size(); ++j)
00285 {
00286 deltas.push_back((sections[i][j].getY() - last_int) / last_int);
00287 last_int = sections[i][j].getY();
00288 if (write_debuginfo)
00289 {
00290 DoubleReal average_delta = std::accumulate(deltas.begin(), deltas.end(), 0.0) / (DoubleReal)3.0;
00291 std::cerr << "AverageDelta: " << average_delta << " (" << sections[i][j].getX() << ", " << sections[i][j].getY() << ")" << std::endl;
00292 }
00293 }
00294 }
00295
00296
00297
00298 for (Size i = 0; i != sections.size(); ++i)
00299 {
00300 if (sections[i].size() > min_num_peaks_per_feature)
00301 {
00302
00303 PeakSpectrum filter_spec;
00304 for (Size j = 0; j != sections[i].size(); ++j)
00305 {
00306 Peak1D p;
00307 p.setMZ(sections[i][j].getX());
00308 p.setIntensity(sections[i][j].getY());
00309 filter_spec.push_back(p);
00310 }
00311
00312
00313
00314 std::vector<DoubleReal> distances;
00315 for (Size j = 1; j < filter_spec.size(); ++j)
00316 {
00317 distances.push_back(filter_spec[j].getMZ() - filter_spec[j - 1].getMZ());
00318 }
00319 DoubleReal dist_average = std::accumulate(distances.begin(), distances.end(), 0.0) / (DoubleReal)distances.size();
00320
00321
00322 Peak1D new_peak;
00323 new_peak.setIntensity(0);
00324 new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
00325 filter_spec.push_back(new_peak);
00326 new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
00327 filter_spec.push_back(new_peak);
00328 new_peak.setMZ(filter_spec.back().getMZ() + dist_average);
00329 filter_spec.push_back(new_peak);
00330
00331
00332 new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
00333 filter_spec.insert(filter_spec.begin(), new_peak);
00334 new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
00335 filter_spec.insert(filter_spec.begin(), new_peak);
00336 new_peak.setMZ(filter_spec.front().getMZ() - dist_average);
00337 filter_spec.insert(filter_spec.begin(), new_peak);
00338
00339 filter_param.setValue("gaussian_width", 4 * dist_average);
00340 filter.setParameters(filter_param);
00341
00342
00343 filter.filter(filter_spec);
00344
00345
00346 std::vector<PeakType> data_to_fit;
00347 for (Size j = 0; j != filter_spec.size(); ++j)
00348 {
00349 PeakType p;
00350 p.setPosition(filter_spec[j].getMZ());
00351 p.setIntensity(filter_spec[j].getIntensity());
00352 data_to_fit.push_back(p);
00353 }
00354 InterpolationModel * model_rt = 0;
00355 DoubleReal quality = fitRT_(data_to_fit, model_rt);
00356
00357 Feature f;
00358 f.setQuality(0, quality);
00359 f.setOverallQuality(quality);
00360
00361 ConvexHull2D::PointArrayType hull_points(sections[i].size());
00362 DoubleReal intensity_sum(0.0), rt_sum(0.0);
00363 for (Size j = 0; j < sections[i].size(); ++j)
00364 {
00365 hull_points[j][0] = sections[i][j].getX();
00366 hull_points[j][1] = first_it->getProduct().getMZ();
00367
00368 rt_sum += sections[i][j].getX();
00369 intensity_sum += sections[i][j].getY();
00370 }
00371
00372
00373 f.setRT((DoubleReal)model_rt->getParameters().getValue("emg:retention"));
00374 f.setMZ((DoubleReal)first_it->getProduct().getMZ());
00375 f.setIntensity(intensity_sum);
00376 ConvexHull2D hull;
00377 hull.addPoints(hull_points);
00378 f.getConvexHulls().push_back(hull);
00379 f.setMetaValue("MZ", (DoubleReal)first_it->getPrecursor().getMZ());
00380
00381
00382
00383 ProductModel<2> prod_model;
00384 prod_model.setModel(RT, model_rt);
00385 f.setModelDescription(ModelDescription<2>(&prod_model));
00386
00387
00388 feature_id++;
00389
00390
00391 if (write_debug_files)
00392 {
00393 String base_name = "debug/" + String((DoubleReal)f.getMetaValue("MZ")) + "_id" + String(feature_id) + "_RT" + String(f.getRT()) + "_Q3" + String(f.getMZ());
00394 std::ofstream data_out(String(base_name + "_data.dat").c_str());
00395 for (Size j = 0; j < sections[i].size(); ++j)
00396 {
00397
00398 DoubleReal rt = sections[i][j].getX();
00399 DoubleReal intensity = sections[i][j].getY();
00400 data_out << rt << " " << intensity << std::endl;
00401 }
00402 data_out.close();
00403
00404 std::ofstream smoothed_data_out(String(base_name + "_smoothed_data.dat").c_str());
00405 for (Size j = 0; j < filter_spec.size(); ++j)
00406 {
00407 smoothed_data_out << filter_spec[j].getMZ() + 0.5 << " " << filter_spec[j].getIntensity() << std::endl;
00408 }
00409 smoothed_data_out.close();
00410
00411 std::ofstream fit_out(String(base_name + "_rt_fit.dat").c_str());
00412 EmgModel emg_model;
00413 emg_model.setParameters(model_rt->getParameters());
00414 emg_model.setSamples();
00415 DoubleReal bb_min((DoubleReal)emg_model.getParameters().getValue("bounding_box:min"));
00416 DoubleReal bb_max((DoubleReal)emg_model.getParameters().getValue("bounding_box:max"));
00417 DoubleReal int_step((DoubleReal)emg_model.getParameters().getValue("interpolation_step"));
00418 for (DoubleReal pos = bb_min; pos < bb_max; pos += int_step)
00419 {
00420
00421 fit_out << pos << " " << emg_model.getIntensity(pos) << std::endl;
00422 }
00423 fit_out.close();
00424
00425 std::ofstream gnuplot_out(String(base_name + "_gnuplot.gpl").c_str());
00426 gnuplot_out << "set terminal png" << std::endl;
00427 gnuplot_out << "set output \"" << base_name << ".png\"" << std::endl;
00428 gnuplot_out << "plot '" << base_name << "_data.dat' w i, '" << base_name << "_smoothed_data.dat' w i, '" << base_name << "_rt_fit.dat' w lp title 'quality=" << f.getOverallQuality() << "'" << std::endl;
00429 gnuplot_out.close();
00430 String gnuplot_call = "gnuplot " + base_name + "_gnuplot.gpl";
00431 int error = system(gnuplot_call.c_str());
00432 if (error != 0)
00433 {
00434 std::cerr << "An error occurred during the gnuplot execution" << std::endl;
00435 }
00436 }
00437
00438 features_->push_back(f);
00439 }
00440 }
00441
00442 ff_->setProgress(++counter);
00443 }
00444 }
00445
00446 static FeatureFinderAlgorithm<PeakType, FeatureType> * create()
00447 {
00448 return new FeatureFinderAlgorithmMRM();
00449 }
00450
00451 static const String getProductName()
00452 {
00453 return "mrm";
00454 }
00455
00456 protected:
00457
00458 DoubleReal fitRT_(std::vector<PeakType> & rt_input_data, InterpolationModel * & model) const
00459 {
00460 DoubleReal quality;
00461 Param param;
00462 EmgFitter1D fitter;
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 fitter.setParameters(param);
00476
00477
00478 quality = fitter.fit1d(rt_input_data, model);
00479
00480
00481 if (boost::math::isnan(quality)) quality = -1.0;
00482
00483 return quality;
00484 }
00485
00486
00487 virtual void updateMembers_()
00488 {
00489 }
00490
00491 };
00492
00493 }
00494
00495 #endif // OPENMS_TRANSFORMATIONS_FEATUREFINDER_FEATUREFINDERALGORITHMMRM_H