/*****************************************************************************
FILE:  easytest.cpp
AUTHOR:	Patrick S. Hamilton
REVISED:	5/13/2002 (PSH); 4/10/2003 (GBM)
  ___________________________________________________________________________

easytest.cpp: Use bdac to generate an annotation file.
Copyright (C) 2001 Patrick S. Hamilton
Copyright (C) 1999 George B. Moody

This file is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.

This software 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 Library General Public License for more
details.

You should have received a copy of the GNU Library General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.

You may contact the author by e-mail (pat@eplimited.edu) or postal mail
(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
MA 02143 USA).  For updates to this software, please visit our website
(http://www.eplimited.com).
  __________________________________________________________________________

Easytest.exe is a simple program to help test the performance of our
beat detection and classification software. Data is read from the
indicated ECG file, the channel 1 signal is fed to bdac.c, and the
resulting detections are saved in the annotation file <record>.ate.
<record>.ate may then be compared to <record>.atr to using bxb to
analyze the performance of the the beat detector and classifier detector.

Note that data in the MIT/BIH Arrythmia database file has been sampled
at 360 samples-per-second, but the beat detection and classification
software has been written for data sampled at 200 samples-per-second.
Date is converterted from 360 sps to 200 sps with the function NextSample.
Code for resampling was copied from George Moody's xform utility.  The beat
locations are then adjusted back to coincide with the original sample
rate of 360 samples/second so that the annotation files generated by
easytest can be compared to the "atruth" annotation files.

This file must be linked with object files produced from:
	wfdb software library (source available at www.physionet.org)
	analbeat.cpp
	match.cpp
	rythmchk.cpp
	classify.cpp
	bdac.cpp
	qrsfilt.cpp
	qrsdet.cpp
	postclass.cpp
	noisechk.cpp
  __________________________________________________________________________

  Revisions
	4/13/02:
		Added conditional define statements that allow MIT/BIH or AHA
			records to be processed.
		Normalize input to 5 mV/LSB (200 A-to-D units/mV).

	4/10/03:
		Moved definitions of Record[] array, ECG_DB_PATH, and REC_COUNT
			into "input.h"
 *******************************************************************************/

/*
 * 	For unknown reasons
 *
 *
 */



#include <wfdb/wfdb.h>
#include <wfdb/ecgcodes.h>
#include <wfdb/ecgmap.h>
#include "stdio.h"
#include "qrsdet.h"		// For sample rate.

#include "inputs.h"	/* list of records to analyze and definitions of
			   ECG_DB_PATH and REC_COUNT */

// External function prototypes.
void ResetBDAC(void) ;
int BeatDetectAndClassify(int ecgSample, int *beatType, int *beatMatch) ;

// Local Prototypes.
int  NextSample(int *vout,int nosig,int ifreq,
		int ofreq,int init) ;
int gcd(int x, int y);

// Global variables.


int main(int argc , char **argv)
{

	int leads=0;
	char *record, *output, *name;

	int i=0,  delay, recNum=0 ;

	int ecg[WFDB_MAXSIG];
	int ADCZero;
	int InputFileSampleFrequency ;
	double gain;

	WFDB_Siginfo sig_info[WFDB_MAXSIG] ;
	WFDB_Anninfo ann_info[WFDB_MAXSIG];
	WFDB_Annotation annot[WFDB_MAXSIG];

	unsigned char byte;
	long long SampleCount = 0, lTemp, DetectionTime ;
	int beatType, beatMatch ;
	int lead;

	//FILE *log= fopen ("Log.txt", "w");

	if (argc<2)
	{
		printf("No valid parameter. Please, enter a valid record\n");
		return -1;
	}

	if (!strcmp(argv[1],"-h"))
	{
		printf("Hello World\n");
		return 0;
	}


	if (argc<3)
	{
		printf("No valid lead");
		return -1;
	}


	record = argv[1];
	lead = atoi(argv[2]);

	output = "./";

	name = (char*) malloc (sizeof(char)*(strlen(argv[2])+strlen(argv[1])+2));

	printf("Record %s\n",record) ;
	//setwfdb(".") ;

	leads=isigopen(record,sig_info,WFDB_MAXSIG);

	if( leads  < 1)
	{
		printf("Couldn't open %s\n",record) ;
		return -1;
	}
	ADCZero = sig_info[lead].adczero ;
	gain = ( (double)200.0) / ( (double)sig_info[i].gain) ;


	InputFileSampleFrequency = sampfreq(record) ;

	sprintf(name,"%s%s",output,record);

	ann_info[0].name = "epl";
	ann_info[0].stat = WFDB_WRITE ;


	if(annopen(name, ann_info, 1) < 0) 	return -1;

	free(name);

	NextSample(ecg,leads,InputFileSampleFrequency,SAMPLE_RATE,1) ;
	ResetBDAC() ;
	SampleCount = 0 ;

	while(NextSample(ecg,leads,InputFileSampleFrequency,SAMPLE_RATE,0) >= 0)
	{

		++SampleCount ;

		lTemp = (int)( ((double)(ecg[lead]-ADCZero)) * gain) ;
		ecg[i] = lTemp ;
		delay = BeatDetectAndClassify(ecg[lead], &beatType, &beatMatch) ;

		if(delay != 0)
		{
			DetectionTime = SampleCount - delay ;
			DetectionTime *= InputFileSampleFrequency ;
			DetectionTime /= SAMPLE_RATE ;
			//annot.time = 1 ;
			//annot.anntyp = 2 ;

			annot[0].time = DetectionTime ;
			annot[0].anntyp = beatType ;

			//fprintf(log,"%d %d\n",annot.time,annot.anntyp) ;
			//printf("%d %d\n",annot.time,annot.anntyp) ;
			putann(0,annot) ;
		}


	}

	//fclose(log);

	wfdbquit() ;


	return 0;
}

/**********************************************************************
	NextSample reads MIT/BIH Arrhythmia data from a file of data
	sampled at ifreq and returns data sampled at ofreq.  Data is
	returned in vout via *vout.  NextSample must be initialized by
	passing in a nonzero value in init.  NextSample returns -1 when
   there is no more data left.
 ***********************************************************************/

int  NextSample(int *vout,int nosig,int ifreq,int ofreq,int init)
{
	int i , rval;
	static int m, n, mn, ot, it, vv[WFDB_MAXSIG], v[WFDB_MAXSIG] ;

	if(init)
	{
		i = gcd(ifreq, ofreq);
		m = ifreq/i;
		n = ofreq/i;
		mn = m*n;
		ot = it = 0 ;
		getvec(vv) ;
		rval = getvec(v) ;
	}
	else
	{
		while(ot > it)
		{
			for(i = 0; i < nosig; ++i)  vv[i] = v[i] ;
			rval = getvec(v) ;
			if (it > mn) { it -= mn; ot -= mn; }
			it += n;
		}
		for(i = 0; i < nosig; ++i) vout[i] = vv[i] + (ot%n)*(v[i]-vv[i])/n;
		ot += m;
	}

	return(rval) ;
}

// Greatest common divisor of x and y (Euclid's algorithm)

int gcd(int x, int y)
{
	while (x != y)
	{
		if (x > y) x-=y;
		else y -= x;
	}
	return (x);
}
