Find Peak value using slope - android - java - java

I'm trying to code that If the sign value of the slope changed from positive to negative, then that value indexing is my pressure peak of the sensor. and even through if it found the peak, there might be another peak because of the pressure is increasing.
How can I do that please? Thank you in advance.
for (int i =1;i<strNumbers.length -2;i++){ //strNumber is the array stream from sensor.
String y1;
y1 = strNumbers[i];
String y2;
y2 = strNumbers[i+1];
float y_2 = Float.parseFloat(y2);
float y_1 = Float.parseFloat(y1);
float delta_y = y_2 - y_1;
float mySlope = 0;
float delta_x;
delta_x = 1; //always difference is 1.
mySlope = (delta_y / delta_x);
activity.FirstPeak.setTextColor(Color.RED);
activity.FirstPeak.setText(String.valueOf(mySlope));
}

At each point in the loop, you need to compare two gradients - the gradient on the left, and the gradient on the right. If the left is positive, and the right is negative, then you have found a peak.
List<Integer> peaks = new ArrayList<>();
for (int i = 1; i < strNumbers.length - 1; i++)
{
float left = Float.parseFloat(strNumbers[i]) - Float.parseFloat(strNumbers[i - 1]);
float right = Float.parseFloat(strNumbers[i + 1]) - Float.parseFloat(strNumbers[i]);
if (left > 0 && right <= 0)
peaks.add(i);
}
Now you have an array, containing the indices of all peaks. You can find the absolute maximum like this:
float max = 0;
float maxIndex = -1;
for (Integer i : peaks)
{
float peak = Float.parseFloat(strNumbers[i]);
if (peak > max)
{
max = peak;
maxIndex = i;
}
}
And you can find the peak-to-peak distances like this:
int sum = 0;
for (int i = 0; i < peaks.size() - 1; i++)
sum += peaks.get(i + 1) - peaks.get(i);
float average = (float)sum / (peaks.size() - 1)

Related

Find Nearest Point Pair (Divide & Conquer), Issue when have many of same x coordinates

I'm trying to develop the Divide & Conquer algorithm for finding the closest 2 points in an array of points.
I'm finding that when the input has a few points with the same x coordinates. Then if 2 of them are divided between Section1 and Section2 I get incorrect results. I'm showing here a minimal input just to show the problem. (As well as a larger input to show that the problem stays with larger input as well). My concern is for when I have many points with the same x coordinates.
I thought about a solution. If I extend the Point2D class and add a field to store the points index in the pointsSortedOnX array, then I can create the pointsSortedOnY array from this class. Now when I go thru the pointsSortedOnY array instead of checking if the point is equal or less then midX I can check if it's less or equal to the mid index of pointsSortedOnX.
I'm just wondering if there isn't a better way.
Input (minimal):
double[][] p = {
{25.6, 67.9},
{25.6, 8.65},
{32.35, 81.26},
{25.32, 67.15},
}
Input (To show problem is in larger input as well):
double[][] p = {
{25.6, 67.9},
{25.6, 8.65},
{32.35, 81.26},
{25.32, 67.15},
{25.6, 60.95},
{25.6, 56.79},
{25.6, 78.49},
{25.6, 6.23},
{25.6, 7.9},
{25.6, 95.9},
{25.6, 35.9},
{25.6, 10.9},
}
Code:
/** Return the distance of the closest PointPair of points */
public static PointPair getClosestPair(double[][] points) {
int size = points.length;
pointsSortedX = new Point2D.Double[size];
pointsSortedY = new Point2D.Double[size];
for (int i = 0; i < size; i++) {
pointsSortedX[i] = new Point2D.Double(points[i][0], points[i][1]);
pointsSortedY[i] = new Point2D.Double(points[i][0], points[i][1]);
}
Arrays.sort(pointsSortedX, (e1, e2) ->
(e1.getX() == e2.getX() ? (e1.getY() > e2.getY() ? 1 : (e1.getY() < e2.getY() ? -1 : 0)) : (e1.getX() > e2.getX() ? 1 : -1)));
Arrays.sort(pointsSortedY, (e1, e2) ->
(e1.getY() > e2.getY() ? 1 : (e1.getY() < e2.getY() ? -1 : 0)));
return findNearstPair(pointsSortedX, 0, size - 1, pointsSortedY, 1);
}
/** Return the distance of the closest PointPair of points
* in pointsOrderedOnX[low..high]. This is a recursive
* method. pointsOrderedOnX and pointsOrderedOnY are
* not changed in the subsequent recursive calls.
*/
public static PointPair findNearstPair(Point2D[] pointsOrderedOnX, int low, int high, Point2D[] pointsOrderedOnY) {
if (low == high)
return new PointPair(pointsOrderedOnX[low], pointsOrderedOnX[high], Double.MAX_VALUE);
else if ((high - low) == 1)
return new PointPair(pointsOrderedOnX[low], pointsOrderedOnX[high], pointsOrderedOnX[low].distance(pointsOrderedOnX[high]));
else{
// Divide
int mid = (high - low) / 2;
PointPair leftPair = findNearstPair(pointsOrderedOnX, low, low + mid, pointsOrderedOnY);
PointPair rightPair = findNearstPair(pointsOrderedOnX, low + mid + 1, high, pointsOrderedOnY);
// Merge the right & left
shortestPair = leftPair.distance > rightPair.distance ? rightPair : leftPair;
System.out.println("shortest " + shortestPair);
// Find points in pointsOrderedOnY that belong in stripL & stripR
// this any x that is less then d away from the middle of
// the 2 sections (between mid & mid + 1)
double minXinS1 = pointsOrderedOnX[low].getX();
// <= midX is S1(left side) > midX is S2(right side)
double midX = pointsOrderedOnX[low + mid].getX();
double maxXinS2 = pointsOrderedOnX[high].getX();
List<Integer> stripL = new ArrayList<Integer>();
List<Integer> stripR = new ArrayList<Integer>();
for(int p = 0; p < pointsOrderedOnY.length; p++){
double pX = pointsOrderedOnY[p].getX();
double pY =pointsOrderedOnY[p].getY();
// is in S1 & less then distance away from middle
// >= minXinS1 & <= midX & >= midX - d = stripL
if(pX <= midX && pX >= minXinS1 && pX >= midX - shortestPair.distance){
stripL.add(p);
}
//is in S2 & less then distance away from middle
// > midX && <= maxXinS2 & > midX & < midX + d
else if(pX > midX && pX <= maxXinS2 && pX < midX + shortestPair.distance){
stripR.add(p);
}
}
// For each point in stripL find the points in stripR that are less then
// distance away (max 6 points in stripR)
int stripRIndx = 0; //
for(int p = 0; p < stripL.size(); p++){
double pY = pointsOrderedOnY[stripL.get(p)].getY();
// Skip points in stripR that are below pY - distance
while(stripRIndx < stripR.size() && pointsOrderedOnY[stripR.get(stripRIndx)].getY()
<= pY - shortestPair.distance)
stripRIndx++;
// Check points in stripR that ate within pY +/- distance
int tempStripRIndex = stripRIndx;
while(tempStripRIndex < stripR.size() && pointsOrderedOnY[stripR.get(tempStripRIndex)].getY()
<= pY + shortestPair.distance){
if(pointsOrderedOnY[stripL.get(p)].distance(pointsOrderedOnY[stripR.get(tempStripRIndex)]) < shortestPair.distance){
shortestPair.p1 = pointsOrderedOnY[stripL.get(p)];
shortestPair.p2 = pointsOrderedOnY[stripR.get(tempStripRIndex)];
shortestPair.distance = pointsOrderedOnY[stripL.get(p)].distance(pointsOrderedOnY[stripR.get(tempStripRIndex)]);
}
tempStripRIndex++;
}
}
return shortestPair;
}
}
class PointPair {
Point2D p1;
Point2D p2;
double distance = Double.MAX_VALUE;
PointPair(){}
PointPair(Point2D p1, Point2D p2, double distance) {
this.p1 = p1;
this.p2 = p2;
this.distance = distance;
}
#Override
public String toString(){
return p1 + ":" + p2 + " distance = " + distance;
}
EDIT
I have seen this question. I'm looking to find what is wrong in my code and how to fix it. I'm trying to implement the same idea as is mentioned there.
After further analysing my code, this is what I came up with.
Code:
public static PointPair findNearstPair(Point2D[] pointsOrderedOnX, int low, int high, Point2D[] pointsOrderedOnY) {
PointPair shortestPair;
if (low == high)
return new PointPair(pointsOrderedOnX[low], pointsOrderedOnX[high], Double.MAX_VALUE);
else if ((high - low) == 1)
return new PointPair(pointsOrderedOnX[low], pointsOrderedOnX[high], pointsOrderedOnX[low].distance(pointsOrderedOnX[high]));
// Divide
int mid = (high - low) / 2;
PointPair leftPair = findNearstPair(pointsOrderedOnX, low, low + mid, pointsOrderedOnY);
PointPair rightPair = findNearstPair(pointsOrderedOnX, low + mid + 1, high, pointsOrderedOnY);
// Merge the right & left
shortestPair = leftPair.distance > rightPair.distance ? rightPair : leftPair;
/* Find points in pointsOrderedOnY that belong in stripL & stripR
* this any x that is less then d away from the middle of
* the 2 sections (between mid & mid + 1)
*/
double midX = pointsOrderedOnX[low + mid].getX();
double midY = pointsOrderedOnX[low + mid].getY();
double leftS1 = pointsOrderedOnX[low].getX();
double leftStripL = Math.max(leftS1, midX - shortestPair.distance);
double rightS2 = pointsOrderedOnX[high].getX();
double rightStripR = Math.min(rightS2, midX + shortestPair.distance);
List<Integer> stripL = new ArrayList<Integer>();
List<Integer> stripR = new ArrayList<Integer>();
for (int p = 0; p < pointsOrderedOnY.length; p++) {
double pX = pointsOrderedOnY[p].getX();
double pY = pointsOrderedOnY[p].getY();
if (pX >= leftStripL && pX <= rightStripR) { // in current section(S1 & S2)
if (pX == midX) {
if (pointsOrderedOnX[mid + low] == pointsOrderedOnY[p]) {
stripL.add(p);
} else if (pY == midY) {
shortestPair.p1 = pointsOrderedOnX[mid + low];
shortestPair.p2 = pointsOrderedOnY[p];
shortestPair.distance = shortestPair.p1.distance(shortestPair.p2);
return shortestPair;
} else if (pY > midY) {
stripR.add(p);
} else {
stripL.add(p);
}
} else if (pX > midX) {
stripR.add(p);
} else {
stripL.add(p);
}
}
}
This works even when the input has many items that divide between S1 & S2.
The main difference in this code is that when I find a point that the x coordinate is the same as the x coordinate of mid I check the y coordinate. if its less then the y coordinate of mid then it goes into stripL. If it's greater it goes into stripR. If it is equal then I check if it's the same point as mid then it's in stripL if not it means we have 2 points with the same coordinates, this will be the closest 2 points, so I return the pair.

What causes Java version Random walk doesn't converge to expected value?

Basically, I implemented a Random walk program in Java. And I know the distance should converge to l * (n ^ 0.5)(l is the step length, n is the total steps). If let l equals to 1, then d = n ^ 0.5 or in other words: d = sqrt(n).
But, strangly, although I cannot find any error in my code, it just converges to unexpected value. For example, given l = 1, n = 100, d should converge to 10, but actually it converges to 8.86 after 1000000 times experiments.
Here is my code:
public class RandomWalk {
private int x = 0;
private int y = 0;
private final Random random = new Random();
private void move(int dx, int dy) {
x += dx;
y += dy;
}
private void randomWalk(int m) {
for (int i = 0; i < m; i++)
randomMove();
}
private void randomMove() {
boolean xOry = random.nextBoolean();
boolean plusOrminus = random.nextBoolean();
int delta = plusOrminus ? 1 : -1;
int dx = xOry ? delta : 0, dy = xOry ? 0 : delta;
move(dx, dy);
}
public double distance() {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
public static double randomWalkMulti(int m, int n) {
double totalDistance = 0;
for (int i = 0; i < n; i++){
RandomWalk walk = new RandomWalk();
walk.randomWalk(m);
totalDistance += walk.distance();
}
return totalDistance/n ;
}
}
I've thought some possiblities. First I think it may be caused by that the generated boolean by random has bias. Second I think it may be caused by float precision lost. But as this is just a very simple use case, I don't think these two situations are possible.
Could any one tell me why it doesn't work as expected?
I don't think it's true that the distance should average out to √n. According to https://math.stackexchange.com/questions/103142/expected-value-of-random-walk, the square of the distance should average out to n, but that's not the same thing (since the average of the square roots of a set of numbers is not the same as the square root of their average).

Formatting of 2D arrays of chars

I have a program which reads in a pair of integers from a file and stores that in a Point class which i have created. The first integer is the x coordinate and the second is the y coordinate on each line of the file. All valid points have x-coordinates in the range [0, 40] and y-coordinates in the range [1, 20].
The input file contains data like this:
I performed some validation checks so that my program ignores invalid data or out of range data.
I then have to plot a regression line on top of those points. I have to use 2D arrays of chars and would prefer to do it this way insetad of using Point2D class of java or some other graphical classes of java.
"X"s is used to represent the points, "-"s the regression line segments, and ""s where a line segment and a point are located at the same spot*
Th formula used for regression line is this:
# Edit #
Below is the code snippet that i got from #sprinter:
initializeArray(charArray);
int xySum = 0;
int xSqSum = 0;
int xSum = 0;
int ySum = 0;
for (Point points: point) {
xySum += points.getX() * points.getY();
xSqSum += points.getX() * points.getX();
xSum += points.getX();
ySum += points.getY();
}
int xMean = xSum / count;
int yMean = ySum / count;
int n = point.size();
int slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);
for (Point points: point) {
charArray[points.getX()][points.getY()] = 'X';
}
// plot the regression line
for (int x = 0; x <charArray.length; x++) {
int y = yMean + slope * (x - xMean); // calculate regression value
charArray[x][y] = charArray[x][y] == 'X' ? '*' : '-';
}
This is my program's output after i ran sprinter's code.:
whereas i want output like this:
Also this is how i am initializing the charArray:
public static void initializeArray(char[][] charArray) {
for(int k =0; k< charArray.length; k++) {
for(int d = 0; d<charArray[k].length;d++) {
charArray[k][d] = ' ';
}
}
}
This is the new output:
I'm finding it hard to understand what the fillArray function is supposed to do. You could have multiple 'y' values for each 'x' value in your list of points so i assume you are calling this once for each point. But the regression line has lots of 'x' values that aren't in the list of points which means you would have to call this once for each regression point. You also don't need to return the array after filling the value.
Your slope calculation doesn't seem to match the formula at all. This would make more sense to me:
float xySum = 0;
float xSqSum = 0;
float xSum = 0;
float ySum = 0;
for (Point point: points) {
xySum += point.x * point.y;
xSqSum += point.x * point.x;
xSum += point.x;
ySum += point.y;
}
float xMean = xSum / count;
float yMean = ySum / count;
float n = points.size();
float slope = (xySum - n* xMean * yMean) / (xSqSum - n * xMean * xMean);
I suspect you would be much better off plotting all the points then plotting the regression line.
List<Point> points = ...;
// first plot the points
for (Point point: points) {
array[point.x][point.y] = 'X';
}
// now plot the regression line
for (int x = 0; x < 40; x++) {
int y = Math.round(yMean + slope * (x - xMean));
array[x][y] = array[x][y] == 'X' ? '*' : '-';
}
By the way, if you are familiar with Java 8 streams then you could use:
double n = points.size();
double xySum = points.stream().mapToDouble(p -> p.x * p.y).sum();
double xSqSum = points.stream().mapToDouble(p -> p.x * p.x).sum();
double xMean = points.stream().mapToDouble(p -> p.x).sum() / n;
double yMean = points.stream().mapToDouble(p -> p.y).sum() / n;
Finally, your x dimension is the first and y dimension second. So to print you need to iterate through y first, not x:
for (int y = 0; y < 20; y++) {
for (int x = 0; x < 40; x++) {
System.out.print(array[x][20-y-1]);
}
System.out.println();
}

Divide and Conquer Closest Pair Algorithm

I'm trying to create an algorithm that returns the closest pair from randomly generated points. I have finished the algorithm, however the divide and conquer method of the algorithm is not much faster than the brute-force method. What can I do to optimize the code so that it returns at (n log n) time?
import java.util.*;
import java.lang.*;
import static java.lang.Math.min;
import static java.lang.StrictMath.abs;
public class closestPair {
private static Random randomGenerator; // for random numbers
public static class Point implements Comparable<Point> {
public long x, y;
// Constructor
public Point(long x, long y) {
this.x = x;
this.y = y;
}
public int compareTo(Point p) {
// compare this and p and there are three results: >0, ==0, or <0
if (this.x == p.x) {
if (this.y == p.y)
return 0;
else
return (this.y > p.y)? 1 : -1;
}
else
return (this.x > p.x)? 1 : -1;
}
public String toString() {
return " ("+Long.toString(this.x)+","+Long.toString(this.y)+")";
}
public double distance(Point p) {
long dx = (this.x - p.x);
long dy = (this.y - p.y);
return Math.sqrt(dx*dx + dy*dy);
}
}
public static Point[] plane;
public static Point[] T;
public static Point[] Y;
public static int N; // number of points in the plane
public static void main(String[] args) {
// Read in the Size of a maze
Scanner scan = new Scanner(System.in);
try {
System.out.println("How many points in your plane? ");
N = scan.nextInt();
}
catch(Exception ex){
ex.printStackTrace();
}
scan.close();
// Create plane of N points.
plane = new Point[N];
Y = new Point[N];
T = new Point[N];
randomGenerator = new Random();
for (int i = 0; i < N; ++i) {
long x = randomGenerator.nextInt(N<<6);
long y = randomGenerator.nextInt(N<<6);
plane[i] = new Point(x, y);
}
Arrays.sort(plane); // sort points according to compareTo.
for (int i = 1; i < N; ++i) // make all x's distinct.
if (plane[i-1].x >= plane[i].x) plane[i].x = plane[i-1].x + 1;
//for (int i = 1; i < N; i++)
// if (plane[i-1].y >= plane[i].y) plane[i].y = plane[i-1].y + 1;
//
//
System.out.println(N + " points are randomly created.");
System.out.println("The first two points are"+plane[0]+" and"+plane[1]);
System.out.println("The distance of the first two points is "+plane[0].distance(plane[1]));
long start = System.currentTimeMillis();
// Compute the minimal distance of any pair of points by exhaustive search.
double min1 = minDisSimple();
long end = System.currentTimeMillis();
System.out.println("The distance of the two closest points by minDisSimple is "+min1);
System.out.println("The running time for minDisSimple is "+(end-start)+" mms");
// Compute the minimal distance of any pair of points by divide-and-conquer
long start1 = System.currentTimeMillis();
double min2 = minDisDivideConquer(0, N-1);
long end1 = System.currentTimeMillis();
System.out.println("The distance of the two closest points by misDisDivideConquer is "+min2);
System.out.println("The running time for misDisDivideConquer is "+(end1-start1)+" mms");
}
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
if (plane[i].distance(plane[j]) < midDis){
midDis = plane[i].distance(plane[j]);
}
}
}
return midDis;
}
static void exchange(int i, int j) {
Point x = plane[i];
plane[i] = plane[j];
plane[j] = x;
}
static double minDisDivideConquer(int low, int high) {
// Initialize necessary values
double minIntermediate;
double minmin;
double minDis;
if (high == low+1) { // two points
if (plane[low].y > plane[high].y) exchange(low, high);
return plane[low].distance(plane[high]);
}
else if (high == low+2) { // three points
// sort these points by y-coordinate
if (plane[low].y > plane[high].y) exchange(low, high);
if (plane[low].y > plane[low+1].y) exchange(low, low+1);
else if (plane[low+1].y > plane[high].y) exchange(low+1, high);
// compute pairwise distances
double d1 = plane[low].distance(plane[high]);
double d2 = plane[low].distance(plane[low+1]);
double d3 = plane[low+1].distance(plane[high]);
return ((d1 < d2)? ((d1 < d3)? d1 : d3) : (d2 < d3)? d2 : d3); // return min(d1, d2, d3)
} else { // 4 or more points: Divide and conquer
int mid = (high + low)/2;
double lowerPartMin = minDisDivideConquer(low,mid);
double upperPartMin = minDisDivideConquer(mid+1,high);
minIntermediate = min(lowerPartMin, upperPartMin);
int k = 0;
double x0 = plane[mid].x;
for(int i = 1; i < N; i++){
if(abs(plane[i].x-x0) <= minIntermediate){
k++;
T[k] = plane[i];
}
}
minmin = 2 * minIntermediate;
for (int i = 1; i < k-1; i++){
for(int j = i + 1; j < min(i+7,k);j++){
double distance0 = abs(T[i].distance(T[j]));
if(distance0 < minmin){
minmin = distance0;
}
}
}
minDis = min(minmin, minIntermediate);
}
return minDis;
}
}
Use the following method with the change for minDisSimple. You can get more performance.
static double minDisSimple() {
// A straightforward method for computing the distance
// of the two closest points in plane[0..N-1].
// to be completed
double midDis = Double.POSITIVE_INFINITY;
double temp;
for (int i = 0; i < N - 1; i++) {
for (int j = i + 1; j < N; j++) {
temp = plane[i].distance(plane[j]);
if (temp < midDis) {
midDis = temp;
}
}
}
return midDis;
}
Performance wise for small amount of points simple method is good but larger amount of points Divide and Conquer is good. Try number of points with 10, 100, 1000, 10000, 100000, 1000000.
One critical aspect in the minDisDivideConquer() is that the loop that constructs the auxiliary array T iterates through all the N points. Since there are O(N) recursive calls in total, making this pass through all the N points every time leads to a complexity of O(N^2), equivalent to that of the simple algorithm.
The loop should actually only consider the points with indices between low and high. Furthermore, it could be split into two separate loops that start from mid (forward and backward), and break when the checked distance is already too large.
Another possible improvement for the minDisDivideConquer() method, in the "4 or more points" situation is to prevent looking into pairs that were already considered in the recursive calls.
If my understanding is correct, the array T contains those points that are close enough on x axis to the mid point, so that there is a chance that a pair of points in T generates a distance smaller than those from the individual half sets.
However, it is not necessary to look into points that are both before mid, or both after mid (since these pairs were already considered in the recursive calls).
Thus, a possible optimization is to construct two lists T_left and T_right (instead of T) and check distances between pairs of points such that one is on the left of mid, and the other to the right.
This way, instead of computing |T| * (|T| - 1) / 2 distances, we would only look into |T_left| * |T_right| pairs, with |T_left| + |T_right| = |T|. This value is at most (|T| / 2) * (|T| / 2) = |T| ^ 2 / 4, i.e. around 2 times fewer distances than before (this is in the worst case, but the actual number of pairs can also be much smaller, inclusively zero).

QRS Detection in java from ecg byte array

i read ecg byte array from file.now i want to detect QRS of read ecg byte.
how can i acheive this in java.
i get byte array from Lifegain defibrilator(an ecg device).i draw ecg on android from these bytes.now i want to detect QRS complex(term used for calculation of time and voltage of a wave of one heart beat).DATA=LeadData":"-284,-127,-122,17,-35,10,32,10,52,16,49,33,38,69,70,58,45,93,47,88,58,90,149,5,82,-12,-4,40,-34,29,-29,5,-4,-17,-13,-29,-13,-4,-9,-9,-10,-20,-15,-22,-32,-25,-23,-2,-15,-7,-13,-19,-17,-28,-27,-27,-33,-20,-16,-13,-20,-10,-22,-20,-19,-28,-15,-19,-22,-21,-9,-3,-6,-8,-6,-11,-8,-8,-5,-10,-5,-6,-9,-4,-6,3,20,3,14,7,11,10,5,11,5,10,2,10,13,14"
Regards,
shah
If the data you have is the data I think you have, you need to use one of the algorithms to detect your QRS complex.
There are a lot of algorithms out there to detect a QRS complex, one of the easiest is A Moving Average based Filtering System with its Application to Real-time QRS Detection by HC Chen and SW Chen (you can get it on http://www.cinc.org/archives/2003/pdf/585.pdf).
The stages are:
High Pass filtering
Low Pass filtering
Descision making stage
From the low pass picture you can notice that now we have the peaks we need to detect our QRS complex. The last stage is the decision stage making. In the article you have a formula to implement this.
We need to know when a QRS complex starts, so we need to set a threshold for this. The formula in this implementation is:
threshold = alpha * gamma * peak + (1 - alpha) * threshold
The peak is the local maximum in the window (we usually search the signal with a window of width 250), the threshold is the initial value (the first one can be the firstly found peak), alpha and gamma are randomly created, alpha is greater than 0 and smaller than 1 whereas gamma is 0.15 or 0.20. If the value of the current signal exceeds the threshold, a QRS complex is found.
Here is the source code in Java for low pass, high pass and decision making:
// High pass filter
// y1[n] = 1/M * Sum[m=0, M-1] x[n-m]
// y2[n] = x[n - (M+1)/2]
public static float[] highPass(int[] sig0, int nsamp) {
float[] highPass = new float[nsamp];
int M = 5; // M is recommended to be 5 or 7 according to the paper
float constant = (float) 1/M;
for(int i=0; i<sig0.length; i++) {
float y1 = 0;
float y2 = 0;
int y2_index = i-((M+1)/2);
if(y2_index < 0) {
y2_index = nsamp + y2_index;
}
y2 = sig0[y2_index];
float y1_sum = 0;
for(int j=i; j>i-M; j--) {
int x_index = i - (i-j);
if(x_index < 0) {
x_index = nsamp + x_index;
}
y1_sum += sig0[x_index];
}
y1 = constant * y1_sum;
highPass[i] = y2 - y1;
}
return highPass;
}
// Low pass filter; na n-to mesto zapiši kvadrat 30ih števil v oknu
public static float[] lowPass(float[] sig0, int nsamp) {
float[] lowPass = new float[nsamp];
for(int i=0; i<sig0.length; i++) {
float sum = 0;
if(i+30 < sig0.length) {
for(int j=i; j<i+30; j++) {
float current = sig0[j] * sig0[j];
sum += current;
}
}
else if(i+30 >= sig0.length) {
int over = i+30 - sig0.length;
for(int j=i; j<sig0.length; j++) {
float current = sig0[j] * sig0[j];
sum += current;
}
for(int j=0; j<over; j++) {
float current = sig0[j] * sig0[j];
sum += current;
}
}
lowPass[i] = sum;
}
return lowPass;
}
public static int[] QRS(float[] lowPass, int nsamp) {
int[] QRS = new int[nsamp];
double treshold = 0;
for(int i=0; i<200; i++) {
if(lowPass[i] > treshold) {
treshold = lowPass[i];
}
}
int frame = 250;
for(int i=0; i<lowPass.length; i+=frame) {
float max = 0;
int index = 0;
if(i + frame > lowPass.length) {
index = lowPass.length;
}
else {
index = i + frame;
}
for(int j=i; j<index; j++) {
if(lowPass[j] > max) max = lowPass[j];
}
boolean added = false;
for(int j=i; j<index; j++) {
if(lowPass[j] > treshold && !added) {
QRS[j] = 1;
added = true;
}
else {
QRS[j] = 0;
}
}
double gama = (Math.random() > 0.5) ? 0.15 : 0.20;
double alpha = 0.01 + (Math.random() * ((0.1 - 0.01)));
treshold = alpha * gama * max + (1 - alpha) * treshold;
}
return QRS;
}
Please follow the link below , i think they will help you.
http://www.cinc.org/archives/2008/pdf/0441.pdf
http://carg.site.uottawa.ca/doc/ELG6163GeoffreyGreen.pdf
http://www.eplimited.com/osea13.pdf
http://mirel.xmu.edu.cn/mirel/public/Teaching/QRSdetection.pdf
http://sourceforge.net/projects/ecgtoolkit-cs/files/ecgtoolkit-cs/ecgtoolkit-cs-2_2/

Categories

Resources