#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	subgroup_ratio,
	subgroup_inter,
	subgroup_bins,
	subgroup_freq,
};
enum{
	method_yfirstxfirst,
	method_ymeanxbinc,
	method_yranxbinc,
};
#include <fft_utils.h>
//put additional include files here
#include <ReportTree.h>
#include <event_utils.h>

/////////////////////////////////////////////////////////////////////////////
// Modification Log
//
// TD 12-15-2008 QA80-12786  DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
// CPY 12/19/08 USE_SHARED_TEMPLATE_FOR_ALL_PREVIEW_XF
// Kyle 12/22/2008 OPEN_DIALOG_WHEN_THEME_IS_USED_AND_ERROR_HAPPENS
// Kyle 12/22/2008 OUTPUT_COLUMN_COMMENTS
// Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
// Kyle 12/23/2008 CHECK_SAMPLING_TYPE_AND_UPDATE_RATE_HINT_LABEL
// Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
// Jack 12/25/2008 OUTPUT_ESTIMATED_SRCDATA_SAMPLING_INTERVAL
// Fisher 12/25/2008 QA80-12405 REDUCE_DATA_XF_SPEED_ISSUE
// Jack 12/26/2008 SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT
// Kyle 12/30/2008 CHECK_UNITS_OF_SAMPLING_INTERVAL
// Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
// Jack 12/31/2008 ADD_RFACTOR_METHOD
// Jack 01/04/2009 ADD_RFREQUENCY_METHOD
// Jack	 05/01/2008 ADD_FIRST_AND_RANDOM_SAMPLING_METHOD
// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
/// Folger 02/09/09 QA80-12786 DATE_TIME_FORMAT_SUPPORT_IN_XF_GETN
// Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
// Kyle 06/03/2009 GET_SOURCE_GRAPH_SCALE_TYPE
//	Kyle 06/24/2009 QA80-13330-P4 RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
//	Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
/// Fisher 07/06/09		LOG_SCALE_IN_FFT_PREVIEW_GRAPH
/// Fisher	07/06/09	USE_SMALLER_FREQ_RANGE_IN_ORIGINAL_FFT_GRAPH
/// Kyle 07/08/2009 GET_REDUCE_FACTOR_FROM_OTHER_OPTIONS
/// Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
/// Kyle 07/30/2009 ALWAYS_PASS_NEGATIVE_NUMBER_AS_RANDOM_SEED
/// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
/// Iris 10/20/2009 ADD_FFT_PREVIEW_FOR_DECIMATE_XF
/// Kyle 10/21/2009 USE_GENERAL_CODE_TO_SET_XYRANGE_DATA
///	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
/////////////////////////////////////////////////////////////////////////////


#ifdef	_DEBUG		///Sophy 6/1/2009 HIDE_DEBUG_INFO
//#define SPEED_TEST
#endif	//_DEBUG	///Sophy 6/1/2009 HIDE_DEBUG_INFO


//put your own support static functions here

///Kyle 12/23/2008 CHECK_SAMPLING_TYPE_AND_UPDATE_RATE_HINT_LABEL
#define STR_UNITS_MILLISECOND	"ms"
#define STR_UNITS_SECOND1 		"s"
#define STR_UNITS_SECOND2 		"sec"
#define STR_UNITS_SECOND3 		"second"
#define STR_UNITS_MINUTE1 		"m"
#define STR_UNITS_MINUTE2 		"min"
#define STR_UNITS_MINUTE3 		"minute"
#define STR_UNITS_HOUR1 		"h"
#define STR_UNITS_HOUR2 		"hour"
#define STR_UNITS_DAY1			"d"
#define STR_UNITS_DAY2			"day"

static double _transform_units_to_seconds(string strUnit)
{
	double dSeconds = -1;
	if(strUnit.CompareNoCase(STR_UNITS_MILLISECOND)==0)
		dSeconds = 0.001;
	else if(strUnit.CompareNoCase(STR_UNITS_SECOND1)==0 || strUnit.CompareNoCase(STR_UNITS_SECOND2)==0 || strUnit.CompareNoCase(STR_UNITS_SECOND3)==0)
		dSeconds = 1.0;
	else if(strUnit.CompareNoCase(STR_UNITS_MINUTE1)==0 || strUnit.CompareNoCase(STR_UNITS_MINUTE2)==0 || strUnit.CompareNoCase(STR_UNITS_MINUTE3)==0)
		dSeconds = 60.0;
	else if(strUnit.CompareNoCase(STR_UNITS_HOUR1)==0 || strUnit.CompareNoCase(STR_UNITS_HOUR2)==0)
		dSeconds = 3600.0;
	else if(strUnit.CompareNoCase(STR_UNITS_DAY1)==0 || strUnit.CompareNoCase(STR_UNITS_DAY2)==0)
		dSeconds = 3600.0 * 24;
	return dSeconds;
}

///Kyle 01/13/2009 v8.0995d CHANGE_SITUATION_FOR_SHOWING_SAMPLING_INTERVAL_HINT
//static bool _need_show_input_sampling_interval_and_new_rate_hint(const TreeNode& trGetN)
//{
/////Jack 12/26/2008 SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT      
///// the time format's sampling interval shown will not be consistent with what was used inside for calculation
////	if( _has_unit(trGetN) && _is_even_sampling(trGetN) )
/////Jack 1/09/2009 ADD_VARIATION_AND_INTERPOLATE_OPTION
////	if( _has_unit(trGetN) && _is_even_sampling(trGetN) && _is_numeric_format(trGetN))
	//if( _has_unit(trGetN) && _is_even_sampling_signal_or_xcol(trGetN) && _is_numeric_format(trGetN))
/////End ADD_VARIATION_AND_INTERPOLATE_OPTION
/////End SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT
		//return true;
	//return false;
//}
//static bool _need_show_input_sampling_interval(const TreeNode& trGetN)
//{
/////Jack 12/26/2008 SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT	
////	if( !_has_unit(trGetN) && _is_even_sampling(trGetN) )
/////Jack 1/09/2009 ADD_VARIATION_AND_INTERPOLATE_OPTION
////	if( !_has_unit(trGetN) && _is_even_sampling(trGetN) && _is_numeric_format(trGetN) )
	//if( !_has_unit(trGetN) && _is_even_sampling_signal_or_xcol(trGetN) && _is_numeric_format(trGetN) )
/////End ADD_VARIATION_AND_INTERPOLATE_OPTION
/////End SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT	
		//return true;
	//return false;
//}
static bool _need_show_sampling_interval_hint(const TreeNode& trGetN)
{
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	//if(_is_even_sampling(trGetN, true) && _is_numeric_format(trGetN) )
	//	return true;
	//return false;
	return _is_even_sampling(trGetN) && _is_numeric_format(trGetN);
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
}
///End CHANGE_SITUATION_FOR_SHOWING_SAMPLING_INTERVAL_HINT

///Jack 12/26/2008 SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT
static bool _is_numeric_format(const TreeNode& trGetN)
{
	///Kyle 12/30/2008 CHECK_UNITS_OF_SAMPLING_INTERVAL
	//int nDataFormat = get_col_data_format(trGetN.iy, OKDATAOBJ_DESIGNATION_X);
	//if(OKCOLTYPE_NUMERIC != nDataFormat && OKCOLTYPE_TEXT_NUMERIC != nDataFormat)
		//return false;
	//return true;
	XYRange xyTemp;
	if(xy_range_from_GetN_data_node(trGetN.iy, xyTemp) && xyTemp.IsValid())
	{
		Column  col;
		xyTemp.GetXColumn(col);
		if(col)
		{
			int nDataFormat = col.GetFormat();
			if(OKCOLTYPE_NUMERIC == nDataFormat || OKCOLTYPE_TEXT_NUMERIC == nDataFormat)
				return true;
		}
		else
		{
			xyTemp.GetYColumn(col);
			if(col && col.IsEvenSampling())
			return true;
		}
	}
	return false;
	///End CHECK_UNITS_OF_SAMPLING_INTERVAL
}
///End SHOW_SAMPLING_RATE_INTERVAL_ONLY_WHEN_NUMERIC_FORMAT

static bool _has_unit(const TreeNode& trGetN)
{
	XYRange xyRange;
	if(!xy_range_from_GetN_data_node(trGetN.iy, xyRange) || !xyRange.IsValid())
		return false;

	Column col;
	xyRange.GetXColumn(col);
	///Kyle 12/30/2008 CHECK_UNITS_OF_SAMPLING_INTERVAL
	//if(!col || _transform_units_to_seconds(col.GetUnits()) <= 0)
		//return false;
	if(col)
	{
		if(_transform_units_to_seconds(col.GetUnits()) <= 0)
			return false;
	}
	else
	{
		xyRange.GetYColumn(col);
		string strUnits;
		if(!col || !col.IsEvenSampling(NULL, NULL, &strUnits) || strUnits.IsEmpty() || _transform_units_to_seconds(strUnits) <= 0)
			return false;
	}
	///End CHECK_UNITS_OF_SAMPLING_INTERVAL
	return true;
}

///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
//static bool _is_even_sampling(const TreeNode& trGetN, bool bStrict)
static bool _is_even_sampling(const TreeNode& trGetN, double *pdInterval = NULL)
///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
{
	XYRange xyRange;
	if(!xy_range_from_GetN_data_node(trGetN.iy, xyRange) || !xyRange.IsValid())
		return false;

	double dInterval;
	vector vx, vy;
	if(!xyRange.GetData(vy, vx))
		return false;
	double variation = 0.05;	// default
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	//if(trGetN.subgroup.nVal == subgroup_ratio && !bStrict)
		//variation = trGetN.variation.dVal/100.0;
	//
	//if(variation < 0.05)
		//variation = 0.05;	// use default
	if(trGetN.subgroup.nVal == subgroup_ratio)
		variation = trGetN.variation.dVal/100.0;
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	
	int nErrCode = ocmath_sampling_resolution(vx.GetSize(), vx, &dInterval, variation);
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	//if(nErrCode != OE_NOERROR)
	//{
		//trGetN.srcsampinterval.dVal = NANUM;  // set srcsampinterval to NANUM when it is not even spaced in the given variation
		//return false;
	//}
	//trGetN.srcsampinterval.dVal = dInterval;
	//return true;
	if(nErrCode == OE_NOERROR)
	{
		if(pdInterval)
			*pdInterval = dInterval;
		return true;
	}
	if(pdInterval)
		*pdInterval = NANUM;
	return false;
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
}


///End OUTPUT_ESTIMATED_SRCDATA_SAMPLING_INTERVAL

///End CHECK_SAMPLING_TYPE_AND_UPDATE_RATE_HINT_LABEL


enum
{
	SUB_RANGE_SUCCESS = 0,
	SUB_RANGE_FAILED = -1
};

enum
{
	stats_mean,
	stats_min,
	stats_max,
	stats_median,
///Jack	 05/01/2008 ADD_FIRST_AND_RANDOM_SAMPLING_METHOD
///Jack 01/05/2008 CHANGE_FIRST_TO_MIDDLE_SAMPLING_METHOD
//	stats_first,
	stats_middle,
///End CHANGE_FIRST_TO_MIDDLE_SAMPLING_METHOD
	stats_random,
///End	ADD_FIRST_AND_RANDOM_SAMPLING_METHOD
};
///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW
static bool s_bInit = false;
static string s_strErrMsg = "";

/// Iris 10/20/2009 ADD_FFT_PREVIEW_FOR_DECIMATE_XF
/*
///Kyle 07/03/2009 ADD_FFT_PREVIEW
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;
	
	fft_amp(vx, vy, vfreq, vAmp, vy.GetSize(), true);
	
	/// 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);

}
///End ADD_FFT_PREVIEW
*/
///end ADD_FFT_PREVIEW_FOR_DECIMATE_XF

///Kyle 07/08/2009 GET_REDUCE_FACTOR_FROM_OTHER_OPTIONS
static double _get_reduct_factor(TreeNode& trGetN)
{
	double dFactor;
	int nSize =  get_input_xyrange_data_size(trGetN.iy);
	switch(trGetN.subgroup.nVal)
	{
	case subgroup_ratio:
		dFactor = trGetN.rfactor.nVal;
		break;
	case subgroup_inter:
		dFactor = nSize * trGetN.dx.dVal  / (trGetN.end.dVal - trGetN.start.dVal);
		break;
		
	case subgroup_bins:
		dFactor = nSize / trGetN.bins.nVal;
		break;
		
	case subgroup_freq:
		ASSERT(trGetN.end.dVal != trGetN.start.dVal);
		dFactor = nSize / ( trGetN.rfre.dVal * (trGetN.end.dVal-trGetN.start.dVal) );
		break;
	}
	return dFactor;
}
///End GET_REDUCE_FACTOR_FROM_OTHER_OPTIONS

static void _run_resample_on_current_data(TreeNode& trGetN, PageBase& pgTemp, Worksheet& wksTemp)
{
	XYRange iy, xyResampled;	
	if(!init_preview_graph(trGetN.iy, pgTemp, wksTemp, NULL, &iy, &xyResampled))
		return;
	///Kyle 12/08/2008 CLEAN_DATA_IN_TEMPORARY_WORKSHEET_BEFORE_DO_UPDATE_PREVIEW_GRAPH
	vector vX, vY;
	xyResampled.SetData(&vY, &vX, 0, NULL, 0);	// clean data
	///End CLEAN_DATA_IN_TEMPORARY_WORKSHEET_BEFORE_DO_UPDATE_PREVIEW_GRAPH

	int subgroup = trGetN.subgroup.nVal;
	double dx = trGetN.dx.dVal;
	int bins = trGetN.bins.nVal;
	int rfactor = trGetN.rfactor.nVal;
	double rfre = trGetN.rfre.dVal;
	string inputsampinterhint;
	string hint;
	double start = trGetN.start.dVal;
	double end = trGetN.end.dVal;
	int method = trGetN.method.nVal;
	//double srcsampinterval = trGetN.srcsampinterval.dVal;
	double variation = trGetN.variation.dVal;
	//int interp = trGetN.interp.nVal;
	int ranseed = trGetN.ranseed.nVal;
	int plot = trGetN.plot.nVal;

	try {
		///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		//reduce_ex(iy, subgroup, dx, bins, rfactor, rfre, inputsampinterhint, hint, start, end, method, srcsampinterval, variation, interp, ranseed, xyResampled);
		reduce_ex(iy, subgroup, dx, bins, rfactor, rfre, inputsampinterhint, hint, start, end, method, variation, ranseed, plot, xyResampled);
		///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	}
	catch(int nErr)
	{
	}
	
	/// Iris 10/20/2009 ADD_FFT_PREVIEW_FOR_DECIMATE_XF
	/*
	///Kyle 07/03/2009 ADD_FFT_PREVIEW
	GraphPage gp = pgTemp;
	GraphLayer gl = gp.Layers(1);
	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");
			gl = gp.Layers(nIndex);
			page_arrange_layers(gp, 2, 1);
		}
		
		/// 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, _get_reduct_factor(trGetN));
		///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();
		page_arrange_layers(gp, 1, 1);
	}
	///End ADD_FFT_PREVIEW
	*/
	bool bRet = show_FFT_preview(trGetN, pgTemp, wksTemp, xyResampled, _get_reduct_factor(trGetN));
	ASSERT(bRet);
	///end ADD_FFT_PREVIEW_FOR_DECIMATE_XF
	
	/// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
	/*
	///Kyle 06/24/2009 QA80-13330-P4 RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
	//GraphPage gp = pgTemp;
	gl = gp.Layers(0);
	if(gl)
		gl.Rescale();
	///End RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
	*/
	///end PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE

}

static bool _is_subgroup_method_support_random_sampling(TreeNode& trGetN)
{
	return ( (trGetN.subgroup.nVal==subgroup_ratio) || (trGetN.subgroup.nVal== subgroup_inter) || (trGetN.subgroup.nVal==subgroup_bins) || (trGetN.subgroup.nVal == subgroup_freq) );
}
static bool _is_random_y_sampling_method(TreeNode& trGetN)
{
	return (trGetN.method.nVal==method_yranxbinc);
}
///End SKIP_POINTS_IN_VECTOR

static int _check_input(TreeNode& trGetN, string& strErrMsg)
{
	int nErr = CER_NO_ERROR;
	int nSize =  get_input_xyrange_data_size(trGetN.iy);
	if(get_input_xyrange_num(trGetN.iy) < 1)
		nErr = XFERR_AT_LEAST_ONE_XYRANGE;
	else if(0 >= nSize)
		nErr = CER_NO_DATA;
	
	if(nErr != CER_NO_ERROR)
	{
		strErrMsg = nErr;
		return false;
	}

	if(!_is_monotonic(trGetN))
	{
		strErrMsg = XFERR_INPUT_DATA_NONMONOTONIC;
		return false;
	}
	
	if(trGetN.subgroup.nVal == subgroup_ratio)
	{
		if(trGetN.variation.Show && (trGetN.variation.dVal<0 || trGetN.variation.dVal>100))
		{
			strErrMsg = XFERR_INVALID_TOLERANCE_VARIATION;
			return false;
		}
		///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		//if(!_is_even_sampling(trGetN, false) && !trGetN.interp.nVal)
		//{
		//	strErrMsg = "The input data is not evenly spaced. Use the Interpolate Before Reduction option to obtain evenly spaced output.";
		//	return false;
		//}
		///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	}

	double dxMin, dxMax;
	dxMin = trGetN.start.dVal;
	dxMax = trGetN.end.dVal;
	
	/*------- Jack no need to check the start and end even if it is out of data range as current requirement is changed
	///Kyle 12/10/2008 GIVE_MORE_CHECK_ABOUT_START_AND_END_VALUES
	//if(trGetN.subgroup.nVal != subgroup_ratio && trGetN.start.dVal > trGetN.end.dVal )
	double dxInputMin, dxInputMax;
	get_data_x_scale(trGetN, dxInputMin, dxInputMax);
	if(trGetN.subgroup.nVal != subgroup_ratio && (dxMin > dxMax || dxMin > dxInputMax || dxMax < dxInputMin))
	///End GIVE_MORE_CHECK_ABOUT_START_AND_END_VALUES
	{
		strErrMsg = XF_REDUCE_START_END_ERROR;
		return false;
	}
	*/
	if( (trGetN.subgroup.nVal == subgroup_inter || trGetN.subgroup.nVal == subgroup_bins) && trGetN.start.dVal > trGetN.end.dVal )
	{
		strErrMsg = XF_REDUCE_START_END_ERROR;
		return false;
	}

	
	/* --- Jack
	if(trGetN.dx.dVal>(dxMax-dxMin) && trGetN.subgroup.nVal == subgroup_inter)
	{
		strErrMsg = XF_REDUCE_BIN_TOO_LARGE;  /// 
		return false;
	}
	*/
	if(trGetN.dx.dVal>(dxMax-dxMin) && trGetN.subgroup.nVal == subgroup_inter)
	{
		strErrMsg = XF_REDUCE_BIN_TOO_LARGE;  /// 
		return false;
	}
	
	//---Jack
	if(trGetN.dx.dVal<=0 && trGetN.subgroup.nVal == subgroup_inter)
	{
		strErrMsg = XF_REDUCE_NEG_SAMPLING_INTER_OR_RATE;  /// todo: can not accept negative sampling interval or sampling frequency XF_REDUCE_NEG_SAMPLING_INTER_OR_RATE
		return false;
	}
	
	if(trGetN.bins.nVal<1 && trGetN.subgroup.nVal == subgroup_bins)
	{
		strErrMsg = XF_REDUCE_BIN_NUM_TOO_SMALL;  /// "Too Small bin numbers"
		return false;
	}
	
	
		

	///Jack 12/31/2008 ADD_RFACTOR_METHOD
	if((trGetN.rfactor.nVal<=0 || trGetN.rfactor.nVal>nSize)&& trGetN.subgroup.nVal == subgroup_ratio)
	{
		strErrMsg = XF_REDUCE_FACTOR;  /// "Improper reduction factor. Reset it properly"  to do:
		return false;
	}
	/// ADD_RFACTOR_METHOD
	
	///Jack 01/04/2009 ADD_RFREQUENCY_METHOD
	if((trGetN.rfre.dVal<=0)&& trGetN.subgroup.nVal == subgroup_freq)
	{
		strErrMsg = XF_REDUCE_NEG_SAMPLING_INTER_OR_RATE;  /// ""  to do XF_REDUCE_NEG_SAMPLING_INTER_OR_RATE
		return false;
	}
	/// ADD_RFREQUENCY_METHOD
	
	if(trGetN.subgroup.nVal == subgroup_freq && trGetN.rfre.dVal * (dxMax - dxMin) <1 )
	{
		strErrMsg = XFERR_INVALID_RESAMPLE_FREQUENCY;
		return false;
	}
	
	///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
	/// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
	//if( trGetN.ranseed.nVal>=0)
	///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
	//if( trGetN.ranseed.nVal>=0 && _is_subgroup_method_support_random_sampling(trGetN) && _is_random_y_sampling_method(trGetN))
	///// End SKIP_POINTS_IN_VECTOR
	//{
		//strErrMsg = "randon number generator seed should be a negative number";  /// ""  to do: XF_REDUCE_RAN_NUMBER_SEED_NEG_NUMBER "randon number generator seed should be a negative number"
		//return false;
	//}
	///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
	///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
	
	///// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
	//if( (trGetN.subgroup.nVal == subgroup_skip) && !_is_even_sampling_signal_or_xcol(trGetN))
	//{
		//strErrMsg = "The input data is not even sampling, not suitable for this method";
		//return false;
	//}
	//if( (trGetN.subgroup.nVal == subgroup_skip) && trGetN.everynpts.nVal>nSize)
	//{
		//strErrMsg = "The input skip sampling size too large";
		//return false;
	//}
	///// ENd SKIP_POINTS_IN_VECTOR
	
	///Jack 1/09/2009 ADD_VARIATION_AND_INTERPOLATE_OPTION
	///End ADD_VARIATION_AND_INTERPOLATE_OPTION
	
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	// warning message
	if(trGetN.subgroup.nVal == subgroup_ratio && !_is_even_sampling(trGetN) )
	{
		strErrMsg = XFERR_REDUCE_INPUT_DATA_NOT_EVEN_SPACE;
		return true;
	}
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION

	return true;	
}
///End UPDATE_XF_TO_SHOW_PREVIEW

// Fisher 12/31/2008 QA80-12405 REDUCE_DATA_XF_SPEED_ISSUE
/////Jack 29/10/2008 QA80-12405 REDUCE_DATA_XF
////static double get_data(const vector& vIn, const int iOption)
//static double get_data(const vector& vIn, const int iOption, int * pMinIndex=NULL, int * pMaxIndex=NULL)
/////End REDUCE_DATA_XF
//{
	//
	///// Fisher 12/25/2008 QA80-12405 REDUCE_DATA_XF_SPEED_ISSUE
	///*
	//double dMin, dMax;
	//if(pMinIndex!=NULL && pMaxIndex!=NULL)
		//vIn.GetMinMax(dMin, dMax, pMinIndex, pMaxIndex);
	//else
		//vIn.GetMinMax(dMin, dMax);
//
	//DescStatResults dsr;
	//int nSize = vIn.GetSize();
	//int nRet = ocmath_desc_stats(vIn, nSize, &dsr);
	//if (nRet != STATS_NO_ERROR)
		//return NANUM;
	//*/
	//double dMin, dMax;
	//int nSize = vIn.GetSize();
	//double dMean = ocmath_d_sum(vIn, nSize, &dMin, &dMax, NULL, NULL, NULL)/nSize;
	///// End REDUCE_DATA_XF_SPEED_ISSUE
//
///// Jack 21/10/2008 QA80-12405 REDUCE_DATA_XF
///*	
	//switch (iOption)
	//{
	//case method_minrow:	
		//return vIn[0];
		//break;
	//case method_maxrow:
		//return vIn[nSize - 1];
		//break;
	//case method_ave:
		//return dsr.Mean;
		//break;
	//case method_min:
		//return dMin;
		//break;
	//case method_max:
		//return dMax;
		//break;
	//case 	method_sum:
		//return dsr.Sum;
		//break;
	//case method_sd:
		//return dsr.SD;
		//break
	//default:
		//return NANUM;	
	//}
//*/
	//double dMedian;
	//
	//switch (iOption)
	//{
	//case stats_mean:
		///// Fisher 12/25/2008 QA80-12405 REDUCE_DATA_XF_SPEED_ISSUE
		////return dsr.Mean;
		//return dMean;		
		///// End REDUCE_DATA_XF_SPEED_ISSUE
		//break;
		//
	//case stats_min:
		//return dMin;
		//break;
		//
	//case stats_max:
		//return dMax;
		//break;
		//
	//case stats_median:
		//ocmath_get_median_in_vector(nSize,vIn,&dMedian);  // there is a sort so only run it when necessary
		//return dMedian;
		//break;
	//default:
		//return NANUM;	
	//}
	//return NANUM;
///// End REDUCE_DATA_XF
//}
// End REDUCE_DATA_XF_SPEED_ISSUE


/// Jack 21/10/2008 QA80-12405 REDUCE_DATA_XF

static bool _trim_missing_values(vector& vX, vector& vData)
{
	if(vX.GetSize()==0 || vData.GetSize()==0)
		return false;
	
	//if missing values, cases are excluded pairwise
	vector<uint> vecIndexX, vecIndexD;
	vX.Find(vecIndexX, NANUM);
	vData.Find(vecIndexD, NANUM);
	
	for (int ii= 0; ii < vecIndexX.GetSize(); ii++)
		vData[vecIndexX[ii]] = NANUM;
	
	for (ii= 0; ii < vecIndexD.GetSize(); ii++)
		vX[vecIndexD[ii]] = NANUM;
		
	vData.Trim();
	vX.Trim();
	if(vX.GetSize()==0 || vData.GetSize()==0)
		return false;
	else
		return true;
}


///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
///Kyle 03/02/2009 MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
//static bool construct_bins_vec_and_merged_x_vec(const double dSampleInterval, const double xStart, const double xEnd, int nSubGrpMethod, bool bUseHalfIntervalinBorder, vector& vBins, vector& vMergedX)
///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
//static bool construct_bins_vec_and_merged_x_vec(const double dSampleInterval, const double xStart, const double xEnd, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int xySamplingMethod, vector& vBins, vector& vMergedX)
static bool construct_bins_vec_and_merged_x_vec(const double dSampleInterval, const double xStart, const double xEnd, int nSubGrpMethod, int xySamplingMethod, vector& vBins, vector& vMergedX)
///End NOT_SUPPORT_Use_Half_Interval_in_Border
///End MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
{
	///Kyle 03/02/2009 MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
	if(xySamplingMethod == method_yfirstxfirst)
	{
		vBins.Data(xStart, xEnd, dSampleInterval);
		int nNumBins = vBins.GetSize()-1;  // minus 1 is needed

		vMergedX.Data(xStart, xStart + (nNumBins-1)* dSampleInterval, dSampleInterval);

		ASSERT(vMergedX.GetSize() == nNumBins);
		return vMergedX.GetSize() == nNumBins;
	}
	///End MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(!bUseHalfIntervalinBorder) // for bin center method for any sub group method
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	{
		vBins.Data(xStart, xEnd, dSampleInterval);
		int nNumBins = vBins.GetSize()-1;  // minus 1 is needed


		vMergedX.Data(xStart, xStart + (nNumBins-1)* dSampleInterval, dSampleInterval);
		ASSERT(vMergedX.GetSize() == nNumBins);
		if(vMergedX.GetSize() != nNumBins)
			return false;
	
		vMergedX = vMergedX + 0.5*dSampleInterval; // for bin center method	
		return true;
	}
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//else  // for bin begin method using half interval in Border
	//{
		//switch(nSubGrpMethod)
		//{
			//case subgroup_inter:
			//case subgroup_freq: // Jack 01/04/2009 ADD_RFREQUENCY_METHOD
				//vBins.Data(xStart+0.5*dSampleInterval, xEnd, dSampleInterval);
				/////Kyle 02/27/2009
				////vector vBinStart(1);
				////vBinStart[0] = xStart;
				////vBinStart.Append(vBins);
				////
				////vBins = vBinStart;
				//vBins.InsertAt(0, xStart);
				/////End ------
//
				//int nNumBins = vBins.GetSize()-1;  // minus 1 is needed
				//vMergedX.Data(xStart, xStart + (nNumBins-1)* dSampleInterval, dSampleInterval);
				//
				//ASSERT(vMergedX.GetSize() == nNumBins);
				//if(vMergedX.GetSize() != nNumBins)
				//return false;
				//
				//break;
			//case subgroup_bins:
			//case subgroup_ratio: // Jack 01/04/2009 ADD_RFREQUENCY_METHOD
				//if( (xEnd-xStart)/dSampleInterval>=2)
				//{
					//vBins.Data(xStart+0.5*dSampleInterval, xEnd-0.5*dSampleInterval, dSampleInterval);
					/////Kyle 02/27/2009
					////vector vBinStart(1);
					////vBinStart[0] = xStart;
					////vBinStart.Append(vBins);
					////
					////vector vBinEnd(1);
					////vBinEnd[0] = xEnd;
					////vBinStart.Append(vBinEnd);
					////
					////vBins = vBinStart;
					//vBins.InsertAt(0, xStart);
					//vBins.Add(xEnd);
					/////End ------
					//
					//int nNumBins = vBins.GetSize()-1;  // minus 1 is needed
					//vMergedX.Data(xStart, xStart + (nNumBins-1)* dSampleInterval, dSampleInterval);
					//
					//ASSERT(vMergedX.GetSize() == nNumBins);
					//if(vMergedX.GetSize() != nNumBins)
					//return false;
				//} /// assert only one bin is 
				//else
				//{
					/////Kyle 02/27/2009
					////vector vBinStart(1);
					////vBinStart[0] = xStart;
									////
					////vector vBinEnd(1);
					////vBinEnd[0] = xEnd;
					////vBinStart.Append(vBinEnd);
					//vBins.SetSize(2);
					//vBins[0] = xStart;
					//vBins[1] = xEnd;
					/////End ------
					//
					//int nNumBins = vBins.GetSize()-1;  // minus 1 is needed
					//vMergedX.SetSize(nNumBins);
					//vMergedX[0] = xStart;
					//
					//ASSERT(vMergedX.GetSize() == nNumBins);
					//if(vMergedX.GetSize() != nNumBins)
					//return false;
				//}
				//break;
			//default: // Jack 01/04/2009 ADD_RFREQUENCY_METHOD
				//return false;
		//}
		//return true;
	//}
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
}
///End ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER

///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
//static bool get_sampling_data(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int ranseed)
static bool get_sampling_data(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, int ranseed)
///End NOT_SUPPORT_Use_Half_Interval_in_Border
{		
	vector vBins; 
	///Kyle 03/02/2009 MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
	//if(!construct_bins_vec_and_merged_x_vec(dSampleInterval, xStart, xEnd, nSubGrpMethod, bUseHalfIntervalinBorder, vBins, vMergedX))
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(!construct_bins_vec_and_merged_x_vec(dSampleInterval, xStart, xEnd, nSubGrpMethod, bUseHalfIntervalinBorder, xySamplingMethod, vBins, vMergedX))
	if(!construct_bins_vec_and_merged_x_vec(dSampleInterval, xStart, xEnd, nSubGrpMethod, xySamplingMethod, vBins, vMergedX))
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	///End MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
		return false;
	
	int nNumBins = vBins.GetSize()-1;

	int nOption;
	switch(xySamplingMethod)
	{
	case method_ymeanxbinc:
		nOption = REDUCE_XY_STATS_MEAN;
		break;
	case method_yranxbinc:
		nOption = REDUCE_XY_STATS_RANDOM;
		break;
	case method_yfirstxfirst:
		nOption = REDUCE_XY_STATS_FIRST;
		break;
	default:
		ASSERT(false);
		return false;
	}
	vMergedY.SetSize(vMergedX.GetSize());//vMergedY.SetSize(nNumBins); should be equivalent
	
	ASSERT(vX.GetSize() == vData.GetSize());

	reduce_xy_get_sampling_data(vX, vData, vX.GetSize(), REDUCE_XY_YINT_MISSING, vMergedY, vMergedX, nNumBins, vBins, vBins.GetSize(), lastinterwithxen, nOption, ranseed);
	return true;
}

/// Fisher 12/31/2008 QA80-12405 MOVE_TO_VC_LEVEL
//static int _get_subrange_of_XY_ex(const vector& vX, const vector& vY, vector& vSubY, int xStartIndex, int xEndIndex)
//{
	//if(xStartIndex > xEndIndex)
		//return SUB_RANGE_FAILED;
	//vY.GetSubVector(vSubY, xStartIndex, xEndIndex);
	//return SUB_RANGE_SUCCESS;
//}

// End REDUCE_DATA_XF_SPEED_ISSUE



///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
//static bool merge_by_sample_interval(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, const int includendx)
///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
//static bool merge_by_sample_interval(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen)
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//static bool merge_by_sample_interval(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder)
///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
//static bool merge_by_sample_interval(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int ranseed)
static bool merge_by_sample_interval(const vector& vX, const vector& vData, const double dSampleInterval, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, int ranseed)
///End NOT_SUPPORT_Use_Half_Interval_in_Border
///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
///End ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
///End SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
{

///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
//	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen, includendx))
///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
//	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen))
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder))
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder, ranseed))
/////End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
/////End	ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
/////End SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
		//return true;
	//else
		//return false;
	return get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, ranseed);
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	
}

///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
//static bool merge_by_nbins(const vector& vX, const vector& vData, int nBins, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, const int includendx)
///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
//static bool merge_by_nbins(const vector& vX, const vector& vData, int nBins, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen)
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//static bool merge_by_nbins(const vector& vX, const vector& vData, int nBins, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder)
///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
//static bool merge_by_nbins(const vector& vX, const vector& vData, int nBins, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int ranseed)
static bool merge_by_nbins(const vector& vX, const vector& vData, int nBins, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, int ranseed)
///End NOT_SUPPORT_Use_Half_Interval_in_Border
///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
///End ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
///End SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING	
{
	//if missing values, cases are excluded pairwise
//	if(!_trim_missing_values(vX,vData))  // no need as in get data from xyrange the missing value is already trimmed
//		return false;
	ASSERT(nBins>=1);

	///Kyle 03/02/2009 MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
	/*
	double dSampleInterval = (xEnd - xStart)/(double)(nBins); 

///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING		
//	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen, includendx))
///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
//if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen))
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder))
	if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder, ranseed))
///End	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
///End ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER	
///End SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING
		return true;
	else
		return false;
	*/
	if(nBins < 1)
		return false;
	vector vBins;
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(xySamplingMethod != method_yfirstxfirst && bUseHalfIntervalinBorder && nBins <= 2)
	//{
		//double dSampleInterval = (xEnd - xStart)/nBins;
		//vBins.Data(xStart, xEnd, dSampleInterval);
//
		//vMergedX.SetSize(nBins);
		//vMergedX[0] = xStart;
		//if(nBins > 1)
			//vMergedX[1] = xEnd;
	//}
	//else
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	{
		///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
		//double dSampleInterval;
		//if(xySamplingMethod == method_yfirstxfirst || !bUseHalfIntervalinBorder || nBins <= 2)		// all are whole bins
			//dSampleInterval = (xEnd - xStart)/nBins;
		//else
			//dSampleInterval = (xEnd - xStart)/(nBins-1);											// the first and the last one are half bins
		//if(!construct_bins_vec_and_merged_x_vec(dSampleInterval, xStart, xEnd, nSubGrpMethod, bUseHalfIntervalinBorder, xySamplingMethod, vBins, vMergedX))
		double dSampleInterval = (xEnd - xStart)/nBins;
		if(!construct_bins_vec_and_merged_x_vec(dSampleInterval, xStart, xEnd, nSubGrpMethod, xySamplingMethod, vBins, vMergedX))
		///End NOT_SUPPORT_Use_Half_Interval_in_Border
			return false;
	}
	
	int nNumBins = vBins.GetSize()-1;

	int nOption;
	switch(xySamplingMethod)
	{
	case method_ymeanxbinc:
		nOption = REDUCE_XY_STATS_MEAN;
		break;
	case method_yranxbinc:
		nOption = REDUCE_XY_STATS_RANDOM;
		break;
	case method_yfirstxfirst:
		nOption = REDUCE_XY_STATS_FIRST;
		break;
	default:
		ASSERT(false);
		return false;
	}
	vMergedY.SetSize(vMergedX.GetSize());//vMergedY.SetSize(nNumBins); should be equivalent

	ASSERT(vX.GetSize() == vData.GetSize());

	reduce_xy_get_sampling_data(vX, vData, vX.GetSize(), REDUCE_XY_YINT_MISSING, vMergedY, vMergedX, nNumBins, vBins, vBins.GetSize(), lastinterwithxen, nOption, ranseed);
	return true;	
	
	///End MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
}

///Jack 12/31/2008 ADD_RFACTOR_METHOD
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//static bool merge_by_ratio(const vector& vX, const vector& vY, double rfactor, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder)
static bool merge_by_ratio(const vector& vX, const vector& vY, double rfactor, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int ranseed)
///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
{
	//if missing values, cases are excluded pairwise
//	if(!_trim_missing_values(vX,vData))  // no need as in get data from xyrange the missing value is already trimmed
//		return false;
//	ASSERT(nBins>=1);

	
	int nDataSize = vX.GetSize();
	
	double dMin, dMax;
	vX.GetMinMax(dMin, dMax);
	
	int nBins = nDataSize/rfactor;
	if( nBins < 2)
	{
		return false;
	}
	double dSampleInterval = (dMax - dMin)/(double)(nBins);
//if (!merge_by_nbins(vX, vY, bins, start, end, method, yintmethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, halfinterbegin))
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//	if(merge_by_nbins(vX, vY, nBins, dMin, dMax, xySamplingMethod, yinterpmethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, bUseHalfIntervalinBorder))
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(merge_by_nbins(vX, vY, nBins, dMin, dMax, xySamplingMethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, bUseHalfIntervalinBorder, ranseed))
/////End	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
		//return true;
	//else
		//return false;
	return merge_by_nbins(vX, vY, nBins, dMin, dMax, xySamplingMethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, ranseed);
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	
}
///End ADD_RFACTOR_METHOD


///Jack 01/04/2009 ADD_RFREQUENCY_METHOD
///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
//static bool merge_by_frequency(const vector& vX, const vector& vData, const double rfre, const double xStart, const double xEnd, const int xySamplingMethod, const int yinterpmethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder)
///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
//static bool merge_by_frequency(const vector& vX, const vector& vData, const double rfre, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, bool bUseHalfIntervalinBorder, int ranseed)
static bool merge_by_frequency(const vector& vX, const vector& vData, const double rfre, const double xStart, const double xEnd, const int xySamplingMethod, vector& vMergedY, vector& vMergedX, const int lastinterwithxen, int nSubGrpMethod, int ranseed)
///End NOT_SUPPORT_Use_Half_Interval_in_Border
///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
{
	ASSERT(rfre>0);
	double dSampleInterval = 1/rfre;
	///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
	//if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, yinterpmethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder))
	///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
	//if(get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, bUseHalfIntervalinBorder, ranseed))
	/////End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
		//return true;
	//else
		//return false;
	return get_sampling_data(vX, vData, dSampleInterval, xStart, xEnd,  xySamplingMethod, vMergedY, vMergedX, lastinterwithxen, nSubGrpMethod, ranseed);
	///End NOT_SUPPORT_Use_Half_Interval_in_Border
	
}
///End ADD_RFREQUENCY_METHOD


#define STARTINEX 0
/// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
static bool skip_sampling(const vector& vx, const vector& vy, int nSize, vector& vSkippedY, vector& vSkippedX, const int everynpts, const int method, int iSeedNeg)
{
	vSkippedX.SetSize(nSize);
	vSkippedY.SetSize(nSize);
	int nRet = ocmath_skip_points_in_every_sampling_size(vx, vy, nSize, vSkippedX, vSkippedY, everynpts, STARTINEX, method, iSeedNeg);
	if(nRet<0)
		return false;
	
	int nSkippedSize = nRet;
	vSkippedX.SetSize(nSkippedSize);
	vSkippedY.SetSize(nSkippedSize);
	return true;
	
}
/// End	SKIP_POINTS_IN_VECTOR

static bool _is_bin_center_method(TreeNode& trGetN)
{
	return ( (trGetN.method.nVal== method_ymeanxbinc)|| (trGetN.method.nVal== method_yranxbinc) );
}

static void _update_method_show(TreeNode& trGetN)
{
	trGetN.inputsampinterhint.Show = trGetN.hint.Show = _need_show_sampling_interval_hint(trGetN);
	//trGetN.halfinterbegin.Enable = trGetN.method.nVal != method_yfirstxfirst;				///Kyle 03/02/2009 MERGED_X_VEC_SHOULD_BE_CONSTRUCTED_BASED_ON_XY_SAMPLING_METHOD
	

	switch(trGetN.subgroup.nVal)
	{
	case subgroup_inter: // sample interval
		trGetN.dx.Show = true;
		trGetN.method.Show = true;		
		trGetN.start.Show = true;
		trGetN.end.Show = true;
		trGetN.bins.Show = false;
		trGetN.rfactor.Show = false; ///Jack 12/31/2008 ADD_RFACTOR_METHOD
		trGetN.rfre.Show = false; /// Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
		///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.ranseed.Show = (trGetN.method.nVal== method_yranxbinc);
		///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.halfinterbegin.Show = true;
		trGetN.variation.Show = false;
		trGetN.interp.Show = false;
		break;
	case subgroup_bins: // bin number
		trGetN.bins.Show = true;
		trGetN.method.Show = true;
		trGetN.start.Show = true;
		trGetN.end.Show = true;
		trGetN.dx.Show = false;
		trGetN.rfactor.Show = false; ///Jack 12/31/2008 ADD_RFACTOR_METHOD
		trGetN.rfre.Show = false; /// Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
		///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.ranseed.Show = (trGetN.method.nVal== method_yranxbinc);
		///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.halfinterbegin.Show = true;
		trGetN.variation.Show = false;
		trGetN.interp.Show = false;
		break;

	case subgroup_ratio:
		trGetN.bins.Show = false;
		trGetN.method.Show = true;
		trGetN.start.Show = false;
		trGetN.end.Show = false;
		trGetN.dx.Show = false;
		trGetN.rfactor.Show = true; 
		trGetN.rfre.Show = false;
		///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.ranseed.Show = (trGetN.method.nVal== method_yranxbinc);
		///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.halfinterbegin.Show = true;
		///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		//trGetN.variation.Show = !_is_even_sampling(trGetN, true);
		//trGetN.interp.Show = trGetN.variation.Show && !_is_even_sampling(trGetN, false);
		trGetN.variation.Show = true;
		///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		break;

	case subgroup_freq:
		trGetN.bins.Show = false;
		trGetN.method.Show = true;
		trGetN.start.Show = true;
		trGetN.end.Show = true;
		trGetN.dx.Show = false;
		trGetN.rfactor.Show = false; 
		trGetN.rfre.Show = true;
		///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.ranseed.Show = (trGetN.method.nVal== method_yranxbinc);
		///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		//trGetN.halfinterbegin.Show = true;
		trGetN.variation.Show = false;
		trGetN.interp.Show = false;
		break;
	}
}

///Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
static void _update_sampling_interval_label(TreeNode& trGetN)
{
	if(!trGetN.hint.Show && !trGetN.inputsampinterhint.Show)
		return;

	string strUnits;
	XYRange xyRange;
	xy_range_from_GetN_data_node(trGetN.iy, xyRange);
	Column col;
	xyRange.GetXColumn(col);
	if(col.IsValid())
		strUnits = col.GetUnits();
	else
	{
		xyRange.GetYColumn(col);
		if(col)
			col.IsEvenSampling(NULL, NULL, &strUnits)
	}
	double dSeconds = _transform_units_to_seconds(strUnits);
	
	double rate, dSamplingInterval;
	dSamplingInterval = NANUM;
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	//double srcinterset = trGetN.srcsampinterval.dVal;
	double srcinterset;
	_is_even_sampling(trGetN, &srcinterset);
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	ASSERT(srcinterset != NANUM);

	
	switch(trGetN.subgroup.nVal)
	{
	case subgroup_inter: // sample interval
		dSamplingInterval = trGetN.dx.dVal;
		break;
		break;
	case subgroup_bins:
		double start = trGetN.start.dVal;
		double end = trGetN.end.dVal;
		int bins = trGetN.bins.nVal;
		dSamplingInterval = (end-start)/(double)(bins);
		break;
	case subgroup_ratio:
		///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		//dSamplingInterval = trGetN.rfactor.nVal*abs(trGetN.srcsampinterval.dVal); // always use positive input interval or sampling rate for showing		break;
		dSamplingInterval = trGetN.rfactor.nVal*abs(srcinterset);
		///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		break;
	case subgroup_freq:
		dSamplingInterval = 1/trGetN.rfre.dVal;
		break;
	//case subgroup_skip:
		//dSamplingInterval = trGetN.everynpts.nVal*trGetN.srcsampinterval.dVal;
	break;
	/// End SKIP_POINTS_IN_VECTOR
		
	}

	
	if(dSamplingInterval>0.0)
	{
		rate = 1/dSamplingInterval;
		if(dSeconds > 0)
			rate /= dSeconds;
	}
	///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	//double inputSamplingInterval = trGetN.srcsampinterval.dVal;
	double inputSamplingInterval = srcinterset;
	///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
	
	double temp = inputSamplingInterval;
	inputSamplingInterval = abs(temp); // always use positive input interval or sampling rate for showing
	double inputRate;
	if(inputSamplingInterval>0.0)
	{
		inputRate = 1/inputSamplingInterval;
		if(dSeconds > 0)
			inputRate /= dSeconds;
	}
	string strSrcHint = _L("Input Sampling Interval") + ": " + ftoa(inputSamplingInterval,"*");
	string strNewHint = _L("New Sampling Interval") + ": " + ftoa(dSamplingInterval,"*");
	if(dSeconds > 0)
	{
		strSrcHint += strUnits;
		strNewHint += strUnits;
		
		strSrcHint += ", or rate " + ftoa(inputRate, "E*") + "Hz";
		strNewHint += ", or rate " + ftoa(rate, "E*") + "Hz";
	}
	if(trGetN.hint.Show)
		trGetN.hint.SetAttribute(STR_LABEL_ATTRIB, strNewHint);
	if(trGetN.inputsampinterhint.Show)
		trGetN.inputsampinterhint.SetAttribute(STR_LABEL_ATTRIB, strSrcHint);
}
///End ADD_SAMPLING_RATE_HINT_LABEL

///Kyle 10/21/2009 USE_GENERAL_CODE_TO_SET_XYRANGE_DATA
/*
static bool _reducexy_set_data_range(XYRange& oy, const vector *pVMergeX, const vector *pVMergeY)
{
	ASSERT(oy.IsValid() && pVMergeX!=NULL || pVMergeY!=NULL);
	if(!oy.IsValid() || pVMergeX==NULL || pVMergeY==NULL)
		return false;
	oy.SetData(pVMergeY,pVMergeX,  0, NULL, DRS_SET_COL_DESIGNATIONS);
	return true;
}
*/
///End USE_GENERAL_CODE_TO_SET_XYRANGE_DATA

/// TD 12-15-2008 QA80-12786  DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
static void _update_dataformat_start_end_interval(TreeNode& trGetN)
{
	///------ Folger 02/09/09 QA80-12786 DATE_TIME_FORMAT_SUPPORT_IN_XF_GETN
	//int nColFormat = get_col_data_format(trGetN.iy);
	//set_node_appropriate_numeric_format(trGetN.start, nColFormat);
	//set_node_appropriate_numeric_format(trGetN.end, nColFormat);
	//set_node_appropriate_numeric_format(trGetN.dx, nColFormat, TRUE);

	update_dataformat_start_end_interval(trGetN.iy, trGetN, "start", "end", "dx");
	///------ End DATE_TIME_FORMAT_SUPPORT_IN_XF_GETN
}
/// end DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS

static bool update_xstartend_show(TreeNode& trGetN)
{
	TreeNode trxmin = trGetN.start;
	TreeNode trxmax = trGetN.end;
	bool bAutoXmin = octree_get_auto_support(&trxmin)==1?true:false;
	bool bAutoXmax = octree_get_auto_support(&trxmax)==1?true:false;

	//----------- CPY 4/11/07 QA70-9562 BETTER_NOT_ASSUME_YI_AS_INPUT_DATA_NODE
	//double dxMin, dxMax
	double dxMin = 0.1, dxMax = 4.9;// some special value to indicate we dont have the yi node and also I can use these for my QA70-9562 testing
	bool bRet = true;
	//-----------
	if(bAutoXmin || bAutoXmax)
	{
		if(!get_data_x_scale(trGetN, dxMin, dxMax))
			bRet = false;
		if(bAutoXmin)
			trGetN.start.dVal = dxMin;
		if(bAutoXmax)
			trGetN.end.dVal = dxMax;
	}
	return bRet;
}

static int _get_input_xyrange_data_size_within_min_max(TreeNode& iy, double dMin, double dMax)
{
	XYRange xyTemp;
	bool bOK = xy_range_from_GetN_data_node(iy, xyTemp);
	if(bOK && xyTemp.IsValid())
	{
		vector vx, vy;
		if(xyTemp.GetData(vy, vx, NULL, 0, 0))
		{
			vector<uint> vecIndex;
			return vx.Find(vecIndex, dMin, dMax);
		}
		return -1;
	}
	return -1;
}

static void _update_auto_settings(TreeNode& trGetN)
{
	if(trGetN.subgroup.nVal == subgroup_inter || trGetN.subgroup.nVal == subgroup_bins || trGetN.subgroup.nVal == subgroup_freq)
		update_xstartend_show(trGetN); // auto intilized start end

	//int nSize =  get_input_xyrange_data_size(trGetN.iy);
	double dxStart = trGetN.start.dVal, dxEnd = trGetN.end.dVal;
	double dxMin, dxMax;
	if(get_data_x_scale(trGetN, dxMin, dxMax))
	{
		if(dxStart < dxMin)
			dxStart = dxMin;
		if(dxEnd > dxMax)
			dxEnd = dxMax;
	}
	int nASize = _get_input_xyrange_data_size_within_min_max(trGetN.iy, dxStart, dxEnd);
	switch(trGetN.subgroup.nVal)
	{
	case subgroup_ratio:
		TreeNode trFactor = trGetN.rfactor;
		if(1==octree_get_auto_support(&trFactor))
		{
			trFactor.nVal = 5;
		}
		break;
		
	case subgroup_inter:
		TreeNode trInterval = trGetN.dx;
		if(1==octree_get_auto_support(&trInterval))
		{
			//trInterval.dVal = (trGetN.end.dVal-trGetN.start.dVal) / nSize * 5;
			trInterval.dVal = (dxEnd-dxStart) / nASize * 5;
		}
		break;
		
	case subgroup_bins:
		TreeNode trBins = trGetN.bins;
		if(1==octree_get_auto_support(&trBins))
		{
			//trBins.nVal = nSize / 5;
			trBins.nVal = nASize / 5;
		}
		break;
		
	case subgroup_freq:
		TreeNode trFre = trGetN.rfre;
		if(1==octree_get_auto_support(&trFre))
		{
			ASSERT(trGetN.end.dVal != trGetN.start.dVal);
			//trFre.dVal = nSize * 0.2 / (trGetN.end.dVal-trGetN.start.dVal);
			trFre.dVal = nASize * 0.2 / (dxEnd-dxStart);
		}
		break;
	}
}

enum
{
	SORTED_ASEENDING=0,
	NOT_SORTED_KEEP_OLD=-1,
};

static bool _is_monotonic(const TreeNode& trGetN) // this is for both column x and y are present in xyrange
{
	XYRange xyRange;
	if(!xy_range_from_GetN_data_node(trGetN.iy, xyRange) || !xyRange.IsValid())
		return false;

	vector vx, vy;

	if(!xyRange.GetData(vy, vx) || MONO_NOT== ocmath_is_monotonic(vx, vx.GetSize(), false) )
		return false;

	return true;
}

static int set_as_monotonic_increase(vector& vx, vector& vy, int nSize, bool bSortDataAscendingFirst = true)
{
	if (bSortDataAscendingFirst)
	{
		vector<uint> vi;
		vx.Sort(SORT_ASCENDING, TRUE, vi);
		vy.Reorder(vi);	
		return SORTED_ASEENDING;
	}
	return NOT_SORTED_KEEP_OLD;
}
///End REDUCE_DATA_XF


	
///Kyle 12/22/2008 OUTPUT_COLUMN_COMMENTS
/// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
//static	void	_set_output_range_comments(XYRange &oy, const XYRange& iy, int nMethod)
static	void	_set_output_range_comments(XYRange &oy, const XYRange& iy, int nMethod)
/// End SKIP_POINTS_IN_VECTOR
{
	string strMethod;

	switch(nMethod)
	{
	case method_yfirstxfirst:
		strMethod = "Y First(X First)";
		break;
	
	case method_ymeanxbinc:
		strMethod = "Y Mean(X Average)";
		break;
	case method_yranxbinc:
		strMethod = "Y Random(X Average)";
		break;
	}
	
	string strComments;
	strComments.Format(_L("%s Stats Reduction of %s"), _L(strMethod), get_input_data_range_string(iy));
	


	if(oy != NULL && oy.IsValid())
		oy.SetOutputComment(strComments);
}
///End OUTPUT_COLUMN_COMMENTS

static	void	_update_min_max(vector &vx, const double& start, const double& end, double &dMin, double &dMax)
{
	vx.GetMinMax(dMin, dMax);
	if(end < dMax)
		dMax = end;
	if(start > dMin)
		dMin = start;
	ASSERT(dMin < dMax);
}


void reduce_ex(const XYRange& iy, const int& subgroup, const double& dx, const int& bins, const int& rfactor, const double& rfre, string& inputsampinterhint, string& hint, const double& start, const double& end, const int& method, const double& variation, const int& ranseed, const int& plot, XYRange& oy)
{
	DWORD dwRules = DRR_NO_WEIGHTS | DRR_GET_DEPENDENT | DRR_NO_FACTORS;
	int nNumRanges = iy.GetNumData(dwRules);
	if (nNumRanges < 1)
		XF_THROW(XFERR_AT_LEAST_ONE_XYRANGE);
	
	double dMax, dMin;
	
	vector vX, vY, vMergedX, vMergedY;
	for( int ii = 0; ii < nNumRanges; ii++ )
	{
		
		iy.GetData(vY, vX, NULL,  ii);  //// note that all the missing value will be trimmed in getting this data
		if(0 == vY.GetSize() || 0 == vX.GetSize())
		{
			XF_THROW(CER_NO_DATA);
		}
	
		switch(subgroup)
		{
			//if defined dx>0  and start and end
			case subgroup_inter:
				ASSERT(dx>0);				
				set_as_monotonic_increase(vX, vY, vY.GetSize());
				_update_min_max(vX, start, end, dMin, dMax);
				
				///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING
				//if (!merge_by_sample_interval(vX, vY, dx, start, end, method, yintmethod, vMergedY, vMergedX, lastinterwithxen, includendx))
				///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
				//if (!merge_by_sample_interval(vX, vY, dx, start, end, method, yintmethod, vMergedY, vMergedX, lastinterwithxen))
				///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				//if (!merge_by_sample_interval(vX, vY, dx, start, end, method, yintmethod, vMergedY, vMergedX, lastinterwithxen, subgroup_inter, halfinterbegin))
				///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
				//if (!merge_by_sample_interval(vX, vY, dx, start, end, method, vMergedY, vMergedX, false, subgroup_inter, halfinterbegin, ranseed))
				if (!merge_by_sample_interval(vX, vY, dx, dMin, dMax, method, vMergedY, vMergedX, false, subgroup_inter, ranseed))
				///End NOT_SUPPORT_Use_Half_Interval_in_Border
				///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				///End ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
				///End	SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING
				{
					XF_THROW(XF_REDUCE_BIN_INTERVAL);
				}
				break;
			///if define nBin   and nBin >0	use second method				
			case subgroup_bins:
				ASSERT(bins>0);
				set_as_monotonic_increase(vX, vY, vY.GetSize());
				_update_min_max(vX, start, end, dMin, dMax);
				///Jack	12/24/2008 SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING
				//if (!merge_by_nbins(vX, vY, bins, start, end, method, yintmethod, vMergedY, vMergedX,lastinterwithxen, includendx))
				///Jack 12/31/2008 ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
				//if (!merge_by_nbins(vX, vY, bins, start, end, method, yintmethod, vMergedY, vMergedX,lastinterwithxen))
				///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				//if (!merge_by_nbins(vX, vY, bins, start, end, method, yintmethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, halfinterbegin))
				///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
				//if (!merge_by_nbins(vX, vY, bins, start, end, method, vMergedY, vMergedX, false, subgroup_bins, halfinterbegin, ranseed))
				if (!merge_by_nbins(vX, vY, bins, dMin, dMax, method, vMergedY, vMergedX, false, subgroup_bins, ranseed))
				///End NOT_SUPPORT_Use_Half_Interval_in_Border
				///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				/// ADD_OPTION_FOR_BIN_BEGIN_USING_HALF_INTERVAL_IN_BORDER
				///End SEPARATE_XF_RESAMPLE_FROM_AVE_RESAMPLING
				{
					XF_THROW(XF_REDUCE_BIN);
				}
				break;
			///Jack 12/31/2008 ADD_RFACTOR_METHOD
			case subgroup_ratio:
				///Kyle 06/25/2009 DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
				//if( srcsampinterval == NANUM) // initilize srcsampinterval if it is NANUM namely failed to estimate  in original
				//{
					//double percentvariation = variation/100.0;
					//int nErrCode = ocmath_sampling_resolution(vX.GetSize(), vX, &srcsampinterval, percentvariation);
					//if( nErrCode != OE_NOERROR && nErrCode != OE_NOT_SPACED_EQUALLY )
						//XF_THROW("Failed to get sampling interval");
			//
					//if(interp)
				 	//{
				 		//int nSize = vY.GetSize();
						//vector vInterpequalSpacedX(nSize);
						//if( OE_NOERROR != ocmath_create_equal_spaced_vec(vInterpequalSpacedX, nSize, vX[0], srcsampinterval) )
						//{
							//XF_THROW("Failed to Create Even Spaced Data check input data properly");
						//}
						//
						//vector vInterpequalSpacedY(nSize);
						//if( OE_NOERROR!= ocmath_interpolate(vInterpequalSpacedX, vInterpequalSpacedY, nSize, vX, vY, nSize) )
						//{
							//XF_THROW("Failed to interpolate");
						//}
						//vX = vInterpequalSpacedX;
						//vY = vInterpequalSpacedY;
				 	//}
				 	//else
				 	//{
				 		//XF_THROW("Input Data is no even sampling");
				 	//}
				//}
				double dInterval;
				double percentvariation = variation/100.0;
				int nErrCode = ocmath_sampling_resolution(vX.GetSize(), vX, &dInterval, percentvariation);
				if( nErrCode != OE_NOERROR )
			 	{
			 		int nSize = vY.GetSize();
					vector vInterpequalSpacedX(nSize);
					if( OE_NOERROR != ocmath_create_equal_spaced_vec(vInterpequalSpacedX, nSize, vX[0], dInterval) )
					{
						XF_THROW("Failed to Create Even Spaced Data check input data properly");
					}
					
					vector vInterpequalSpacedY(nSize);
					if( OE_NOERROR!= ocmath_interpolate(vInterpequalSpacedX, vInterpequalSpacedY, nSize, vX, vY, nSize) )
					{
						XF_THROW("Failed to interpolate");
					}
					vX = vInterpequalSpacedX;
					vY = vInterpequalSpacedY;
			 	}
				///End DO_INTERP_IF_DATA_IS_NOT_EVEN_SPACE_IN_THE_GIVEN_VARIATION
		
				if( !skip_sampling(vX, vY, vY.GetSize(), vMergedY, vMergedX, rfactor, method, ranseed) )
				{
					XF_THROW("Failed to resampling by skip data points method. check option setting or data"); // todo:
				}
				///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
				//if(halfinterbegin && (method==method_ymeanxbinc || method==method_yranxbinc) )
				//{
					//vMergedX = vMergedX - 0.5*(rfactor-1)*srcsampinterval;
					/////Kyle 02/27/2009
					//if(vMergedX.GetSize() && vX.GetSize())
						//vMergedX[0] = vX[0];
					/////End ---
				//}
				///End NOT_SUPPORT_Use_Half_Interval_in_Border
				break;
	
				//ASSERT(rfactor>0);
				//set_as_monotonic_increase(vX, vY, vY.GetSize());
				/////Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				////if (!merge_by_ratio(vX, vY, rfactor, method, yintmethod, vMergedY, vMergedX,lastinterwithxen, subgroup_bins, halfinterbegin)) // note that subgroup_bins is used,  can use subgroup variable if construct_bins_vec_and_merged_x_vec properly handled
				//if (!merge_by_ratio(vX, vY, rfactor, method, vMergedY, vMergedX, false, subgroup_bins, halfinterbegin, ranseed)) // note that subgroup_bins is used,  can use subgroup variable if construct_bins_vec_and_merged_x_vec properly handled
				/////End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				//{
					//XF_THROW(XF_REDUCE_BIN);
				//}
				//break;
			///End ADD_RFACTOR_METHOD
			///Jack 01/04/2009 ADD_RFREQUENCY_METHOD
			case subgroup_freq:
				ASSERT(rfre>0);
				set_as_monotonic_increase(vX, vY, vY.GetSize());
				_update_min_max(vX, start, end, dMin, dMax);
				///Jack 01/06/2009	ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				//if (!merge_by_frequency(vX, vY, rfre, start, end, method, yintmethod, vMergedY, vMergedX, lastinterwithxen, subgroup_inter, halfinterbegin)) // note that subgroup_inter is used ,  can use subgroup variable if construct_bins_vec_and_merged_x_vec properly handled
				///Kyle 05/26/2009 NOT_SUPPORT_Use_Half_Interval_in_Border
				//if (!merge_by_frequency(vX, vY, rfre, start, end, method, vMergedY, vMergedX, false, subgroup_inter, halfinterbegin, ranseed)) // note that subgroup_inter is used ,  can use subgroup variable if construct_bins_vec_and_merged_x_vec properly handled
				if (!merge_by_frequency(vX, vY, rfre, dMin, dMax, method, vMergedY, vMergedX, false, subgroup_inter, ranseed)) // note that subgroup_inter is used ,  can use subgroup variable if construct_bins_vec_and_merged_x_vec properly handled
				///End NOT_SUPPORT_Use_Half_Interval_in_Border
				///End ADD_RANDOM_GENERATOR_SEED_SETTING_OPTION
				{
					XF_THROW(XF_REDUCE_FRE_METHOD_FAIL); // todo: XF_REDUCE_FRE_METHOD_FAIL Fail to resample or reduce data by frequency method
				}
				break;
			///End ADD_RFREQUENCY_METHOD
			
			///// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
			//case subgroup_skip:
				//if( !skip_sampling(vX, vY, vY.GetSize(), vMergedY, vMergedX, everynpts, method, ranseed) )
				//{
					//XF_THROW("Failed to resampling by skip data points method. check option setting or data"); // todo:
				//}
				//if(halfinterbegin && (method==method_ymeanxbinc || method==method_yranxbinc) )
				//{
					//vMergedX = vMergedX - 0.5*(rfactor-1)*srcsampinterval;
				//}
	//
			/////End SKIP_POINTS_IN_VECTOR
			//
		}
		/// End REDUCE_DATA_XF
		
		if(!oy)  // if not specified an output range, create one for it
		{
			Worksheet wks;
			wks.Create();
			wks.SetSize(-1, 2);
			oy.Create();
			xy_range_from_wks_cols(oy,wks,0,1);
		}
		///Kyle 10/21/2009 USE_GENERAL_CODE_TO_SET_XYRANGE_DATA
		//_reducexy_set_data_range(oy,&vMergedX, &vMergedY);
		set_xyrange_data_ex(oy, &vMergedY, &vMergedX, 0, iy, NULL, SXYDC_RECALCULATE_SAMPLING_INTERVAL);
		///End USE_GENERAL_CODE_TO_SET_XYRANGE_DATA
		//_reducexy_update_report_data(rd, vMergedX, vMergedY);
		
		//else
		// supply each yStatsChecked to yStats for each check box to 
		// use vTempMergedX
		// append to vector  and set to range
		
		///Kyle 12/04/2008 ADD_PLOT_TO_GRAPH_IF_FROM_GRAPH
		xf_check_plot_output_rng_in_source_rng_graph(iy, oy);
		///End ADD_PLOT_TO_GRAPH_IF_FROM_GRAPH
		///Kyle 12/22/2008 OUTPUT_COLUMN_COMMENTS
		/// Jack 01/07/2008 SKIP_POINTS_IN_VECTOR
		//_set_output_range_comments(oy, iy, method);
		_set_output_range_comments(oy, iy, method);
		/// End SKIP_POINTS_IN_VECTOR
		///End OUTPUT_COLUMN_COMMENTS
	}	
	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int reduce_ex_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return reduce_ex_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	return false;

}

int reduce_ex_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void reduce_ex_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW
	/// Folger 12/10/08 v8.0984d, auto update should be skipped here
	//if(is_xf_startup(nGetNDialog, dwCntrl))
	///Kyle 10/09/2009 QA80-14127-P15 SHOULD_NOT_SKIP_AUTO_UPDATE
	//if(is_xf_startup(nGetNDialog, dwCntrl, true))
	if(is_xf_startup(nGetNDialog, dwCntrl))
	///End SHOULD_NOT_SKIP_AUTO_UPDATE
	{
		///Kyle 07/14/2009 USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		TreeNode trRanseed = trGetN.ranseed;
		if(1==octree_get_auto_support(&trRanseed))
		{
			///Kyle 07/30/2009 ALWAYS_PASS_NEGATIVE_NUMBER_AS_RANDOM_SEED
			//trRanseed.nVal = GetTickCount();
			trRanseed.nVal = -GetTickCount();
			///End ALWAYS_PASS_NEGATIVE_NUMBER_AS_RANDOM_SEED
		}
		///Kyle 07/30/2009 ALWAYS_PASS_NEGATIVE_NUMBER_AS_RANDOM_SEED
		else if(trRanseed.nVal > 0)
			trRanseed.nVal = -trRanseed.nVal;
		///End ALWAYS_PASS_NEGATIVE_NUMBER_AS_RANDOM_SEED
		///End USE_TIME_AS_AUTO_RANDOM_Y_GENERATOR_SEED
		///Kyle 12/10/2008 SHOULD_CHECK_IF_AUTO_WHILD_SET_START_END_VALUE
		//double dxMin, dxMax;
		//if(get_data_x_scale(trGetN, dxMin, dxMax))
		//{
			//trGetN.start.dVal = dxMin;
			//trGetN.end.dVal = dxMax;
		//}
		///Kyle 07/03/2009 ADD_AUTO_SETTINGS
		//update_xstartend_show(trGetN);
		_update_auto_settings(trGetN);
		///End ADD_AUTO_SETTINGS
		///End SHOULD_CHECK_IF_AUTO_WHILD_SET_START_END_VALUE
		_update_method_show(trGetN); /// for showing different setting for different reduce method (or group method)
		
		
	
	
		///Kyle 12/22/2008 OPEN_DIALOG_WHEN_THEME_IS_USED_AND_ERROR_HAPPENS
		if ( (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0 )
		{
			string strErrMsg;
			if(!_check_input(trGetN, strErrMsg))
				nRet = XFEVT_PROCEED_WITH_DLG;
		}
		///End OPEN_DIALOG_WHEN_THEME_IS_USED_AND_ERROR_HAPPENS
		
		///Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
		_update_sampling_interval_label(trGetN);
		///End ADD_SAMPLING_RATE_HINT_LABEL
		
	}
	///End UPDATE_XF_TO_SHOW_PREVIEW
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int reduce_ex_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}


// put your grid initialization here
// you may also initialize wksTemp here
static void GetNGraphPreview_OnInitGrid(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF, as requested in OnDialogSetup 
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid, // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID
	///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW
	_update_method_show(trGetN); /// for showing different setting for different reduce method (or group method)
	
	
	/// TD 12-15-2008 QA80-12786  DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
	///Jack 01/04/2009 ADD_RFREQUENCY_METHOD
	//if((trGetN.subgroup.nVal == subgroup_inter) || (trGetN.subgroup.nVal == subgroup_bins))
	///------ Folger 02/09/09 QA80-12786 DATE_TIME_FORMAT_SUPPORT_IN_XF_GETN
	//if((trGetN.subgroup.nVal == subgroup_inter) || (trGetN.subgroup.nVal == subgroup_bins) || (trGetN.subgroup.nVal == subgroup_freq))
	///------ End DATE_TIME_FORMAT_SUPPORT_IN_XF_GETN
	///End ADD_RFREQUENCY_METHOD
		_update_dataformat_start_end_interval(trGetN);
	/// end DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
	bOKEnable = _check_input(trGetN, strErrMsg);

	///Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
	_update_sampling_interval_label(trGetN);
	///End ADD_SAMPLING_RATE_HINT_LABEL

	
	//if(bOKEnable)			///Kyle 10/22/2009 SHOULD_ALWAYS_INIT_THE_TEMP_WKS
	{
		Worksheet wks = wksTemp;
		///Kyle 07/03/2009 ADD_FFT_PREVIEW
		//wks.SetSize(-1, 2);
		//wks.SetColDesignations("XY");
		//wks.Columns(1).SetLongName("ReSampled");
		wks.SetSize(-1, 6);
		wks.SetColDesignations("XYXYXY");
		wks.Columns(1).SetLongName(_L("Reduced"));
		/// Iris 10/20/2009 ADD_FFT_PREVIEW_FOR_DECIMATE_XF
		/*
		wks.Columns(3).SetLongName("spectrum1");
		wks.Columns(5).SetLongName("spectrum2");
		*/
		wks.Columns(3).SetComments(_L("Input")); // display for plot legend
		wks.Columns(5).SetComments(_L("Output"));// display for plot legend
		wks.Columns(2).SetLongName(_L("Frequency")); // display for X Axis title
		wks.Columns(3).SetLongName(_L("FFT Amplitude")); // display for Y Axis title
		///end ADD_FFT_PREVIEW_FOR_DECIMATE_XF
		///End ADD_FFT_PREVIEW

	}
	s_bInit = false;
	s_strErrMsg = strErrMsg;
	bUpdateGraph = bOKEnable;
	bUpdateGrid = true;
	///End UPDATE_XF_TO_SHOW_PREVIEW
}

///////////////////////////////////////////////////////

// pgTemp is the graph for preview or control
// wksTemp is the the temp wks created to hold data to plot into pgTemp
static void GetNGraphPreview_OnInitGraph(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF, as requested in OnDialogSetup  
DWORD& dwUpdateGrid, // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRID
	///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW
	strErrMsg = s_strErrMsg;
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//GraphPage gp = pgTemp;
	//page_load(gp, "NonePreview");
	//load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
	xf_load_nopreview(pgTemp);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	///End UPDATE_XF_TO_SHOW_PREVIEW
}

///////////////////////////////////////////////////////

static void GetNGraphPreview_OnUpdateGraph(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{
	///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW
	Worksheet wks = wksTemp;
	if(!s_bInit)
	{
		Worksheet wks = wksTemp;
		wks.SetSize(0,-1, true);
		//---- CPY 12/19/08 USE_SHARED_TEMPLATE_FOR_ALL_PREVIEW_XF
		//init_preview_graph(trGetN.iy, pgTemp, wks, "resampleline");
		///Kyle 06/03/2009 GET_SOURCE_GRAPH_SCALE_TYPE
		//init_preview_graph(trGetN.iy, pgTemp, wks, "CurvePreview");
		init_preview_graph(trGetN.iy, pgTemp, wks, "CurvePreview", NULL, NULL, 0, 0, 1, PREVIEW_LAYER_FORMAT_SCALE_TYPE);
		///End GET_SOURCE_GRAPH_SCALE_TYPE

		//----
		GraphPage gp = pgTemp;
		gp.Refresh(true);
		s_bInit = true;
	}
	_run_resample_on_current_data(trGetN, pgTemp, wks);
	///End UPDATE_XF_TO_SHOW_PREVIEW
}

///////////////////////////////////////////////////////

static void GetNGraphPreview_OnChange(TreeNode& trGetN, TreeNode& trNode, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF that might be present, as requested in OnDialogSetup  
bool bChangedByGraph, // called when graph has been modified by user, like dragging a vertical line
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid,  // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,	// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID
	//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
	//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
	//strErrMsg = allowing messages to be shown
	///Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW, centralize code to _check_input
	//int nErr = CER_NO_ERROR;
	//int nSize =  get_input_xyrange_data_size(trGetN.iy);
	//if(get_input_xyrange_num(trGetN.iy) < 1)
		//nErr = XFERR_AT_LEAST_ONE_XYRANGE;
	//else if(0 >= nSize)
		//nErr = CER_NO_DATA;
	////	else if (trGetN.dx.nVal > nSize)
	////		nErr = XF_REDUCE_DX;
	//
	//
	//
	///// Jack 21/10/2008 QA80-12405 REDUCE_DATA_XF
	//_update_method_show(trGetN); /// for showing different setting for different reduce method (or group method)
	//double dxMin, dxMax;
	//get_data_x_scale(trGetN, dxMin, dxMax);
	//
	//
	//if(trGetN.subgroup.nVal == subgroup_inter) // by sample interval
	//{
		//update_xstartend_show(trGetN); // auto intilized start end
	////		update_sample_dx(trGetN, dxMin, dxMax, nSize); //auto intilize sample interval
		 //
	//}
	//
	//if(trGetN.subgroup.nVal == subgroup_bins)
	//{
		//update_xstartend_show(trGetN); // auto intilized start end
	////		update_binnum(trGetN, nSize);
	//}
	/////Kyle 12/02/2008 QA80-12405-S1 UPDATE_XF_TO_SHOW_PREVIEW, to check start & end
	//if(trGetN.subgroup.nVal != subgroup_ratio && trGetN.start.dVal > trGetN.end.dVal )
	//{
		//bOKEnable = false;
		//strErrMsg = XF_REDUCE_START_END_ERROR;
	//}
	/////End UPDATE_XF_TO_SHOW_PREVIEW
	//
	///*
	//if(trGetN.subgroup.nVal == subgroup_ratio)
	//{
		//update_ratio(trGetN); // auto intilized start end
	//}
	//*/
	///// End REDUCE_DATA_XF
	//
	//
	//
	///// Jack 21/10/2008 QA80-12405 REDUCE_DATA_XF
	//if(trGetN.dx.dVal>(dxMax-dxMin) && trGetN.subgroup.nVal == subgroup_inter)
	//{
		//bOKEnable = false;
		//strErrMsg = XF_REDUCE_BIN_TOO_LARGE;  /// 
	//}
	//
	//if(trGetN.bins.nVal<2 && trGetN.subgroup.nVal == subgroup_bins)
	//{
		//bOKEnable = false;
		//strErrMsg = XF_REDUCE_BIN_NUM_TOO_SMALL;  /// "Too Small bin numbers"
	//}
	//
	//if(trGetN.rfactor.nVal<0 && trGetN.subgroup.nVal == subgroup_ratio)
	//{
		//bOKEnable = false;
		//strErrMsg = XF_REDUCE_FACTOR;  /// "Improper reduction factor. Reset it properly"  to do:
	//}
	/////End REDUCE_DATA_XF
	//
	//if(nErr != CER_NO_ERROR)
	//{
		//bOKEnable = false;
		//strErrMsg = nErr;
	//}
	
	_update_method_show(trGetN); /// for showing different setting for different reduce method (or group method)
	///Kyle 07/03/2009 ADD_AUTO_SETTINGS
	//if(trGetN.subgroup.nVal == subgroup_inter) // by sample interval
	//{
		//update_xstartend_show(trGetN); // auto intilized start end
	//}
	//if(trGetN.subgroup.nVal == subgroup_bins)
	//{
		//update_xstartend_show(trGetN); // auto intilized start end
	//}
	//
	/////Jack 01/04/2009 ADD_RFREQUENCY_METHOD
	//if(trGetN.subgroup.nVal == subgroup_freq)
	//{
		//update_xstartend_show(trGetN); // auto intilized start end
	//}
	_update_auto_settings(trGetN);
	///End ADD_RFREQUENCY_METHOD
	
	/// TD 12-15-2008 QA80-12786  DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
	///Jack 01/04/2009 ADD_RFREQUENCY_METHOD
	//if(trNode && (trNode.tagName =="iy") && ((trGetN.subgroup.nVal == subgroup_inter) || (trGetN.subgroup.nVal == subgroup_bins)))
	if(trNode && (trNode.tagName =="iy") && ((trGetN.subgroup.nVal == subgroup_inter) || (trGetN.subgroup.nVal == subgroup_bins) ||(trGetN.subgroup.nVal == subgroup_freq)))
	///End	ADD_RFREQUENCY_METHOD
		_update_dataformat_start_end_interval(trGetN);
	/// end DYNACONTROL_DOUBLES_TO_SUPPORT_DATE_TIME_INCR_FMTS
	
	bOKEnable = _check_input(trGetN, strErrMsg);
	bUpdateGrid = true;
	///End UPDATE_XF_TO_SHOW_PREVIEW
	
	///Jack 12/22/2008 ADD_SAMPLING_RATE_HINT_LABEL
		_update_sampling_interval_label(trGetN);
	///End ADD_SAMPLING_RATE_HINT_LABEL
	///Kyle 01/14/2009 SET_NO_PREVIEW_IF_THERE_IS_ERROR_IN_CHECKING_INPUT
	if(!bOKEnable || (trNode && trNode.tagName =="iy"))
	{
		string strErrMsg;
		GetNGraphPreview_OnInitGraph(trGetN, pgTemp, wksTemp, pict, bUpdateGrid, dwEnables, strErrMsg);
		s_bInit = false;
	}
	///End SET_NO_PREVIEW_IF_THERE_IS_ERROR_IN_CHECKING_INPUT

	
	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID; //nUpdateGraph = UPDATE_GRAPH_ERROR;
	else
		bUpdateGraph = bOKEnable;
	///End UPDATE_XF_TO_SHOW_PREVIEW
}

// called from OnInitDialog to allow options on setting up of dialog
// dwOptions = 0 (default) will create a line graph with data in a temp worksheet
// dwOptions = XFGSETUP_IMAGEGRAPH_CNTRL to create an image graph with data in a temp matrix book
// dwOptions = XFGSETUP_MATRIX_CNTRL to have a MatrixControl with data in a temp matrix book
// dwOptions = XFGSETUP_2_TABS | XFGSETUP_EMF_1ST to have a PictureControl on 1st tab and a GraphControl on 2nd tab
// vsTabTitles is empty on entering the event, but you can put tab title strings in this array.
static void GetNGraphPreview_OnDialogSetup(TreeNode& trGetN, WndContainer& theDlg, DWORD& dwOptions, vector<string>& vsTabTitles)
{

}

// called when dialog is being destroyed, either as OK button or as Cancel button being pressed
static void GetNGraphPreview_OnDestroy(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{

}
//------------
//
static void GetNGraphPreview_OnCustomButton(TreeNode& trGetN, int nButton, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF that might be present, as requested in OnDialogSetup  
bool bChangedByGraph, // called when graph has been modified by user, like dragging a vertical line
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid,  // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,	// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID

}
//


///////////////////////////////////////////////////////
	
int GetNGraphBox_reduce_ex(TreeNode& trGetN, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{
	return xf_GetNPreviewDlg_event_handler(trGetN, nRow, nCol, trNode, dwCntrl, nType, theDlg, pgTemp, wksTemp, pict,
	GetNGraphPreview_OnInitGrid, GetNGraphPreview_OnInitGraph,
	GetNGraphPreview_OnChange, GetNGraphPreview_OnUpdateGraph, GetNGraphPreview_OnDialogSetup, GetNGraphPreview_OnDestroy,
	GetNGraphPreview_OnCustomButton);	
}


//This file is the template for GetNEvent4

///////////////////////////////////////////////////////

