FFT Analysis of ECG Signals in EDF Format A Project by Michael Christian Abay Juan Wilfredo Ibanez Mary Julia Segismundo Submitted to Luisito L. Agustin Instructor, ELC 152 In Partial Fulfillment of the Requirements for the Course ELC 152: Signal Processing Department of Electronics, Computer and Communications Engineering School of Science and Engineering Loyola Schools Ateneo de Manila University Quezon City, Philippines October 2010
38
Embed
FFT Analysis of ECG Signals in EDF Formatohm.ecce.admu.edu.ph/wiki/pub/Main/DSPProjectsOctober...FFT Analysis of ECG Signals in EDF Format A Project by Michael Christian Abay Juan
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
FFT Analysis of ECG
Signals in EDF FormatA Project by
Michael Christian AbayJuan Wilfredo Ibanez
Mary Julia Segismundo
Submitted to
Luisito L. AgustinInstructor, ELC 152
In Partial Fulfillment of the Requirements for the CourseELC 152: Signal Processing
Department of Electronics, Computer and Communications EngineeringSchool of Science and Engineering
Loyola SchoolsAteneo de Manila University
Quezon City, Philippines
October 2010
Abstract
This project is a particular application to ECG Signals in EDF(European Data
Format). The program reads and extracts data from the EDF. After the extraction of data,
a Fast Fourier Transform is performed on the data. There are three algorithms for the Fast
Fourier Transform (FFT): 1) a recursive FFT 2) a non-recursive FFT 3) an algorithm for
computing direct DFT. All three algorithms are compiled in a library. The results of the
three FFT algorithms are compared using a separate program that computes the
percentage of the error. The output of the program is in CSV file can be opened using an
Open Office.
Acknowledgments
The group would like to thank Mr. Ericson Santos and Ms. Catherine Manuela-
Lee for their helpful insights on ECG signals which helped us come up with our topic.
We would also like to thank Mr. Luisito Agustin for guiding and motivating us to do our
project on time. His comments during consultations really helped us a lot to succeed in
our project. Lastly, we would also like to express our gratitude to our Almighty Father for
the wisdom and all the blessings we received from Him.
For the greater Glory of God.
Table of Contents
1. Introduction...................................................................................................................51.1. Objectives.......................................................................................................51.2. Significance....................................................................................................51.3. Scope and Limitations....................................................................................6
3. Methodology.................................................................................................................103.1 Test of three implementations of FFT..............................................................10
3.1.1. DFT Definition.................................................................................103.1.2. Recursive FFT..................................................................................113.1.3. Non-recursive FFT...........................................................................123.1.4. Comparison of the three implementations.......................................13
3.2. Main Program..................................................................................................163.2.1 Extracting EDF ….............................................................................163.2.2 Processing ECG signals in FFT.........................................................173.2.3 CSV Output.......................................................................................18
AppendicesAppendix 1: Program Source Codes.....................................................................21
A1.1. Main Program..................................................................................21A1.2. fourier.h...........................................................................................32A1.3. errorcompute.cpp.............................................................................34
Appendix 2: Original Project Proposal................................................................35
value_tmp = ((*(((signed short *)cnv_buf)+edfparam[j].buf_offset+edfparam[j].smp_written)) + edfparam[j].offset) *
edfparam[j].sense;
dynamicArray[(i*recordsize)+edfparam[j].smp_written] = value_tmp; //put value_tmp to dynamicArray
edfparam[j].smp_written++;
}
3.2.2 Processing ECG signals in FFT
Since dynamicArray is a one-dimesional array and we want to divide it into blocks
of size 512, there is a need to create a second array and copy the contents onto it the
contents of the dynamicArray. This array (array512) is a dynamically allocated two-
dimesional array. It is composed of 512-sized sub-arrays. The number of sub-arrays is
equal to (dynamicArray/ 512).
int numArrays = 0; numArrays = (datarecords*recordsize)/512; //Initialize 2-dimensional array512 complex<float> **array512 = new complex<float>*[numArrays]; //Initialize sub-arrays of array512 with 512 block-size for(int i = 0; i < numArrays; i++){ array512[i] = new complex<float>[512]; }
//Copy contents of dynamicArray to array512 int ctr = 0; for(int j=0;j<numArrays && ctr<numSamples;j++){ for(int k=0;k<512 && ctr<numSamples;k++) { array512[j][k] = dynamicArray[ctr]; ctr++; } }
17
3.2.3 CSV output
After copying all the contents from the dynamicArray to array512, FFT is then
applied to array512 by blocks or sub-arrays. For the main program, we have use the
function fft_rec. This means that the fft implemented is the one with recursion. The
Fourier transform output for each block is then printed on a CSV file on the same
directory as the main program.
//Perform FFT for each 512-size block ofstream outStream; outStream.open("fft.csv"); complex<float> *newArray = new complex<float>[512]; float incfreq = (recordsize/data_record_duration)/512.000; float frequency = 0.000; for(int i=0;i<numArrays;i++){ newArray = fft_rec(512,array512[i]); outStream << "Array " << i+1 << "\n"; for(int j=0;j<256;j++) { frequency = incfreq*j; outStream << frequency << ","; outStream << abs(newArray[j]) << "\n"; } } outStream.close();
After the Fourier transform of the whole array is finished, all dynamically
In this program, it is important to note that the input should have a filename
extension of .edf in order for it to be implemented. As mentioned in the earlier part, this
deals with ecg signals. Furthermore, the program gets FFT of the input using Radix-2
algorithm in our program code.
4.2 Using the Program
Figure 4.1: Program File
The program is run by dragging an EDF file into the executable file, or through
the use of MSDOS by typing: edf2ascii <edf file>. The program produces four output
text files: header, annotation, signal and data. For our purpose, we are only concerned on
the data part and some information found in the header and signal parts. While the
annotations part is unused since we are using the basic EDF version. The one with the
.csv filename extension will be used. This file will contain two columns of numbers. The
first one is the values for the magnitude while the other one will be values for the
frequency domain. In order to see that, the user will have to open it in an Open Office
Application and perform there the part of the data.
19
5. Recommendation
Our group was able to succeed in achieving our aim. However, we also know that
there are also room for improvements in some of the parts of our project. One of this is to
explore on the possibility of creating a Graphic User Interface for aesthetics and
efficiency. In the future, other groups can also implement a code that can also process
additional file aside from those in EDF. In that way, the program can be more flexible.
20
Appendix 1: Program Source CodesA1.1. Main Program#include <iostream>#include <fstream>#include <complex>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <malloc.h>#include "fourier.h"using namespace std;
struct edfparamblock{ int smp_per_record; int smp_written; int dig_min; int dig_max; int offset; int buf_offset; double phys_min; double phys_max; double time_step; double sense; } *edfparam;
int main(int argc, char *argv[]){ FILE *inputfile, *outputfile, *annotationfile;
const char *fileName;
int i, j, k, p, r, n, pathlen, fname_len, signals, datarecords, datarecordswritten, recordsize, recordfull, edfplus, annot_ch[256], nr_annot_chns, skip, max, onset, duration, zero, max_tal_ln;
for(i=0; fileName[i]!=0; i++); if(i==0) { printf("Error, filename must contain at least five characters.\n"); return(1); }
i -= 4; if((strcmp((const char *)fileName + i, ".edf"))&&(strcmp((const char *)fileName + i, ".EDF"))) { printf("Error, filename extension must have the form \".edf\" or \".EDF\"\n"); return(1); }
scratchpad[4] = 0; signals = atoi(scratchpad); if((signals<1)||(signals>256)) { printf("Error, number of signals in header is %i\n", signals); fclose(inputfile); return(1); }
for(i=0; i<((signals+1)*256); i++) { if(edf_hdr[i]==',') edf_hdr[i] = '\''; /* replace all comma's in header by single quotes because they */ } /* interfere with the comma-separated txt-files */
if(++n>max_tal_ln) { printf("Error, TAL in record %i exceeds my buffer\n", datarecordswritten + 1); fclose(inputfile); fclose(annotationfile); fclose(outputfile); free(edf_hdr);
28
free(edfparam); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); return(1); } } } } else elapsedtime = datarecordswritten * data_record_duration; /* done with timekeeping and annotations, continue with the data */
// conversion from ascii character to raw values if((d_tmp<(time_tmp+0.00000000000001))&&(d_tmp>(time_tmp-0.00000000000001))&&(edfparam[j].smp_written<edfparam[j].smp_per_record)) { value_tmp = ((*(((signed short *)cnv_buf)+edfparam[j].buf_offset+edfparam[j].smp_written)) + edfparam[j].offset) * edfparam[j].sense; dynamicArray[(i*recordsize)+edfparam[j].smp_written] = value_tmp; //put value_tmp to dynamicArray edfparam[j].smp_written++;
29
} else fputc(',', outputfile); }
if(fputc('\n', outputfile)==EOF) { printf("Error when writing to outputfile during conversion\n"); fclose(inputfile); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparam); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); return(1); }
Discrete Fourier Transfrom. Retreived September 2010, from:https://ccrma.stanford.edu/~jos/mdft/DFT_Definition.html
European Data Format. Retrieved August 2010, from: http://www.edfplus.info/specs/edf.html
Fast Fourier Transform. Retrieved September 2010, from:http://www.cmlab.csie.ntu.edu.tw/cml/dsp/training/coding/transform/fft.html Fast Fourier Transform. Retrieved September 2010, from: <http://mathworld.wolfram.com/FastFourierTransform.html>