ref #6 peak detection implementiert, noch ohne prominence faktor von matlab. läuft aber gut
This commit is contained in:
@@ -3,6 +3,7 @@ import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
@@ -15,6 +16,9 @@ public class Main {
|
||||
File[] listOfFiles = folder.listFiles();
|
||||
Utils.ShowPNG windowRaw = new Utils.ShowPNG();
|
||||
Utils.ShowPNG windowAuto = new Utils.ShowPNG();
|
||||
Utils.ShowPNG windowPeaksX = new Utils.ShowPNG();
|
||||
Utils.ShowPNG windowPeaksY = new Utils.ShowPNG();
|
||||
Utils.ShowPNG windowPeaksZ = new Utils.ShowPNG();
|
||||
|
||||
// iterate trough files in measurements folder
|
||||
for (File file : listOfFiles) {
|
||||
@@ -78,10 +82,50 @@ public class Main {
|
||||
windowAuto.set(plotCorr.draw());
|
||||
|
||||
//find peaks
|
||||
LinkedList<Integer> peaksX = Utils.findPeaks(xAutoCorr, 50, 0.1f, 0, false);
|
||||
|
||||
double[] dPeaksXX = IntStream.range(0, peaksX.size()).mapToDouble(i -> (peaksX.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
|
||||
double[] dPeaksXY = IntStream.range(0, peaksX.size()).mapToDouble(i -> (dXAuto[peaksX.get(i)])).toArray();
|
||||
Plot plotPeaksX = Plot.plot(Plot.plotOpts().
|
||||
title("Peak Detection on X").
|
||||
legend(Plot.LegendFormat.BOTTOM)).
|
||||
series("x", Plot.data().xy(rangeAuto, dXAuto), Plot.seriesOpts().color(Color.RED)).
|
||||
series("Peaks", Plot.data().xy(dPeaksXX, dPeaksXY), Plot.seriesOpts().color(Color.CYAN).
|
||||
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
|
||||
|
||||
windowPeaksX.set(plotPeaksX.draw());
|
||||
|
||||
LinkedList<Integer> peaksY = Utils.findPeaks(yAutoCorr, 50, 0.1f, 0, false);
|
||||
|
||||
double[] dPeaksYX = IntStream.range(0, peaksY.size()).mapToDouble(i -> (peaksY.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
|
||||
double[] dPeaksYY = IntStream.range(0, peaksY.size()).mapToDouble(i -> (dYAuto[peaksY.get(i)])).toArray();
|
||||
Plot plotPeaksY = Plot.plot(Plot.plotOpts().
|
||||
title("Peak Detection on Y").
|
||||
legend(Plot.LegendFormat.BOTTOM)).
|
||||
series("x", Plot.data().xy(rangeAuto, dYAuto), Plot.seriesOpts().color(Color.RED)).
|
||||
series("Peaks", Plot.data().xy(dPeaksYX, dPeaksYY), Plot.seriesOpts().color(Color.CYAN).
|
||||
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
|
||||
|
||||
windowPeaksY.set(plotPeaksY.draw());
|
||||
|
||||
LinkedList<Integer> peaksZ = Utils.findPeaks(zAutoCorr, 50, 0.1f, 0, false);
|
||||
|
||||
double[] dPeaksZX = IntStream.range(0, peaksZ.size()).mapToDouble(i -> (peaksZ.get(i) - 1024)).toArray();//peaks.stream().mapToDouble(i->i).toArray();
|
||||
double[] dPeaksZY = IntStream.range(0, peaksZ.size()).mapToDouble(i -> (dZAuto[peaksZ.get(i)])).toArray();
|
||||
Plot plotPeaksZ = Plot.plot(Plot.plotOpts().
|
||||
title("Peak Detection on Z").
|
||||
legend(Plot.LegendFormat.BOTTOM)).
|
||||
series("x", Plot.data().xy(rangeAuto, dZAuto), Plot.seriesOpts().color(Color.RED)).
|
||||
series("Peaks", Plot.data().xy(dPeaksZX, dPeaksZY), Plot.seriesOpts().color(Color.CYAN).
|
||||
marker(Plot.Marker.DIAMOND).line(Plot.Line.NONE));
|
||||
|
||||
windowPeaksZ.set(plotPeaksZ.draw());
|
||||
|
||||
//fill hols improve peaks
|
||||
|
||||
//estimate bpm between detected peaks
|
||||
|
||||
int dummyForBreakpoint = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
|
||||
public class Utils {
|
||||
@@ -97,7 +98,6 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static float sqr(float x) {
|
||||
return x * x;
|
||||
}
|
||||
@@ -180,8 +180,70 @@ public class Utils {
|
||||
return c;
|
||||
}
|
||||
|
||||
//TODO: findPeaks
|
||||
//TODO: findPeaks method identical to Matlab... with PeakProminence
|
||||
|
||||
/**
|
||||
* Simple method for finding local maxima in an array
|
||||
* @param data input
|
||||
* @param width minimum distance between peaks
|
||||
* @param threshold minimum value of peaks
|
||||
* @param decayRate how quickly previous peaks are forgotten
|
||||
* @param isRelative minimum value of peaks is relative to local average
|
||||
* @return array of peaks
|
||||
*/
|
||||
public static LinkedList<Integer> findPeaks(float[] data, int width, float threshold, float decayRate, boolean isRelative) {
|
||||
LinkedList<Integer> peaks = new LinkedList<>();
|
||||
int maxp = 0;
|
||||
int mid = 0;
|
||||
int end = data.length;
|
||||
float av = data[0];
|
||||
while (mid < end) {
|
||||
av = decayRate * av + (1 - decayRate) * data[mid];
|
||||
if (av < data[mid])
|
||||
av = data[mid];
|
||||
int i = mid - width;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
int stop = mid + width + 1;
|
||||
if (stop > data.length)
|
||||
stop = data.length;
|
||||
maxp = i;
|
||||
for (i++; i < stop; i++)
|
||||
if (data[i] > data[maxp])
|
||||
maxp = i;
|
||||
if (maxp == mid) {
|
||||
if (overThreshold(data, maxp, width, threshold, isRelative, av)){
|
||||
peaks.add(new Integer(maxp));
|
||||
}
|
||||
}
|
||||
mid++;
|
||||
}
|
||||
return peaks;
|
||||
}
|
||||
|
||||
private static boolean overThreshold(float[] data, int index, int width,
|
||||
float threshold, boolean isRelative,
|
||||
float av) {
|
||||
int pre = 3;
|
||||
int post = 1;
|
||||
|
||||
if (data[index] < av)
|
||||
return false;
|
||||
if (isRelative) {
|
||||
int iStart = index - pre * width;
|
||||
if (iStart < 0)
|
||||
iStart = 0;
|
||||
int iStop = index + post * width;
|
||||
if (iStop > data.length)
|
||||
iStop = data.length;
|
||||
float sum = 0;
|
||||
int count = iStop - iStart;
|
||||
while (iStart < iStop)
|
||||
sum += data[iStart++];
|
||||
return (data[index] > sum / count + threshold);
|
||||
} else
|
||||
return (data[index] > threshold);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
Reference in New Issue
Block a user