41 const int n =
static_cast<int>(data.size());
42 VectorXd proms(peakIndices.size());
44 for (
int p = 0; p < peakIndices.size(); ++p) {
45 int idx = peakIndices[p];
46 double peakVal = data(idx);
49 double leftMin = peakVal;
50 for (
int i = idx - 1; i >= 0; --i) {
51 if (data(i) > peakVal)
53 leftMin = std::min(leftMin, data(i));
57 double rightMin = peakVal;
58 for (
int i = idx + 1; i < n; ++i) {
59 if (data(i) > peakVal)
61 rightMin = std::min(rightMin, data(i));
65 double highestValley = std::max(leftMin, rightMin);
66 proms(p) = peakVal - highestValley;
77 const int n =
static_cast<int>(data.size());
78 QList<QPair<int, double>> peaks;
86 for (
int i = 1; i < n - 1; ++i) {
87 if (data(i) > data(i - 1) && data(i) > data(i + 1)) {
95 if (params.
dProminence > 0.0 && !peakIdx.isEmpty()) {
98 for (
int i = 0; i < peakIdx.size(); ++i) {
100 filtered.append(peakIdx[i]);
109 std::vector<int> sortedIdx(peakIdx.begin(), peakIdx.end());
110 std::sort(sortedIdx.begin(), sortedIdx.end(),
111 [&data](
int a,
int b) { return data(a) > data(b); });
114 std::vector<bool> suppressed(
static_cast<size_t>(n),
false);
116 for (
int idx : sortedIdx) {
117 if (suppressed[
static_cast<size_t>(idx)])
124 for (
int s = lo; s <= hi; ++s) {
126 suppressed[
static_cast<size_t>(s)] =
true;
132 std::sort(kept.begin(), kept.end());
137 for (
int idx : peakIdx) {
138 peaks.append(qMakePair(idx, data(idx)));
149 QList<QPair<int, double>> result;
150 const Index s = data.size();
153 if (std::isnan(thresh))
154 thresh = (data.maxCoeff() - data.minCoeff()) / 4.0;
155 const VectorXd x0 = extrema < 0 ? VectorXd(-data) : data;
158 std::vector<Index> ind{0};
159 for (Index i = 1; i + 1 < s; ++i) {
160 double left = x0(i) - x0(i - 1);
161 double right = x0(i + 1) - x0(i);
163 left = -std::numeric_limits<double>::epsilon();
165 right = -std::numeric_limits<double>::epsilon();
166 if (left * right < 0.0)
169 ind.push_back(s - 1);
170 std::vector<double> x(ind.size());
171 for (std::size_t i = 0; i < ind.size(); ++i)
174 const double minMag = *std::min_element(x.begin(), x.end());
175 std::vector<Index> peakInds;
176 std::vector<double> peakMags;
178 double tempMag = minMag;
179 double leftMin = minMag;
180 bool foundPeak =
false;
182 const auto sign = [](
double v) {
183 return (v > 0.0) - (v < 0.0);
185 const int sign0 = sign(x[1] - x[0]);
186 const int sign1 = sign(x[2] - x[1]);
190 if (sign0 == sign1) {
191 x.erase(x.begin() + 1);
192 ind.erase(ind.begin() + 1);
194 }
else if (sign0 == sign1) {
196 ind.erase(ind.begin());
198 const long length =
static_cast<long>(x.size());
200 const std::size_t maxPeaks =
static_cast<std::size_t
>(std::ceil(length / 2.0));
201 const auto lastSlot = [&]() {
202 return peakMags.size() == maxPeaks ? peakMags.back() : 0.0;
204 while (ii < length - 1) {
206 if (foundPeak && (x[ii] > lastSlot() || leftMin < lastSlot() - thresh)) {
210 if (ii == length - 1)
212 if (x[ii] > tempMag && x[ii] > leftMin + thresh) {
217 if (!foundPeak && tempMag > thresh + x[ii]) {
220 peakInds.push_back(tempLoc);
221 peakMags.push_back(tempMag);
222 }
else if (x[ii] < leftMin) {
226 if (x.back() > tempMag && x.back() > leftMin + thresh) {
227 peakInds.push_back(length - 1);
228 peakMags.push_back(x.back());
229 }
else if (!foundPeak && tempMag > minMag) {
230 peakInds.push_back(tempLoc);
231 peakMags.push_back(tempMag);
233 for (std::size_t k = 0; k < peakInds.size(); ++k)
234 result.append(qMakePair(
static_cast<int>(ind[peakInds[k]]), extrema < 0 ? -peakMags[k] : peakMags[k]));
236 const auto best = std::max_element(x.begin(), x.end());
237 if (*best > minMag + thresh)
238 result.append(qMakePair(
static_cast<int>(ind[best - x.begin()]), extrema < 0 ? -*best : *best));
Local-maxima peak detection in 1-D signals with prominence filtering.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
DSPSHARED_EXPORT QList< QPair< int, double > > peakFinder(const Eigen::VectorXd &data, const PeakFinderParams ¶ms=PeakFinderParams())
Find peaks in a 1D signal.
DSPSHARED_EXPORT Eigen::VectorXd peakProminences(const Eigen::VectorXd &data, const QList< int > &peakIndices)
Compute prominence of each peak.
DSPSHARED_EXPORT QList< QPair< int, double > > peakFinderMne(const Eigen::VectorXd &data, double thresh=std::numeric_limits< double >::quiet_NaN(), int extrema=1)
Noise-tolerant extrema search of mne.preprocessing.peak_finder.