Visual Vibration Tracking 0.2
Загрузка...
Поиск...
Не найдено
Функции
PeakFinder

Функции

void PeakFinder::findPeaks (std::vector< float > x0, std::vector< int > &peakInds, bool includeEndpoints=true, float extrema=1)
 

Подробное описание

Функции

◆ findPeaks()

void PeakFinder::findPeaks ( std::vector< float >  x0,
std::vector< int > &  peakInds,
bool  includeEndpoints = true,
float  extrema = 1 
)
Аргументы
x0входной массив
extrema1 - если нужен максимум, -1 - если нужен минимум
includeEndpointstrue - если границы интервала входного массива x0 должны быть включены в поиск пика, false - в противном случае
Возвращает
peakInds: индексы пиков, найденные в x0

См. определение в файле peak_finder.cpp строка 66

67{
68 int minIdx = distance(x0.begin(), min_element(x0.begin(), x0.end()));
69 int maxIdx = distance(x0.begin(), max_element(x0.begin(), x0.end()));
70
71 float sel = (x0[maxIdx]-x0[minIdx])/4.0;
72 int len0 = x0.size();
73
74 scalarProduct(extrema, x0, x0);
75
76 std::vector<float> dx;
77 diff(x0, dx);
78 replace(dx.begin(), dx.end(), 0.0f, -PeakFinder::EPS);
79 std::vector<float> dx0(dx.begin(), dx.end()-1);
80 std::vector<float> dx0_1(dx.begin()+1, dx.end());
81 std::vector<float> dx0_2;
82
83 vectorElementsProduct(dx0, dx0_1, dx0_2);
84
85 std::vector<int> ind;
86 findIndicesLessThan(dx0_2, 0, ind); // Find where the derivative changes sign
87 std::vector<float> x;
88 float leftMin;
89 int minMagIdx;
90 float minMag;
91
92 if(includeEndpoints)
93 {
94 //x = [x0(1);x0(ind);x0(end)];
95 selectElementsFromIndices(x0, ind, x);
96 x.insert(x.begin(), x0[0]);
97 x.insert(x.end(), x0[x0.size()-1]);
98 //ind = [1;ind;len0];
99 ind.insert(ind.begin(), 1);
100 ind.insert(ind.end(), len0);
101 minMagIdx = distance(x.begin(), std::min_element(x.begin(), x.end()));
102 minMag = x[minMagIdx];
103 //std::cout<<"Hola"<<std::endl;
104 leftMin = minMag;
105 }
106 else
107 {
108 selectElementsFromIndices(x0, ind, x);
109 if(x.size()>2)
110 {
111 minMagIdx = distance(x.begin(), std::min_element(x.begin(), x.end()));
112 minMag = x[minMagIdx];
113 leftMin = x[0]<x0[0]?x[0]:x0[0];
114 }
115 }
116
117 int len = x.size();
118
119 if(len>2)
120 {
121 float tempMag = minMag;
122 bool foundPeak = false;
123 int ii;
124
125 if(includeEndpoints)
126 {
127 // Deal with first point a little differently since tacked it on
128 // Calculate the sign of the derivative since we tacked the first
129 // point on it does not neccessarily alternate like the rest.
130 std::vector<float> xSub0(x.begin(), x.begin()+3);//tener cuidado subvector
131 std::vector<float> xDiff;//tener cuidado subvector
132 diff(xSub0, xDiff);
133
134 std::vector<int> signDx;
135 signVector(xDiff, signDx);
136
137 if (signDx[0] <= 0) // The first point is larger or equal to the second
138 {
139 if (signDx[0] == signDx[1]) // Want alternating signs
140 {
141 x.erase(x.begin()+1);
142 ind.erase(ind.begin()+1);
143 len = len-1;
144 }
145 }
146 else // First point is smaller than the second
147 {
148 if (signDx[0] == signDx[1]) // Want alternating signs
149 {
150 x.erase(x.begin());
151 ind.erase(ind.begin());
152 len = len-1;
153 }
154 }
155 }
156
157 //Skip the first point if it is smaller so we always start on maxima
158 if ( x[0] >= x[1] )
159 ii = 0;
160 else
161 ii = 1;
162
163 //Preallocate max number of maxima
164 float maxPeaks = ceil((float)len/2.0);
165 std::vector<int> peakLoc(maxPeaks,0);
166 std::vector<float> peakMag(maxPeaks,0.0);
167 int cInd = 1;
168 int tempLoc = 0;
169
170 while(ii < len)
171 {
172 ii = ii+1;//This is a peak
173 //Reset peak finding if we had a peak and the next peak is bigger
174 //than the last or the left min was small enough to reset.
175 if(foundPeak)
176 {
177 tempMag = minMag;
178 foundPeak = false;
179 }
180
181 //Found new peak that was lager than temp mag and selectivity larger
182 //than the minimum to its left.
183
184 if( x[ii-1] > tempMag && x[ii-1] > leftMin + sel )
185 {
186 tempLoc = ii-1;
187 tempMag = x[ii-1];
188 }
189
190 //Make sure we don't iterate past the length of our vector
191 if(ii == len)
192 break; //We assign the last point differently out of the loop
193
194 ii = ii+1; // Move onto the valley
195
196 //Come down at least sel from peak
197 if(!foundPeak && tempMag > sel + x[ii-1])
198 {
199 foundPeak = true; //We have found a peak
200 leftMin = x[ii-1];
201 peakLoc[cInd-1] = tempLoc; // Add peak to index
202 peakMag[cInd-1] = tempMag;
203 cInd = cInd+1;
204 }
205 else if(x[ii-1] < leftMin) // New left minima
206 leftMin = x[ii-1];
207
208 }
209
210 // Check end point
211 if(includeEndpoints)
212 {
213 if ( x[x.size()-1] > tempMag && x[x.size()-1] > leftMin + sel )
214 {
215 peakLoc[cInd-1] = len-1;
216 peakMag[cInd-1] = x[x.size()-1];
217 cInd = cInd + 1;
218 }
219 else if( !foundPeak && tempMag > minMag )// Check if we still need to add the last point
220 {
221 peakLoc[cInd-1] = tempLoc;
222 peakMag[cInd-1] = tempMag;
223 cInd = cInd + 1;
224 }
225 }
226 else if(!foundPeak)
227 {
228 float minAux = x0[x0.size()-1]<x[x.size()-1]?x0[x0.size()-1]:x[x.size()-1];
229 if ( x[x.size()-1] > tempMag && x[x.size()-1] > leftMin + sel )
230 {
231 peakLoc[cInd-1] = len-1;
232 peakMag[cInd-1] = x[x.size()-1];
233 cInd = cInd + 1;
234 }
235 else if( !tempMag > minAux + sel)// Check if we still need to add the last point
236 {
237 peakLoc[cInd-1] = tempLoc;
238 peakMag[cInd-1] = tempMag;
239 cInd = cInd + 1;
240 }
241 }
242
243 //Create output
244 if( cInd > 0 )
245 {
246 std::vector<int> peakLocTmp(peakLoc.begin(), peakLoc.begin()+cInd-1);
247 selectElementsFromIndices(ind, peakLocTmp, peakInds);
248 }
249
250 }
251 //else
252 //{
253 //input signal length <= 2
254 //}
255}