OpenMS
Loading...
Searching...
No Matches
KERNEL/PeakTypeEstimator.h
Go to the documentation of this file.
1// Copyright (c) 2002-present, OpenMS Inc. -- EKU Tuebingen, ETH Zurich, and FU Berlin
2// SPDX-License-Identifier: BSD-3-Clause
3//
4// --------------------------------------------------------------------------
5// $Maintainer: Chris Bielow $
6// $Authors: Chris Bielow $
7// --------------------------------------------------------------------------
8
9#pragma once
10
12
13#include <limits>
14#include <cmath>
15#include <numeric>
16#include <vector>
17
18namespace OpenMS
19{
25 class OPENMS_DLLAPI PeakTypeEstimator
26 {
27public:
44 template <typename PeakConstIterator>
45 static SpectrumSettings::SpectrumType estimateType(const PeakConstIterator& begin, const PeakConstIterator& end)
46 {
47 typedef typename PeakConstIterator::value_type PeakT;
48 // abort if there are less than 5 peak in the iterator range
49 if (end - begin < 5)
50 {
51 return SpectrumSettings::SpectrumType::UNKNOWN;
52 }
53
54 const int max_peaks = 5; // maximal number of peaks we are looking at
55 int profile_evidence = 0; // number of peaks found to be profile
56 int centroid_evidence = 0; // number of peaks found to be centroided
57
58 // copy data, since we need to modify
59 std::vector<PeakT> data(begin, end);
60 // total intensity of spectrum
61 double total_int = std::accumulate(begin, end, 0.0, [](double int_, const PeakT& p) { return int_ + p.getIntensity(); } );
62 double explained_int = 0;
63 // get the 5 highest peaks
64 for (int i = 0; i < max_peaks; ++i)
65 {
66 // stop if we explained +50% of all intensity
67 // (due to danger of interpreting noise - usually wrongly classified as centroided data)
68 if (explained_int > 0.5 * total_int) break;
69
70 double int_max = 0;
71 Size idx = std::numeric_limits<Size>::max();
72 // find highest peak position
73 for (Size i = 0; i < data.size(); ++i)
74 {
75 if (data[i].getIntensity() > int_max)
76 {
77 int_max = data[i].getIntensity();
78 idx = i;
79 }
80 }
81 // no more peaks
82 if (idx == std::numeric_limits<Size>::max()) break;
83
84 // check left and right peak shoulders and count number of sample points
85 typedef typename std::vector<PeakT>::iterator PeakIterator; // non-const version, since we need to modify the peaks
86 PeakIterator it_max = data.begin() + idx;
87 PeakIterator it = it_max;
88 double int_last = int_max;
89 while (it != data.begin()
90 && it->getIntensity() <= int_last // at most 100% of last sample point
91 && it->getIntensity() > 0
92 && (it->getIntensity() / int_last) > 0.1 // at least 10% of last sample point
93 && it->getMZ() + 1 > it_max->getMZ()) // at most 1 Th away
94 {
95 int_last = it->getIntensity();
96 explained_int += int_last;
97 it->setIntensity(0); // remove peak from future consideration
98 --it;
99 }
100 // if the current point is rising again, restore the intensity of the
101 // previous 'sink' point (because it could belong to a neighbour peak)
102 // e.g. imagine intensities: 1-2-3-2-1-2-4-2-1. We do not want to destroy the middle '1'
103 if (it->getIntensity() > int_last) (it+1)->setIntensity(int_last);
104
105 //std::cerr << " Peak candidate: " << it_max->getMZ() << " ...";
106 bool break_left = false;
107 if (it_max - it < 2+1) // 'it' does not fulfill the conditions, i.e. does not count
108 { // fewer than two sampling points on left shoulder
109 //std::cerr << " break left " << it_max - it << " points\n";
110 break_left = true;
111 // do not end loop here.. we still need to clean up the right side
112 }
113 it_max->setIntensity(int_max); // restore center intensity
114 explained_int -= int_max;
115 it = it_max;
116 int_last = int_max;
117 while (it != data.end()
118 && it->getIntensity() <= int_last // at most 100% of last sample point
119 && it->getIntensity() > 0
120 && (it->getIntensity() / int_last) > 0.1 // at least 10% of last sample point
121 && it->getMZ() - 1 < it_max->getMZ()) // at most 1 Th away
122 {
123 int_last = it->getIntensity();
124 explained_int += int_last;
125 it->setIntensity(0); // remove peak from future consideration
126 ++it;
127 }
128 // if the current point is rising again, restore the intensity of the
129 // previous 'sink' point (because it could belong to a neighbour peak)
130 // e.g. imagine intensities: 1-2-4-2-1-2-3-2-1. We do not want to destroy the middle '1'
131 // (note: the sequence is not identical to the one of the left shoulder)
132 if (it != data.end() && it->getIntensity() > int_last) (it-1)->setIntensity(int_last);
133
134 if (break_left || it - it_max < 2+1) // 'it' does not fulfill the conditions, i.e. does not count
135 { // fewer than two sampling points on right shoulder
136 //std::cerr << " break right " << it - it_max << " points\n";
137 ++centroid_evidence;
138 continue;
139 }
140 // peak has at least two sampling points on either side within 1 Th
141 ++profile_evidence;
142 //std::cerr << " PROFILE " << it - it_max << " points right\n";
143
144 }
145
146 float evidence_ratio = profile_evidence / float(profile_evidence + centroid_evidence);
147 //std::cerr << "--> Evidence ratio: " << evidence_ratio;
148
149 if (evidence_ratio > 0.75) // 80% are profile
150 {
151 //std::cerr << " PROFILE\n";
152 return SpectrumSettings::SpectrumType::PROFILE;
153 }
154 else
155 {
156 //std::cerr << " CENTROID\n";
157 return SpectrumSettings::SpectrumType::CENTROID;
158 }
159 }
246 };
247
248} // namespace OpenMS
Estimates if the data of a spectrum is raw data or peak data.
Definition KERNEL/PeakTypeEstimator.h:26
static SpectrumSettings::SpectrumType estimateType(const PeakConstIterator &begin, const PeakConstIterator &end)
Estimates the peak type of the peaks in the iterator range based on intensity characteristics of up t...
Definition KERNEL/PeakTypeEstimator.h:45
SpectrumType
Spectrum peak type.
Definition SpectrumSettings.h:48
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition Types.h:97
Main OpenMS namespace.
Definition openswathalgo/include/OpenMS/OPENSWATHALGO/DATAACCESS/ISpectrumAccess.h:19