/*------------------------------------------------------------------------------*
 * 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/20/05 FREQ_COUNT_USE_OCMATH_TO_AVOID_STATS_UTILS						*
 *	Kevin 09/01/05 CHANGE_STATISTICS_NAME										*
 *	Echo 9/15/06 QA70-8541 CORRECT_NOTCH_BOX_CL									*
 *	Echo 9/25/06 UPDATE_DESC_STAT_FUNC_FOR_EFFICIENCY							*
 *	Arvin 02/08/07 QA70-9334 WRONG_NUMBER_BINS									*
 *	YuI 03/30/07 QA70-9523 BOXCHART_UPDATE_AFTER_SOURCE_DATA_UPDATE				*
 *	ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE			*
 *	YuI 06/13/07 QA70-9915 NOTCHED_BOXCHART_PROBLEM								*
 *	YuI 11/16/07 QA70-10654 FREQUENCY_COUNT_CRASH								*
 *	YuI 12/21/07 QA7-10854 MOVE_HISTOGRAM_TO_VC									*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// 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 <DataPlot.h>
#include "OriginEvents.h"

#ifdef _FOR_SMART_LOADING_ONLY
#include "wksOperation.h" //---- CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER
#endif

////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.

////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.


BOOL	create_dataplot_class(string strClassName, DataPlot& dp)
{
	DataPlot& dpTemp = (DataPlot&) Project.CreateClass(strClassName);
	if( dpTemp != NULL )
	{
		dpTemp = dp; // to attach to internal object
		return TRUE;
	}
	
	return FALSE;
}

/// YuI 12/21/07 QA7-10854 MOVE_HISTOGRAM_TO_VC
// compiling out
#ifdef 	OC_STATS_DATA_PLOT
/// end MOVE_HISTOGRAM_TO_VC

///////////////////////////////////////////////////////////////////////////////////
//	class	StatDataPlot
///////////////////////////////////////////////////////////////////////////////////
StatDataPlot::StatDataPlot()
{
}

StatDataPlot::~StatDataPlot()
{
}

BOOL	StatDataPlot::GetPercentileDataset(Dataset& ds)
{
	string strDatasetName;
	if( GetLinkedDatasetName(strDatasetName) )
		ds.Attach(strDatasetName);
	
	return ds.IsValid();
}

/// ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
//BOOL	StatDataPlot::UpdatePercentileDataset()
BOOL	StatDataPlot::UpdatePercentileDataset(int nOptions)
/// end RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
{
	Dataset ds;
	if( !GetPercentileDataset(ds) )
	{
		CreatePercentileDataset(ds);
	}
		
	/// ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
	//return UpdatePercentileDatasetEx(ds);
	return UpdatePercentileDatasetEx(ds, nOptions);
	/// end RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
}

static BOOL	_stats_plot_frequiency_count(vector& vData, vector<uint>& vCounts, double dBinMin, double dBinMax, double dBinSize)
{
	/// YuI 11/16/07 QA70-10654 FREQUENCY_COUNT_CRASH
	if( dBinSize == 0 )
		return FALSE;
	/// end FREQUENCY_COUNT_CRASH
	//Arvin 02/08/07 QA70-9334 WRONG_NUMBER_BINS
	//int nNumBins = 1.5 + (dBinMax - dBinMin)/dBinSize;// convert double to int, so add 0.5, and need to +1 for size
	int nNumBins = ceil((dBinMax - dBinMin)/dBinSize);
	///END WRONG_NUMBER_BINS
	vCounts.SetSize(nNumBins);
	return (OE_NOERROR == ocmath_d_frequency_count(vData, vData.GetSize(), vCounts, vCounts.GetSize(), dBinMin, dBinSize));
}

BOOL	StatDataPlot::FrequencyCount(vector<uint>& vCounts)
{
	/// YuI 08/11/06 CATEGORICAL_SUPPORT_FOR_STAT_PLOTS
	/*
	//generic implemetation with no operation
	string strDatasetName = GetDatasetName();
	Dataset dsSource(strDatasetName);
	if( !dsSource )
		return FALSE;
	
	vector<double> vSource = dsSource;
	*/
	vector	vSource;
	if( !GetSourceData(vSource) )
		return FALSE;
	/// end CATEGORICAL_SUPPORT_FOR_STAT_PLOTS
	double dMin;
	double dMax;
	double dStep;
	
	if( !GetBinMinMax(dMin, dMax, dStep) )
		return FALSE;
	//--- CPY 5/20/05 FREQ_COUNT_USE_OCMATH_TO_AVOID_STATS_UTILS
	/*
	FreqCountOptions stOptions;
	stOptions.FromMin = dMin;
	stOptions.ToMax = dMax;
	stOptions.StepSize = dStep;
	
	vector vBins;
	vector vCountTemp;
	
	stats_frequency_count(vSource, stOptions, vBins, vCountTemp);
	
	vCounts = vCountTemp;
	*/
	/*
	int nNumBins = 1.5 + (dMax - dMin)/dStep;// convert double to int, so add 0.5, and need to +1 for size
	vCounts.SetSize(nNumBins);
	///Mouqx/Leo 2005-9-26 QA70-8110 TO_CENTRALIZE_ERROR_CODES_IN_OCMATH
	//bool bRet = ocmath_d_frequency_count(vSource, vSource.GetSize(), vCounts, vCounts.GetSize(), dMin, dStep);
	int nRet = ocmath_d_frequency_count(vSource, vSource.GetSize(), vCounts, vCounts.GetSize(), dMin, dStep);
	//--- end FREQ_COUNT_USE_OCMATH_TO_AVOID_STATS_UTILS
	return (nRet == OE_NOERROR);
	*/
	
	return _stats_plot_frequiency_count(vSource, vCounts, dMin, dMax, dStep); 
}
	
static vector l_vPercents = {1, 5, 10, 25, 50, 75, 90, 95, 99};
enum
{
	PERCENTILE_VECTOR_POS1,
	PERCENTILE_VECTOR_POS5,
	PERCENTILE_VECTOR_POS10,
	PERCENTILE_VECTOR_POS25,
	PERCENTILE_VECTOR_POS50,
	PERCENTILE_VECTOR_POS75,
	PERCENTILE_VECTOR_POS90,
	PERCENTILE_VECTOR_POS95,
	PERCENTILE_VECTOR_POS99,
	
};
static vector l_vPercentilePositionInDataset = 
{
	PDSP_PERC_1,
	PDSP_PERC_5,
	PDSP_PERC_10,
	PDSP_PERC_25,
	PDSP_PERC_50,
	PDSP_PERC_75,
	PDSP_PERC_90,
	PDSP_PERC_95,
	PDSP_PERC_99
};

static BOOL	_stats_plot_get_stats_results(vector& vData, DescStatResults& dsr, double& dMin, double& dMax)
{
	///Echo 9/25/06 UPDATE_DESC_STAT_FUNC_FOR_EFFICIENCY
	//if( STATS_NO_ERROR == ocmath_desc_stats(vData, vData.GetSize(), &dsr) )
	double dMean, dSD, dSE, dLC, dUC;
	
	/// YuI 06/13/07 QA70-9915 NOTCHED_BOXCHART_PROBLEM
	//	if( STATS_NO_ERROR == ocmath_basic_summary_stats(vData.GetSize(), vData, NULL, &dMean, &dSD, &dSE) && 
	//		STATS_NO_ERROR == ocmath_opt_summary_stats(vData.GetSize(), vData, 0.95, NULL, NULL, NULL, &dLC, &dUC) )
	int nN;
	if( STATS_NO_ERROR == ocmath_basic_summary_stats(vData.GetSize(), vData, &nN, &dMean, &dSD, &dSE) && 
		STATS_NO_ERROR == ocmath_opt_summary_stats(vData.GetSize(), vData, 0.95, NULL, NULL, NULL, &dLC, &dUC) )
	/// end NOTCHED_BOXCHART_PROBLEM
	{
		/// YuI 06/13/07 QA70-9915 NOTCHED_BOXCHART_PROBLEM
		dsr.N = nN;
		/// end NOTCHED_BOXCHART_PROBLEM
		dsr.SD = dSD;
		dsr.SEM = dSE;
		dsr.LCL = dLC;
		dsr.UCL = dUC;
		dsr.Mean = dMean; /// YuI 11/07/06 seems to be nmissing here
		///end UPDATE_DESC_STAT_FUNC_FOR_EFFICIENCY
		vData.GetMinMax(dMin, dMax);
		return TRUE;
	}
	
	return FALSE;
}

BOOL	StatDataPlot::GetStatsResults(DescStatResults& dsr, double& dMin, double& dMax)
{
	vector vSource;
	if( !GetSourceData(vSource) )
		return FALSE;
	
	return _stats_plot_get_stats_results(vSource, dsr, dMin, dMax);
}

BOOL	StatDataPlot::GetStatResults(double& dMin, double& dMax, double& dMean, double& dSD, double& dSE, double& dLC, double& dUC)
{
	DescStatResults dsr;
	if( GetStatsResults(dsr, dMin, dMax) )
	{
		dMean = dsr.Mean;
		dSD = dsr.SD;
		dSE = dsr.SEM;
		dLC = dsr.LCL;
		dUC = dsr.UCL;
		return TRUE;
	}
	
	return FALSE;
}

static BOOL	_stats_plot_precentiles(vector& vData, vector& vPerc)
{
	vector vTemp;
	int nInterpolate = Project.Settings.GetPercentileInterpolateMethod();
	vTemp.SetSize(l_vPercents.GetSize());
	int nErr=ocmath_percentiles(vData, vData.GetSize(), l_vPercents, l_vPercents.GetSize(), vTemp, nInterpolate);
	if(nErr == STATS_NO_ERROR)
	{
		vPerc = vTemp;
		return TRUE;
	}

	return FALSE;		
}

BOOL	StatDataPlot::Percentiles(vector& vPerc)
{
	vector vSource;
	if( !GetSourceData(vSource) )
		return FALSE;
	
	return _stats_plot_precentiles(vSource, vPerc);
}

int		StatDataPlot::GetSourceDataSize()
{
	vector vSource;
	if( !GetSourceData(vSource) )
		return -1;
	
	return vSource.GetSize();
}

BOOL	StatDataPlot::GetBinMinMax(double& dMin, double& dMax, double& dStep)
{
	GraphLayer gl;
	GetParent(gl);
	if( !gl )
		return FALSE;
	/// TD 8-3-06 QA70-8843 DOWNCAST_BUG
	//TreeNode trHistogram = gl.Histogram;
	TreeNode trHistogram;
	trHistogram = gl.Histogram;
	/// end DOWNCAST_BUG
	dMin = trHistogram.BinBegin.dVal;
	dMax = trHistogram.BinEnd.dVal;
	dStep = trHistogram.BinSize.dVal;
	return TRUE;
}

static BOOL	_stats_plot_update_percentile_dataset(Dataset& ds, TreeNode& trStats)
{
	vector vCounts;
	tree_stats_get_set_counts(trStats, vCounts);
	
	vector vPercentiles;
	tree_stats_get_set_percentiles(trStats, vPercentiles);
	
	DescStatResults dsr;
	double dMin = NANUM;
	double dMax = NANUM;
	tree_stats_get_set_stats_results(trStats, dsr, dMin, dMax);
	
	double dBinMin = NANUM;
	double dBinMax = NANUM;
	double dBinSize = NANUM;
	tree_stats_get_set_bin_info(trStats, dBinMin, dBinMax, dBinSize);  
	
	ds = vCounts;
	ds.SetSize(PDSP_UP_MEDIAN_CONFIDENCE + 1);
	ds[PDSP_NUM_HIST] = vCounts.GetSize();
	ds[PDSP_HIST_MIN] = dBinMin;
	ds[PDSP_HIST_INC] = dBinSize;
	for( int ii = 0; ii < vPercentiles.GetSize(); ii++ )
	{
		ds[l_vPercentilePositionInDataset[ii]] = vPercentiles[ii];
	}

	ds[PDSP_PERC_MIN] = dMin;
	ds[PDSP_PERC_MAX] = dMax;
	ds[PDSP_PERC_MEAN] = dsr.Mean;
	ds[PDSP_PERC_SD] = dsr.SD;
	ds[PDSP_PERC_SE] = dsr.SEM;
	ds[PDSP_LOW_MEDIAN_CONFIDENCE] = dsr.LCL;
	ds[PDSP_UP_MEDIAN_CONFIDENCE] = dsr.UCL;
	ds[PDSP_DATA_SIZE] = dsr.N;
	
	double dMinCount;
	double dMaxCount;
	vCounts.GetMinMax(dMinCount, dMaxCount);
	ds[PDSP_MAX_HIST_COUNT] = dMaxCount;
	
	double dBoxTop;
	double dBoxTopX;
	double dBoxBottom;
	double dBoxBottomX;
	double dBoxCenter;
	tree_stats_get_set_box_info(trStats, dBoxTop, dBoxTopX, dBoxBottom, dBoxBottomX, dBoxCenter);
	
	double dWhiskerTop;
	double dWhiskerBottom;
	tree_stats_get_set_whisker_info(trStats, dWhiskerTop, dWhiskerBottom);
	
	ds[PDSP_BAR_TOP] = dBoxTop;
	ds[PDSP_BAR_TOP_X] = dBoxTopX;
	ds[PDSP_BAR_BOT] = dBoxBottom;
	ds[PDSP_BAR_BOT_X] = dBoxBottomX;
	ds[PDSP_BAR_CENTER] = dBoxCenter;
	
	ds[PDSP_WHISK_TOP] = dWhiskerTop;
	ds[PDSP_WHISK_BOT] = dWhiskerBottom;
	
	return TRUE;
}

BOOL	StatDataPlot::UpdateBoxAndWhiskerInfoInStatsTree(TreeNode& trStats)
{
	int nBoxType = DBC_BOX_25_75;
	double dBoxCoeff = 1;
	int nWhiskerType = DBC_WHISKER_OUTLIER;
	double dWhiskerCoeff = 1;
	if( GetBoxAndWhiskerType(nBoxType, dBoxCoeff, nWhiskerType, dWhiskerCoeff) )
	{
		TreeNode trBox = tree_stats_get_boxchart_box_node(trStats);
		TreeNode trWhisker = tree_stats_get_boxchart_whisker_node(trStats);
		
		// need to check if anything changed from the last update, if not we just return TRUE
		if( trBox.Type && (trBox.Type.nVal == nBoxType) &&
			trBox.Coeff && (trBox.Coeff.dVal == dBoxCoeff) && 
			trWhisker.Type && (trWhisker.Type.nVal == nWhiskerType) &&
			trWhisker.Coeff && (trWhisker.Coeff.dVal == dWhiskerCoeff) )
			return TRUE;
			
			
		if( UpdateBoxAndWhiskerInfoInStatsTree(trStats, nBoxType, dBoxCoeff, nWhiskerType, dWhiskerCoeff) )
		{
			trBox.Type.nVal = nBoxType;
			trBox.Coeff.dVal = dBoxCoeff;
			trWhisker.Type.nVal = nWhiskerType;
			trWhisker.Coeff.dVal = dWhiskerCoeff;
			
			return TRUE;
		}
	}
	
	return FALSE;
}

BOOL	StatDataPlot::UpdateBoxInfoInStatsTree(TreeNode& trStats, int nBoxType, double dBoxCoeff, vector& vPercentiles, DescStatResults& dsr)
{
	double dBoxBottom;
	double dBoxBottomX;
	double dBoxTop;
	double dBoxTopX;
	
	switch( nBoxType )
	{
	case DBC_BOX_NONE:
		dBoxBottom = vPercentiles[PERCENTILE_VECTOR_POS25];
		dBoxTop = vPercentiles[PERCENTILE_VECTOR_POS75];
		dBoxTopX = dsr.Mean;
		dBoxBottomX = dsr.Mean;
		break;
		
	case DBC_BOX_SE:
		dBoxBottom = dBoxBottomX = dsr.Mean - dsr.SEM * dBoxCoeff;
		dBoxTop = dBoxTopX = dsr.Mean + dsr.SEM * dBoxCoeff;
		break;
		
	case DBC_BOX_SD:
		dBoxBottom = dBoxBottomX = dsr.Mean - dsr.SD * dBoxCoeff;
		dBoxTop = dBoxTopX = dsr.Mean + dsr.SD * dBoxCoeff;
		break;
		
	case DBC_BOX_25_75:
		dBoxBottom = dBoxBottomX = vPercentiles[PERCENTILE_VECTOR_POS25];
		dBoxTop = dBoxTopX = vPercentiles[PERCENTILE_VECTOR_POS75];
		break;

	case DBC_BOX_10_25_75_90:
 		dBoxBottomX = vPercentiles[PERCENTILE_VECTOR_POS10];
 		dBoxBottom = vPercentiles[PERCENTILE_VECTOR_POS25];
 		
 		dBoxTopX = vPercentiles[PERCENTILE_VECTOR_POS90];
 		dBoxTop = vPercentiles[PERCENTILE_VECTOR_POS75];
		break;
		
	case BSC_BOX_CONSTANT:		
		dBoxBottom = dBoxBottomX =  dsr.Mean - dBoxCoeff;
		dBoxTop = dBoxTopX =  dsr.Mean + dBoxCoeff;		
		break;

	case DBC_NOTCHED_BOX:
		///Echo 9/15/06 QA70-8541 CORRECT_NOTCH_BOX_CL		
		//dBoxBottom = dsr.LCL;
		double dIQR = vPercentiles[PERCENTILE_VECTOR_POS75] - vPercentiles[PERCENTILE_VECTOR_POS25];
		dBoxBottom = vPercentiles[PERCENTILE_VECTOR_POS50] - 1.58 * (dIQR / sqrt(dsr.N));
		///end CORRECT_NOTCH_BOX_CL
		dBoxBottomX = vPercentiles[PERCENTILE_VECTOR_POS25];
		
		//dBoxTop = dsr.UCL; ///Echo 9/15/06 QA70-8541 CORRECT_NOTCH_BOX_CL		
		dBoxTop = vPercentiles[PERCENTILE_VECTOR_POS50] + 1.58 * (dIQR / sqrt(dsr.N));
		dBoxTopX = vPercentiles[PERCENTILE_VECTOR_POS75];		
		break;
 	}			

 	tree_stats_get_set_box_info(trStats, dBoxTop, dBoxTopX, dBoxBottom, dBoxBottomX, vPercentiles[PERCENTILE_VECTOR_POS50], FALSE);
	return TRUE;
}
	
BOOL	StatDataPlot::UpdateWhiskerInfoInStatsTree(TreeNode& trStats, int nWhiskerType, double dWhiskerCoeff, vector& vPercentiles, DescStatResults& dsr, double dMin, double dMax)
{
	double dBottom;
	double dTop;

	switch( nWhiskerType )
	{		
		case DBC_WHISKER_SE:
			dBottom = dsr.Mean - dsr.SEM * dWhiskerCoeff;
			dTop = dsr.Mean + dsr.SEM * dWhiskerCoeff;
			break;
			
		case DBC_WHISKER_OUTLIER:
			{
				// old code that came from VC level function
				// is incorrect. According to Eoutlier should be outer-most data point that falls 
				// withing IQR * coeff.
				/*
				double dBoxTop = trStats.BoxChart.Box.Top.dVal;
				double dBoxBottom = trStats.BoxChart.Box.Bottom.dVal;
				double dDistanceFromBox = (dBoxTop - dBoxBottom) * dWhiskerCoeff;
				dBottom = dBoxBottom - dDistanceFromBox;
				dTop = dBoxTop + dDistanceFromBox;
				*/
				double dIQR = vPercentiles[PERCENTILE_VECTOR_POS75] - vPercentiles[PERCENTILE_VECTOR_POS25];
				double dTopBorder = vPercentiles[PERCENTILE_VECTOR_POS75] + dIQR * dWhiskerCoeff;
				double dBottomBorder = vPercentiles[PERCENTILE_VECTOR_POS25] - dIQR * dWhiskerCoeff;
		
				vector	vSource;
				if( !GetSourceData(vSource) )
					return FALSE;
				
				int nMin = -1;
				int nMax = -1;
				double dMissing = NANUM;
				ocmath_d_minmax_in_range(vSource, vSource.GetSize(), dBottomBorder, dTopBorder, &dMissing, &nMin, &nMax);
				if( nMin >= 0 )
					dBottom = vSource[nMin];
				else
					dBottom = dBottomBorder;
				
				if( nMax >= 0 )
					dTop = vSource[nMax];
				else
					dTop = dTopBorder;
			}
			break;
			
		case DBC_WHISKER_CONSTANT:		
			dBottom = dsr.Mean - dWhiskerCoeff;
			dTop = dsr.Mean + dWhiskerCoeff;
			break;
			
		case DBC_WHISKER_9901:
			dBottom = vPercentiles[PERCENTILE_VECTOR_POS1];
			dTop = vPercentiles[PERCENTILE_VECTOR_POS99];
			break;		

		case DBC_WHISKER_9010:
			dBottom = vPercentiles[PERCENTILE_VECTOR_POS10];
			dTop = vPercentiles[PERCENTILE_VECTOR_POS90];
			break;		

		case DBC_WHISKER_MAXMIN:		
			dBottom = dMin;
			dTop = dMax;
			break;
			
		case DBC_WHISKER_SD:
			dBottom = dsr.Mean - dsr.SD * dWhiskerCoeff;
			dTop = dsr.Mean + dsr.SD * dWhiskerCoeff;
			break;		
			
		case DBC_WHISKER_QUANTILE:
			dBottom = dMin;
			dTop = dMax;	
			break;

		case DBC_WHISKER_9505:
		default:		
			dBottom = vPercentiles[PERCENTILE_VECTOR_POS5];
			dTop = vPercentiles[PERCENTILE_VECTOR_POS95];
			break;		
	}

	tree_stats_get_set_whisker_info(trStats, dTop, dBottom, FALSE);
	return TRUE;
}

BOOL	StatDataPlot::UpdateBoxAndWhiskerInfoInStatsTree(TreeNode& trStats, int nBoxType, double dBoxCoeff, int nWhiskerType, double dWhiskerCoeff)
{
	DescStatResults dsr;
	double dMin = NANUM;
	double dMax = NANUM;
	tree_stats_get_set_stats_results(trStats, dsr, dMin, dMax);
	vector vPercentiles;
	tree_stats_get_set_percentiles(trStats, vPercentiles);

	return 	(UpdateBoxInfoInStatsTree(trStats, nBoxType, dBoxCoeff, vPercentiles, dsr) && 
			UpdateWhiskerInfoInStatsTree(trStats, nWhiskerType, dWhiskerCoeff, vPercentiles, dsr, dMin, dMax));
}

BOOL	StatDataPlot::GetBoxAndWhiskerType(int& nBoxType, double& dBoxCoeff, int& nWhiskerType, double& dWhiskerCoeff)
{
	GraphLayer gl;
	GetParent(gl);
	if( !gl )
		return FALSE;
	TreeNode trHist;
	trHist = gl.Histogram;
	nBoxType = trHist.BoxChart.BoxRange.nVal;
	dBoxCoeff = trHist.BoxChart.BoxCoeff.dVal;
	
	nWhiskerType = trHist.BoxChart.WhiskerRange.nVal;
	dWhiskerCoeff = trHist.BoxChart.WhiskerCoeff.dVal;
	return TRUE;
}
string		StatDataPlot::GetStatsTreeStorageTag(BOOL& bOperation)
{
	/// YuI 03/30/07 QA70-9523 BOXCHART_UPDATE_AFTER_SOURCE_DATA_UPDATE
	/*
	string strStorageTag = GetEventHandler();
	if( strStorageTag.IsEmpty() )
	{
		if( NULL != bOperation )
			bOperation = FALSE;

		
		/// YuI 03/09/07 BIN_SERIES_NOT_SAVED_IF_SINGLE_WINDOW
		//strStorageTag.Format("%s%d", HISTOGRAM_STORAGE_TAG, GetUID(TRUE));
		string strGUID;
		UINT uid = GetUID(TRUE, &strGUID);
		if( strGUID.IsEmpty() )
			strStorageTag.Format("%s%d", HISTOGRAM_STORAGE_TAG, uid);
		else
			strStorageTag.Format("%s%s", HISTOGRAM_STORAGE_TAG, strGUID);
		/// end BIN_SERIES_NOT_SAVED_IF_SINGLE_WINDOW
	}
	else
	{
		if( NULL != bOperation )
			bOperation = TRUE;
	}
	
	okutil_make_valid_c_name(&strStorageTag);
	
	return strStorageTag;
	*/
	
	BOOL bOperationTemp = FALSE;
	string strTag;
	if( DataPlot::GetStatsTreeStorageTag(strTag, bOperationTemp) )
	{
		if( NULL != bOperation )
			bOperation = bOperationTemp;
	}
	
	return strTag;
	/// end BOXCHART_UPDATE_AFTER_SOURCE_DATA_UPDATE
}

TreeNode	StatDataPlot::GetStatsTree(TreeNode& trHistogram)
{
	DatasetObject dsObj(GetDatasetName());
	if( !dsObj )
		return FALSE;
	
	BOOL bOperationOutput = FALSE;
	string strStorageTag = GetStatsTreeStorageTag(bOperationOutput);

	TreeNode trStats;
	dsObj.GetBinaryStorage(strStorageTag, trHistogram);
	/*
	if( bOperationOutput )
	{
		trStats = trHistogram;
	}
	else
	{
		octree_tree_check_get_node(&trStats, &trHistogram, strStorageTag);
	}	
	*/
	/// YuI 03/30/07 QA70-9523 BOXCHART_UPDATE_AFTER_SOURCE_DATA_UPDATE
	trStats = trHistogram;
	/// end BOXCHART_UPDATE_AFTER_SOURCE_DATA_UPDATE
	return trStats;
}

/// ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
//BOOL	StatDataPlot::UpdatePercentileDatasetEx(Dataset& ds)
BOOL	StatDataPlot::UpdatePercentileDatasetEx(Dataset& ds, int nOptions)
/// end RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
{
	DatasetObject dsObj(GetDatasetName());
	if( !dsObj )
		return FALSE;
	
	Tree trHistogram;
	TreeNode trStats = GetStatsTree(trHistogram);
	BOOL bTreeUpdated = FALSE;
	/// ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
	//if( UpdateStatsTree(trStats, bTreeUpdated) )
	if( UpdateStatsTree(trStats, bTreeUpdated, nOptions) )
	/// end RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
	{
		if( bTreeUpdated )
			dsObj.PutBinaryStorage(GetStatsTreeStorageTag(), trHistogram);
		
		return _stats_plot_update_percentile_dataset(ds, trStats);	
	}
	
	return FALSE;
}

static BOOL	_stats_plot_update_stats_tree(vector& vData, double dBinMin, double dBinMax, double dBinSize, TreeNode& trStats)
{
	vector<uint> vCounts;
	/// YuI 11/16/07 QA70-10654 FREQUENCY_COUNT_CRASH
	if( !_stats_plot_frequiency_count(vData, vCounts, dBinMin, dBinMax, dBinSize) )
		return FALSE;
	/// end FREQUENCY_COUNT_CRASH
	vector vPercentiles;
	
	/// YuI 11/16/07 QA70-10654 FREQUENCY_COUNT_CRASH
	//	_stats_plot_precentiles(vData, vPercentiles);
	if( !_stats_plot_precentiles(vData, vPercentiles) )
		return FALSE;
	/// end FREQUENCY_COUNT_CRASH

	DescStatResults dsr;
	double dMin;
	double dMax;
	/// YuI 11/16/07 QA70-10654 FREQUENCY_COUNT_CRASH
	//	_stats_plot_get_stats_results(vData,  dsr, dMin, dMax);
	if( !_stats_plot_get_stats_results(vData,  dsr, dMin, dMax) )
		return FALSE;
	/// end FREQUENCY_COUNT_CRASH

	vector vTemp;
	vTemp = vCounts;
	tree_stats_get_set_counts(trStats, vTemp, FALSE);
	tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
	tree_stats_get_set_stats_results(trStats, dsr, dMin, dMax, FALSE);
	tree_stats_get_set_bin_info(trStats, dBinMin, dBinMax, dBinSize, FALSE);
	return TRUE;
}

/// ML 5/24/2007 QA70-8342 RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
//BOOL	StatDataPlot::UpdateStatsTree(TreeNode& trStats, BOOL& bUpdated)
BOOL	StatDataPlot::UpdateStatsTree(TreeNode& trStats, BOOL& bUpdated, int nOptions)
/// end RECALCULATING_WHISKERS_ETC_ON_PD_DLG_CHANGE
{
	bUpdated = FALSE;
	string	strOperationUID = GetEventHandler();
	if( !strOperationUID.IsEmpty() )
	{
		//---- CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER
		//DataPlotDrawEvent& eventHandler = (DataPlotDrawEvent&) Project.FindClass("DataPlotDrawEvent");
		OriginEventsBase& eventHandler = (OriginEventsBase&) Project.FindClass("DataPlotDrawEvent");
		//---
		if( eventHandler )
		{
			eventHandler.SetObj(*this);
			if( eventHandler.OnDataPlotUpdateStatsTree(strOperationUID, trStats, bUpdated) )
			{
				SetEventHandler(strOperationUID);
				return UpdateBoxAndWhiskerInfoInStatsTree(trStats);
			}
			else
			{
				// this is valid outcome
				// operation may not be there anymore - we leave histogram as is without updating
				return UpdateBoxAndWhiskerInfoInStatsTree(trStats);
			}
		}
	}
	else
	{
		double dBinMin;
		double dBinMax;
		double dBinSize;
		if( !GetBinMinMax(dBinMin, dBinMax, dBinSize) )
			return error_report("failed GetBinMinMax");
		if( (trStats.Bin.Min && trStats.Bin.Min.dVal == dBinMin) &&
			(trStats.Bin.Max && trStats.Bin.Max.dVal == dBinMax) &&
			(trStats.Bin.Size && trStats.Bin.Size.dVal == dBinSize) )
		{
			return UpdateBoxAndWhiskerInfoInStatsTree(trStats);
		}
		bUpdated = TRUE;
		
		vector	vSource;
		if( !GetSourceData(vSource) )
			return FALSE;
		
		if( _stats_plot_update_stats_tree(vSource, dBinMin, dBinMax, dBinSize, trStats) )
			return UpdateBoxAndWhiskerInfoInStatsTree(trStats);
	}
	
	return FALSE;
}


void	StatDataPlot::CreatePercentileDataset(Dataset& ds)
{
	ds.Create(PDSP_UP_MEDIAN_CONFIDENCE, 1, "SBin_"); //nOption 1 to create persistent dataset
	string strName = ds.GetName();
	SetLinkedDataset(strName);
}

BOOL	StatDataPlot::GetTickLabel(string& strLabel)
{
	string	strOperationUID = GetEventHandler();
	if( !strOperationUID.IsEmpty() )
	{
		//---- CPY 10/14/06 SEPARATE_OUT_OPERATION_BASE_INTO_SEPARATE_HEADER
		//DataPlotDrawEvent& eventHandler = (DataPlotDrawEvent&) Project.FindClass("DataPlotDrawEvent");
		OriginEventsBase& eventHandler = (OriginEventsBase&) Project.FindClass("DataPlotDrawEvent");
		//---
		if( eventHandler )
		{
			eventHandler.SetObj(*this);
			if( eventHandler.OnGetTickLabel(strOperationUID, strLabel) )
			{
				SetEventHandler(strOperationUID); // it may be changed by event handler itself
				return TRUE;
			}
		}
	}
	
	return FALSE;
}

/// YuI 08/11/06 CATEGORICAL_SUPPORT_FOR_STAT_PLOTS
BOOL	StatDataPlot::GetSourceData(vector& vSource)
{
	string strDatasetName = GetDatasetName();
	DataObject dataObj;
	dataObj = Project.GetDataObject(strDatasetName);
	
	/// YuI 07/16/07 HISTOGRAM_OGG_OLE_PROBLEM
	/*
	Column col = dataObj;
	if( !col )
	{
		MatrixObject mObj = dataObj;
		if( mObj )
		{
			matrixbase& mat = mObj.GetDataObject();
			mat.GetAsVector(vSource);
			return TRUE;
		}
		return FALSE;
	}

	if( OKCOLTYPE_TEXT_NUMERIC == col.GetFormat() || OKCOLTYPE_NUMERIC == col.GetFormat() )
	{
		///Arvin 03/06/07 QA70-9442 DATASET_ONLY_SUPPORT_DOUBLE
		//Dataset& ds = col.GetDataObject();
		//ds.GetSubVector(vSource, i1, i2);
		vectorbase& vec = col.GetDataObject();
		vec.GetSubVector(vSource, i1, i2);
		///end DATASET_ONLY_SUPPORT_DOUBLE
	}
	else
	{
		CategoricalData dsCat;
		dsCat.Attach(strDatasetName, CMT_ORDINAL);
		if( dsCat )
		{
			dsCat.GetSubVector(vSource, i1, i2);		
		}
	}
	return TRUE;
	*/
	MatrixObject mObj = dataObj;
	if( mObj )
	{
		matrixbase& mat = mObj.GetDataObject();
		mat.GetAsVector(vSource);
		return TRUE;
	}
	vector vx;
	return (GetDataPoints(0, -1, vx, vSource) > 0);
	/// end HISTOGRAM_OGG_OLE_PROBLEM
}
/// end CATEGORICAL_SUPPORT_FOR_STAT_PLOTS

/// YuI 12/21/07 QA7-10854 MOVE_HISTOGRAM_TO_VC
// compiling out
#endif //	OC_STATS_DATA_PLOT
/// end MOVE_HISTOGRAM_TO_VC
