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_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
00110
00111
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
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
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
00152 last_pos_extracted_[Peak2D::RT] = this->getPeakRt(seed);
00153 last_pos_extracted_[Peak2D::MZ] = this->getPeakMz(seed);
00154
00155
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
00163 result_region.charge = seed_region.charge;
00164
00165
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
00179 const IndexPair current_index = boundary_.top().index;
00180 boundary_.pop();
00181
00182
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
00187 last_pos_extracted_[Peak2D::RT] = this->getPeakRt(current_index);
00188 last_pos_extracted_[Peak2D::MZ] = this->getPeakMz(current_index);
00189
00190
00191
00192
00193
00194 running_avg_.add(last_pos_extracted_, this->getPeakIntensity(current_index));
00195
00196
00197 moveMzUp_(current_index);
00198 moveMzDown_(current_index);
00199 moveRtUp_(current_index);
00200 moveRtDown_(current_index);
00201
00202
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 }
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 }
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
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
00296 return true;
00297 }
00298
00299
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
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
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
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