/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	CPY 5/27/06 FFT_SAMPLE_INTERVAL_USE_OCMATH_FUNC								*
 *  Sandy 2006-7-4 FOR_MATCH_IGOR_RESULT										*
 *	Cheney 2006-7-19 AUTO_COMPUTE_SAMPLING_INTERVAL_FROM_INPUTDATA				*
 *	Cheney 2006-7-19 AUTO_COMPUTE_PARAMS_VALUE									*
 *	Cheney 2006-8-4 WINDOW_FILTER												*
 *  Justin 2007-3-22 v8.0587 CORRECT_METHOD_TO_GET_AUTO_SUPPORT					*
 *  Justin 2007-3-22 v8.0587 CHECK_USER_INPUTED_INTERVAL 						*
 *  Justin 2007-3-23 v8.0588 MOVE_BACK_FFTUTILIS_BECAUSE_COMPILE_ERROR			*
 *	CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV, replace >0 with !=0	*
 *	Fisher 2008-9-13	GRAPH_OBJ_CURVE_TOOL									*
 *	Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X		*
 *	Fisher 07/29/09 QA80-14034 SET_2DFFT_FREQUENCY_DOMAIN						*
 *	YuI 10/14/09 QA70-13728-P3 WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN*
 *	Kyle 10/22/2009 QA80-13487-P4 SUPPORT_DESCENDING_DATA						*
 *	Sophy 2/23/2010 IMPROVE_ROI_FFT_RESULTS										*
 *	Kit 10/26/2010 ORG-1227-P3 SUPPORT_OTHER_FFT_TOOL_SHOW_UNITS_ON_REPORT_TABLE*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
#include <event_utils.h>
#include <fft_utils.h> /// AW 05/21/04 QA70-6387 v7.0876 CENTRALIZE_CODE_FOR_STFT
//#include <ReportTree.h>
#include <xfutils.h> //--CPY 5/26/06
#include <oErrMsg.h>
#include <OCTreeUtils.h>  ///Justin 2007-3-22 v8.0587 CORRECT_METHOD_TO_GET_AUTO_SUPPORT
#include <OC_nag8.h>
#include <ReportTree.h>  ///-----Kit 10/26/2010 ORG-1227-P3 SUPPORT_OTHER_FFT_TOOL_SHOW_UNITS_ON_REPORT_TABLE

#pragma labtalk(0) //--- CPY 7/26/05 hide all functions in this file from LT access, as XF should be used instead

enum FFT_FILTER_TYPE{ 
		FFT_LOWPASS = 0, FFT_HIGHPASS, FFT_BANDPASS, FFT_BANDBLOCK
};

///sandy 2006-7-7 change to use the general error defined in <oErrMsg.h>
//enum
//{
	////0 for success
	//CER_UNKNOWN_ERROR = 1000,	// " Unknown error"
	//CER_INVALID_SIZE,			// " Invalid Size"
	//CER_DATA_SIZE_ERROR,		// " The size of data is not same as iSize provided"
	//CER_INVALID_DATA,			// " Data value invalid"
	//CER_FFT_INVALID_INTERVAL,		// " The interval is less than 1e-20, used in fft_sampling_resolution";
	//CER_FFT_UNEVENLY_SPACE,			// " Unevenly spaced values, used in fft_sampling_resolution";
	//CER_MEMORY_ALLOCATE_ERROR,	// " Not enough memory allocated to a pointer, used by calloc()";
	//CER_INVALID_INCREMENT,		// " The increment is less than 1e-20, used in OC_Data";
	//CER_INVALID_ARGUMENT,		// " Invalid argument";
	//CER_MEMORY_DUPLICATE		// use the same pointer to represent different data
//};
//
// handle erro codes in fft 
//int fft_error_handle(int nError, LPCSTR lpcstrErrInfo)// , 
//{
	//if ( 0 == nError )
		//return 0;
	//string strErr;
	//switch ( nError )
	//{
		//case UNKNOWN_ERROR:
			//strErr = " Unknown error";
			//break;
		//case INVALID_SIZE:
			//strErr = " Invalid Size";
			//break;
		//case DATA_SIZE_ERROR:
			//strErr = " The size of data is not same as iSize provided";
			//break;
		//case INVALID_DATA:
			//strErr = " Data value invalid";
			//break; 
		//case INVALID_INTERVAL:
			//strErr = " The interval is less than 1e-20, used in fft_sampling_resolution";
			//break;
		//case UNEVENLY_SPACE:
			//strErr = " Unevenly spaced values, used in fft_sampling_resolution";
			//break;
		//case MEMORY_ALLOCATE_ERROR:	 
			//strErr = " Not enough memory allocated to a pointer, used by calloc()";
			//break;
		//case INVALID_INCREMENT:		 
			//strErr = " The increment is less than 1e-20, used in OC_Data";
			//break;
		//case INVALID_ARGUMENT:		
			//strErr = " Invalid argument";
			//break;
		//default:
			//ASSERT(FALSE);  // check why come here, new error codes?
	//}
	//if ( lpcstrErrInfo )
		//strErr = strErr + " : " + lpcstrErrInfo;
	//out_str("Error!!!"+ strErr);
	//return nError;
//}

///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
void	recreate_even_space_time_vector(vector& vTime, double rInc)
{
	int		nSize = vTime.GetSize();
	if ( nSize <= 1 )
		return;
	
	double	rMin, rMax;
	vTime.GetMinMax(rMin, rMax);
	rInc = abs(rInc);
	vTime.Data(rMin, rMin + rInc * nSize, rInc);
	vTime.SetSize(nSize);
}
///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X

/**
	This function performs normalization of the response function
*/
void fft_normalize_response(vector& vecResponse)
{
	vector vsquare;
	vsquare = vecResponse * vecResponse;
	
	// Find the sum of all response elements
	double dSumResp;
	vsquare.Sum(dSumResp);
	
	// Normalize response so that sum of all elements is unity
	vecResponse /= sqrt(dSumResp);
}

///sandy 2006-7-7 remove no meaning code
/**
	This function sets valute 1 to the vector
*/
//int SetSize1(vector& vWin)
//{
	//vWin = 1;
	//return 0;
//}

/**
	This function performs wrapping of the response function
*/
void fft_wrap_response(vector& vecResponse)
{
	// Find position of max element in response
	int iMax;
	double dmin, dmax;
	vecResponse.GetMinMax(dmin, dmax, NULL, &iMax); 

	// Take response and "wrap it around" so that the point with the max value
	// is now the first point in the response dataset.
	if(iMax != 0)
	{
		vecResponse.Wrap(iMax);
	}
}

///Cheney 2006-7-13 REMOVE_CODE_TO_XF
/*
int convolute(vector& vecSignal, vector& vecResponse, vector& vecResult, bool bNormalize, bool bWrap, bool bCircular)
{
	int iRet;
	vector vSignal, vResponse;
	
	//if ( iRet = ocmath_count(NANUM, vecSignal.GetSize(), vecSignal) ) 
		//return INVALID_DATA;

	//if ( iRet = ocmath_count(NANUM, vecResponse.GetSize(), vecResponse) ) 
		//return INVALID_DATA;
	
	// Get length of signal and pad with zeroes for the shorter one
	int iSize = vecSignal.GetSize();
	int iSize1 = vecResponse.GetSize();

	if (iSize < 1 || iSize1 < 1) 
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}

	vSignal = vecSignal;
	vResponse = vecResponse;
	if(!bCircular)
	{
		//iSize = vSignal.GetSize() + vResponse.GetSize() - 1;
		iSize = iSize + iSize1 - 1;
		//vSignal.SetSize(iSize);
		//vResponse.SetSize(iSize);
	}
	else
	{
		//2006-6-1 sandy only for reduce code
		//if(iSize < iSize1)
		//{
			//iSize = iSize1;
			//vSignal.SetSize(iSize);
		//}
		//else
		//{
			//vResponse.SetSize(iSize);
		//}
		iSize = max(iSize, iSize1);
		
	}
	//2006-6-1 sandy only for reduce code
	vSignal.SetSize(iSize);
	vResponse.SetSize(iSize);
	
	// Call FFT function(s) to perform convolution
	//vecResult = vSignal;
	//vecResult.SetSize(iSize);
	
	// Wrap/Normalize response if requested
	if(bWrap)
	{
		_fft_wrap_response(vResponse);	//Shift for count
	}
	if(bNormalize) 
	{
		_fft_normalize_response(vResponse);	//normalize
	}

	//if((iRet = fft_fft_convolution(iSize, vecResult, vResponse)) != 0) 
	if((iRet = fft_fft_convolution(iSize, vSignal, vResponse)) != 0) 
		return iRet;
	
	vecResult = vSignal;
	// Return 0 error code on successful completion
	return 0;
}
*/
///end REMOVE_CODE_TO_XF

///Cheney 2006-7-13 REMOVE_CODE_TO_XF
/**
	use fft to get correlate result
*/
/*
int correlate(vector& vecSignal1, vector& vecSignal2, vector& vecCorrelation, bool bNormalize, bool bCircular) ///Soapy 07/03/05 ADD_CORRELATION_OPTION_LINEAR_CIRCULAR
{
	int iRet;
	vector vSignal1, vSignal2;
	
	vSignal1 = vecSignal1;
	vSignal2 = vecSignal2;

	//if ( iRet = ocmath_count(NANUM, vSignal1.GetSize(), vSignal1) ) 
		//return INVALID_DATA;
	//
	//if ( iRet = ocmath_count(NANUM, vSignal2.GetSize(), vSignal2) ) 
		//return INVALID_DATA;

	// Get length of signal and pad with zeroes for the shorter one
	int iSize = vSignal1.GetSize();
	int iSize1 = vSignal2.GetSize();

	if (iSize < 1 || iSize1 < 1) 
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;

	//if(iSize < iSize1)
	//{
		//iSize = iSize1;
		//vSignal1.SetSize(iSize);
	//}
	//else
	//{
		//vSignal2.SetSize(iSize);
	//}
	//2006-6-1 sandy only for reduce code
	iSize = max(iSize, iSize1);
	if(!bCircular)
	{
		iSize = 2 * iSize - 1;
		//vSignal1.SetSize(iSize);
		//vSignal2.SetSize(iSize);
	}

	vSignal1.SetSize(iSize);
	vSignal2.SetSize(iSize);
	
	if(bNormalize) 	//normalize
	{
		_fft_normalize_response(vSignal1);
		_fft_normalize_response(vSignal2);
	}

	// Call NAG function(s) to perform convolution
	
	if((iRet = fft_fft_correlation(iSize, vSignal1, vSignal2)) != 0) 
		return iRet;
	
	if(!bCircular)
	{
		vSignal1.Wrap((iSize + 1) / 2);
	}
	else
	{
		///Sandy 2006-7-4 FOR_MATCH_IGOR_RESULT
		vector<uint> vUpDown;
		vUpDown.Data(vSignal1.GetSize() - 1, 0, -1);
		vSignal1.Reorder(vUpDown);
		//end
	}
	
	vecCorrelation = vSignal1;

	// Return 0 error code on successful completion
	return 0;
}
*/
///end REMOVE_CODE_TO_XF

///Cheney 2006-7-13 REMOVE_CODE_TO_XF
/**
	use fft to get reverse convolute result
*/
/*
int deconvolute(vector& vecSignal, vector& vecResponse, vector& vecResult, bool bNormalize, bool bWrap, bool bCircular)

{
	int iRet;
	vector vSignal, vResponse;

	//if ( iRet = ocmath_count(NANUM, vecSignal.GetSize(), vecSignal) )
	//{
		//return INVALID_DATA;
	//}
	//
	//if ( iRet = ocmath_count(NANUM, vecResponse.GetSize(), vecResponse) ) 
	//{
		//return INVALID_DATA;
	//}
	
	int iSize = vecSignal.GetSize();
	int iSize1 = vecResponse.GetSize();
	if (iSize < 1 || iSize1 < 1)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}

	if(iSize < iSize1)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	int nResultSize = iSize - iSize1 + 1 ;
	//else
	//{
		//vResponse.SetSize(iSize);
	//}

	vSignal = vecSignal;
	vResponse = vecResponse;	

	if(!bCircular)
	{
		iSize = 2 * iSize - 1;
		//vSignal.SetSize(iSize);
		//vResponse.SetSize(iSize);
	}
	else
	{
		iSize = iSize - iSize1 + 1;
	}
	
	vSignal.SetSize(iSize);
	vResponse.SetSize(iSize);
	
	// Call function(s) to perform deconvolution
	//vecResult = vSignal;
	
	// Wrap/Normalize response if requested
	if(bWrap)
	{
		_fft_wrap_response(vResponse);	//shift for count
	}
	if(bNormalize)
	{
		_fft_normalize_response(vResponse);	//normalize
	}

	if((iRet = fft_fft_deconvolution(iSize, vSignal, vResponse)) != 0) 
	{
		return iRet;
	}

	vecResult = vSignal;
	vecResult.SetSize(nResultSize);
	
	// Return 0 error code on successful completion
	return 0;
}
*/
///end REMOVE_CODE_TO_XF

/// Fisher 2008-9-13	GRAPH_OBJ_CURVE_TOOL
void fft_amp(vector &vx, vector &vy, vector &vfreq, vector &vAmp, int nSize, bool bNormalize, bool bOneSide)
{
	ASSERT(nSize == vx.GetSize());	// number of points
	if( 0 >= nSize )
		return;
	
	vfreq.SetSize(nSize);
	double dTimeInterval;
	///Sophy 2/23/2010 IMPROVE_ROI_FFT_RESULTS
	//if(nSize > 2)
	if ( nSize >= 2 ) //allow 2 points, like fft1.oxf
	///end IMPROVE_ROI_FFT_RESULTS
	{
		//dTimeInterval = vx[1] - vx[0];
		//if(!fft_sampling_resolution(&vx, dTimeInterval))
		//	get_frequence_from_interval(nSize, vfreq, dTimeInterval);
		//else
		//	vfreq = vx;
		dTimeInterval = vx[1] - vx[0];	
		fft_sampling_resolution(&vx, dTimeInterval);
		///Kyle 10/22/2009 QA80-13487-P4 SUPPORT_DESCENDING_DATA
		if(dTimeInterval <= 0)
			dTimeInterval *= -1;
		///End SUPPORT_DESCENDING_DATA
		get_frequence_from_interval(nSize, vfreq, dTimeInterval);
	}
	else
		vfreq[0] = 0;
	
	vector<complex> vout;
	vout.SetSize(nSize);
	fft_real(nSize, vy);
	fft_hermitian_to_complex(nSize, vy, vout);
	
	if(bOneSide)
	{
		///Sophy 2/23/2010 IMPROVE_ROI_FFT_RESULTS
		//vfreq.SetSize(nSize/2);
		//vout.SetSize(nSize/2);
		//vAmp.SetSize(nSize/2);
#define	CUTOFF(_N)	((_N)/2 + 1)
		vfreq.SetSize(CUTOFF(nSize));
		vout.SetSize(CUTOFF(nSize));
		///end IMPROVE_ROI_FFT_RESULTS
	}
	else
		vAmp.SetSize(nSize);
	
	vout.GetAmplitude(vAmp);
	///Sophy 2/23/2010 IMPROVE_ROI_FFT_RESULTS
	//refer to /// Fisher 11/4/08 FIX_INCORRECT_DC_AMPLITUDE_FACTOR in fft1.xfc
	if ( bOneSide )
	{
		vAmp[0] *= 0.5;
		vAmp[vAmp.GetSize() - 1] *= 0.5;
	}
	///end IMPROVE_ROI_FFT_RESULTS
	if(bNormalize)
		vAmp *= 2.0/nSize;			// normalize amplitude
	
}
/// end	GRAPH_OBJ_CURVE_TOOL

int fft_real(int nFFT, vector& vSig, FFT_SIGN iSign)
{
	if(nFFT < 1)
		return CER_INVALID_SIZE;
	
	int nRet;
	//int nRet = ocmath_count(NANUM, vSig.GetSize(), vSig);
	//if (nRet)
	//{
		//return INVALID_DATA;
	//}
	
	vSig.SetSize(nFFT);	
	nRet = fft_fft_real(nFFT, vSig, iSign);
	return nRet;
}

int fft_complex(int nFFT, vector<complex>& vSig, FFT_SIGN iSign)
{
	if(nFFT < 1)
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	
	int nRet;
	vSig.SetSize(nFFT);
	
	///Cheney 2006-7-12 REMOVE_REDUNDANT_CODE
	//vector vReal, vImag;
	//vSig.GetReal(vReal);
	//vSig.GetImaginary(vImag);
	///end REMOVE_REDUNDANT_CODE
	//if (ocmath_count(NANUM, nFFT, vReal) || ocmath_count(NANUM, nFFT, vImag))
	//{
		//return INVALID_DATA;
	//}
	
	nRet = fftw_fft_complex(nFFT, vSig, iSign);
	return nRet;
}

int get_frequence_from_interval(int nSize, vector& vFreq, double interval)
{
	if(interval == 0)
	{
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
	}
	
	if(nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	
	vFreq.Data(0, 1.0/interval-1.0/(interval*nSize), 1.0/(interval*nSize));
	
	return OE_NOERROR;
}

int get_lag_from_interval(int nSize, vector& vLag, double interval, bool bCircular)
{
	if(interval == 0)
	{
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
	}
	
	if(nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}

	if(!bCircular)
	{	
		vLag.Data(interval*(-nSize + 1), interval*(nSize-1), interval);
	}
	else
	{
		vLag.Data(0, interval*(nSize-1), interval);
	}
	
	return OE_NOERROR;
}	

int fft_norm_amp(vector<complex>& vSignal)
{
	int nSize = vSignal.GetSize();
	if (nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	
	if(nSize>1)
		vSignal /= nSize/2.0;
	
	return OE_NOERROR;
}

int fft_factor(vector<complex>& vSignal)
{
	int nSize = vSignal.GetSize();
	if (nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	
	vector<uint> vN;
	vN.Data(nSize - 1, 1, -1);
	vN.InsertAt(0, 0);
	vSignal.Reorder(vN);
	
	return OE_NOERROR;
}

int fft_shift(vector<complex>& vSignal, vector& vFreq)
{
	int nSize = vSignal.GetSize();
	if (nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	//justin 08/03/2006 SHIF_NOT_CHANGE_ZERO 
	/*
	double dStart = vFreq[0];
	double dEnd = vFreq[nSize - 1];
		
	vFreq.Data((-0.5*(dEnd - dStart)), 0.5*(dEnd - dStart), (dEnd - dStart)/(nSize - 1));

	if(nSize%2)
		vSignal.Wrap(nSize/2 + 1);
	else
		vSignal.Wrap(nSize/2);
	*/
	///justin 11/20/2006 IMPROVE_SPEED_OF_SHIFT
	//if (1 == nSize ) 
		//return OE_NOERROR; 
		//
	//int nWrapSize = nSize/2 + 1;
	//double dAdjust = (vFreq[nSize-1] - vFreq[0]) * nSize /(nSize -1.0);
	//
	//vSignal.Wrap(nWrapSize);
	 //
	//vFreq.Wrap(nWrapSize);
	//for(int ii = 0; ii < nSize-nWrapSize; ii++)
	//{
		//vFreq[ii] -= dAdjust;
	//}
		
	int nWrapSize = nSize/2 + 1;

	vSignal.Wrap(nWrapSize);
	
	if(vFreq && nSize > 1)
	{
		if(nSize != vFreq.GetSize())
		{
			return CER_INVALID_SIZE;
		}
		double dAdjust = vFreq[(nSize-1)/2];
		vFreq -= dAdjust;
	}
	///END IMPROVE_SPEED_OF_SHIFT
	//end SHIF_NOT_CHANGE_ZERO
	return OE_NOERROR;
}

//add by sandy 2006-6-13
///justin 08/23/2006 FIX_UNDO_SHIFT
//int ifft_shift(vector<complex>& vSignal, vector& vFreq)
//end FIX_UNDO_SHIFT
/*
{	
	int nSize = vSignal.GetSize();
	if (nSize <= 0 )
	{
		return CER_INVALID_SIZE;
	}
	
	double dStart = vFreq[0];
	double dEnd = vFreq[nSize - 1];
	
	vFreq = vFreq + (dEnd - dStart)/2.0;
	//if(nSize%2)
		//vSignal.Wrap(nSize/2+1);
	//else
	vSignal.Wrap(nSize/2);
	
	return OE_NOERROR;
}
*/	
int undo_fft_shift(vector<complex>& vSignal, vector& vFreq)
{
	int nSize = vSignal.GetSize();
	if (nSize <= 0)
	{
		return CER_INVALID_SIZE;
	}

	///justin 11/20/2006 IMPROVE_SPEED_OF_SHIFT
	//if (1 == nSize )  
		//return OE_NOERROR; 
	///END IMPROVE_SPEED_OF_SHIFT
		
	int nWrapSize = (nSize-1)/2 ;

	vSignal.Wrap(nWrapSize);
	
	///justin 11/20/2006 IMPROVE_SPEED_OF_SHIFT
	//if(vFreq)
	//{
		//if(nSize != vFreq.GetSize())
		//{
			//return CER_INVALID_SIZE;
		//}
		//
		//double dAdjust = (vFreq[nSize-1] - vFreq[0]) * nSize /(nSize -1.0);
		//for(int ii = 0; ii < nWrapSize; ii++)
		//{
			//vFreq[ii] += dAdjust;
		//}
		//vFreq.Wrap(nWrapSize);
	//}
	
	if(vFreq && nSize > 1)
	{
		if(nSize != vFreq.GetSize())
		{
			return CER_INVALID_SIZE;
		}
		
		double dAdjust = vFreq[0]; 
		vFreq -= dAdjust;
	}
	///END IMPROVE_SPEED_OF_SHIFT

	return OE_NOERROR;
}
//end FIX_UNDO_SHIFT

int fft_unwrap_phase(vector& vPhase)
{
	int nSize = vPhase.GetSize();
	if (nSize <= 0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	
	int nRet = fftw_fft_unwrap_phase(nSize, vPhase);
	
	if (nRet)
		return nRet;
	
	return OE_NOERROR;
}	
///justin 08/14/2006 	GET_COMPENSATING
//int apply_window_data(vector& vSignal, int nType)
int apply_window_data(vector& vSignal, int nType, double* pdCom)
///end GET_COMPENSATING
{
	//if (ocmath_count(NANUM, vSignal.GetSize(), vSignal))
	//{
		//return INVALID_DATA;
	//}
	
	vector vWin;
	int nRet;
	if (nRet = get_window_data(nType, vSignal.GetSize(), vWin, 0, 0))
	{
		return nRet;
	}
	vSignal *= vWin;
	///justin 08/14/2006 	GET_COMPENSATING
	if(pdCom)
	{
		double dTemp;
		vector vTemp; 
		vTemp = vWin * vWin;
		vTemp.Sum(dTemp);
		*pdCom =dTemp / vTemp.GetSize();
	}
	///end GET_COMPENSATING
	return OE_NOERROR;
}

int get_window_data( int nWindowMethod, int nSize, vector& vWindow, double dAlpha, double dBeta)
{
	if (nSize<=0)
	{
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	}
	
	vWindow.SetSize(nSize);
	if (nSize == 1)
	{
		vWindow = 1;
		///Sandy 2006-7-7 remove no meaning code
		//if(SetSize1(vWindow)) 
			////return fft_error_handle(UNKNOWN_ERROR);
			//return CER_UNKNOWN_ERROR;
		return OE_NOERROR;
	}
	
	return fftw_create_window_data(nSize, vWindow, nWindowMethod, dAlpha, dBeta);
}


/**
	lowpass to the signal
*/
///Cheney 2006-7-12 RENAME
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
//int lowpass(Curve& crvSignal, double dFc)
int fft_lowpass(Curve& crvSignal, double dFc)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
///end RENAME
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFc < 0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = _check_curve(crvSignal))	
		return nRet;
	
	//if(check_curve(crvSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION 

	///Cheney 2007-7-12 CLEAN_CODE
	vector vSignal, vTime;
	crvSignal.CopyData(vTime, vSignal);
	return fft_lowpass(vSignal, dFc, &vTime);
	//int np=crvSignal.GetSize();   //the number of points in the original data

	// Check the time resolution
	//double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = _fft_sampling_resolution(crvSignal, dFreqStep))	
	//	return nRet;
	//if(!fft_sampling_resolution(crvSignal, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION

	//dFreqStep = 1.0/np/dFreqStep; ///Soapy 12/30/03 CHANGE_RETURN_ON_TIME_RESOLUTION
	
	//vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = fft_filter_window(np, FFT_LOWPASS, vWindow, 0, dFc, dFreqStep, 1))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, crvSignal, vWindow))	
	//	return nRet;
	//fft_filter_window(np, FFT_LOWPASS, vWindow, 0, dFc, dFreqStep, 1); //make a filter window with dFc as highest frequence
	//fft_fft_filter(np, crvSignal, vWindow);	//apply filter to signal
	///End RETURN_VALUE_UNIFICATION
	//return 0;
	///end CLEAN_CODE
}

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
int lowpass(vector& vecSignal, double dFc, vector& vecTime)
//int fft_lowpass(vector& vecSignal, double dFc, vector& vecTime)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFc<0)	
		return fft_error_handle(INVALID_ARGUMENT);
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = check_vector(vecSignal))	
		return nRet;
	//if(check_vector(vecSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION

	int np=vecSignal.GetSize();   //the number of points in the original data
	if (vecTime)
	{
		int npTime = vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if (npTime!=np)	
			return fft_error_handle(DATA_SIZE_ERROR);
		//if (npTime!=np)
			//return -1;
	///End RETURN_VALUE_UNIFICATION
	}

	// Check the time resolution
	double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_sampling_resolution(vecTime, dFreqStep))	return nRet;
	//if(!fft_sampling_resolution(vecTime, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION

	dFreqStep = 1.0/np/dFreqStep;
	
	vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_filter_window(np, FFT_LOWPASS, vWindow, 0, dFc, dFreqStep, 1))	return nRet;
	if(nRet = fft_fft_filter(np, vecSignal, vWindow))	return nRet;
	//fft_filter_window(np, FFT_LOWPASS, vWindow, 0, dFc, dFreqStep, 1); //make a filter window with dFc as highest frequence
	//fft_fft_filter(np, vecSignal, vWindow);	//apply filter to signal
	///End RETURN_VALUE_UNIFICATION

	return 0;
}
///End FFT_RELATED_OVERLOAD
*/

///Cheney 2006-7-12 RENAME
//int lowpass(vector& vecSignal, double dFc, vector* vecTime)
int fft_lowpass(vector& vecSignal, double dFc, vector* vecTime)
///end RENAME
{
	if(dFc < 0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
			
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//if( nRet = check_vector(vecSignal) )	return nRet;
	//if ( nRet = ocmath_count(NANUM,vecSignal.GetSize(),vecSignal) ) 
		//return INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT

	int np = vecSignal.GetSize();
	if(np < 1)
		return CER_INVALID_SIZE;
		
	if(vecTime)
		if (vecTime->GetSize() != np)	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return CER_DATA_SIZE_ERROR;

	double dFreqStep;
	int nRet = fft_sampling_resolution(vecTime, dFreqStep);
	
	///Sandy 2009-4-10 QA80-13429 ALLOW_UNSORT_DESCENDING_X
	/*
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV
	if(nRet != 0)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY || dFreqStep < 0) 
			return nRet;
	}
	dFreqStep = 1.0/np/dFreqStep;
	*/
	if(nRet != 0 || dFreqStep == 0 || dFreqStep == NANUM)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY ) 
			return nRet;
		///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
		if ( vecTime )
			recreate_even_space_time_vector(*vecTime, dFreqStep);
		///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
	}
	dFreqStep = abs(1.0/np/dFreqStep);
	//end ALLOW_UNSORT_DESCENDING_X
	
	///Cheney 2007-7-12 REMOVE_AND_CALL_NEW_ADD_LOWPASS_FUNCTION
	int nRet1 = fft_lowpass_filtering(vecSignal.GetSize(), vecSignal, dFreqStep, dFc);
	if(nRet1 != 0)
		return nRet1;
	
	return nRet;
	//vector vWindow(np);
	//if( nRet = fft_filter_window(np, FFT_LOWPASS, vWindow, 0, dFc, dFreqStep, 1) )	
	//	return nRet;
	//if( nRet = fft_fft_filter(np, vecSignal, vWindow) )	
	//	return nRet;
	
	//return 0;
	///end REMOVE_AND_CALL_NEW_ADD_LOWPASS_FUNCTION
}
///End CHANGE_PROTOTYPE

/**   
	highpass to the signal
*/
///Cheney 2006-7-12 RENAME
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
//int highpass(Curve& crvSignal, double dFc, bool bAddOffset)
int fft_highpass(Curve& crvSignal, double dFc, bool bAddOffset)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
///end RENAME
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFc<0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
	///End ROBUSTNESS_CHECK

	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = _check_curve(crvSignal))	
		return nRet;
	//if(check_curve(crvSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION
	///Cheney 2007-7-13 CLEAN_CODE
	vector vSignal, vTime;
	crvSignal.CopyData(vTime, vSignal);
	return fft_highpass(vSignal, dFc, &vTime, bAddOffset);
	//int np=crvSignal.GetSize();   //the number of points in the original data

	// Check the time resolution
	//double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = _fft_sampling_resolution(crvSignal, dFreqStep))	
	//	return nRet;
	//if(!fft_sampling_resolution(crvSignal, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	//dFreqStep = 1.0/np/dFreqStep; ///Soapy 12/30/03 CHANGE_RETURN_ON_TIME_RESOLUTION

	//vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = fft_filter_window(np, FFT_HIGHPASS, vWindow, dFc, 0, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, crvSignal, vWindow))	
	//	return nRet;
	//fft_filter_window(np, FFT_HIGHPASS, vWindow, dFc, 0, dFreqStep, bAddOffset); //make a filter window with dFc as the lowest frequence
	//fft_fft_filter(np, crvSignal, vWindow);	//apply filter to signal
	///End RETURN_VALUE_UNIFICATION
	
	//return 0;
	///end CLEAN_CODE
}

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
int highpass(vector& vecSignal, double dFc, bool bAddOffset, vector& vecTime)
//int fft_highpass(vector& vecSignal, double dFc, bool bAddOffset, vector& vecTime)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFc<0)	
		return fft_error_handle(INVALID_ARGUMENT);
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = check_vector(vecSignal))	return nRet;
	//if(check_vector(vecSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION

	int np=vecSignal.GetSize();   //the number of points in the original data
	if (vecTime)
	{
		int npTime = vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if (npTime!=np)	
			return fft_error_handle(DATA_SIZE_ERROR);
		//if (npTime!=np)
			//return -1;
	///End RETURN_VALUE_UNIFICATION
	}

	// Check the time resolution
	double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_sampling_resolution(vecTime, dFreqStep))	return nRet;
	//if(!fft_sampling_resolution(vecTime, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	dFreqStep = 1.0/np/dFreqStep;

	vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_filter_window(np, FFT_HIGHPASS, vWindow, dFc, 0, dFreqStep, bAddOffset))	return nRet;
	if(nRet = fft_fft_filter(np, vecSignal, vWindow))	return nRet;
	//fft_filter_window(np, FFT_HIGHPASS, vWindow, dFc, 0, dFreqStep, bAddOffset); //make a filter window with dFc as the lowest frequence
	//fft_fft_filter(np, vecSignal, vWindow);	//apply filter to signal
	///End RETURN_VALUE_UNIFICATION

	return 0;
}
///End FFT_RELATED_OVERLOAD
*/

///Cheney 2006-7-12 RENAME_AND_CHANGE_PROTOTYPE
//int highpass(vector& vecSignal, double dFc, bool bAddOffset, vector* vecTime)
int fft_highpass(vector& vecSignal, double dFc, vector* vecTime, bool bAddOffset)
///end RENAME_AND_CHANGE_PROTOTYPE
{
	if(dFc < 0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
		
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	///if( nRet = check_vector(vecSignal) )	return nRet;
	//if ( nRet = ocmath_count(NANUM, vecSignal.GetSize(), vecSignal) ) 
		//return INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT

	int np = vecSignal.GetSize();
	if(np < 1)
		return CER_INVALID_SIZE;
	
	if (vecTime)
		if (vecTime->GetSize() != np)	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return CER_DATA_SIZE_ERROR;

	double dFreqStep;
	int nRet = fft_sampling_resolution(vecTime, dFreqStep);
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV	
		//return nRet;
		
	///Sandy 2009-4-10 QA80-13429 ALLOW_UNSORT_DESCENDING_X
	/*
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV
	if(nRet != 0)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY || dFreqStep < 0) 
			return nRet;
	}
	dFreqStep = 1.0/np/dFreqStep;
	*/
	if(nRet != 0 || dFreqStep == 0 || dFreqStep == NANUM)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY ) 
			return nRet;
		///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
		if ( vecTime )
			recreate_even_space_time_vector(*vecTime, dFreqStep);
		///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
	}
	dFreqStep = abs(1.0/np/dFreqStep);
	//end ALLOW_UNSORT_DESCENDING_X
	
	///Cheney 2007-7-13 REMOVE_AND_CALL_NEW_ADD_HIGHPASS_FUNCTION
	int nRet1 = fft_highpass_filtering(vecSignal.GetSize(), vecSignal, dFreqStep, dFc, bAddOffset);
	if(nRet1 != 0)
		return nRet1;
	
	return nRet;
	//vector vWindow(np);
	//if(nRet = fft_filter_window(np, FFT_HIGHPASS, vWindow, dFc, 0, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, vecSignal, vWindow))	
	//	return nRet;
	
	//return 0;
	///end REMOVE_AND_CALL_NEW_ADD_HIGHPASS_FUNCTION
}
///End CHANGE_PROTOTYPE


/**
	band-pass filter to the signal
*/
///Cheney 2006-7-12 RENAME 
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
//int bandpass(Curve& crvSignal, double dFLow, double dFHigh, bool bAddOffset)
int fft_bandpass(Curve& crvSignal, double dFLow, double dFHigh, bool bAddOffset)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
///end RENAME
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	//if(dFLow<0 || dFHigh<0)	///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
	if(dFLow < 0 || dFHigh < 0 || dFLow > dFHigh)
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;;
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = _check_curve(crvSignal))	
		return nRet;
	//if(check_curve(crvSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION
	///Cheney 2007-7-13 CLEAN_CODE
	vector vSignal, vTime;
	crvSignal.CopyData(vTime, vSignal);
	return fft_bandpass(vSignal, dFLow, dFHigh, &vTime, bAddOffset);
	//int np=crvSignal.GetSize();   //the number of points in the original data

	// Check the time resolution
	//double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = _fft_sampling_resolution(crvSignal, dFreqStep))	
	//	return nRet;
	//if(!fft_sampling_resolution(crvSignal, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	//dFreqStep = 1.0/np/dFreqStep; ///Soapy 12/30/03 CHANGE_RETURN_ON_TIME_RESOLUTION

	//vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = fft_filter_window(np, FFT_BANDPASS, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, crvSignal, vWindow))	
	//	return nRet;
	//fft_filter_window(np, FFT_BANDPASS, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset); //make a filter window with dFLow and dFHigh as band pass
	//fft_fft_filter(np, crvSignal, vWindow);
	///End RETURN_VALUE_UNIFICATION	

	//return 0;
	///end CLEAN_CODE
}

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
int bandpass(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector& vecTime)
//int fft_bandpass(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector& vecTime)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFLow<0 || dFHigh<0)	
		return fft_error_handle(INVALID_ARGUMENT);
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = check_vector(vecSignal))	return nRet;
	//if(check_vector(vecSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION

	int np=vecSignal.GetSize();   //the number of points in the original data
	if (vecTime)
	{
		int npTime = vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if (npTime!=np)	
			return fft_error_handle(DATA_SIZE_ERROR);
		//if (npTime!=np)
			//return -1;
	///End RETURN_VALUE_UNIFICATION
	}

	// Check the time resolution
	double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_sampling_resolution(vecTime, dFreqStep))	return nRet;
	//if(!fft_sampling_resolution(vecTime, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	dFreqStep = 1.0/np/dFreqStep;

	vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_filter_window(np, FFT_BANDPASS, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	return nRet;
	if(nRet = fft_fft_filter(np, vecSignal, vWindow))	return nRet;
	//fft_filter_window(np, FFT_BANDPASS, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset); //make a filter window with dFLow and dFHigh as band pass
	//fft_fft_filter(np, vecSignal, vWindow);
	///End RETURN_VALUE_UNIFICATION
	
	return 0;
}
///End FFT_RELATED_OVERLOAD
*/

///Cheney 2006-7-12 RENAME_AND_CHENGE_PROTOTYPE
//int bandpass(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector* vecTime)
int fft_bandpass(vector& vecSignal, double dFLow, double dFHigh, vector* vecTime, bool bAddOffset)
///end RENAME_AND_CHENGE_PROTOTYPE
{
	if( dFLow < 0 || dFHigh < 0 || dFLow > dFHigh )	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;;

	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//if(nRet = check_vector(vecSignal))	return nRet;
	//if ( nRet = ocmath_count(NANUM, vecSignal.GetSize(), vecSignal) ) 
		//return INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT


	int np=vecSignal.GetSize(); 
	if(np < 1)
		return CER_INVALID_SIZE;
	
	if (vecTime)
		if (vecTime->GetSize()!=np)	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return CER_DATA_SIZE_ERROR;
	
	double dFreqStep;
	int nRet = fft_sampling_resolution(vecTime, dFreqStep);
	///Sandy 2009-4-10 QA80-13429 ALLOW_UNSORT_DESCENDING_X
	/*
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV
	if(nRet != 0)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY || dFreqStep < 0) 
			return nRet;
	}
	dFreqStep = 1.0/np/dFreqStep;
	*/
	if(nRet != 0 || dFreqStep == 0 || dFreqStep == NANUM)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY ) 
			return nRet;
		///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
		if ( vecTime )
			recreate_even_space_time_vector(*vecTime, dFreqStep);
		///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
	}
	dFreqStep = abs(1.0/np/dFreqStep);
	//end ALLOW_UNSORT_DESCENDING_X

	///Cheney 2007-7-13 REMOVE_AND_CALL_NEW_ADD_BANDPASS_FUNCTION
	int nRet1 = fft_bandpass_filtering(vecSignal.GetSize(), vecSignal, dFreqStep, dFLow, dFHigh, bAddOffset);
	if(nRet1 != 0)
		return nRet1;
	
	return nRet;
	//vector vWindow(np);
	//if(nRet = fft_filter_window(np, FFT_BANDPASS, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, vecSignal, vWindow))	
	//	return nRet;
	//return 0;
	///end REMOVE_AND_CALL_NEW_ADD_BANDPASS_FUNCTION
}
///End CHANGE_PROTOTYPE

/**
	band-block filter to the signal
*/
///Cheney 2006-7-12 RENAME
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
//int bandblock(Curve& crvSignal, double dFLow, double dFHigh, bool bAddOffset)
int fft_bandblock(Curve& crvSignal, double dFLow, double dFHigh, bool bAddOffset)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
///end RENAME
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	//if(dFLow<0 || dFHigh<0)	///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
	if(dFLow < 0 || dFHigh < 0 || dFLow > dFHigh)
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;;
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = _check_curve(crvSignal))	
		return nRet;
	//if(check_curve(crvSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION
	///Cheney 2006-7-13 CLEAN_CODE
	vector vSignal, vTime;
	crvSignal.CopyData(vTime, vSignal);
	return fft_bandblock(vSignal, dFLow, dFHigh, &vTime, bAddOffset);
	//int np=crvSignal.GetSize();   //the number of points in the original data

	// Check the time resolution
	//double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = _fft_sampling_resolution(crvSignal, dFreqStep))
	//	return nRet;
	//if(!fft_sampling_resolution(crvSignal, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	//dFreqStep = 1.0/np/dFreqStep; ///Soapy 12/30/03 CHANGE_RETURN_ON_TIME_RESOLUTION

	//vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = fft_filter_window(np, FFT_BANDBLOCK, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, crvSignal, vWindow))	
	//	return nRet;
	//fft_filter_window(np, FFT_BANDBLOCK, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset); //make a filter window with dFLow and dFHigh as band block
	//fft_fft_filter(np, crvSignal, vWindow);
	///End RETURN_VALUE_UNIFICATION
	
	//return 0;
	///end CLEAN_CODE
}

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
int bandblock(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector& vecTime)
//int fft_bandblock(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector& vecTime)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
{
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dFLow<0 || dFHigh<0)	
		return fft_error_handle(INVALID_ARGUMENT);
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = check_vector(vecSignal))	return nRet;
	//if(check_vector(vecSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION

	int np=vecSignal.GetSize();   //the number of points in the original data
	if (vecTime)
	{
		int npTime = vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if (npTime!=np)	
			return fft_error_handle(DATA_SIZE_ERROR);
		//if (npTime!=np)
			//return -1;
	///End RETURN_VALUE_UNIFICATION
	}

	// Check the time resolution
	double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_sampling_resolution(vecTime, dFreqStep))	return nRet;
	//if(!fft_sampling_resolution(vecTime, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	dFreqStep = 1.0/np/dFreqStep; ///Soapy 12/30/03 CHANGE_RETURN_ON_TIME_RESOLUTION

	vector vWindow(np);
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_filter_window(np, FFT_BANDBLOCK, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	return nRet;
	if(nRet = fft_fft_filter(np, vecSignal, vWindow))	return nRet;
	//fft_filter_window(np, FFT_BANDBLOCK, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset); //make a filter window with dFLow and dFHigh as band block
	//fft_fft_filter(np, vecSignal, vWindow);
	///End RETURN_VALUE_UNIFICATION

	return 0;
}
///End FFT_RELATED_OVERLOAD
*/

///Cheney 2006-7-12 RENAME_AND_CHENGE_PROTOTYPE
//int bandblock(vector& vecSignal, double dFLow, double dFHigh, bool bAddOffset, vector* vecTime)
int fft_bandblock(vector& vecSignal, double dFLow, double dFHigh, vector* vecTime, bool bAddOffset)
///end RENAME AND CHENGE PROTOTYPE
{
	if( dFLow < 0 || dFHigh < 0 || dFLow > dFHigh )	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;;
	
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//if( nRet = check_vector(vecSignal) )	return nRet;
	//if ( nRet = ocmath_count(NANUM, vecSignal.GetSize(), vecSignal) ) 
		//return INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	 
	int np = vecSignal.GetSize();  
	if(np < 1)
		return CER_INVALID_SIZE;
	
	if(vecTime)
		if ( vecTime->GetSize() != np )	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return CER_DATA_SIZE_ERROR;
	
	double dFreqStep;
	int nRet = fft_sampling_resolution(vecTime, dFreqStep);
	///Sandy 2009-4-10 QA80-13429 ALLOW_UNSORT_DESCENDING_X
	/*
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV
	if(nRet != 0)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY || dFreqStep < 0) 
			return nRet;
	}
	dFreqStep = 1.0/np/dFreqStep;
	*/
	if(nRet != 0 || dFreqStep == 0 || dFreqStep == NANUM)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY ) 
			return nRet;
		///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
		if ( vecTime )
			recreate_even_space_time_vector(*vecTime, dFreqStep);
		///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
	}
	dFreqStep = abs(1.0/np/dFreqStep);
	//end ALLOW_UNSORT_DESCENDING_X
	
	///Cheney 2007-7-13 REMOVE_AND_CALL_NEW_ADD_BANDBLOCK_FUNCTION
	int nRet1 = fft_bandblock_filtering(vecSignal.GetSize(), vecSignal, dFreqStep, dFLow, dFHigh, bAddOffset);
	if(nRet1 != 0)
		return nRet1;
	
	return nRet;
	//vector vWindow(np);
	//if(nRet = fft_filter_window(np, FFT_BANDBLOCK, vWindow, dFLow, dFHigh, dFreqStep, bAddOffset))	
	//	return nRet;
	//if(nRet = fft_fft_filter(np, vecSignal, vWindow))	
	//	return nRet;
	
	//return 0;
	///end REMOVE_AND_CALL_NEW_ADD_BANDBLOCK_FUNCTION
}
///End CHANGE_PROTOTYPE

/**
	threshold filter to the signal
*/
///Cheney 2006-7-12 RENAME
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
//int threshold_filter(Curve& crvSignal, double dThreshold)
int fft_threshold(Curve& crvSignal, double dThreshold)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
///end RENAME
{
	// Check the threshold
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dThreshold<0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;;
	//if(dThreshold<0)
		//return 0;
	///End ROBUSTNESS_CHECK
	
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = _check_curve(crvSignal))	
		return nRet;
	//if(check_curve(crvSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION
	
	///Cheney 2006-7-13 CLEAN_CODE
	vector vSignal, vTime;
	crvSignal.CopyData(vTime, vSignal);
	return fft_threshold(vSignal, dThreshold, &vTime);
	//int np=crvSignal.GetSize();   //the number of points in the original data
	// Check the time resolution
	//double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nRet = _fft_sampling_resolution(crvSignal, dFreqStep))	
	//	return nRet;
	//if(!fft_sampling_resolution(crvSignal, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	///Soapy 12/30/03 ADD_THRESHOLD_FILTERING_TO_DLL
	/*
	// Calculate the spectra by FFT
	vector vecFFT(np);
	vecFFT = crvSignal;
	int nRet = fft_fft_real(vecFFT.GetSize(), vecFFT, -1);
	if(nRet!=0)
		return nRet;

	// Discard the components below dThreshold.
	int np2 = np/2;
	double dAmp;
	dThreshold =dThreshold*dThreshold*np/4.0;
	
	for(int i=1;i< np2;i++)
	{
		dAmp=vecFFT[i]^2.0 + vecFFT[np-i]^2.0;
		if(dAmp<dThreshold)
		{
			vecFFT[i]=0.0;
			vecFFT[np-i]=0.0;
		}
	}

	dAmp=vecFFT[np2]^2.0 + vecFFT[np-np2]^2.0;
	if(np2*2 == np)
	{
		dAmp /= 2.0;
		if(dAmp<dThreshold)
		{
			vecFFT[np2]=0.0;
		}
	}
	else
	{
		if(dAmp<dThreshold)
		{
			vecFFT[np2]=0.0;
			vecFFT[np2+1]=0.0;
		}
	}
	
	if(vecFFT[0]*vecFFT[0]< dThreshold*4.0)
		vecFFT[0]=0.0;
	
	// Compute inverse FFT, extract real part, and place in signal curve
	nRet = fft_fft_real(vecFFT.GetSize(), vecFFT, 1);
	if( nRet !=0 )
		return nRet;
	
	crvSignal = vecFFT;
	*/
	//nRet = fft_threshold_filtering(np, crvSignal,dThreshold);
	/// END Soapy 12/30/03 ADD_THRESHOLD_FILTERING_TO_DLL
	//return nRet;
	///end CLEAN_CODE
}

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/23/04 HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
int threshold_filter(vector& vecSignal, double dThreshold, vector& vecTime)
//int fft_threshold_filter(vector& vecSignal, double dThreshold, vector& vecTime)
///End HIGH_LEVEL_ROUTINE_INTERFACE_MODIFICATION
{
	// Check the validity of the curve
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = check_vector(vecSignal))	return nRet;
	//if(check_vector(vecSignal))
		//return -2;
	///End RETURN_VALUE_UNIFICATION

	int np=vecSignal.GetSize();   //the number of points in the original data
	if (vecTime)
	{
		int npTime = vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if (npTime!=np)	
			return fft_error_handle(DATA_SIZE_ERROR);
		//if (npTime!=np)
			//return -1;
	///End RETURN_VALUE_UNIFICATION
	}

	// Check the threshold
	///Annie 4/23/04 ROBUSTNESS_CHECK
	if(dThreshold<0)	
		return fft_error_handle(INVALID_ARGUMENT);
	//if(dThreshold<0)
		//return 0;
	///End ROBUSTNESS_CHECK

	// Check the time resolution
	double dFreqStep;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(nRet = fft_sampling_resolution(vecTime, dFreqStep))	return nRet;
	//if(!fft_sampling_resolution(vecTime, dFreqStep))	//check if signal is evenly spaced frequency
		//return -1;
	///End RETURN_VALUE_UNIFICATION
	
	nRet = fft_threshold_filtering(np, vecSignal,dThreshold);
	return nRet;
}
///End FFT_RELATED_OVERLOAD
*/

///Cheney 2006-7-12 RENAME
//int threshold_filter(vector& vecSignal, double dThreshold, vector* vecTime)
int fft_threshold(vector& vecSignal, double dThreshold, vector* vecTime)
///end RENAME
{
	if(dThreshold < 0)	
		//return fft_error_handle(INVALID_ARGUMENT);
		return CER_INVALID_ARGUMENT;
		
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//if( nRet = check_vector(vecSignal) )	return nRet;
	//if ( nRet = ocmath_count(NANUM,vecSignal.GetSize(),vecSignal) ) 
		//return INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT

	int np = vecSignal.GetSize(); 
	if(np < 1)
		return CER_INVALID_SIZE;
	
	if(vecTime)
		if(vecTime->GetSize() != np)	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return CER_DATA_SIZE_ERROR;

	double dFreqStep;
	int nRet = fft_sampling_resolution(vecTime, dFreqStep);
	///Sandy 2009-4-10 QA80-13429 ALLOW_UNSORT_DESCENDING_X
	/*
	//if(nRet != 0) //if( nRet > 0 ) CPY 6/15/08 FOUND_FFT_FILTER_FAILED_WHEN_TESTING_LV
	if(nRet != 0)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY || dFreqStep < 0) 
			return nRet;
	}
	dFreqStep = 1.0/np/dFreqStep;
	*/
	if(nRet != 0 || dFreqStep == 0 || dFreqStep == NANUM)////Sandy 2009-4-9 QA80-13429 JUST_WARNNING_WHEN_UNEVEN_INTERVAL
	{
		if(nRet != OE_NOT_SPACED_EQUALLY ) 
			return nRet;
		///------ Folger 04/17/09 QA80-13429 RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
		if ( vecTime )
			recreate_even_space_time_vector(*vecTime, dFreqStep);
		///------ End RECREATE_X_DATA_FOR_NOT_EVEN_SPACE_INPUT_X
	}
	dFreqStep = abs(1.0/np/dFreqStep);
	//end ALLOW_UNSORT_DESCENDING_X
	
	int nRet1 = fft_threshold_filtering(np, vecSignal,dThreshold);
	if(nRet1 != 0)
		return nRet1;
	
	return nRet;
}
///End CHANGE_PROTOTYPE

/**
	Check the validity of the curve
*/
///Cheney 2006-7-12 CHANGE_TO_STATIC
///Leo 2005-9-22 v8.0340 REWRITE_CHECK_CURVE
//int check_curve(Curve& crvInput)
static int _check_curve(Curve& crvInput)
///end  CHANGE_TO_STATIC
{
	if(!crvInput.IsValid())	
		return CER_INVALID_DATA;

	//vector vY;
	//crvInput.CopyData(NULL, vY);
	//if (ocmath_count(NANUM, vY.GetSize(), vY))
		//return CER_INVALID_DATA;
	
	return OE_NOERROR;
}
///End REWRITE_CHECK_CURVE

//int check_curve(Curve & crvInput)
//{
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//	if(!crvInput.IsValid())	
//		return fft_error_handle(INVALID_DATA);
//	//if(!crvInput.IsValid())
//		//return -1;
//	///End RETURN_VALUE_UNIFICATION
//	
//	///Forest 08/27/04 MODIFY_ERROR_HANDING
//	//crvInput.TrimLeft(true);
//	//crvInput.TrimRight();
//	crvInput.Trim();
//	///End MODIFY_ERROR_HANDING
//
//	int np=crvInput.GetSize();   
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//	if(np<1)	
//		return fft_error_handle(INVALID_DATA);
//	//if(np<1)
//	//{
//		//return -2;
//	//}
//	///End RETURN_VALUE_UNIFICATION
//	
//	///Forest 08/27/04 MODIFY_ERROR_HANDING
//	/*
//	for(int i = 0; i< np-1; i++)
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//		if (crvInput[i] == NANUM)	
//			return fft_error_handle(INVALID_DATA);
//		//if (crvInput[i] == NANUM)   // there are NANUM in the data, break;
//			//return -1; 
//	///End RETURN_VALUE_UNIFICATION
//	*/
//	///End MODIFY_ERROR_HANDING
//	
//	return 0;
//}

/// Austin/Leo 09/20/05 REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
/// Annie 4/15/04 CHECK_VECTOR: check the validity of vector;
//int check_vector(vectorbase& vecInput)
//{
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//	int nSize = vecInput.GetSize(); ///Soapy 07/10/05 QA70-5060 ADD_COHERENCE_FUNCTION
//	if(nSize<1)	
//		//return fft_error_handle(INVALID_DATA); ///Forest 08/27/04 MODIFY_ERROR_HANDING
//		return fft_error_handle(INVALID_SIZE);
//	//if(vecInput.GetSize()<1)
//		//return -1;
//	///End RETURN_VALUE_UNIFICATION
//	
//	///Forest 08/27/04 MODIFY_ERROR_HANDING
//	//vecInput.TrimLeft(true);
//	//vecInput.TrimRight();
//	vecInput.Trim();
//	///End MODIFY_ERROR_HANDING
//	
//	int np = vecInput.GetSize();
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//	if(np<nSize)	return INVALID_DATA; ///Soapy 07/10/05 QA70-5060 ADD_COHERENCE_FUNCTION
//
//	//if(np<1)
//		//return -2;
//	///End RETURN_VALUE_UNIFICATION
//	
//	///Forest 08/27/04 MODIFY_ERROR_HANDING
//	/*
//	for(int i=0;i<np;i++)
//	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
//		if(vecInput[i]==NANUM)	
//			return fft_error_handle(INVALID_DATA);
//		//if(vecInput[i]==NANUM)
//			//return -1;
//	///End RETURN_VALUE_UNIFICATION
//	*/
//	///End MODIFY_ERROR_HANDING
//		
//	return 0;
//}
///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT

///Soapy 07/10/05 QA70-5060 ADD_COHERENCE_FUNCTION
//int check_vector_2d(matrixbase& mInput)
//{
	//int nCol = mInput.GetNumCols();
	//int nRow = mInput.GetNumRows();
	/////Annie 4/26/04 RETURN_VALUE_UNIFICATION
	//if(nCol<1 || nRow<1)	
		////return fft_error_handle(INVALID_DATA); ///Forest 08/27/04 MODIFY_ERROR_HANDING
		//return fft_error_handle(INVALID_SIZE);
	////if(nCol<1 || nRow<1)
		////return -2;
	/////End RETURN_VALUE_UNIFICATION
	//
	//for(int i=0;i<nRow;i++)
		//for(int j=0;j<nCol;j++)
	/////Annie 4/26/04 RETURN_VALUE_UNIFICATION
			//if(mInput[i][j]==NANUM)	
				//return fft_error_handle(INVALID_DATA);
			////if(mInput[i][j]==NANUM)
				////return -1;
	/////End RETURN_VALUE_UNIFICATION
		//
	//return 0;
//}
/// End CHECK_VECTOR
///END ADD_COHERENCE_FUNCTION


////////////////////////////////////////////////////////////////////////////////////
// This function performs normalization of the response function
//
//static void fft_normalize_response(vector& vecResponse)
//{
	/////Soapy 07/03/05 FIX_NORMALIZATION_FUNCTION
	//vector vsquare;
	//vsquare = vecResponse * vecResponse;
	//
	//// Find the sum of all response elements
	//double dSumResp;
	//vsquare.Sum(dSumResp);
	//
	//// Normalize response so that sum of all elements is unity
	/////Annie 4/23/04 NORMALIZE_MODIFICATION: normalization should not change its positive/negative sign
	////vecResponse /= dSumResp; 
	////vecResponse /= abs(dSumResp);
	/////End Annie 4/23/04 NORMALIZE_MODIFICATION
	//
	//vecResponse /= sqrt(dSumResp);
	/////END FIX_NORMALIZATION_FUNCTION
//}

////////////////////////////////////////////////////////////////////////////////////
// This function checks sampling resolution of time vector for FFT operations
//
///Cheney 2006-7-13 REMOVE
/*
///Annie 4/26/04 FFT_SAMPLING_RESOLUTION_INTERFACE_UPDATE
static int _fft_sampling_resolution(Curve& crvSignal, double& dTimeStep, double* dInitTime = NULL)
//static bool fft_sampling_resolution(Curve& crvSignal, double& dTimeStep, double* dInitTime = NULL)
///End FFT_SAMPLING_RESOLUTION_INTERFACE_UPDATE
{
	// Get the size of crvSignal
	int np=crvSignal.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(np<2)	
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	//if(np<2)
	//{
		//return false;
	//}
	///End RETURN_VALUE_UNIFICATION

	// Get X dataset of the signal curve
	Dataset dsTime;
	if(crvSignal.HasX())   // If the curve has x column
	{
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if(!crvSignal.AttachX(dsTime))	
			//return fft_error_handle(UNKNOWN_ERROR);
			return CER_UNKNOWN_ERROR;
		//if(!crvSignal.AttachX(dsTime)) return false;  //fail to attach x column
	///End RETURN_VALUE_UNIFICATION

		int iSize=dsTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		if(iSize!=np )	
			//return fft_error_handle(DATA_SIZE_ERROR);
			return DATA_SIZE_ERROR;
		//if(iSize!=np )
		//{
			//return false;
		//}
	///End RETURN_VALUE_UNIFICATION
	}
	else  // the curve does not have x column, use 1 as the sampling rate
	{
		dTimeStep =1.0;
		if(dInitTime)  *dInitTime = 1;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		return 0;
		//return true;
	///End RETURN_VALUE_UNIFICATION
	}
	
	///Annie 3/1/04 SAMPLING_RESOLUTION_PARA_MODIFICATION: There is problem when transfer value from dataset to vector.
	vector vTime;
	vTime = dsTime;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = fft_sampling_resolution(np, vTime, &dTimeStep) != 0)	
		return nRet;
	//if(fft_sampling_resolution(np, vTime, &dTimeStep) != 0)
		//return false;
	///End RETURN_VALUE_UNIFICATION
	
	//if(fft_sampling_resolution(np, dsTime, &dTimeStep) != 0)
	//	return false;
	///End SAMPLING_RESOLUTION_PARA_MODIFICATION

	if(dInitTime)  
		*dInitTime= dsTime[0];
	
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	return 0;
	//return true;
	///End RETURN_VALUE_UNIFICATION
}
*/
///end REMOVE

///Forest 09/21/04 QA70-6227 CHANGE_PROTOTYPE
/*
///Annie 4/22/04 FFT_RELATED_OVERLOAD
///Annie 4/26/04 FFT_SAMPLING_RESOLUTION_INTERFACE_UPDATE
static int fft_sampling_resolution(vector& vecTime, double& dTimeStep, double* dInitTime = NULL)
//static bool fft_sampling_resolution(vector& vecTime, double& dTimeStep, double* dInitTime = NULL)
///End FFT_SAMPLING_RESOLUTION_INTERFACE_UPDATE
{
	// Get the size of crvSignal
	int np=vecTime.GetSize();
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	if(np<2)	
		return fft_error_handle(INVALID_SIZE);
	//if(np<2)
	//{
		//return false;
	//}
	///End RETURN_VALUE_UNIFICATION

	if(vecTime == NULL)
	{
		dTimeStep=1.0;
		if(dInitTime)  *dInitTime= 1;
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
		return 0;
		//return true;
	///End RETURN_VALUE_UNIFICATION
	}
	
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	int nRet;
	if(nRet = fft_sampling_resolution(np, vecTime, &dTimeStep))	return nRet;
	//if(fft_sampling_resolution(np, vecTime, &dTimeStep) != 0)
		//return false;
	///End RETURN_VALUE_UNIFICATION
	
	if(dInitTime)  *dInitTime= vecTime[0];
	
	///Annie 4/26/04 RETURN_VALUE_UNIFICATION
	return 0;
	//return true;
	///End RETURN_VALUE_UNIFICATION
}
///End FFT_RELATED_OVERLOAD
*/

int fft_sampling_resolution(vector* vecTime, double& dTimeStep, double* dInitTime)
{

	int np;
	if(vecTime == NULL || (np = vecTime->GetSize()) < 2)
	{
		dTimeStep = 1.0;
		if(dInitTime)  
			*dInitTime = 1;
	}
	else
	{
		//--- CPY 5/27/06 FFT_SAMPLE_INTERVAL_USE_OCMATH_FUNC
		// I found the DLL fft_sampling_resolution function is not good, it only use 1st two points and then assume a 5% to determine
		// if consistent
		/*
		int nRet = fft_sampling_resolution(np, vecTime[0], &dTimeStep);
		if( nRet ) 
			return	nRet;
		*/
		int nRet = ocmath_sampling_resolution(np, *vecTime, &dTimeStep);
		
		///Justin 12/10/2006 ONLY_RESET_TO_1_WHEN_0_OR_MISSING_VALUE
		//if(nRet != OE_NOERROR)
		/////Cheney 2006-8-3 IF_FAILED_USE_DEFAULT_INCREMENT
		//{
			//dTimeStep = 1.0;
			//return nRet; 
		//}
		///end IF_FAILED_USE_DEFAULT_INCREMENT
		
		///Sandy 2006-12-25 remove 
		//if(dTimeStep == 0.0 || dTimeStep == NANUM)
		//{
			//dTimeStep = 1.0;
		//}
		///end 
		
		///end ONLY_RESET_TO_1_WHEN_0_OR_MISSING_VALUE
		//--- end FFT_SAMPLE_INTERVAL_USE_OCMATH_FUNC
		
		if( dInitTime )  
			*dInitTime = vecTime[0][0];
		
		return nRet;
	}
	
	return OE_NOERROR; 
}
///End CHANGE_PROTOTYPE


int fft_sine(int nFFT, vector& vSig)
{
	if(nFFT<1)
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//int nRet = check_vector(vSig);
	int nRet;
	//if (nRet = ocmath_count(NANUM, vSig.GetSize(), vSig))
		//return CER_INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	
	vSig.SetSize(nFFT);
	
	nRet = fft_fft_sine(nFFT, vSig);
	return nRet;
}

int fft_cosine(int nFFT, vector& vSig)
{
	if(nFFT < 1)
		//return fft_error_handle(INVALID_SIZE);
		return CER_INVALID_SIZE;
	
	///Austin/Leo 09/20/05	REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	//int nRet = check_vector(vSig);
	int nRet;
	//if (nRet = ocmath_count(NANUM, vSig.GetSize(), vSig))
		//return CER_INVALID_DATA;	///Mouqx 2005-9-22
	///End REPLACE_CHECK_VECTOR_BY_OCMATH_COUNT
	
	vSig.SetSize(nFFT);
	
	nRet = fft_fft_cosine(nFFT, vSig);
	return nRet;
}


//--------- CPY 5/29/06 FFT_PLOTTING_AND_TIME_INTERVAL
/// YuI 10/14/09 QA70-13728-P3 WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
//	int get_fft_interval_by_x_input(const TreeNode& tr, double* pdInterval)
int get_fft_interval_by_x_input(const TreeNode& tr, double* pdInterval, const TreeNode& trReference)
/// end WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
{
	///justin 10/23/2006 FIRSTLY_SET_DEFAULT
	if(pdInterval)   
		*pdInterval = 1;
	//end FIRSTLY_SET_DEFAULT

	if( !tr )
	{
		///Sandy 2006-8-18
		//return -1;
		return CER_INVALID_TREENODE;
	}
	
	vector<complex> vComplex;
	vector vTime;
	int nSize;
	if( okxf_resolve_tree_get_data_into_vector(&tr, &vComplex, &vTime) )//if( okxf_resolve_tree_get_data_into_vector(&tr, &vComplex, &vTime) && (nSize = vTime.GetSize()) > 0)  //justin  08/31/2006 HANDLE_NO_X_COL
	{
		/// YuI 10/14/09 QA70-13728-P3 WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
		// if time vector came from reference data range - should not be used
		if( NULL != trReference && vTime.GetSize() > 0 )
		{
			DataRange drReference;
			if( okxf_resolve_tree_construct_range(&trReference, &drReference) )
			{
				DataRange drTime;
				drTime = vTime.GetSourceDataRange();
				if( drTime && drTime.Intersects(drReference) )
				{
					// if time vector came from reference data range (output data range of the same operation- should not be used
					// as it was created modified by operation being executed
					vTime.SetSize(0);
				}
			}
		}
		/// end WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
		
		double dTimeInterval;
		//---- CPY 7/8/06 GET_X0_XINC_IF_X_COL_MISSING
		if(vTime.GetSize() == 2 && vComplex.GetSize() > 2) // when col has even X (no real X col), we return x0,x1
		{
			dTimeInterval = vTime[1] - vTime[0];
			if(pdInterval)
				*pdInterval = dTimeInterval;
			return OE_NOERROR;
		}
		//----

		///justin 10/23/2006 FIRSTLY_SET_DEFAULT
		/////justin 08/31/2006 HANDLE_NO_X_COL
		//if( vTime.GetSize() ==0 )
		//{
			//if(pdInterval)   
				//*pdInterval = 1;
			//return OE_NOERROR
		//}
		/////end 	HANDLE_NO_X_COL
		//end FIRSTLY_SET_DEFAULT	

		int nRet = fft_sampling_resolution(&vTime, dTimeInterval);
		
		///justin ALWAYS_SET_INTERVA_WITHE_MEAN_INC_ALTHOUGH_NOT_SAPACED_EQUALLY
		//if(nRet == 0)
		//{
			//if(pdInterval)
				//*pdInterval = dTimeInterval;
			//return OE_NOERROR;
		//}
		
		///Sandy 2006-12-25 no need transfer value again..
		//if( dTimeInterval < 0)
		//	dTimeInterval = - dTimeInterval;
		///end
		
		if(pdInterval)
			*pdInterval = dTimeInterval;
		///end ALWAYS_SET_INTERVA_WITHE_MEAN_INC_ALTHOUGH_NOT_SAPACED_EQUALLY
		
		///justin 10/23/2006 FIRSTLY_SET_DEFAULT
		//if(pdInterval)   //justin 08/31/2006 
			//*pdInterval = 1;
		//end FIRSTLY_SET_DEFAULT	
		return nRet;
	}
	
	return CER_FAIL_RESOLVE_TREENODE_TO_VECTOR;

	//}
	//return -1;
}
//---CPY 7/24/06, not used anymore, moved to inside FFT xf
/*
//	FFTPLOT_NONE, FFTPLOT_AMP, FFTPLOT_POWER
//		FFT results worksheet is assumed to have frequency in col(1) and Real/Imaginary in col 2,3 and 
//		Amplitude/Phase in col 4,5 and Power Spectrum in col 6
bool plot_fft_results(int nPlotType, GraphPage& gp, Worksheet& wks, bool bFreqFrom0)
{
	if(nPlotType < 0 || nPlotType > FFTPLOT_POWER)
		return error_report("Invalid nPlot for _update_fft_graphs");
	int nCols = wks.GetNumCols();
	if( nCols < 6)
		return error_report("FFT results wks must have at least 6 columns");
	
	vector<string> vsTemplates = {"origin", "FFTPlot", "FFTPower"};
	
	page_load(gp, vsTemplates[nPlotType]);
	if(nPlotType == FFTPLOT_NONE)
		return true;
	
	// first plot 2nd layer which is the phase in both cases
	GraphLayer gl = gp.Layers(1);
	if(!gl)
		return error_report("plot_fft_results found invalid template, 2nd layer is missing");
	Curve cuvPhase(wks, 0, 4); //col(5)
	int n2 = gl.AddPlot(cuvPhase, IDM_PLOT_LINE);
	gl.Rescale();
	
	// next plot the 1st layer, bottom layer, either Power or Amplitude
	GraphLayer glb = gp.Layers(0);// no need to check error if layer1 is valid, layer 0 must be
	Curve cuv(wks, 0, FFTPLOT_POWER==nPlotType? 5:3); //col(6): col(4)
	int n1 = glb.AddPlot(cuv, IDM_PLOT_LINE);
	glb.Rescale();
	
	// the template has linked X so we can set 1st layer X and it will have effect on both
	if(bFreqFrom0)
		glb.LT_execute("x1=0");// to show freq only the positive part
	return true;
}*/
//---- end FFT_PLOTTING_AND_TIME_INTERVAL

///justin 11/03/2006 MOVE_INTO_EVET_UTILS
/////justin 10/31/2006 GET_FFT_INPUT_COMPLEX_VECTOR
//int get_fft_input_vector(const TreeNode& trInput, vector<complex>& vx)
//{
	//vector<complex> vx1;
	//if(trInput)
	//{
		//if(okxf_resolve_tree_get_data_into_vector(&trInput, &vx1))
		//{
			//if(vx1.GetSize()>1)
			//{
				//if(vx)
					//vx = vx1;
				//return OE_NOERROR; 
			//} 
			//else
				//return CER_INVALID_DATA;
		//}
		//else
		//{
			//return XFERR_GET_DATA_FAILED;
		//}
	//}
	//return CER_INVALID_TREENODE;	
//}
/////end GET_FFT_INPUT_COMPLEX_VECTOR
///end MOVE_INTO_EVET_UTILS

///Justin 2007-3-22 v8.0587 CHECK_USER_INPUTED_INTERVAL ///move auto_compute_sampling_interval_from_InputData into event_utils.c
/////Cheney 2006-7-19 AUTO_COMPUTE_SAMPLING_INTERVAL_FROM_INPUTDATA
//int auto_compute_sampling_interval_from_InputData(TreeNode& trGetN, string strNodeName)
//{
	//TreeNode trInterval = trGetN.GetNode(strNodeName);
	//if( trInterval == NULL)
		//return CER_INVALID_TREENODE;
	//
	//int nIntervalType = _get_sample_interval_type(trInterval);
	//if(PDS_AUTO == nIntervalType || PDS_UNASSIGNED == nIntervalType)
	//{		
		//double dInterval = 0;
		//TreeNode trInput = trGetN.Children.Item(0);///temp solution, need to improve
		//if(trInput == NULL)
			//return CER_INVALID_TREENODE;
		//
		//int nRet = get_fft_interval_by_x_input(trInput, &dInterval);
		//
		/////Sandy 2006-8-18
		////if(-1 != nRet)
		////if(nRet >= OE_NOERROR)  ///justin 08/31/2006 IF_FALSE_THEN_SET_1
			//trInterval.dVal = dInterval;
		//
		//return nRet;
	//}
	//
	//return OE_NOERROR;
//}
/////end AUTO_COMPUTE_SAMPLING_INTERVAL_FROM_INPUTDATA
//
/////justin 10/31/2006 OVERLOAD_AUTO_COMPUTE_SAMPLING  
/////justin 11/21/2006 RENAME_ARGUMENT
////int auto_compute_sampling_interval_from_InputData(const TreeNode& trInput, TreeNode& trInterval, bool bSet, double *pdInterval)
////int auto_compute_sampling_interval_from_InputData(const TreeNode& trInput, TreeNode& trInterval, bool bKeepAuto, double* pdInterval)
///// Justin 2007-3-22 v8.0587 CHECK_USER_INPUTED_INTERVAL
//int auto_compute_sampling_interval_from_InputData(const TreeNode& trInput, TreeNode& trInterval)
/////END CHECK_USER_INPUTED_INTERVAL
/////END RENAME_ARGUMENT
//{
	//if(trInput == NULL || trInterval == NULL)
		//return CER_INVALID_TREENODE;
//
	//double dInterval = 1;
	//int nRet = OE_NOERROR;
	//
	////int nIntervalType = _get_sample_interval_type(trInterval); ///Justin 2007-3-22 v8.0587 CORRECT_METHOD_TO_GET_AUTO_SUPPORT
	/////justin 01/11/2007 APPLY_EDIT_BOX_WITH_AUTO_CHECKE_BOX
	////if(PDS_AUTO == nIntervalType || PDS_UNASSIGNED == nIntervalType)
	/////Justin 2007-3-22 v8.0587 CORRECT_METHOD_TO_GET_AUTO_SUPPORT
	////int nAuto = 0;
	////trInterval.GetAttribute(STR_ATTRIB_AUTO, nAuto);
	//int nAuto = octree_get_auto_support(&trInterval);
	///// End CORRECT_METHOD_TO_GET_AUTO_SUPPORT
	//if(1 == nAuto)
	/////end APPLY_EDIT_BOX_WITH_AUTO_CHECKE_BOX
	//{		
	//
		//nRet = get_fft_interval_by_x_input(trInput, &dInterval);
		//
		/////Sandy 2006-12-25 add error message return when the interval value invalid(less than 0 or missing
		////if( nRet || dInterval <= 0 || dInterval == NANUM)
		//if( dInterval <= 0 || dInterval == NANUM)
		//{
			//dInterval = 1; ///Justin ALWAYS_SET_INTERVA_WITHE_MEAN_INC_ALTHOUGH_NOT_SAPACED_EQUALLY
			////nRet = CER_FFT_UNEVENLY_SPACE;
			//nRet = CER_INVALID_SIGNAL_INTERVAL;
		//}
		//else if(nRet == OE_NOT_SPACED_EQUALLY)
			//nRet = CER_FFT_UNEVENLY_SPACE;
		//trInterval.dVal = dInterval;		
	//}
	//else
	//{
		//if( trInterval.dVal <= 0 || trInterval.dVal == NANUM)
		//{
			//nRet = CER_INVALID_SIGNAL_INTERVAL;
		//}
		//else
		//{
			//dInterval = trInterval.dVal;
		//}
	//}
	//if(!bKeepAuto) //if(bSet) ///justin 11/21/2006 
		//trInterval.dVal = dInterval;
	//if(pdInterval)
		//*pdInterval = dInterval;
	//return nRet;	
//}
/////end OVERLOAD_AUTO_COMPUTE_SAMPLING
///end CHECK_USER_INPUTED_INTERVAL

///Justin 2007-3-23 v8.0588 MOVE_BACK_FFTUTILIS_BECAUSE_COMPILE_ERROR
/// YuI 10/14/09 QA70-13728-P3 WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
//	int auto_compute_sampling_interval_from_InputData(const TreeNode& trInput, TreeNode& trInterval)
int auto_compute_sampling_interval_from_InputData(const TreeNode& trInput, TreeNode& trInterval, const TreeNode& trReference)
/// end WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
{
	if(trInput == NULL || trInterval == NULL)
		return CER_INVALID_TREENODE;

	double dInterval = 1.0;
	int nRet = OE_NOERROR;
	int nErr = OE_NOERROR;
	if( 1 == octree_get_auto_support(&trInterval) )
	{
		
		
		//----Sandy 2008-6-13 make error checking more perfect
		/*
		nRet = get_fft_interval_by_x_input(trInput, &dInterval);
		if( dInterval <= 0 || dInterval == NANUM )
		{
			dInterval = 1; 
			nRet = FFT_AUTO_INTERVAL_NOT_SUITABLE; //nRet = CER_INVALID_SIGNAL_INTERVAL; ///Justin 2007-3-23 v8.0588 
		}
		else if(nRet == OE_NOT_SPACED_EQUALLY)
			nRet = CER_FFT_UNEVENLY_SPACE;
		
		trInterval.dVal = dInterval;
		*/
		/// YuI 10/14/09 QA70-13728-P3 WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
		//	nErr = get_fft_interval_by_x_input(trInput, &dInterval);
		nErr = get_fft_interval_by_x_input(trInput, &dInterval, trReference);
		/// end WRONG_AUTOSAMPLING_INTERVAL_IF_OUTPUT_PRODUCES_X_COLUMN
		if( dInterval <= 0 || dInterval == NANUM )
		{
			if(dInterval == 0 || dInterval == NANUM)
			{
				dInterval = 1; 
				nRet = FFT_AUTO_INTERVAL_NOT_SUITABLE; 		
			}
			else//dInterval<0
			{
				nRet = CER_FFT_DESCENDING_SPACE;
			}
			
		}
		
		if(nErr == OE_NOT_SPACED_EQUALLY)
		//	nRet = CER_FFT_UNEVENLY_SPACE;
			nRet = XFWAR_TIME_SEQ_INVALID;//Sandy 2009-4-10 found the error string isn't correct, the compute interval should be the mean increment.
		
		trInterval.dVal = abs(dInterval);
		//end of make error checking more perfect
	
		
	}
	
	return nRet;
}
///END  MOVE_BACK_FFTUTILIS_BECAUSE_COMPILE_ERROR


///Sandy 2006-8-25 only reuse for cohere and move to XF
//Cheney 2006-7-19 AUTO_COMPUTE_PARAMS_VALUE
//bool auto_compute_params_value(TreeNode& trGetN, LPCSTR lpcszFFT, LPCSTR lpcszWin, LPCSTR lpcszOverlap)
//bool auto_compute_cohere_params(TreeNode& trGetN)
//{
	//TreeNode trFFT = trGetN.GetNode(lpcszFFT);
	//TreeNode trWin = trGetN.GetNode(lpcszWin);
	//if(trFFT == NULL || trWin == NULL)
		//return false;
	//
	//TreeNode trOverlap;
	//if(lpcszOverlap != NULL)
	//{
		//trOverlap = trGetN.GetNode(lpcszOverlap);
		//if( trOverlap == NULL)
			//return false;
	//}
	//
	//TreeNode trInput = trGetN.Children.Item(0);
	//if(trInput == NULL)
		//return false;
	//
	//int nFFTType = _get_sample_interval_type(trFFT);
	//if(PDS_AUTO == nFFTType || PDS_UNASSIGNED == nFFTType)
	//{
		//vector<complex> vSignal;
		//okxf_resolve_tree_get_data_into_vector(&trInput, &vSignal);
		//int nSize = vSignal.GetSize();
		//trFFT.nVal = min(nSize, 256);
	//}
	//
	//int nWinType = _get_sample_interval_type(trWin);	
	//if(PDS_AUTO == nWinType || PDS_UNASSIGNED == nWinType)
	//{
		//trWin.nVal = trFFT.nVal;
	//}
	//
	//if(trOverlap != NULL)
	//{
		//int nOverlapType = _get_sample_interval_type(trOverlap);
		//if(PDS_AUTO == nOverlapType || PDS_UNASSIGNED == nOverlapType)
		//{
			//trOverlap.nVal = trWin.nVal / 2;
		//}
	//}
	//
	//return true;
//}
///end AUTO_COMPUTE_PARAMS_VALUE

///Cheney 2006-7-19 _GET_SAMPLE_PARAM_TYPE
static int _get_sample_interval_type(TreeNode& trParam)
{
	string strParam = trParam.strVal;
	if(strParam.IsEmpty())	// <> will be converted to "" by XF framework
		return PDS_UNASSIGNED;
	
	return okutil_cvt_str_to_predefined_type(strParam);
}
///end _GET_SAMPLE_PARAM_TYPE

///Cheney 2006-8-4 WINDOW_FILTER
int window_filter(vector& vFilter, int nWindowMethod, int nResponseType, int nOrder, double dFs, double dLow, double dHigh, double dAlpha, double dBeta)
{
	double dUnity = dFs / 2;
	if(nOrder < 2 || dFs <= 0 || dLow <= 0 || dHigh <= 0 || dLow >= dUnity || dHigh >= dUnity)
		return CER_INVALID_ARGUMENT;
	
	//normalize dLow and dHigh
	dLow /= dFs;
	dHigh /= dFs;
	
	vector vResponse(nOrder);
	int nRet = create_response_data(nOrder, vResponse, dLow, dHigh, nResponseType);
	if(nRet > 0)
		return nRet;
	
	vector vWindow(nOrder);
	nRet = get_window_data( nWindowMethod, nOrder, vWindow, dAlpha, dBeta);
	if(nRet > 0)
		return nRet;
	
	vFilter.SetSize(nOrder);
	vFilter = vResponse * vWindow;
	return OE_NOERROR;
}
///end WINDOW_FILTER


/// Fisher 2008-8-19 QA80-12043 MISSING_75_FUNCTIONS


int FFT(matrix& matSource, matrix<complex>& matFFTResult, int nColProcess)
{
	NagError fail;
	matrix matTemp;
	int nRet;
	if(nRet = set_matrix_with_padding_truncting(matSource, matTemp, -1, nColProcess))
		return nRet;
	int nNumCols = matTemp.GetNumCols();
	int nNumRows = matTemp.GetNumRows();
	vector vecTrig;
	vecTrig.SetSize(2 * nNumCols);
	nag_fft_init_trig(nNumCols, vecTrig, &fail);
	nag_fft_multiple_real(nNumRows, nNumCols, matTemp, vecTrig, &fail);
	
	matrix matReal, matImage;
	matReal.SetSize(nNumRows, nNumCols);
	matImage.SetSize(nNumRows, nNumCols);
	
	nag_multiple_hermitian_to_complex(nNumRows, nNumCols, matTemp, matReal, matImage, &fail);
	matFFTResult.MakeComplex(matReal, matImage);

	return nRet;
	
}

int FFT(matrix<complex>& matSource, matrix<complex>& matFFTResult, int nColProcess)
{
	NagError fail;
	int nRet;
	matrix matReal, matImage;
	if(nRet = seperate_complex_mat_to_real_and_imag_mat(matSource, matReal, matImage, -1, nColProcess))
		return nRet;
	int nNumCols = matImage.GetNumCols();
	int nNumRows = matImage.GetNumRows();
	vector vecTrig;
	vecTrig.SetSize(2 * nNumCols); 
	nag_fft_init_trig(nNumCols, vecTrig, &fail);
	nag_fft_multiple_complex(nNumRows, nNumCols, matReal, matImage, vecTrig, &fail);
	matFFTResult.MakeComplex(matReal, matImage);
	return nRet;
}

int FFT(vector<complex>& vecSource, vector<complex>& vecFFTResult)
{
	// Get size of source vector
	int iSize = vecSource.GetSize();
	if(iSize < 1) return -5;
	
	// Create a complex matrix of size 1xn and copy source vector into matrix
	matrix<complex> matSource;
	matSource.SetSize(1,iSize);
	matSource.SetByVector(vecSource);
	
	// Create complex matrix to hold result of FFT operation
	matrix<complex> matFFTResult;
	
	// Call the matrix-based FFT function to perform FFT on this one row
	int iRet = FFT(matSource, matFFTResult, -1);
	if(iRet) return iRet;

	// Extract FFT result from result matrix, into a complex matrix, and return
	matFFTResult.GetAsVector(vecFFTResult);
	
	// return 0 on success
	return 0;
}

int IFFT(vector<complex>& vecSource, vector<complex>& vecFFTResult)
{
	// Get size of source vector
	int iSize = vecSource.GetSize();
	if(iSize < 1) return -5;
	
	// Create a complex matrix of size 1xn and copy source vector into matrix
	matrix<complex> matSource;
	matSource.SetSize(1,iSize);
	matSource.SetByVector(vecSource);
	
	// Create complex matrix to hold result of IFFT operation
	matrix<complex> matFFTResult;
	
	// Call the matrix-based IFFT function to perform IFFT on this one row
	int iRet = IFFT(matSource, matFFTResult, -1);
	if(iRet) return iRet;

	// Extract IFFT result from result matrix, into a complex matrix, and return
	matFFTResult.GetAsVector(vecFFTResult);
	
	// return 0 on success
	return 0;
}
		
int IFFT(matrix<complex>& matSource, matrix<complex>& matFFTResult, int nColProcess)
{
	int nRet;
	matrix<complex> matSourceCopy(matSource);
	if(nRet = matSourceCopy.Conjugate())
		return nRet;

	if(nRet = FFT(matSourceCopy, matFFTResult, nColProcess))
		return nRet;

	if(nRet = matFFTResult.Conjugate())
		return nRet;	
	
}


int FFT2(matrix& matSource, matrix<complex>& matFFT2Result, int nRowProcess, int nColProcess)
{
	matrix matReal;
	matrix matTemp(matSource);
	int nRet;
	if(nRet = set_matrix_with_padding_truncting(matTemp, matReal, nRowProcess, nColProcess))
		return nRet;
	matrix matImage;
		
	int nNumCols = matReal.GetNumCols();
	int nNumRows = matReal.GetNumRows();
	matImage.SetSize(nNumRows, nNumCols);
	matImage = 0;	
	if(nRet = fft2_for_complex_matrix(nNumRows, nNumCols, matReal, matImage, matFFT2Result))
		return nRet;
	return nRet;
}


int FFT2(matrix<complex>& matSource, matrix<complex>& matFFT2Result, int nRowProcess, int nColProcess )
{
	int nRet;
	matrix matReal, matImage;
	if(nRet = seperate_complex_mat_to_real_and_imag_mat(matSource, matReal, matImage, nRowProcess, nColProcess))
		return nRet;
	
	int nNumCols = matImage.GetNumCols();
	int nNumRows = matImage.GetNumRows();
	if(nRet = fft2_for_complex_matrix(nNumRows, nNumCols, matReal, matImage, matFFT2Result))
		return nRet;
	
}

static int fft2_for_complex_matrix(int nNumRows, int nNumCols,  matrix& matReal, matrix& matImage, matrix<complex>& matFFT2Result)
{
	vector vecTrigRows;
	vecTrigRows.SetSize(2 * nNumRows);
	//cal nage function to prepare the trig value
	NagError fail;
	nag_fft_init_trig(nNumRows, vecTrigRows, &fail);
	
	vector vecTrigCols;
	vecTrigCols.SetSize(2 * nNumCols);
	nag_fft_init_trig(nNumCols, vecTrigCols, &fail);
	
	//call the nag function to do the fft2
	nag_fft_2d_complex(nNumRows, nNumCols, matReal, matImage, vecTrigRows, vecTrigCols, &fail);

	//set the data back
	int nRet;
	if( nRet = matFFT2Result.MakeComplex(matReal, matImage))
		return nRet;
	
}

int IFFT2(matrix<complex>& matSource, matrix<complex>& matFFT2Result, int nRowProcess, int nColProcess)
{

	int nRet;
	matrix<complex> matSourceCopy(matSource);
	if(nRet = matSourceCopy.Conjugate())
		return nRet;
	
	if(nRet = FFT2(matSourceCopy, matFFT2Result,nRowProcess, nColProcess ))
		return nRet;
	
	if(nRet = matFFT2Result.Conjugate())
		return nRet;
}

/// end MISSING_75_FUNCTIONS


/// Fisher	07/29/09 QA80-14034  SET_2DFFT_FREQUENCY_DOMAIN
void	get_sampling_interval_2d(MatrixObject &mo, double &dx, double &dy)
{
	int nRows = mo.GetNumRows();
	int nCols = mo.GetNumCols();
	
	double dxMin, dxMax, dyMin, dyMax;
	mo.GetXY(dxMin, dyMin, dxMax, dyMax);
	dx = nCols <= 1 ? 1.0 : (dxMax-dxMin)/(nCols-1);
	dy = nRows <= 1 ? 1.0 : (dyMax-dyMin)/(nRows-1);
}

void	set_frequency_domain_2d(MatrixObject &mo, double dx, double dy, int shift)
{
	dx = fabs(dx);
	dy = fabs(dy);

	double  dxMin, dxMax, dyMin, dyMax;
	if( shift )
	{
		dxMin = (-0.5/dx);
		dxMax = (0.5/dx);
		dyMin = (-0.5/dy);
		dyMax = (0.5/dy);
	}
	else
	{
		dxMin = (0.0);
		dxMax = (1.0/dx);
		dyMin = (0.0);
		dyMax = (1.0/dy);
	}
	mo.SetXY(dxMin, dyMin, dxMax, dyMax);
}
/// end SET_2DFFT_FREQUENCY_DOMAIN

/// Iris 10/20/2009 ADD_FFT_PREVIEW_FOR_DECIMATE_XF
/// Iris 10/21/2009 NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
static bool _get_layer_borders(GraphLayer& gl, double& left, double& top, double& right, double& bottom)
{
	Tree tr;
	tr = gl.GetFormat(FPB_DIMENSION, FOB_ALL, true, true);
	
	TreeNode trDimension = tr.Root.Dimension;
	ASSERT(trDimension);
	if( !trDimension )
		return false;
	
	left = trDimension.Left.dVal;
	top = trDimension.Top.dVal;
	right = left + trDimension.Width.dVal;
	bottom = top + trDimension.Height.dVal;
	return true;
}

static bool _get_preview_layers_border(GraphPage& gp, stLayersGridFormat& stFormat)
{
	int nLayers = gp.Layers.Count();
	if( nLayers < 1 )
		return false;
	
	stFormat.nXGap = 5;		
	stFormat.nYGap = 5;		

	if( nLayers > 1 )
	{
		GraphLayer glFirst = gp.Layers(0);
		GraphLayer glLast = gp.Layers(nLayers-1);
		
		double left1, top1, right1, bottom1;
		if( !_get_layer_borders(glFirst, left1, top1, right1, bottom1) )
			return false;
		
		double left2, top2, right2, bottom2;
		if( !_get_layer_borders(glLast, left2, top2, right2, bottom2) )
			return false;
		
		stFormat.nLeftMg = nint(left1);
		stFormat.nRightMg = nint(100 - right1);			
		stFormat.nTopMg = nint(top1);			
		stFormat.nBottomMg = nint(100 - bottom2);			
	}
	else if( 1 == nLayers )
	{
		GraphLayer gl = gp.Layers(0);
		double left, top, right, bottom;
		if( !_get_layer_borders(gl, left, top, right, bottom) )
			return false;
		
		stFormat.nLeftMg = nint(left);
		stFormat.nRightMg = nint(100 - right);			
		stFormat.nTopMg = nint(top);			
		stFormat.nBottomMg = nint(100 - bottom);		
	}
	
	return true;		
}
///end NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER

static void _update_reduce_fft_amp(const XYRange& iy, XYRange& oy, int factor)
{
	vector vx, vy;
	if(!iy || !iy.GetData(vy, vx,NULL, 0, 0))
		return;

	vector vfreq, vAmp;	
	///Sophy 2/23/2010 CLEAN_CODE_FOR_FUNCTION_FFT_AMP
	//string strPath;
	//strPath.Format("%sOriginC\\OriginLab\\fft_utils.c", GetAppPath(TRUE)); 
	//Function fn = Project.FindFunction("fft_amp", strPath);
	//FUNC_POINTER_FFT_AMP pfn = fn;
	//ASSERT( pfn );
	//if( !pfn )
		//return;
	//pfn(vx, vy, vfreq, vAmp, vy.GetSize(), true);	
	fft_amp(vx, vy, vfreq, vAmp, vy.GetSize(), true);
	///end CLEAN_CODE_FOR_FUNCTION_FFT_AMP
	/// Fisher	07/06/09	USE_SMALLER_FREQ_RANGE_IN_ORIGINAL_FFT_GRAPH
	if(factor > 0)
	{
		int SizeNew = vfreq.GetSize() / factor;
		
		vfreq.SetSize(SizeNew);
		vAmp.SetSize(SizeNew);
	}
	/// End USE_SMALLER_FREQ_RANGE_IN_ORIGINAL_FFT_GRAPH	
	
	if(oy.IsValid())
		oy.SetData(&vAmp, &vfreq);

}

bool show_FFT_preview(TreeNode& trGetN, PageBase& pgTemp, Worksheet& wksTemp, XYRange& xyResampled, double dFactor)
{
	bool plot = (bool)trGetN.plot.nVal;
	
	XYRange iy;
	if( !xy_range_from_GetN_data_node(trGetN.iy, iy) || !iy.IsValid())
		return false;	
	
	///Kyle 07/03/2009 ADD_FFT_PREVIEW
	GraphPage gp = pgTemp;
	GraphLayer gl = gp.Layers(1);
	
	/// Iris 10/21/2009 NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
	stLayersGridFormat stFormat;
	stLayersGridFormat* pstFormat = NULL;
	if( _get_preview_layers_border(gp, stFormat) )
		pstFormat = &stFormat;
	///end NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
	
	if(plot)
	{
		// prepare layer
		bool bNewCreated = false; /// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
		if(!gl)
		{
			bNewCreated = true; /// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
			int nIndex = gp.AddLayer("Amp", 0, "CurvePreview");
			gl = gp.Layers(nIndex);
			/// Iris 10/21/2009 NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
			//page_arrange_layers(gp, 2, 1);
			page_arrange_layers(gp, 2, 1, pstFormat);
			///end NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
		}
		
		/// Fisher 07/06/09		LOG_SCALE_IN_FFT_PREVIEW_GRAPH
		Scale sc(gl.Y);
		sc.Type = LOG10_SPACE;
		
		// data
		XYRange rngSrcFFT, rngResFFT;
		int nXSrc = 2, nYSrc = 3,
			nXRes = 4, nYRes = 5;
		xy_range_from_wks_cols(rngSrcFFT, wksTemp, nXSrc, nYSrc);
		xy_range_from_wks_cols(rngResFFT, wksTemp, nXRes, nYRes);
		vector vX, vY;
		rngSrcFFT.SetData(&vY, &vX, 0, NULL, 0);	// clean data
		rngResFFT.SetData(&vY, &vX, 0, NULL, 0);
		/// Fisher	07/06/09	USE_SMALLER_FREQ_RANGE_IN_ORIGINAL_FFT_GRAPH
		//_update_reduce_fft_amp(iy, rngSrcFFT);
		//_update_reduce_fft_amp(xyResampled, rngResFFT);
		///Kyle 07/08/2009 GET_REDUCE_FACTOR_FROM_OTHER_OPTIONS
		//_update_reduce_fft_amp(iy, rngSrcFFT, rfactor);
		_update_reduce_fft_amp(iy, rngSrcFFT, dFactor);
		///End GET_REDUCE_FACTOR_FROM_OTHER_OPTIONS
		_update_reduce_fft_amp(xyResampled, rngResFFT, 0);		
		/// End	USE_SMALLER_FREQ_RANGE_IN_ORIGINAL_FFT_GRAPH
	
		// plot
		int nPlots = gl.DataPlots.Count();
		for(int ii = 0; ii < nPlots; ii++)
			gl.RemovePlot(0);
		Curve cuvSrc(wksTemp, nXSrc, nYSrc);
		Curve cuvRes(wksTemp, nXRes, nYRes);
		int nSrc = gl.AddPlot(cuvSrc, IDM_PLOT_LINE);
		int nRes = gl.AddPlot(cuvRes, IDM_PLOT_LINE);
		DataPlot dpSrc = gl.DataPlots(nSrc);
		if(dpSrc)
		{
			dpSrc.SetColor(0);
			legend_update(gl);
		}
		DataPlot dpRes = gl.DataPlots(nRes);
		if(dpRes)
		{
			dpRes.SetColor(1);
			legend_update(gl);
		}
		
		/// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
		//gl.Rescale();
		if( bNewCreated )
		{
			gl.Rescale();
		}
		///end PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
	}
	else
	{
		if(gl)
		{
			gl.Destroy();
			/// Iris 10/21/2009 NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
			//page_arrange_layers(gp, 1, 1);
			page_arrange_layers(gp, 1, 1, pstFormat);
			///end NEED_KEEP_TEMPLATE_LAYER_BORDER_AFTER_ARRANGE_LAYER
		}
	}
	///End ADD_FFT_PREVIEW
	
	return true;
}
///end ADD_FFT_PREVIEW_FOR_DECIMATE_XF

///-----Kit 10/26/2010 ORG-1227-P3 SUPPORT_OTHER_FFT_TOOL_SHOW_UNITS_ON_REPORT_TABLE
ShowUnitsHelperBase::ShowUnitsHelperBase(const DataRange &dr)
{
	m_drInput = dr;	
	m_strUnitX = "";
	m_strUnitReal = "";
	m_strUnitImag = "";
	m_nRealColIndex = -1;
	m_nImagColIndex = -1;
}

bool	ShowUnitsHelperBase::ShowUnitsRowOnReportTable(Worksheet &wksFFT, const ReportTable &rtFFT)
{
	if( !updateUnitStr() )
		return false;
		
	wksFFT.CheckAddLabelByType( RCLT_UNIT );
	
	if( wksFFT.Columns.Count() != rtFFT.Children.Count() )
	{
		ASSERT( false );
		return false;
	}
	
	int iColIndex = 0;
	foreach( TreeNode tr in rtFFT.Children )
	{	
		string strUnit;
		if( CreateReportUnitStr(tr.ID, strUnit) )
		{
			Column col = wksFFT.Columns( iColIndex );
			col.SetUnits( strUnit );
		}
	
		iColIndex++;
	}

	return true;
}  

bool	ShowUnitsHelperBase::updateInputWksAndInputColIndex()
{
	if( !m_drInput.IsValid() || (m_drInput.GetNumRanges() == 0) )
		return false;
	
	int nColStart, nColEnd;
	if( !m_drInput.GetRange( m_wksInput, nColStart, nColEnd, 0 ) )
	{
		return false;
	}

	m_nRealColIndex = nColStart;

	if( m_drInput.GetNumRanges() == 2 )
	{
		Worksheet wksTmp;
		if( !m_drInput.GetRange( wksTmp, nColStart, nColEnd, 1 ) )
		{
			return false;
		}
		
		if( wksTmp.GetUID() != m_wksInput.GetUID() )
			return false;
		
		m_nImagColIndex = nColStart;
	}

	return true;
}

bool	ShowUnitsHelperBase::CheckUnitIsCompoiste(const string &strUnit)
{
	vector<string> vsOperator = { "+", "-", "*", "*/", "^", "%" };
	
	for( int ii=0; ii<vsOperator.GetSize(); ++ii )
	{
		if( -1 != strUnit.Find( vsOperator[ii] ) )
		{
			return true;
		}
	}
	
	return false;
}

bool	ShowUnitsHelperBase::updateUnitStr()
{
	if( !updateInputWksAndInputColIndex() )
	{
		ASSERT( false );
		return false;
	}
	
	Column colReal;

	// get real unit
	if( m_nRealColIndex < 0 || m_nRealColIndex >= m_wksInput.Columns.Count() )
		return false;

	colReal = m_wksInput.Columns( m_nRealColIndex );
	m_strUnitReal = colReal.GetUnits();

	// get X(time) unit
	string strXUnit;
	if( (m_drInput.GetNumRanges() == 1) && colReal.IsEvenSampling( NULL, NULL, &strXUnit, NULL ) )
	{
		m_strUnitX = strXUnit;
	}
	else
	{
		ASSERT( m_drInput.GetNumRanges() == 2 );
		int nXColIndex = m_wksInput.FindColIndex(colReal.GetIndex(), OKDATAOBJ_DESIGNATION_X);
		
		if( (nXColIndex < 0) || (nXColIndex >= m_wksInput.Columns.Count()) )
			return false;
		
		Column colX = m_wksInput.Columns(nXColIndex);

		m_strUnitX = colX.GetUnits();
	
		// get imaginary unit
		if( m_nImagColIndex > 0 && (m_nImagColIndex < m_wksInput.Columns.Count()) )
		{
			Column colImag = m_wksInput.Columns(m_nImagColIndex);
			m_strUnitImag = colImag.GetUnits();
			
			if( m_strUnitImag != m_strUnitReal )
				return false;
		}
	}

	if( m_strUnitX.IsEmpty() || m_strUnitReal.IsEmpty() )
		return false;

	return true;
}

bool	ShowUnitsHelperBase::CreateReportUnitStr(int nRDID, string &strUnit)
{
	ASSERT(false);
	return false;
}

bool ShowUnitsHelperBase::AddParenthesis( string &strUnit )
{
	string strTmp = "(";
	strTmp += strUnit + ")";
	strUnit = strTmp;
	return true;
}

bool ShowUnitsHelperBase::HandleReciprocalCase( string &strUnit )
{
	int nPos = m_strUnitX.Find( "1/" );
	if( 0 == nPos )
	{

		string strRight = m_strUnitX.Mid(lstrlen("1/"));
		//// case : 1/(a*b), strRight = (a*b)
		if( strRight[0] == '(' && strRight[strRight.GetLength()-1] == ')')
		{
			strUnit = strRight;
		}
		//// case : 1/a, strRight = a
		else if( !CheckUnitIsCompoiste(strRight) )
		{
			strUnit = strRight;
			AddParenthesis(strUnit);
		}
		//// case : m_strUnitX = 1/a*b, strUnit = 1/(m_strUnitX)
		else
		{
			strUnit = m_strUnitX;
			AddParenthesis(strUnit);
			strUnit = "1/" + strUnit;
		}
		
		return true;
	}

	return false;
}
///-----End SUPPORT_OTHER_FFT_TOOL_SHOW_UNITS_ON_REPORT_TABLE