Improving the Quality of ECGs Collected using Mobile Phones: The PhysioNet/Computing in Cardiology Challenge 2011 1.0.0

File: <base>/sources/chudacv_at_fel.cvut.cz-ChallengeEntry.java (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;
	}

}