#include "peak_finder.h" #include #include #include #include namespace graft_cv { void diff(std::vector in, std::vector& out) { out = std::vector(in.size() - 1); for (int i = 1; i a, std::vector b, std::vector& out) { out = std::vector(a.size()); for (int i = 0; i in, float threshold, std::vector& indices) { for (int i = 0; i in, std::vector indices, std::vector& out) { for (int i = 0; i in, std::vector indices, std::vector& out) { for (int i = 0; i in, std::vector& out) { out = std::vector(in.size()); for (int i = 0; i0) out[i] = 1; else if (in[i]<0) out[i] = -1; else out[i] = 0; } } void scalarProduct(float scalar, std::vector in, std::vector& out) { out = std::vector(in.size()); for (int i = 0; i x0, std::vector& peakInds, bool includeEndpoints, float extrema) { int minIdx = distance(x0.begin(), min_element(x0.begin(), x0.end())); int maxIdx = distance(x0.begin(), max_element(x0.begin(), x0.end())); float sel = (x0[maxIdx] - x0[minIdx]) / 4.0; int len0 = x0.size(); scalarProduct(extrema, x0, x0); std::vector dx; diff(x0, dx); replace(dx.begin(), dx.end(), 0.0f, - EPS); std::vector dx0(dx.begin(), dx.end() - 1); std::vector dx0_1(dx.begin() + 1, dx.end()); std::vector dx0_2; vectorElementsProduct(dx0, dx0_1, dx0_2); std::vector ind; findIndicesLessThan(dx0_2, 0, ind); // Find where the derivative changes sign std::vector x; float leftMin; int minMagIdx; float minMag; if (includeEndpoints) { //x = [x0(1);x0(ind);x0(end)]; selectElementsFromIndices(x0, ind, x); x.insert(x.begin(), x0[0]); x.insert(x.end(), x0[x0.size() - 1]); //ind = [1;ind;len0]; ind.insert(ind.begin(), 1); ind.insert(ind.end(), len0); minMagIdx = distance(x.begin(), std::min_element(x.begin(), x.end())); minMag = x[minMagIdx]; //std::cout<<"Hola"<2) { minMagIdx = distance(x.begin(), std::min_element(x.begin(), x.end())); minMag = x[minMagIdx]; leftMin = x[0]2) { float tempMag = minMag; bool foundPeak = false; int ii; if (includeEndpoints) { // Deal with first point a little differently since tacked it on // Calculate the sign of the derivative since we tacked the first // point on it does not neccessarily alternate like the rest. std::vector xSub0(x.begin(), x.begin() + 3);//tener cuidado subvector std::vector xDiff;//tener cuidado subvector diff(xSub0, xDiff); std::vector signDx; signVector(xDiff, signDx); if (signDx[0] <= 0) // The first point is larger or equal to the second { if (signDx[0] == signDx[1]) // Want alternating signs { x.erase(x.begin() + 1); ind.erase(ind.begin() + 1); len = len - 1; } } else // First point is smaller than the second { if (signDx[0] == signDx[1]) // Want alternating signs { x.erase(x.begin()); ind.erase(ind.begin()); len = len - 1; } } } //Skip the first point if it is smaller so we always start on maxima if (x[0] >= x[1]) ii = 0; else ii = 1; //Preallocate max number of maxima float maxPeaks = ceil((float)len / 2.0); std::vector peakLoc(maxPeaks, 0); std::vector peakMag(maxPeaks, 0.0); int cInd = 1; int tempLoc; while (ii < len) { ii = ii + 1;//This is a peak //Reset peak finding if we had a peak and the next peak is bigger //than the last or the left min was small enough to reset. if (foundPeak) { tempMag = minMag; foundPeak = false; } //Found new peak that was lager than temp mag and selectivity larger //than the minimum to its left. if (x[ii - 1] > tempMag && x[ii - 1] > leftMin + sel) { tempLoc = ii - 1; tempMag = x[ii - 1]; } //Make sure we don't iterate past the length of our vector if (ii == len) break; //We assign the last point differently out of the loop ii = ii + 1; // Move onto the valley //Come down at least sel from peak if (!foundPeak && tempMag > sel + x[ii - 1]) { foundPeak = true; //We have found a peak leftMin = x[ii - 1]; peakLoc[cInd - 1] = tempLoc; // Add peak to index peakMag[cInd - 1] = tempMag; cInd = cInd + 1; } else if (x[ii - 1] < leftMin) // New left minima leftMin = x[ii - 1]; } // Check end point if (includeEndpoints) { if (x[x.size() - 1] > tempMag && x[x.size() - 1] > leftMin + sel) { peakLoc[cInd - 1] = len - 1; peakMag[cInd - 1] = x[x.size() - 1]; cInd = cInd + 1; } else if (!foundPeak && tempMag > minMag)// Check if we still need to add the last point { peakLoc[cInd - 1] = tempLoc; peakMag[cInd - 1] = tempMag; cInd = cInd + 1; } } else if (!foundPeak) { float minAux = x0[x0.size() - 1] tempMag && x[x.size() - 1] > leftMin + sel) { peakLoc[cInd - 1] = len - 1; peakMag[cInd - 1] = x[x.size() - 1]; cInd = cInd + 1; } else if (!tempMag > minAux + sel)// Check if we still need to add the last point { peakLoc[cInd - 1] = tempLoc; peakMag[cInd - 1] = tempMag; cInd = cInd + 1; } } //Create output if (cInd > 0) { std::vector peakLocTmp(peakLoc.begin(), peakLoc.begin() + cInd - 1); selectElementsFromIndices(ind, peakLocTmp, peakInds); } } //else //{ //input signal length <= 2 //} } void indexPeaks( std::vector&stem_width, std::vector&peak_indices, float mu, std::vector& peak_power) { int radius = 10; for (int& pos : peak_indices) { /*float left_min, right_min; left_min = right_min = stem_width.at(pos); for (int i = pos - radius; i < pos; ++i) { if (i < 0) { continue; } if (stem_width.at(i) <= 0) { continue; } if (stem_width.at(i) < left_min) { left_min = stem_width.at(i); } } for (int i = pos+1 ; i <= pos- radius; ++i) { if (i >= stem_width.size()) { break; } if (stem_width.at(i) <= 0) { continue; } if (stem_width.at(i) < right_min) { right_min = stem_width.at(i); } } left_min = 0.5 * (right_min + left_min); float h = stem_width.at(pos) - left_min; float r = 1.0 -fabs(left_min - mu) / mu; float power = h*r;*/ std::vectortmp; for (int i = pos - radius; i < pos + radius; ++i) { if (i < 0) { continue; } if (i >= stem_width.size()) { break; } if (stem_width.at(i) == 0) { continue; } tmp.push_back(stem_width.at(i)); } //median if (tmp.size() > 0) { std::sort(tmp.begin(), tmp.end()); float median = tmp.at(int(tmp.size() / 2.0)); float power = stem_width.at(pos) - median; peak_power.push_back(power); } else { peak_power.push_back(0.0); } } } }