Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

MRMTransitionGroupPicker.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Hannes Roest $
00032 // $Authors: Hannes Roest $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_ANALYSIS_OPENSWATH_MRMTRANSITIONGROUPPICKER_H
00036 #define OPENMS_ANALYSIS_OPENSWATH_MRMTRANSITIONGROUPPICKER_H
00037 
00038 #include <OpenMS/KERNEL/MRMTransitionGroup.h>
00039 #include <OpenMS/KERNEL/MRMFeature.h>
00040 #include <OpenMS/KERNEL/MSSpectrum.h>
00041 #include <OpenMS/KERNEL/MSChromatogram.h>
00042 #include <OpenMS/KERNEL/ChromatogramPeak.h>
00043 
00044 #include <OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h>
00045 #include <OpenMS/FILTERING/SMOOTHING/SavitzkyGolayFilter.h>
00046 #include <OpenMS/FILTERING/SMOOTHING/GaussFilter.h>
00047 
00048 #include <OpenMS/FILTERING/TRANSFORMERS/LinearResampler.h>
00049 #include <OpenMS/FILTERING/TRANSFORMERS/LinearResamplerAlign.h>
00050 
00051 #include <OpenMS/TRANSFORMATIONS/RAW2PEAK/PeakPickerHiRes.h>
00052 
00053 //#define DEBUG_TRANSITIONGROUPPICKER
00054 
00055 namespace OpenMS
00056 {
00057 
00076   class OPENMS_DLLAPI MRMTransitionGroupPicker :
00077     public DefaultParamHandler
00078   {
00079 
00080 public:
00081 
00082     // this is the type in which we store the chromatograms for this analysis
00083     typedef MSSpectrum<ChromatogramPeak> RichPeakChromatogram; 
00084 
00085 protected:
00086     UInt sgolay_frame_length_;
00087     UInt sgolay_polynomial_order_;
00088     DoubleReal gauss_width_;
00089     bool use_gauss_;
00090 
00091     String background_subtraction_;
00092 
00093     DoubleReal peak_width_;
00094     DoubleReal signal_to_noise_;
00095 
00096     DoubleReal sn_win_len_;
00097     UInt sn_bin_count_;
00098 
00099     int stop_after_feature_;
00100     DoubleReal stop_after_intensity_ratio_;
00101 
00102     std::vector<RichPeakChromatogram> picked_chroms_;
00103     std::vector<RichPeakChromatogram> smoothed_chroms_;
00104 
00106 
00107 
00108     template <typename SpectrumT, typename TransitionT>
00109     void prepareMasterContainer_(MRMTransitionGroup<SpectrumT, TransitionT> & transition_group,
00110       SpectrumT & master_peak_container, int chr_idx, double best_left, double best_right)
00111     {
00112       const SpectrumT & ref_chromatogram = transition_group.getChromatograms()[chr_idx];
00113 
00114       // search for begin / end of the reference chromatogram (and add one more point)
00115       typename SpectrumT::const_iterator begin = ref_chromatogram.begin();
00116       while (begin != ref_chromatogram.end() && begin->getMZ() < best_left) {begin++; }
00117       if (begin != ref_chromatogram.begin()) {begin--; }
00118 
00119       typename SpectrumT::const_iterator end = begin;
00120       while (end != ref_chromatogram.end() && end->getMZ() < best_right) {end++; }
00121       if (end != ref_chromatogram.end()) {end++; }
00122 
00123       // resize the master container and set the m/z values to the ones of the master container
00124       master_peak_container.resize(distance(begin, end));
00125       typename SpectrumT::iterator it = master_peak_container.begin();
00126       for (typename SpectrumT::const_iterator chrom_it = begin; chrom_it != end; chrom_it++, it++)
00127       {
00128         it->setMZ(chrom_it->getMZ());
00129       }
00130     }
00131 
00133     template <typename SpectrumT>
00134     SpectrumT resampleChromatogram_(const SpectrumT & chromatogram,
00135       SpectrumT & master_peak_container, double best_left, double best_right)
00136     {
00137       // get the start / end point of this chromatogram => go one past
00138       // best_left / best_right to make the resampling accurate also at the
00139       // edge.
00140       typename SpectrumT::const_iterator begin = chromatogram.begin();
00141       while (begin != chromatogram.end() && begin->getMZ() < best_left) {begin++; }
00142       if (begin != chromatogram.begin()) {begin--; }
00143 
00144       typename SpectrumT::const_iterator end = begin;
00145       while (end != chromatogram.end() && end->getMZ() < best_right) {end++; }
00146       if (end != chromatogram.end()) {end++; }
00147 
00148       SpectrumT resampled_peak_container = master_peak_container; // copy the master container, which contains the RT values
00149       LinearResamplerAlign lresampler;
00150       lresampler.raster(begin, end, resampled_peak_container.begin(), resampled_peak_container.end());
00151 
00152 #if DEBUG_TRANSITIONGROUPPICKER
00153       {
00154         std::cout << "===========================================================================  " << std::endl;
00155         double tot;
00156         tot = 0;
00157         for (typename SpectrumT::const_iterator it = begin; it != end; it++)
00158         {
00159           std::cout << " before resampl " << *it << std::endl;
00160           tot += it->getIntensity();
00161         }
00162         std::cout << " total " << tot << std::endl;
00163 
00164         tot = 0;
00165         for (typename SpectrumT::iterator it = resampled_peak_container.begin(); it != resampled_peak_container.end(); it++)
00166         {
00167           std::cout << " resampl " << *it << std::endl;
00168           tot += it->getIntensity();
00169         }
00170         std::cout << " total " << tot << std::endl;
00171         std::cout << " resampled size " << resampled_peak_container.size() << std::endl;
00172       }
00173 #endif
00174       return resampled_peak_container;
00175     }
00176 
00178 
00180     double calculateBgEstimation_(const RichPeakChromatogram& smoothed_chromat, double best_left, double best_right);
00181 
00183     void updateMembers_();
00184 
00186     MRMTransitionGroupPicker& operator=(const MRMTransitionGroupPicker& rhs);
00187 
00188 public:
00189 
00191 
00192     MRMTransitionGroupPicker();
00193 
00195     ~MRMTransitionGroupPicker();
00197 
00201     template <typename SpectrumT, typename TransitionT>
00202     void pickTransitionGroup(MRMTransitionGroup<SpectrumT, TransitionT> & transition_group)
00203     {
00204       // Pick chromatograms
00205       picked_chroms_.clear();
00206       for (Size k = 0; k < transition_group.getChromatograms().size(); k++)
00207       {
00208         RichPeakChromatogram& chromatogram = transition_group.getChromatograms()[k];
00209         if (!chromatogram.isSorted()) { chromatogram.sortByPosition(); }
00210 
00211         // pickChromatogram will return the picked and the smoothed chromatogram
00212         RichPeakChromatogram picked_chrom, smoothed_chrom;
00213         pickChromatogram(chromatogram, smoothed_chrom, picked_chrom);
00214         picked_chrom.sortByIntensity(); // we could do without that
00215         picked_chroms_.push_back(picked_chrom);
00216         smoothed_chroms_.push_back(smoothed_chrom);
00217       }
00218 
00219       // Find features (peak groups) in this group of transitions.
00220       // While there are still peaks left, one will be picked and used to create
00221       // a feature. Whenever we run out of peaks, we will get -1 back as index
00222       // and terminate.
00223       int chr_idx, peak_idx, cnt = 0;
00224       while (true)
00225       {
00226         chr_idx = -1; peak_idx = -1;
00227         findLargestPeak(picked_chroms_, chr_idx, peak_idx);
00228         if (chr_idx == -1 && peak_idx == -1) break;
00229 
00230         /*
00231         // FEATURE (hroest) check that this left/right do not collide with any already present features -- if so, re-set the left/right
00232         double best_left = picked_chroms[chr_idx].getFloatDataArrays()[1][peak_idx];
00233         double best_right = picked_chroms[chr_idx].getFloatDataArrays()[2][peak_idx];
00234         */
00235 
00236         // get feature, prevent non-extended zero features to be added
00237         MRMFeature mrm_feature = createMRMFeature(transition_group, picked_chroms_, chr_idx, peak_idx);
00238         if (mrm_feature.getIntensity() > 0)
00239         {
00240           transition_group.addFeature(mrm_feature);
00241         }
00242 
00243         cnt++;
00244         if ((stop_after_feature_ > 0 && cnt > stop_after_feature_) && mrm_feature.getIntensity() / (double)mrm_feature.getMetaValue("total_xic") < stop_after_intensity_ratio_)
00245         {
00246           break;
00247         }
00248       }
00249     }
00250 
00252     // This function will return a smoothed chromatogram and a picked chromatogram
00253     void pickChromatogram(const RichPeakChromatogram& chromatogram, RichPeakChromatogram& smoothed_chrom, RichPeakChromatogram& picked_chrom);
00254 
00256     template <typename SpectrumT, typename TransitionT>
00257     MRMFeature createMRMFeature(MRMTransitionGroup<SpectrumT, TransitionT> & transition_group,
00258       std::vector<SpectrumT> & picked_chroms, int & chr_idx, int & peak_idx)
00259     {
00260       MRMFeature mrmFeature;
00261       const double best_left = picked_chroms[chr_idx].getFloatDataArrays()[1][peak_idx];
00262       const double best_right = picked_chroms[chr_idx].getFloatDataArrays()[2][peak_idx];
00263       const double peak_apex = picked_chroms[chr_idx][peak_idx].getRT();
00264 
00265       // Remove other, overlapping, picked peaks (in this and other
00266       // chromatograms) and then ensure that at least one peak is set to zero
00267       // (the currently best peak).
00268       remove_overlapping_features(picked_chroms, best_left, best_right);
00269       picked_chroms[chr_idx][peak_idx].setIntensity(0.0);
00270 
00271       // Prepare linear resampling of all the chromatograms, here creating the
00272       // empty master_peak_container with the same RT (m/z) values as the reference
00273       // chromatogram.
00274       SpectrumT master_peak_container;
00275       prepareMasterContainer_(transition_group, master_peak_container, chr_idx, best_left, best_right);
00276 
00277       double total_intensity = 0; double total_peak_apices = 0; double total_xic = 0;
00278       for (Size k = 0; k < transition_group.getChromatograms().size(); k++)
00279       {
00280         const SpectrumT& chromatogram = transition_group.getChromatograms()[k];
00281         for (typename SpectrumT::const_iterator it = chromatogram.begin(); it != chromatogram.end(); it++)
00282         {
00283           total_xic += it->getIntensity();
00284         }
00285 
00286         // resample the current chromatogram
00287         const SpectrumT used_chromatogram = resampleChromatogram_(chromatogram, master_peak_container, best_left, best_right);
00288         // const SpectrumT& used_chromatogram = chromatogram; // instead of resampling
00289 
00290         Feature f;
00291         double quality = 0;
00292         f.setQuality(0, quality);
00293         f.setOverallQuality(quality);
00294 
00295         ConvexHull2D::PointArrayType hull_points;
00296         DoubleReal intensity_sum(0.0), rt_sum(0.0);
00297         double peak_apex_int = -1;
00298         double peak_apex_dist = std::fabs(used_chromatogram.begin()->getMZ() - peak_apex);
00299         // FEATURE : use RTBegin / MZBegin -> for this we need to know whether the template param is a real chromatogram or a spectrum!
00300         for (typename SpectrumT::const_iterator it = used_chromatogram.begin(); it != used_chromatogram.end(); it++)
00301         {
00302           if (it->getMZ() > best_left && it->getMZ() < best_right)
00303           {
00304             DPosition<2> p;
00305             p[0] = it->getMZ();
00306             p[1] = it->getIntensity();
00307             hull_points.push_back(p);
00308             if (std::fabs(it->getMZ() - peak_apex) <= peak_apex_dist)
00309             {
00310               peak_apex_int = p[1];
00311               peak_apex_dist = std::fabs(it->getMZ() - peak_apex);
00312             }
00313             rt_sum += it->getMZ();
00314             intensity_sum += it->getIntensity();
00315           }
00316         }
00317 
00318         if (background_subtraction_ != "none")
00319         {
00320           double background = 0;
00321           // we use the smoothed chromatogram here to have a more accurate estimatation of the noise at the flanks of the peak
00322           if (background_subtraction_ == "smoothed")
00323           {
00324             if (smoothed_chroms_.size() <= k)
00325             {
00326               std::cerr << "Tried to calculate background estimation without any smoothed chromatograms" << std::endl;
00327               background =  0;
00328             }
00329             else
00330             {
00331               background = calculateBgEstimation_(smoothed_chroms_[k], best_left, best_right);
00332             }
00333           }
00334           else if (background_subtraction_ == "original")
00335           {
00336             background = calculateBgEstimation_(used_chromatogram, best_left, best_right);
00337           }
00338           intensity_sum -= background;
00339           if (intensity_sum < 0)
00340           {
00341             std::cerr << "Warning: Intensity was below 0 after background subtraction: " << intensity_sum << ". Setting it to 0." << std::endl;
00342             intensity_sum = 0;
00343           }
00344         }
00345 
00346         f.setRT(picked_chroms[chr_idx][peak_idx].getMZ());
00347         f.setMZ(chromatogram.getMetaValue("product_mz"));
00348         f.setIntensity(intensity_sum);
00349         ConvexHull2D hull;
00350         hull.setHullPoints(hull_points);
00351         f.getConvexHulls().push_back(hull);
00352         f.setMetaValue("MZ", chromatogram.getMetaValue("product_mz"));
00353         f.setMetaValue("native_id", chromatogram.getNativeID());
00354         f.setMetaValue("peak_apex_int", peak_apex_int);
00355         //f.setMetaValue("leftWidth", best_left);
00356         //f.setMetaValue("rightWidth", best_right);
00357 
00358         total_intensity += intensity_sum;
00359         total_peak_apices += peak_apex_int;
00360         mrmFeature.addFeature(f, chromatogram.getNativeID()); //map index and feature
00361       }
00362       mrmFeature.setRT(picked_chroms[chr_idx][peak_idx].getMZ());
00363       mrmFeature.setIntensity(total_intensity);
00364       mrmFeature.setMetaValue("PeptideRef", transition_group.getTransitionGroupID());
00365       mrmFeature.setMetaValue("leftWidth", best_left);
00366       mrmFeature.setMetaValue("rightWidth", best_right);
00367       mrmFeature.setMetaValue("total_xic", total_xic);
00368       mrmFeature.setMetaValue("peak_apices_sum", total_peak_apices);
00369 
00370       return mrmFeature;
00371     }
00372 
00373     // maybe private, but we have tests
00374 
00376     template <typename SpectrumT>
00377     void remove_overlapping_features(std::vector<SpectrumT> & picked_chroms, double best_left, double best_right)
00378     {
00379       // delete all seeds that lie within the current seed
00380       for (Size k = 0; k < picked_chroms.size(); k++)
00381       {
00382         for (Size i = 0; i < picked_chroms[k].size(); i++)
00383         {
00384           if (picked_chroms[k][i].getMZ() >= best_left && picked_chroms[k][i].getMZ() <= best_right)
00385           {
00386             picked_chroms[k][i].setIntensity(0.0);
00387           }
00388         }
00389       }
00390 
00391       // delete all seeds that overlap within the current seed
00392       for (Size k = 0; k < picked_chroms.size(); k++)
00393       {
00394         for (Size i = 0; i < picked_chroms[k].size(); i++)
00395         {
00396           double left = picked_chroms[k].getFloatDataArrays()[1][i];
00397           double right = picked_chroms[k].getFloatDataArrays()[2][i];
00398           if ((left >= best_left && left <= best_right)
00399              || (right >= best_left && right <= best_right))
00400           {
00401             picked_chroms[k][i].setIntensity(0.0);
00402           }
00403         }
00404       }
00405     }
00406 
00408     void findLargestPeak(std::vector<RichPeakChromatogram>& picked_chroms, int& chr_idx, int& peak_idx);
00409   };
00410 }
00411 
00412 #endif

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:42 using doxygen 1.7.1