Improving the Quality of ECGs Collected using Mobile Phones: The PhysioNet/Computing in Cardiology Challenge 2011 1.0.0
(3,918 bytes)
/**
* Dept. of Cybernetics
* Faculty of Electrical Engineering
* Czech Technical University in Prague
* Czech Republic
*
* Lukas Zach, Vaclav Chudacek, Jakub Kuzilek, Jiri Spilka and Lenka Lhotska
* e-mail: zachluk1@fel.cvut.cz; chudacv@fel.cvut.cz
*/
package org.physionet.challenge2011;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import android.util.Log;
public class ChallengeEntry {
public static final String DEBUGTAG = ChallengeEntry.class.toString();
final static int FS = 500; //Sampling Frequency
final static int CH = 12;
final static int WIN = FS*10;
//Define Quality values (could also be defined as enum...)
final static int GOOD = 0;
final static int BAD = 1;
short[] data = new short[WIN*CH];
short[] lead = new short[WIN];
int sumAbsLead;
int[] maxAbsLead;
//training set A
final static int lowestPossibleAmp = 20;
final static int highestPossibleAmp = 1000000;
final static int highAmpArtefact = 750;
final static double highNoise = 0.20;
final static int sumUnderCurve = 2000;
synchronized public int get_result(InputStream iFile, final ECG_MetaData m_MetaData) throws IOException {
ObjectInputStream in = new ObjectInputStream(iFile);
try {
data = (short[])in.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e(DEBUGTAG,"Could not open data file.");
}
int result = GOOD; // Set initial result
////// RULES
short skipFound = 0;
for (int ch = 0; ch < CH; ch++) {
//load signal
for (int index = 0; index < WIN; index++) {
lead[index] = data[index*CH + ch];
}
//init
sumAbsLead = sumOfAbsArray(lead);
maxAbsLead = maxOfAbsArrayExt(lead);
if (sumAbsLead < lowestPossibleAmp && skipFound == 0) {
skipFound = 1;
}
if (sumAbsLead > highestPossibleAmp && skipFound == 0) {
skipFound = 1;
}
if (maxAbsLead[0] > highAmpArtefact && skipFound == 0) {
if (maxAbsLead[1] > 1 && maxAbsLead[1] < 5000) {
skipFound = 1;
}
}
if (((double)sumAbsLead/(double)maxAbsLead[0]) > sumUnderCurve && skipFound == 0) {
skipFound = 1;
}
if ( (double)( (double)std(lead, 1499, 4499)/(double)( (double)2 * (double)maxOfAbsArray(lead, 1499, 4499) ) ) > highNoise && skipFound == 0 ) {
skipFound = 1;
}
//if is result bad
if (skipFound == 1) {
result = BAD;
break;
}
}
//clean-up
iFile.close();
return result;
}
private int sumOfAbsArray(short[] array) {
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += Math.abs((int)array[i]);
}
return sum;
}
private int[] maxOfAbsArrayExt(short[] array) {
int[] max = new int[2];
max[0] = Short.MIN_VALUE; //max value
max[1] = 0; //index of max value in array
for (int i = 0; i < array.length; i++) {
int abs = Math.abs(array[i]);
if (abs > max[0]) {
max[0] = abs;
max[1] = i;
}
}
return max;
}
private int maxOfAbsArray(short[] array, int indS, int indE) {
int max = Short.MIN_VALUE;
for (int i = indS; i < indE+1; i++) {
int abs = Math.abs(array[i]);
if (abs > max)
max = abs;
}
return max;
}
private double std(short[] array, int indS, int indE) {
int sumaMean = 0;
int n = 0;
double mean = 0;
double sumaAll = 0;
for (int i = indS; i < indE+1; i++) {
sumaMean += array[i];
n++;
}
mean = (double)sumaMean / (double)n;
for (int i = indS; i < indE+1; i++) {
sumaAll += Math.pow(((double)array[i] - mean), 2);
}
sumaAll = 1/(n-1) * sumaAll;
sumaAll = Math.sqrt(sumaAll);
return sumaAll;
}
}