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

SimpleExtender.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: Clemens Groepl $
00032 // $Authors: $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_TRANSFORMATIONS_FEATUREFINDER_SIMPLEEXTENDER_H
00036 #define OPENMS_TRANSFORMATIONS_FEATUREFINDER_SIMPLEEXTENDER_H
00037 
00038 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/FeaFiModule.h>
00039 #include <OpenMS/MATH/STATISTICS/AveragePosition.h>
00040 
00041 #include <queue>
00042 #include <iostream>
00043 #include <fstream>
00044 
00045 namespace OpenMS
00046 {
00047 
00078   template <class PeakType, class FeatureType>
00079   class SimpleExtender :
00080     public FeaFiModule<PeakType, FeatureType>,
00081     public FeatureFinderDefs
00082   {
00083 public:
00084     typedef FeaFiModule<PeakType, FeatureType> Base;
00085 
00087     typedef typename Base::IntensityType IntensityType;
00089     typedef typename Base::CoordinateType CoordinateType;
00091     typedef DoubleReal ProbabilityType;
00092 
00094     SimpleExtender(const MSExperiment<PeakType> * map, FeatureMap<FeatureType> * features, FeatureFinder * ff) :
00095       Base(map, features, ff),
00096       last_pos_extracted_()
00097     {
00098       this->setName("SimpleExtender");
00099 
00100       this->defaults_.setValue("dist_mz_up", 6.0, "Maximum high m/z distance of peak in the region/boundary from the seed.");
00101       this->defaults_.setMinFloat("dist_mz_up", 0.0);
00102       this->defaults_.setValue("dist_mz_down", 2.0, "Maximum low m/z distance of peak in the region/boundary from the seed.");
00103       this->defaults_.setMinFloat("dist_mz_down", 0.0);
00104       this->defaults_.setValue("dist_rt_up", 5.0, "Maximum high RT distance of peak in the region/boundary from the seed.");
00105       this->defaults_.setMinFloat("dist_rt_up", 0.0);
00106       this->defaults_.setValue("dist_rt_down", 5.0, "Maximum low RT distance of peak in the region/boundary from the seed.");
00107       this->defaults_.setMinFloat("dist_rt_down", 0.0);
00108 
00109       // priority check is per default switched off
00110       // these values were used for the Myoglobin quantification project
00111       // DON'T REMOVE THIS
00112       this->defaults_.setValue("priority_thr", -0.1, "Minimum priority for data points to be included into the boundary of the feature (default 0.0). The priority of a data point is a function of its intensity and its distance to the last point included into the feature region. Setting this threshold to zero or a very small value is usually a good idea.", StringList::create("advanced"));
00113 
00114       this->defaults_.setValue("intensity_factor", 0.03, "Influences for intensity (ion count) threshold in the feature extension. We include only raw data points into this region if their intensity is larger than [intensity_factor * (intensity of the seed)].");
00115       this->defaults_.setMinFloat("intensity_factor", 0.0);
00116       this->defaults_.setMaxFloat("intensity_factor", 1.0);
00117 
00118       this->defaultsToParam_();
00119     }
00120 
00122     virtual ~SimpleExtender()
00123     {
00124     }
00125 
00127     void extend(const ChargedIndexSet & seed_region, ChargedIndexSet & result_region)
00128     {
00129       // empty region and boundary datastructures
00130       result_region.clear();
00131       priorities_.clear();
00132       running_avg_.clear();
00133       boundary_ = std::priority_queue<IndexWithPriority, std::vector<IndexWithPriority>, typename IndexWithPriority::PriorityLess>();
00134 
00135 #ifdef DEBUG_FEATUREFINDER
00136       std::vector<IndexPair> debug_vector;
00137 #endif
00138       // find maximum of region (seed)
00139       CoordinateType max_intensity = 0.0;
00140       IndexPair seed;
00141 
00142       for (IndexSet::const_iterator citer = seed_region.begin(); citer != seed_region.end(); ++citer)
00143       {
00144         if (this->getPeakIntensity(*citer) > max_intensity)
00145         {
00146           seed = *citer;
00147           max_intensity = this->getPeakIntensity(seed);
00148         }
00149       }
00150 
00151       // remember last extracted point (in this case the seed !)
00152       last_pos_extracted_[Peak2D::RT] = this->getPeakRt(seed);
00153       last_pos_extracted_[Peak2D::MZ] = this->getPeakMz(seed);
00154 
00155       // Add peaks received from seeder directly to boundary
00156       for (IndexSet::const_iterator citer = seed_region.begin(); citer != seed_region.end(); ++citer)
00157       {
00158         ProbabilityType priority = computePeakPriority_(*citer);
00159         priorities_[*citer] = priority;
00160         boundary_.push(IndexWithPriority(*citer, priority));
00161       }
00162       // pass on charge information
00163       result_region.charge = seed_region.charge;
00164 
00165       // re-compute intensity threshold
00166       intensity_threshold_ = (DoubleReal)(this->param_).getValue("intensity_factor") * this->getPeakIntensity(seed);
00167 
00168 #ifdef DEBUG_FEATUREFINDER
00169       std::cout << "\n";
00170       std::cout << "Extending from " << this->getPeakRt(seed) << "/" << this->getPeakMz(seed) << std::endl;
00171       std::cout << "Intensity of seed " << this->getPeakIntensity(seed);
00172       std::cout << " (" << seed.first << "/" << seed.second << ")" << std::endl;
00173       std::cout << "Intensity_threshold: " << intensity_threshold_ << std::endl;
00174 #endif
00175 
00176       while (!boundary_.empty())
00177       {
00178         // remove peak with highest priority
00179         const IndexPair  current_index = boundary_.top().index;
00180         boundary_.pop();
00181 
00182         //  check for corrupt index
00183         OPENMS_PRECONDITION(current_index.first < (*this->map_).size(), "Scan index outside of map!");
00184         OPENMS_PRECONDITION(current_index.second < (*this->map_)[current_index.first].size(), "Peak index outside of scan!");
00185 
00186         // remember last extracted peak
00187         last_pos_extracted_[Peak2D::RT] = this->getPeakRt(current_index);
00188         last_pos_extracted_[Peak2D::MZ] = this->getPeakMz(current_index);
00189 
00190         // Now we explore the neighbourhood of the current peak. Points in this area are included
00191         // into the boundary if their intensity is not too low and they are not too
00192         // far away from the seed.
00193         // Add position to the current average of positions weighted by intensity
00194         running_avg_.add(last_pos_extracted_, this->getPeakIntensity(current_index));
00195 
00196         // explore neighbourhood of current peak
00197         moveMzUp_(current_index);
00198         moveMzDown_(current_index);
00199         moveRtUp_(current_index);
00200         moveRtDown_(current_index);
00201 
00202         // set peak flags and add to boundary
00203         this->ff_->getPeakFlag(current_index) = USED;
00204 #ifdef DEBUG_FEATUREFINDER
00205         debug_vector.push_back(current_index);
00206 #endif
00207         result_region.insert(current_index);
00208 
00209       }       // end of while ( !boundary_.empty() )
00210 
00211 #ifdef DEBUG_FEATUREFINDER
00212       std::cout << "Feature region size: " << result_region.size() << std::endl;
00213 #endif
00214 
00215 #ifdef DEBUG_FEATUREFINDER
00216       static UInt number = 1;
00217       writeDebugFile_(debug_vector, number++);
00218       debug_vector.clear();
00219 #endif
00220 
00221       return;
00222     }     // end of extend
00223 
00236     struct IndexWithPriority
00237     {
00238       IndexWithPriority(const FeatureFinderDefs::IndexPair & i, DoubleReal p) :
00239         index(i),
00240         priority(p)
00241       {
00242       }
00243 
00244       IndexPair index;
00245       ProbabilityType priority;
00246 
00248       struct PriorityLess
00249       {
00250         inline bool operator()(const IndexWithPriority & x, const IndexWithPriority & y) const
00251         {
00252           return x.priority < y.priority;
00253         }
00254 
00255       };
00256     };
00257 
00258 protected:
00259 
00260     virtual void updateMembers_()
00261     {
00262       dist_mz_up_ = this->param_.getValue("dist_mz_up");
00263       dist_mz_down_ = this->param_.getValue("dist_mz_down");
00264       dist_rt_up_ = this->param_.getValue("dist_rt_up");
00265       dist_rt_down_ = this->param_.getValue("dist_rt_down");
00266       priority_threshold_ = this->param_.getValue("priority_thr");
00267     }
00268 
00270     void writeDebugFile_(const std::vector<IndexPair> & peaks, UInt nr_feat)
00271     {
00272       String filename = String(nr_feat).fillLeft('0', 4) + "_Extension.dta2d";
00273       std::ofstream file(filename.c_str());
00274       for (Size i = 0; i < peaks.size(); ++i)
00275       {
00276         file << this->getPeakRt(peaks[i]) << " " << this->getPeakMz(peaks[i]) << " " << peaks.size() - i << std::endl;
00277       }
00278       file.close();
00279     }
00280 
00282     bool isTooFarFromCentroid_(const IndexPair & index)
00283     {
00284       //Corrupt index
00285       OPENMS_PRECONDITION(index.first < (*this->map_).size(), "Scan index outside of map!");
00286       OPENMS_PRECONDITION(index.second < (*this->map_)[index.first].size(), "Peak index outside of scan!");
00287 
00288       const DPosition<2> & curr_mean = running_avg_.getPosition();
00289 
00290       if (this->getPeakMz(index) > curr_mean[Peak2D::MZ] + dist_mz_up_   ||
00291           this->getPeakMz(index) < curr_mean[Peak2D::MZ] - dist_mz_down_ ||
00292           this->getPeakRt(index) > curr_mean[Peak2D::RT] + dist_rt_up_   ||
00293           this->getPeakRt(index) < curr_mean[Peak2D::RT] - dist_rt_down_)
00294       {
00295         //too far
00296         return true;
00297       }
00298 
00299       //close enough
00300       return false;
00301     }
00302 
00304     void moveMzUp_(const IndexPair & index)
00305     {
00306       try
00307       {
00308         IndexPair tmp = index;
00309         while (true)
00310         {
00311           this->getNextMz(tmp);
00312           if (isTooFarFromCentroid_(tmp)) break;
00313           checkNeighbour_(tmp);
00314         }
00315       }
00316       catch (NoSuccessor)
00317       {
00318       }
00319     }
00320 
00322     void moveMzDown_(const IndexPair & index)
00323     {
00324       try
00325       {
00326         IndexPair tmp = index;
00327         while (true)
00328         {
00329           this->getPrevMz(tmp);
00330           if (isTooFarFromCentroid_(tmp)) break;
00331           checkNeighbour_(tmp);
00332         }
00333       }
00334       catch (NoSuccessor)
00335       {
00336       }
00337     }
00338 
00340     void moveRtUp_(const IndexPair & index)
00341     {
00342       try
00343       {
00344         IndexPair tmp = index;
00345 
00346         while (true)
00347         {
00348           this->getNextRt(tmp);
00349           if (isTooFarFromCentroid_(tmp)) break;
00350           checkNeighbour_(tmp);
00351         }
00352       }
00353       catch (NoSuccessor)
00354       {
00355       }
00356     }
00357 
00359     void moveRtDown_(const IndexPair & index)
00360     {
00361       try
00362       {
00363         IndexPair tmp = index;
00364         while (true)
00365         {
00366           this->getPrevRt(tmp);
00367           if (isTooFarFromCentroid_(tmp)) break;
00368           checkNeighbour_(tmp);
00369         }
00370       }
00371       catch (NoSuccessor)
00372       {
00373       }
00374     }
00375 
00377     ProbabilityType computePeakPriority_(const IndexPair & index)
00378     {
00379       return (*this->map_)[index.first][index.second].getIntensity();
00380     }
00381 
00383     void checkNeighbour_(const IndexPair & index)
00384     {
00385       //Corrupt index
00386       OPENMS_PRECONDITION(index.first < (*this->map_).size(), "Scan index outside of map!");
00387       OPENMS_PRECONDITION(index.second < (*this->map_)[index.first].size(), "Peak index outside of scan!");
00388 
00389       // skip this point if its intensity is too low
00390       if (this->getPeakIntensity(index) <= intensity_threshold_)
00391       {
00392         return;
00393       }
00394       if (this->ff_->getPeakFlag(index) == UNUSED)
00395       {
00396         DoubleReal pr_new = computePeakPriority_(index);
00397 
00398         if (pr_new > priority_threshold_)
00399         {
00400           //std::map<IndexPair, DoubleReal>::iterator piter = priorities_.find(index);
00401           this->ff_->getPeakFlag(index) = USED;
00402           priorities_[index] = pr_new;
00403           boundary_.push(IndexWithPriority(index, pr_new));
00404         }
00405       }
00406     }
00407 
00409     Math::AveragePosition<2> running_avg_;
00410 
00412     std::map<IndexPair, ProbabilityType> priorities_;
00413 
00415     DPosition<2> last_pos_extracted_;
00416 
00418     std::priority_queue<IndexWithPriority, std::vector<IndexWithPriority>, typename IndexWithPriority::PriorityLess> boundary_;
00419 
00421     IntensityType intensity_threshold_;
00422 
00424     CoordinateType dist_mz_up_;
00426     CoordinateType dist_mz_down_;
00428     CoordinateType dist_rt_up_;
00430     CoordinateType dist_rt_down_;
00431 
00433     ProbabilityType priority_threshold_;
00434 
00436     ChargedIndexSet region_;
00437 
00438 private:
00440     SimpleExtender();
00442     SimpleExtender & operator=(const SimpleExtender &);
00444     SimpleExtender(const SimpleExtender &);
00445 
00446   };
00447 }
00448 #endif // OPENMS_TRANSFORMATIONS_FEATUREFINDER_SIMPLEEXTENDER_H

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