Improving the Quality of ECGs Collected using Mobile Phones: The PhysioNet/Computing in Cardiology Challenge 2011 1.0.0
(3,579 bytes)
package org.physionet.challenge2011;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
public class ChallengeEntry {
// ECG data characteristics. In the general case, these should be read
// from metadata. In the Challenge, they are givens, as below.
final static int sfreq = 500; // samples per second per signal
final static int nsig = 12; // number of signals
final static int tmax = 5000; // total number of samples per signal
// Histogram parameters. In the general case, these should be calculated
// from the ADC characteristics. For the Challenge, the ADC characteristics
// (16 bit, 5 microvolt steps, signed (two's complement) output) are known.
final static int nbins = 2048; // number of bins per histogram
final static int binwidth = 32; // raw ADC units; 1 unit = 5 microvolts
final static int zbin = 1024; // bin number corresponding to 0 V input
// Classifier parameters and variables.
int nb; // number of non-empty bins in a histogram
final static int nbmax = nbins/100; // acceptable signals have nb <= nbmax
final static int nbmin = nbins/1000;// acceptable signals have nb >= nbmin
final static int thr = 2*nsig-3; // decision threshold
int score = 0; // ECG quality (0 - nsig*2). Each signal with
// nbmin <= nb contributes 2 to score if nb <= nbmax,
// or 1 if nb > nbmax; acceptable ECGs have score >= thr
final static int GOOD = 0; // acceptable ECG
final static int BAD = 1; // unacceptable ECG
int result = BAD; // result
// Raw ECG samples and histograms. The raw ECG samples are read from iFile
// as short (16-bit) signed integers, in sets of nsig (12) samples (one
// from each signal); tmax sets from the input are stored consecutively in
// data[]. The histograms are constructed by the code below, one for each
// signal.
short[] data = new short[tmax*nsig];
short[][] ah = new short[nsig][nbins]; // amplitude histograms
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) {
e.printStackTrace();
}
iFile.close();
// Build amplitude histograms for each lead.
// Each histogram has 2048 bins, and each bin covers a range of 160
// microvolts (32 adu). Shifting a raw sample right by 5 bits and
// adding 1024 converts it to a bin number.
for (int i = 0, t = 0; t < tmax; t++) {
for (int s = 0; s < nsig; s++) {
int n = (data[i++] / binwidth) + zbin;
ah[s][n]++;
}
}
score = 0; // initialize the score for this ECG
// Examine each histogram to determine if the signal is flat (missing),
// or else if it contains a reasonable range of amplitudes.
for (int s = 0; s < nsig; s++) {
// Count non-empty bins in histogram for signal s
int nb = 0;
for (int n = 0; n < nbins; n++) {
if (ah[s][n] > 0) nb++;
ah[s][n] = 0; // reset histogram for the next ECG
}
// Adjust quality estimate based on signal s
if (nbmin <= nb) {
score++;
if (nb <= nbmax) { score++; }
}
}
// Classify this ECG based on the quality estimate. If the value
// returned is -9 to 0, the ECG is classified as acceptable; a
// return value of 1 to 10 indicates it is unacceptable (by the
// rules of the challenge.
result = thr - score;
if (result > 10) {
result = 10;
}
return result;
}
}