Initial commit
This commit is contained in:
664
ecgsyn-1.0.0/C/src/ecgsyn.c
Normal file
664
ecgsyn-1.0.0/C/src/ecgsyn.c
Normal file
@@ -0,0 +1,664 @@
|
||||
/* 09 Oct 2003 "ecgsyn.c" */
|
||||
/* */
|
||||
/* Copyright (c)2003 by Patrick McSharry & Gari Clifford, All Rights Reserved */
|
||||
/* See IEEE Transactions On Biomedical Engineering, 50(3),289-294, March 2003.*/
|
||||
/* Contact P. McSharry (patrick AT mcsharry DOT net) or */
|
||||
/* G. Clifford (gari AT mit DOT edu) */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it and/or modify */
|
||||
/* it under the terms of the GNU General Public License as published by */
|
||||
/* the Free Software Foundation; either version 2 of the License, or */
|
||||
/* (at your option) any later version. */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* GNU General Public License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General Public License */
|
||||
/* along with this program; if not, write to the Free Software Foundation */
|
||||
/* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
/* */
|
||||
/* ecgsyn.m and its dependents are freely availble from Physionet - */
|
||||
/* http://www.physionet.org/ - please report any bugs to the authors above. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "opt.h"
|
||||
#define PI (2.0*asin(1.0))
|
||||
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
|
||||
#define MIN(a,b) (a < b ? a : b)
|
||||
#define MAX(a,b) (a > b ? a : b)
|
||||
#define PI (2.0*asin(1.0))
|
||||
#define OFFSET 1
|
||||
#define ARG1 char*
|
||||
|
||||
#define IA 16807
|
||||
#define IM 2147483647
|
||||
#define AM (1.0/IM)
|
||||
#define IQ 127773
|
||||
#define IR 2836
|
||||
#define NTAB 32
|
||||
#define NDIV (1+(IM-1)/NTAB)
|
||||
#define EPS 1.2e-7
|
||||
#define RNMX (1.0-EPS)
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DEFINE PARAMETERS AS GLOBAL VARIABLES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char outfile[100]="ecgsyn.dat";/* Output data file */
|
||||
int N = 256; /* Number of heart beats */
|
||||
int sfecg = 256; /* ECG sampling frequency */
|
||||
int sf = 256; /* Internal sampling frequency */
|
||||
double Anoise = 0.0; /* Amplitude of additive uniform noise*/
|
||||
double hrmean = 60.0; /* Heart rate mean */
|
||||
double hrstd = 1.0; /* Heart rate std */
|
||||
double flo = 0.1; /* Low frequency */
|
||||
double fhi = 0.25; /* High frequency */
|
||||
double flostd = 0.01; /* Low frequency std */
|
||||
double fhistd = 0.01; /* High frequency std */
|
||||
double lfhfratio = 0.5; /* LF/HF ratio */
|
||||
|
||||
int Necg = 0; /* Number of ECG outputs */
|
||||
int mstate = 3; /* System state space dimension */
|
||||
double xinitial = 1.0; /* Initial x co-ordinate value */
|
||||
double yinitial = 0.0; /* Initial y co-ordinate value */
|
||||
double zinitial = 0.04; /* Initial z co-ordinate value */
|
||||
int seed = 1; /* Seed */
|
||||
long rseed;
|
||||
double h;
|
||||
double *rr,*rrpc;
|
||||
double *ti,*ai,*bi;
|
||||
|
||||
/* prototypes for externally defined functions */
|
||||
void dfour1(double data[], unsigned long nn, int isign);
|
||||
float ran1(long *idum);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* ALLOCATE MEMORY FOR VECTOR */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
double *mallocVect(long n0, long nx)
|
||||
{
|
||||
double *vect;
|
||||
|
||||
vect=(double *)malloc((size_t) ((nx-n0+1+OFFSET)*sizeof(double)));
|
||||
if (!vect){
|
||||
printf("Memory allocation failure in mallocVect");
|
||||
}
|
||||
return vect-n0+OFFSET;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* FREE MEMORY FOR MALLOCVECT */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void freeVect(double *vect, long n0, long nx)
|
||||
{
|
||||
free((ARG1) (vect+n0-OFFSET));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* MEAN CALCULATOR */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
double mean(double *x, int n)
|
||||
/* n-by-1 vector, calculate mean */
|
||||
{
|
||||
int j;
|
||||
double add;
|
||||
|
||||
add = 0.0;
|
||||
for(j=1;j<=n;j++) add += x[j];
|
||||
|
||||
return (add/n);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* STANDARD DEVIATION CALCULATOR */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
double stdev(double *x, int n)
|
||||
/* n-by-1 vector, calculate standard deviation */
|
||||
{
|
||||
int j;
|
||||
double add,mean,diff,total;
|
||||
|
||||
add = 0.0;
|
||||
for(j=1;j<=n;j++) add += x[j];
|
||||
mean = add/n;
|
||||
|
||||
total = 0.0;
|
||||
for(j=1;j<=n;j++)
|
||||
{
|
||||
diff = x[j] - mean;
|
||||
total += diff*diff;
|
||||
}
|
||||
|
||||
return (sqrt(total/(n-1)));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* WRITE VECTOR IN A FILE */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void vecfile(char filename[], double *x, int n)
|
||||
{
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(filename,"w");
|
||||
for(i=1;i<=n;i++) fprintf(fp,"%e\n",x[i]);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* INTERP */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void interp(double *y, double *x, int n, int r)
|
||||
{
|
||||
int i,j;
|
||||
double a;
|
||||
|
||||
for(i=1;i<=n-1;i++)
|
||||
{
|
||||
for(j=1;j<=r;j++)
|
||||
{
|
||||
a = (j-1)*1.0/r;
|
||||
y[(i-1)*r+j] = (1.0-a)*x[i] + a*x[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* GENERATE RR PROCESS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void rrprocess(double *rr, double flo, double fhi,
|
||||
double flostd, double fhistd, double lfhfratio,
|
||||
double hrmean, double hrstd, double sf, int n)
|
||||
{
|
||||
int i,j;
|
||||
double c1,c2,w1,w2,sig1,sig2,rrmean,rrstd,xstd,ratio;
|
||||
double df,dw1,dw2,*w,*Hw,*Sw,*ph0,*ph,*SwC;
|
||||
|
||||
w = mallocVect(1,n);
|
||||
Hw = mallocVect(1,n);
|
||||
Sw = mallocVect(1,n);
|
||||
ph0 = mallocVect(1,n/2-1);
|
||||
ph = mallocVect(1,n);
|
||||
SwC = mallocVect(1,2*n);
|
||||
|
||||
|
||||
w1 = 2.0*PI*flo;
|
||||
w2 = 2.0*PI*fhi;
|
||||
c1 = 2.0*PI*flostd;
|
||||
c2 = 2.0*PI*fhistd;
|
||||
sig2 = 1.0;
|
||||
sig1 = lfhfratio;
|
||||
rrmean = 60.0/hrmean;
|
||||
rrstd = 60.0*hrstd/(hrmean*hrmean);
|
||||
|
||||
df = sf/n;
|
||||
for(i=1;i<=n;i++) w[i] = (i-1)*2.0*PI*df;
|
||||
for(i=1;i<=n;i++)
|
||||
{
|
||||
dw1 = w[i]-w1;
|
||||
dw2 = w[i]-w2;
|
||||
Hw[i] = sig1*exp(-dw1*dw1/(2.0*c1*c1))/sqrt(2*PI*c1*c1)
|
||||
+ sig2*exp(-dw2*dw2/(2.0*c2*c2))/sqrt(2*PI*c2*c2);
|
||||
}
|
||||
for(i=1;i<=n/2;i++) Sw[i] = (sf/2.0)*sqrt(Hw[i]);
|
||||
for(i=n/2+1;i<=n;i++) Sw[i] = (sf/2.0)*sqrt(Hw[n-i+1]);
|
||||
|
||||
|
||||
/* randomise the phases */
|
||||
for(i=1;i<=n/2-1;i++) ph0[i] = 2.0*PI*ran1(&rseed);
|
||||
ph[1] = 0.0;
|
||||
for(i=1;i<=n/2-1;i++) ph[i+1] = ph0[i];
|
||||
ph[n/2+1] = 0.0;
|
||||
for(i=1;i<=n/2-1;i++) ph[n-i+1] = - ph0[i];
|
||||
|
||||
|
||||
/* make complex spectrum */
|
||||
for(i=1;i<=n;i++) SwC[2*i-1] = Sw[i]*cos(ph[i]);
|
||||
for(i=1;i<=n;i++) SwC[2*i] = Sw[i]*sin(ph[i]);
|
||||
|
||||
/* calculate inverse fft */
|
||||
dfour1(SwC,n,-1);
|
||||
|
||||
/* extract real part */
|
||||
for(i=1;i<=n;i++) rr[i] = (1.0/n)*SwC[2*i-1];
|
||||
|
||||
xstd = stdev(rr,n);
|
||||
ratio = rrstd/xstd;
|
||||
|
||||
for(i=1;i<=n;i++) rr[i] *= ratio;
|
||||
for(i=1;i<=n;i++) rr[i] += rrmean;
|
||||
|
||||
freeVect(w,1,n);
|
||||
freeVect(Hw,1,n);
|
||||
freeVect(Sw,1,n);
|
||||
freeVect(ph0,1,n/2-1);
|
||||
freeVect(ph,1,n);
|
||||
freeVect(SwC,1,2*n);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* THE ANGULAR FREQUENCY */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
double angfreq(double t)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 1 + (int)floor(t/h);
|
||||
|
||||
return 2.0*PI/rrpc[i];
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* THE EXACT NONLINEAR DERIVATIVES */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void derivspqrst(double t0,double x[],double dxdt[])
|
||||
{
|
||||
int i,k;
|
||||
double a0,w0,r0,x0,y0,z0;
|
||||
double t,dt,dt2,*xi,*yi,zbase;
|
||||
|
||||
k = 5;
|
||||
xi = mallocVect(1,k);
|
||||
yi = mallocVect(1,k);
|
||||
|
||||
w0 = angfreq(t0);
|
||||
r0 = 1.0; x0 = 0.0; y0 = 0.0; z0 = 0.0;
|
||||
a0 = 1.0 - sqrt((x[1]-x0)*(x[1]-x0) + (x[2]-y0)*(x[2]-y0))/r0;
|
||||
|
||||
for(i=1;i<=k;i++) xi[i] = cos(ti[i]);
|
||||
for(i=1;i<=k;i++) yi[i] = sin(ti[i]);
|
||||
|
||||
zbase = 0.005*sin(2.0*PI*fhi*t0);
|
||||
|
||||
t = atan2(x[2],x[1]);
|
||||
dxdt[1] = a0*(x[1] - x0) - w0*(x[2] - y0);
|
||||
dxdt[2] = a0*(x[2] - y0) + w0*(x[1] - x0);
|
||||
dxdt[3] = 0.0;
|
||||
for(i=1;i<=k;i++)
|
||||
{
|
||||
dt = fmod(t-ti[i],2.0*PI);
|
||||
dt2 = dt*dt;
|
||||
dxdt[3] += -ai[i]*dt*exp(-0.5*dt2/(bi[i]*bi[i]));
|
||||
}
|
||||
dxdt[3] += -1.0*(x[3] - zbase);
|
||||
|
||||
freeVect(xi,1,k);
|
||||
freeVect(yi,1,k);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* RUNGA-KUTTA FOURTH ORDER INTEGRATION */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void drk4(double y[], int n, double x, double h, double yout[],
|
||||
void (*derivs)(double, double [], double []))
|
||||
{
|
||||
int i;
|
||||
double xh,hh,h6,*dydx,*dym,*dyt,*yt;
|
||||
|
||||
dydx=mallocVect(1,n);
|
||||
dym=mallocVect(1,n);
|
||||
dyt=mallocVect(1,n);
|
||||
yt=mallocVect(1,n);
|
||||
|
||||
hh=h*0.5;
|
||||
h6=h/6.0;
|
||||
xh=x+hh;
|
||||
(*derivs)(x,y,dydx);
|
||||
for (i=1;i<=n;i++) yt[i]=y[i]+hh*dydx[i];
|
||||
(*derivs)(xh,yt,dyt);
|
||||
for (i=1;i<=n;i++) yt[i]=y[i]+hh*dyt[i];
|
||||
(*derivs)(xh,yt,dym);
|
||||
for (i=1;i<=n;i++) {
|
||||
yt[i]=y[i]+h*dym[i];
|
||||
dym[i] += dyt[i];
|
||||
}
|
||||
(*derivs)(x+h,yt,dyt);
|
||||
for (i=1;i<=n;i++)
|
||||
yout[i]=y[i]+h6*(dydx[i]+dyt[i]+2.0*dym[i]);
|
||||
|
||||
freeVect(dydx,1,n);
|
||||
freeVect(dym,1,n);
|
||||
freeVect(dyt,1,n);
|
||||
freeVect(yt,1,n);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DETECT PEAKS */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
double detectpeaks(double *ipeak, double *x, double *y, double *z, int n)
|
||||
{
|
||||
int i,j,j1,j2,jmin,jmax,d;
|
||||
double thetap1,thetap2,thetap3,thetap4,thetap5;
|
||||
double theta1,theta2,d1,d2,zmin,zmax;
|
||||
|
||||
/* use globally defined angles for PQRST */
|
||||
thetap1 = ti[1];
|
||||
thetap2 = ti[2];
|
||||
thetap3 = ti[3];
|
||||
thetap4 = ti[4];
|
||||
thetap5 = ti[5];
|
||||
|
||||
for(i=1;i<=n;i++) ipeak[i] = 0.0;
|
||||
theta1 = atan2(y[1],x[1]);
|
||||
for(i=1;i<n;i++)
|
||||
{
|
||||
theta2 = atan2(y[i+1],x[i+1]);
|
||||
if( (theta1 <= thetap1) && (thetap1 <= theta2) )
|
||||
{
|
||||
d1 = thetap1 - theta1;
|
||||
d2 = theta2 - thetap1;
|
||||
if(d1 < d2) ipeak[i] = 1.0;
|
||||
else ipeak[i+1] = 1.0;
|
||||
}
|
||||
else if( (theta1 <= thetap2) && (thetap2 <= theta2) )
|
||||
{
|
||||
d1 = thetap2 - theta1;
|
||||
d2 = theta2 - thetap2;
|
||||
if(d1 < d2) ipeak[i] = 2.0;
|
||||
else ipeak[i+1] = 2.0;
|
||||
}
|
||||
else if( (theta1 <= thetap3) && (thetap3 <= theta2) )
|
||||
{
|
||||
d1 = thetap3 - theta1;
|
||||
d2 = theta2 - thetap3;
|
||||
if(d1 < d2) ipeak[i] = 3.0;
|
||||
else ipeak[i+1] = 3.0;
|
||||
}
|
||||
else if( (theta1 <= thetap4) && (thetap4 <= theta2) )
|
||||
{
|
||||
d1 = thetap4 - theta1;
|
||||
d2 = theta2 - thetap4;
|
||||
if(d1 < d2) ipeak[i] = 4.0;
|
||||
else ipeak[i+1] = 4.0;
|
||||
}
|
||||
else if( (theta1 <= thetap5) && (thetap5 <= theta2) )
|
||||
{
|
||||
d1 = thetap5 - theta1;
|
||||
d2 = theta2 - thetap5;
|
||||
if(d1 < d2) ipeak[i] = 5.0;
|
||||
else ipeak[i+1] = 5.0;
|
||||
}
|
||||
theta1 = theta2;
|
||||
}
|
||||
|
||||
/* correct the peaks */
|
||||
d = (int)ceil(sfecg/64);
|
||||
for(i=1;i<=n;i++)
|
||||
{
|
||||
if( ipeak[i]==1 || ipeak[i]==3 || ipeak[i]==5 )
|
||||
{
|
||||
j1 = MAX(1,i-d);
|
||||
j2 = MIN(n,i+d);
|
||||
jmax = j1;
|
||||
zmax = z[j1];
|
||||
for(j=j1+1;j<=j2;j++)
|
||||
{
|
||||
if(z[j] > zmax)
|
||||
{
|
||||
jmax = j;
|
||||
zmax = z[j];
|
||||
}
|
||||
}
|
||||
if(jmax != i)
|
||||
{
|
||||
ipeak[jmax] = ipeak[i];
|
||||
ipeak[i] = 0;
|
||||
}
|
||||
}
|
||||
else if( ipeak[i]==2 || ipeak[i]==4 )
|
||||
{
|
||||
j1 = MAX(1,i-d);
|
||||
j2 = MIN(n,i+d);
|
||||
jmin = j1;
|
||||
zmin = z[j1];
|
||||
for(j=j1+1;j<=j2;j++)
|
||||
{
|
||||
if(z[j] < zmin)
|
||||
{
|
||||
jmin = j;
|
||||
zmin = z[j];
|
||||
}
|
||||
}
|
||||
if(jmin != i)
|
||||
{
|
||||
ipeak[jmin] = ipeak[i];
|
||||
ipeak[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* MAIN PROGRAM */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
|
||||
/* First step is to register the options */
|
||||
|
||||
optregister(outfile,CSTRING,'O',"Name of output data file");
|
||||
optregister(N,INT,'n',"Approximate number of heart beats");
|
||||
optregister(sfecg,INT,'s',"ECG sampling frequency [Hz]");
|
||||
optregister(sf,INT,'S',"Internal Sampling frequency [Hz]");
|
||||
optregister(Anoise,DOUBLE,'a',"Amplitude of additive uniform noise [mV]");
|
||||
optregister(hrmean,DOUBLE,'h',"Heart rate mean [bpm]");
|
||||
optregister(hrstd,DOUBLE,'H',"Heart rate standard deviation [bpm]");
|
||||
optregister(flo,DOUBLE,'f',"Low frequency [Hz]");
|
||||
optregister(fhi,DOUBLE,'F',"High frequency [Hz]");
|
||||
optregister(flostd,DOUBLE,'v',"Low frequency standard deviation [Hz]");
|
||||
optregister(fhistd,DOUBLE,'V',"High frequency standard deviation [Hz]");
|
||||
optregister(lfhfratio,DOUBLE,'q',"LF/HF ratio");
|
||||
optregister(seed,INT,'R',"Seed");
|
||||
opt_title_set("ECGSYN: A program for generating a realistic synthetic ECG\n"
|
||||
"Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.\n");
|
||||
|
||||
getopts(argc,argv);
|
||||
|
||||
dorun();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* DORUN PART OF PROGRAM */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int dorun()
|
||||
{
|
||||
int i,j,k,q,Nrr,Nt,Nts;
|
||||
double *x,tstep,tecg,rrmean,qd,hrfact,hrfact2;
|
||||
double *xt,*yt,*zt,*xts,*yts,*zts;
|
||||
double timev,*ipeak,zmin,zmax,zrange;
|
||||
FILE *fp;
|
||||
void (*derivs)(double, double [], double []);
|
||||
|
||||
/* perform some checks on input values */
|
||||
q = (int)rint(sf/sfecg);
|
||||
qd = (double)sf/(double)sfecg;
|
||||
if(q != qd) {
|
||||
printf("Internal sampling frequency must be an integer multiple of the \n");
|
||||
printf("ECG sampling frequency!\n");
|
||||
printf("Your current choices are:\n");
|
||||
printf("ECG sampling frequency: %d Hertz\n",sfecg);
|
||||
printf("Internal sampling frequency: %d Hertz\n",sf);
|
||||
exit(1);}
|
||||
|
||||
|
||||
/* declare and initialise the state vector */
|
||||
x=mallocVect(1,mstate);
|
||||
x[1] = xinitial;
|
||||
x[2] = yinitial;
|
||||
x[3] = zinitial;
|
||||
|
||||
/* declare and define the ECG morphology vectors (PQRST extrema parameters) */
|
||||
ti=mallocVect(1,5);
|
||||
ai=mallocVect(1,5);
|
||||
bi=mallocVect(1,5);
|
||||
/* P Q R S T */
|
||||
ti[1]=-60.0; ti[2]=-15.0; ti[3]=0.0; ti[4]=15.0; ti[5]=90.0;
|
||||
ai[1]=1.2; ai[2]=-5.0; ai[3]=30.0; ai[4]=-7.5; ai[5]=0.75;
|
||||
bi[1]=0.25; bi[2]=0.1; bi[3]=0.1; bi[4]=0.1; bi[5]=0.4;
|
||||
|
||||
/* convert angles from degrees to radians */
|
||||
for(i=1;i<=5;i++) ti[i] *= PI/180.0;
|
||||
|
||||
/* adjust extrema parameters for mean heart rate */
|
||||
hrfact = sqrt(hrmean/60.0);
|
||||
hrfact2 = sqrt(hrfact);
|
||||
for(i=1;i<=5;i++) bi[i] *= hrfact;
|
||||
ti[1]*=hrfact2; ti[2]*=hrfact; ti[3]*=1.0; ti[4]*=hrfact; ti[5]*=1.0;
|
||||
|
||||
|
||||
/* calculate time scales */
|
||||
h = 1.0/sf;
|
||||
tstep = 1.0/sfecg;
|
||||
|
||||
printf("ECGSYN: A program for generating a realistic synthetic ECG\n"
|
||||
"Copyright (c) 2003 by Patrick McSharry & Gari Clifford. All rights reserved.\n"
|
||||
"See IEEE Transactions On Biomedical Engineering, 50(3), 289-294, March 2003.\n"
|
||||
"Contact P. McSharry (patrick@mcsharry.net) or G. Clifford (gari@mit.edu)\n");
|
||||
|
||||
printf("Approximate number of heart beats: %d\n",N);
|
||||
printf("ECG sampling frequency: %d Hertz\n",sfecg);
|
||||
printf("Internal sampling frequency: %d Hertz\n",sf);
|
||||
printf("Amplitude of additive uniformly distributed noise: %g mV\n",Anoise);
|
||||
printf("Heart rate mean: %g beats per minute\n",hrmean);
|
||||
printf("Heart rate std: %g beats per minute\n",hrstd);
|
||||
printf("Low frequency: %g Hertz\n",flo);
|
||||
printf("High frequency std: %g Hertz\n",fhistd);
|
||||
printf("Low frequency std: %g Hertz\n",flostd);
|
||||
printf("High frequency: %g Hertz\n",fhi);
|
||||
printf("LF/HF ratio: %g\n",lfhfratio);
|
||||
|
||||
/* initialise seed */
|
||||
rseed = -seed;
|
||||
|
||||
|
||||
/* select the derivs to use */
|
||||
derivs = derivspqrst;
|
||||
|
||||
/* calculate length of RR time series */
|
||||
rrmean = (60/hrmean);
|
||||
Nrr = (int)pow(2.0, ceil(log10(N*rrmean*sf)/log10(2.0)));
|
||||
printf("Using %d = 2^%d samples for calculating RR intervals\n",
|
||||
Nrr,(int)(log10(1.0*Nrr)/log10(2.0)));
|
||||
|
||||
|
||||
/* create rrprocess with required spectrum */
|
||||
rr = mallocVect(1,Nrr);
|
||||
rrprocess(rr, flo, fhi, flostd, fhistd, lfhfratio, hrmean, hrstd, sf, Nrr);
|
||||
vecfile("rr.dat",rr,Nrr);
|
||||
|
||||
/* create piecewise constant rr */
|
||||
rrpc = mallocVect(1,2*Nrr);
|
||||
tecg = 0.0;
|
||||
i = 1;
|
||||
j = 1;
|
||||
while(i <= Nrr)
|
||||
{
|
||||
tecg += rr[j];
|
||||
j = (int)rint(tecg/h);
|
||||
for(k=i;k<=j;k++) rrpc[k] = rr[i];
|
||||
i = j+1;
|
||||
}
|
||||
Nt = j;
|
||||
vecfile("rrpc.dat",rrpc,Nt);
|
||||
|
||||
printf("Printing ECG signal to file: %s\n",outfile);
|
||||
|
||||
/* integrate dynamical system using fourth order Runge-Kutta*/
|
||||
xt = mallocVect(1,Nt);
|
||||
yt = mallocVect(1,Nt);
|
||||
zt = mallocVect(1,Nt);
|
||||
|
||||
timev = 0.0;
|
||||
for(i=1;i<=Nt;i++)
|
||||
{
|
||||
xt[i] = x[1];
|
||||
yt[i] = x[2];
|
||||
zt[i] = x[3];
|
||||
drk4(x, mstate, timev, h, x, derivs);
|
||||
timev += h;
|
||||
}
|
||||
|
||||
|
||||
/* downsample to ECG sampling frequency */
|
||||
xts = mallocVect(1,Nt);
|
||||
yts = mallocVect(1,Nt);
|
||||
zts = mallocVect(1,Nt);
|
||||
|
||||
j=0;
|
||||
for(i=1;i<=Nt;i+=q)
|
||||
{
|
||||
j++;
|
||||
xts[j] = xt[i];
|
||||
yts[j] = yt[i];
|
||||
zts[j] = zt[i];
|
||||
}
|
||||
Nts = j;
|
||||
|
||||
|
||||
/* do peak detection using angle */
|
||||
ipeak = mallocVect(1,Nts);
|
||||
detectpeaks(ipeak, xts, yts, zts, Nts);
|
||||
|
||||
/* scale signal to lie between -0.4 and 1.2 mV */
|
||||
zmin = zts[1];
|
||||
zmax = zts[1];
|
||||
for(i=2;i<=Nts;i++)
|
||||
{
|
||||
if(zts[i] < zmin) zmin = zts[i];
|
||||
else if(zts[i] > zmax) zmax = zts[i];
|
||||
}
|
||||
zrange = zmax-zmin;
|
||||
for(i=1;i<=Nts;i++) zts[i] = (zts[i]-zmin)*(1.6)/zrange - 0.4;
|
||||
|
||||
/* include additive uniformly distributed measurement noise */
|
||||
for(i=1;i<=Nts;i++) zts[i] += Anoise*(2.0*ran1(&rseed) - 1.0);
|
||||
|
||||
/* output ECG file */
|
||||
fp = fopen(outfile,"w");
|
||||
for(i=1;i<=Nts;i++) fprintf(fp,"%f %f %d\n",(i-1)*tstep,zts[i],(int)ipeak[i]);
|
||||
fclose(fp);
|
||||
|
||||
|
||||
printf("Finished ECG output\n");
|
||||
|
||||
freeVect(x,1,mstate);
|
||||
freeVect(rr,1,Nrr);
|
||||
freeVect(rrpc,1,2*Nrr);
|
||||
freeVect(ti,1,5);
|
||||
freeVect(ai,1,5);
|
||||
freeVect(bi,1,5);
|
||||
freeVect(xt,1,Nt);
|
||||
freeVect(yt,1,Nt);
|
||||
freeVect(zt,1,Nt);
|
||||
freeVect(xts,1,Nt);
|
||||
freeVect(yts,1,Nt);
|
||||
freeVect(zts,1,Nt);
|
||||
freeVect(ipeak,1,Nts);
|
||||
|
||||
/* END OF DORUN */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user