Reputation: 91640
I essentially have a bunch of data objects which map timestamps in milliseconds to float values. I'm looking to essentially find the peak/max of the data in a given range. I've been essentially using something like this:
float previousValue = 0;
for (int i = 0; i < data.size(); i++) {
MyData value = data.get(i);
if (value.getData() < previousValue) {
// found the peak!
break;
} else {
previousValue = value.getData();
}
}
The only problem with this algorithm is that it doesn't account for noise. Essentially, I could have values like this:
[0.1025, 0.3000, 0.3025, 0.3500, 0.3475, 0.3525, 0.1025]
The actual peak is at 0.3525, but my algorithm above would see it as 0.3500, as it comes first. Due to the nature of my calculations, I can't just do max()
on the array and find out the largest value, I need to find the largest value that comes first before it falls.
How can I find the top of my peak, while accounting for some variance in noise?
Upvotes: 0
Views: 177
Reputation: 1
an easier method to find a single peak (or the highest value) in an array (any numeric array: int, double) is to loop through the array and set a variable to the highest value...
Example: (all examples use a float array called "data")
float highest = 0; //use a number equal to or below the lowest possible value
for (int i = 0; i < data.length; i++){
if (data[i] > highest){
highest = data[i];
}
}
to find multiple peaks in noisy data filtering some of the noise out I used this method:
boolean[] isPeak = new boolean[20]; // I am looking for 20 highest peaks
float[] filter = new float[9]; // the range to which I want to define a peak is 9
float[] peaks = new float[20]; // again the 20 peaks I want to find
float lowpeak = 100; // use a value higher than the highest possible value
// first we start the filter cycling through the data
for (int i = 0; i < data.length; i++){
for (int a = filter.length-1; a > 0; a--){
filter[a] = filter[a-1];
}
filter[0] = data[1]
// now we check to see if the filter detects a peak
if (filter[4]>filter[0] && filter[4]>filter[1] && filter[4]>filter[2] &&
filter[4]>filter[3] && filter[4]>filter[5] && filter[4]>filter[6] &&
filter[4]>filter[7] && filter[4]>filter[8]){
// now we find the lowest peak
for (int x = 0; x < peaks.lengt-1; x++){
if (peaks[x] < lowpeak){
lowpeak = peaks[x];
}
}
// now we check to see if the peak is above the lowest peak
for (int x = 0; x < peaks.length; x++){
if (peaks[x] > lowpeak && peaks[x] != peaks[x+1]){
for (int y = peaks.length-1; y > 0 && !isPeak[y]; y--){
peaks[y] = peaks[y-1];
}
peaks[0] = filter[4];
}
}
}
}
this may not be the most efficient way to do this but it gets the job done!
Upvotes: 0
Reputation: 500367
There are two issues:
It seems like you already have a solution for 2, and need to solve 1.
To filter out the noise, you need some kind of low-pass filter. A moving average is one such filter. For example, exponential moving average is very easy to implement and should work well.
In summary: put your series through the filter, and then apply the peak finding algorithm.
Upvotes: 1