/*------------------------------------------------------------------------------*
 * File Name: PeakFitHelperBase.h												*
 * Creation: Jasmine 11/11/08													*
 * Purpose: Origin C Header Files												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Folger 12/03/08 QA80-12701 v8.0982 THEME_SETTING_CONTROL_FOR_BASELINE_FUNCTION_APPLIED_IN_PA_FIT
 *	Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
 *  Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
 *	Folger 12/22/08 v8.0990 CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
 *  Iris 12/24/2008 v8.0990c FIX_APPLY_SHARE_TO_BASELINE_PARAM_IF_CHANGED_FUNC_IN_BASECREATE_PAGE*
 *	Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT		*
 *	Folger 01/05/09 v8.0993d REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG
 *	Folger 01/07/09 QA80-12925-P1 v8.0994b ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
 *  Iris 01/16/2009 FIX_APPLY_SHARE_TO_INCORRECT_PARAM_IF_HAS_BASELINE_FUNC_WITHOUT_FIT*
 *	Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP							*
 *	Kyle 01/24/2009 SHOULD_NOT_APPLY_PARAMETER_VALUES_WHEN_AUTO_UPDATE_IS_ON	*
 *	Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
 *	Folger 02/12/09 SHOULD_USE_PARAMS_SAVED_IN_GETN_IF_EXISTS_FOR_CHANGE_PARAM	*
 *	Folger 02/13/09 IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM			*
 *  Iris 02/13/2009 NOT_CORRECT_APPLY_PARAM_SHARE_STATUS_FOR_CONSTANT_BASELINE	*
 *  Iris 2/19/2009 FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG_MORE_CHANGE			*
 *	Folger 02/23/09 PLOTTED_CURVES_FAILS_TO_CONTROL_PEAK_PLOTTING_OUTPUT_IN_REPORT_GENERATION
 *	Folger 02/24/09 FITWORKAREA_SHOULD_CONTAIN_BASELINE_PARAMETERS_NUMBER_INFO_INORDER_TO_CORRECTLY_APPLY
 *  Iris 02/24/2009 QA80-13170 NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM*
 *  Iris 2/25/2009 QA80-13180 FIX_NOT_APPLY_CORRECT_DEFAULT_FUNC_FOR_NEWLY_ADD_PEAK*
 *	Folger 02/25/09 QA80-13181 SHARE_BASELINE_FIX_STATUS_BETWEEN_BASELINE_TREATMENT_AND_FITTING
 *	Folger 03/05/09 QA80-12821-P2 CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
 *	Folger 03/09/09 BASELINE_PARAMETER_NUMBER_SAVE_IN_THEME_OF_SR4_NOT_APPLICABLE_IN_SR5
 *	Folger 03/11/09 SHOULD_ONLY_USE_SHARED_FIXBASE_NODE_WHEN_FITTING_WITH_BASELINE
 *  Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
 *	Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION									*
 *	Jasmine 05/05/09 SetFitType_WAS_ONCE_DONE_IN_InitFromOperationTree			*
 *	Jasmine 05/05/09 OPENRATION_TREE_IS_CHANGED_AND_SHOULD_SET_IN_OPENRATION	*
 *	Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT								*
 *	Jasmine 06/12/09 VIRTUAL_FOR_NANOSIZER										*
 *	Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE									*
 *	Jasmine 07/02/09 PA_AND_NANOSIZER_NEED_UPDATE_DATA_TYPE						*
 *	Folger 07/13/09 QA80-12142 FITTED_CURVE_GRAPH_IS_MISSING_IN_PA_REPORT		*
 *	Folger 07/14/09 NANOSIZER_FAILS_TO_UPDATE_PARAMETERS_HIDE_GUI_AFTER_CHANGE_FUNCTION
 *	Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
 *	Folger 09/27/09 QA80-14380 FIT_PEAK_PARAMETERS_DIALOG_FAILS_TO_BE_MODALESS_WHEN_SWITCH_TO_OTHER_PAGES
 *	Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT						*
 *	Folger 10/28/09 QA81-14552 WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA		*
 *	Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE					*
 *	Hong 01/12/10 QA80-14948 NLFIT_SUPPORT_OK_BTN_WHICH_DONOT_FIT_AGAIN			*
 *------------------------------------------------------------------------------*/

#ifndef _PEAK_FIT_HELPER_BASE_H
#define _PEAK_FIT_HELPER_BASE_H

#include	<operation.h>
#include	<..\OriginLab\XFWizard_utils.h>
#include	"NLFitSession.h"

enum
{
	PEAK_UPDATE_INVALID_TYPE,
	PEAK_ADD,
	PEAK_MODIFY,
	PEAK_DELETE
};

///------ Folger 02/23/09 PLOTTED_CURVES_FAILS_TO_CONTROL_PEAK_PLOTTING_OUTPUT_IN_REPORT_GENERATION
enum
{
	PLOT_CURVE_INDIVIDUAL,
	PLOT_CURVE_CUMULATIVE,
	PLOT_CURVE_BOTH,
};
///------ End PLOTTED_CURVES_FAILS_TO_CONTROL_PEAK_PLOTTING_OUTPUT_IN_REPORT_GENERATION

#include	"PeakParamInitHelperBase.h"
///Sophy 10/7/2008 MOVE_PEAKFIT_PREVIEW_CTRL_TO_PEAKFITPREVIEWCTRL_H
//#include 	"NLFPreviewCtrl.h"
#include	"PeakFitPreviewCtrl.h"
///end MOVE_PEAKFIT_PREVIEW_CTRL_TO_PEAKFITPREVIEWCTRL_H

#include 	"FitWizCoreBase.h"				///Jasmine 11/10/08 v8.0968 CENTRALIZE_FIT_CODE_TO_SHARE_WITH_NANOSIZER

#include 	"pa_utils.h"
#include 	"graph_utils.h"

#ifdef _DEBUG
#include <Profiler.h>
#endif

class PFParamDlg;		//------ Folger 10/28/08 v8.0962 CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES

///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
struct XFEventStatus
{
	XFEventStatus()
	{
		m_bOKEnable = true;
	}
	
	string					m_strXFErrMsg;
	bool					m_bOKEnable;
};
///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT

///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
static	void	_set_output_range(Operation* pOp, /*int nIndex, const DataRange& range*/const vector<int>& vnUIDs)
{
	//------ Folger 11/13/08 QA80-12488 v8.970 PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	for ( int ii=0; ii<vnUIDs.GetSize(); ++ii )
	{
		DataRange rng;
		rng = (DataRange)Project.GetObject(vnUIDs[ii]);
		if ( rng )
			int nRet = pOp->SetOutput(rng, ii);
	}
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
}

class PeakFitOperationOutputHelper
{
public:
	PeakFitOperationOutputHelper(DWORD dwWizOp, Operation* pFitPeakOp)
	{
		m_dwWizOp = dwWizOp;
		
		removeWizOpOutputs();
		setFitPeakOpOutputs(pFitPeakOp);
	}
	
	void	RestoreWizOpOutputs()
	{
		if ( m_dwWizOp <= 0 )
			return;		
		Operation& opWiz = (Operation&)Project.GetOperationObject(m_dwWizOp);
		
		for ( int ii=0; ii<m_vnUIDs.GetSize(); ++ii )
		{
			DataRange rng;
			rng = (DataRange)Project.GetObject(m_vnUIDs[ii]);
			opWiz.SetOutput(rng);
		}
	}
	
private:
	void	setFitPeakOpOutputs(Operation* pFitPeakOp)
	{
		_set_output_range(pFitPeakOp, m_vnUIDs);
	}
		
	void	removeWizOpOutputs()
	{
		if ( m_dwWizOp <= 0 )
			return;		
		Operation& opWiz = (Operation&)Project.GetOperationObject(m_dwWizOp);
		
		for ( int ii=opWiz.GetOutputCount()-1; ii>=0; --ii )
		{
			DataRange rng;
			opWiz.GetOutput(rng, ii);
			
			if ( rng )
			{
				if ( rng.GetName().Compare(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME) != 0 )
					continue;
				
				m_vnUIDs.InsertAt(0, rng.GetUID());
				opWiz.RemoveOutput(rng);
			}
		}
	}
	
private:
	DWORD			m_dwWizOp;
	vector<int>		m_vnUIDs;
};
///------ End PEAK_FITTING_OUTPUTS_HELPER_CLEANUP

#define		STR_IS_PARAMS_SAVED_IN_GETN_ATTRIB		"IsParamsSavedInGetN"		///------ Folger 02/12/09 SHOULD_USE_PARAMS_SAVED_IN_GETN_IF_EXISTS_FOR_CHANGE_PARAM

/////////////////////////////////////////////////////////
/////////////////	PeakFitHelperBase	/////////////////
///////////////////////////////////////////////////////// 
class PeakFitHelperBase
{
public:
	PeakFitHelperBase(FitWizCoreBase *pFitWizCore = NULL, bool bCreateOp = true);
	~PeakFitHelperBase();	

private:	

	virtual void 			initSessionSettingsFromGetN(const TreeNode& trGetN);
	
	///Sophy 10/9/2008 FIX_FAIL_TO_GET_OUTPUT_MANAGER_AND_OPERATION_POINTER_IN_OUTPUT_EVENT
	bool	updateOperationAndOutManagerPointer( const TreeNode& trGUI, TreeNode& trResult );
	///end FIX_FAIL_TO_GET_OUTPUT_MANAGER_AND_OPERATION_POINTER_IN_OUTPUT_EVENT
	
	virtual void 			copySettingsToOperation(const TreeNode& trGetN, TreeNode& trGUI);	
	
	virtual void 			setBaselineRangeToOperation(TreeNode& trGUI);
	
	virtual void			prepareOutputGraph(GraphLayer& gl, TreeNode& trGUI, const TreeNode& trGetN, bool bHasBaselinePeak);	
	
	virtual	bool			addOtherInformation(TreeNode &trOp){ASSERT_AND_RETURN_FALSE}
	
	/////// Theme relative
	void 	checkUpdateParamSettingsOnBaselineParamsNumber(TreeNode& trOneCol, int numBaselineParams, int nBaselineParamNumInTheme); /// Iris 02/24/2009 QA80-13170 NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
	/// Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	void 	checkUpdateParamSettingsOnBaselineFunctionChanged(TreeNode& trOneCol, const vector& vBaselineParamVals, int nBaselineParamNumInTheme, bool bIsParamValNode);
	bool 	isBaselineFunctionChanged(TreeNode& trParams);
	virtual int 	getBaselineParams(vector* pvParamVals = NULL, vector<string>* pstrParamNames = NULL) { return 0; }
	///end FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	
	/////// fit funciton, data, parameters relative
	virtual bool			setParams(bool bOnInit = false, TreeNode& trGetN = NULL);
	bool					setFunctions(bool bOnInit = false, TreeNode& trGetN = NULL);
	virtual void			prepareFunctions(vector<string>& vsFunctions, bool bOnInit = false, TreeNode& trGetN = NULL, bool bIncludeBaselineFunction = false);
	bool					setData(TreeNode& trGetN);
	virtual TreeNode		prepareData(TreeNode& trGetN);	
	
//--- create, access and destory object ////virtual 
	virtual bool 	hasSpecInfo(StringArray& saOptions, string& strSetInfoFromXF){ASSERT_AND_RETURN_FALSE}	///Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION
	
	bool 	createFitSessionAndPAParamInitHelper();	
	void	destroyFitSessionAndPAParamInitHelper();
	
	virtual bool	createPreivewCtrl();
	virtual void	destroyPreivewCtrl();
	
	/////------ Folger 12/22/08 v8.0990 CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
	//void	checkUpdateCacheFitFunctionInfo(LPCSTR lpcszFunction);
	/////------ End CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
	
protected:
	//NLFitPreviewCtrl*		getPreivewCtrl();
	PeakFitPreviewCtrl*		getPreivewCtrl();
	
	NLParametersManager* 	getParamsMngr();
	
	bool 					createOperation();	///Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION
	
	virtual	void 			initGetN(TreeNode& trGetN);
	
	/////// Theme relative
	void	applyAutoParamsInitOnTheme(const TreeNode& trGetN);
	bool	applyParamsOnTheme(TreeNode& trGetN);
	
public:
	NLFitSession*			GetFitSession();	
//---	
	#define		NOTIFY_NLFSESSION_ON_PARAMETERS_CHANGED		GetFitSession()->NotifyParameterChangedByEdit();
	
	bool	InitParams(PEAKINFOARGUMENTSLISTPARAMS*				pstPEAKINFOARGUMENTSLISTPARAMS = NULL,
					PEAKINFOARGUMENTSLISTFUNCTIONS*				pstPEAKINFOARGUMENTSLISTFUNCTIONS = NULL,
					PEAKINFOARGUMENTSLISTBASE*					pstPEAKINFOARGUMENTSLISTBASE = NULL,
					PEAKINFOARGUMENTSLISTBASELINE*				pstPEAKINFOARGUMENTSLISTBASELINE = NULL,
					bool*										pbHasBaselinePeak = NULL,
					bool										bLoadValuesFromFDFOnly = false);
					
	bool	ReinitParamsOnFuncChange(const vector<int>&				vnPeakIndecies,
					PEAKINFOARGUMENTSLISTFUNCTIONS*		pstPEAKINFOARGUMENTSLISTFUNCTIONS = NULL,
					bool								bLoadValuesFromFDFOnly = false);

protected:
	
	bool	ReinitParamsOnPeakChange(const vector<int>&				vnPeakIndecies,
					PEAKINFOARGUMENTSLISTPARAMS&		stPEAKINFOARGUMENTSLISTPARAMS,
					LPCSTR								lpcszDefaultFunction,
					bool								bLoadValuesFromFDFOnly = false,
					bool								bRemovePeak = false
					);
					
public:
	
	string	GetDefaultFunction();
	void	SetDefaultFunction(LPCSTR lpcszFunc);
	
	virtual bool	SetFunction(string strFunction, int nFunc = 0, bool bResetFunction = true);
	///Jasmine 06/12/09 VIRTUAL_FOR_NANOSIZER
	virtual bool	SetFunctions(const vector<string>& vsFunctions, bool bSkipBaseline = false);
	///End VIRTUAL_FOR_NANOSIZER
	
	bool 	UpdateData(TreeNode& trInputData);
	
	virtual void 	InitPreview(const TreeNode& trGetN);
	int 	GetInitRuntimeError() { return m_nInitRuntimeError; }
	
	// fit relative
	bool 	IsReadyIterations(bool *pbChiSqrReady = NULL); /// Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION
	void 	SetLinearConstraints(TreeNode& trLinearConstraints, bool bConstraints);
	void 	SetTolerance(double dTolerance);
	void 	SetNumMaxIter(int nMaxIter);
	void	SetIsGetParamsConf(const TreeNode& trQuantities);	///Jasmine 06/06/08 QA80-11656 PA_FIT_HAS_NOT_UPDATED_LCL_SETTING
	
	void 	UpdateFitCurveOptions(TreeNode& trGraph1, bool bUpdateXDataMinMaxByAuto = false);///Jasmine 05/17/08 UPDATE_X_DATA_MIN_MAX_BY_AUTO	
	
	//void 	UpdateSettingOnChange(Page& pg, TreeNode& trGetN, int nSetting = -1, bool bUpdatePeakLabel = true);	///Jasmine 05/05/08 UPDATE_PEAK_LABEL_PLOT_AFTER_PEAK_CENTER_PARAM_CHANGE 
	bool 	UpdateSettingOnChange(TreeNode& trGetN);
	
	bool	IsBaselineFitWithPeaks()	{ return GetFitSession()->GetBaselineFitMode(); }
	
	void 	SetPFWTree(const TreeNode& trGetN, const TreeNode& trPFWTree);
	void 	GetPFWTree(const TreeNode& trGetN, TreeNode& trPFWTree);
	
	virtual bool	Init(TreeNode& trGetN);
	virtual int 	ExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode& trUID);
	bool 			PrepareOperationTree(TreeNode& trOp, const TreeNode& trGetN);
		
	//------ Folger 11/05/08 QA80-12509 v8.0965 SUPPORT_BOTH_PEAKS_SORTING_AND_REORDERING_FOR_MULTIPLE_PEAKS_FITTING
	bool	GetPeakReorderingEnable()				{ return m_bPeakReorderingEnable; }
	void	SetPeakReorderingEnable(bool bEnable)	{ m_bPeakReorderingEnable = bEnable; }
	//------
	
	//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
	bool			UpdateFitWorkArea(TreeNode& trFitWorkArea);
	//------
	
	///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	XFEventStatus*	GetXFEventStatus()		{ return &m_xfEventStatus; }
	///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	
	///------ Folger 01/05/09 v8.0993d REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG
	void			SetGetParamHideTree(TreeNode& trParamHide, bool bSet = true);
	///------ End REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG
	
	///------ Folger 01/07/09 QA80-12925-P1 v8.0994b ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
	void			ResetOperationPtr()			{ m_pnlOp = NULL; }
	///------ End ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
	
	///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	void			SetUpdatePreviewInfo(bool bPlotIndividualPeak, bool bPlotCumulativeCurve);
	
	void			SetUseSmartX(bool bOn = true)
						{ m_bPlotCurveOptionChanged = true; GetFitSession()->SetUseSmartX(bOn); }
	void			SetXPtsForEachPeak(int nPts = FITCURVE_POINTS_FOR_INDIVIDUAL_PEAKS)
						{ GetFitSession()->SetXPtsForEachPeak(nPts); }	
						
	FitWizCoreBase*	GetFitWizCoreBase()		{ return m_pFitWizCore; }
	///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	
	///------ Folger 02/25/09 QA80-13181 SHARE_BASELINE_FIX_STATUS_BETWEEN_BASELINE_TREATMENT_AND_FITTING
	virtual	void	CheckSetBaseParamFixMode(bool* pbFixed = NULL)		{}
	///------ End SHARE_BASELINE_FIX_STATUS_BETWEEN_BASELINE_TREATMENT_AND_FITTING
	
	///------ Folger 03/11/09 SHOULD_ONLY_USE_SHARED_FIXBASE_NODE_WHEN_FITTING_WITH_BASELINE
	/// we assume that if BaselineParameters has been assigned, then runtime theme is available ... seems ugly, enough for SR5
	bool			IsRuntimeThemeAvailable(TreeNode& trParams)		{ return !trParams.BaselineParameters.IsEmpty(); }
	///------ End SHOULD_ONLY_USE_SHARED_FIXBASE_NODE_WHEN_FITTING_WITH_BASELINE
	
	//------ Folger 10/28/08 v8.0962 CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES
	///------ Folger 09/27/09 QA80-14380 FIT_PEAK_PARAMETERS_DIALOG_FAILS_TO_BE_MODALESS_WHEN_SWITCH_TO_OTHER_PAGES
	//bool	GetPreviewLayer(GraphLayer& gl);
	bool	GetPreviewLayer(GraphLayer& gl,  bool bSetActive = true);
	///------ End FIT_PEAK_PARAMETERS_DIALOG_FAILS_TO_BE_MODALESS_WHEN_SWITCH_TO_OTHER_PAGES
	
	void			SetPeakFitDlgPointer(PFParamDlg* pPFDlg);
	PFParamDlg*		GetPeakFitDlgPointer();
	//------ End CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES
	
	bool			IsFitConverged();
	
	LPCSTR			GetPeakFuncCategory();
	LPCSTR			GetBaselineFuncCategory();
	
	///------ Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
	//virtual	bool		AccessPeakLabelSettings(int& nLabelXYType, bool bGet = true)		{ ASSERT_AND_RETURN_FALSE }
	bool		AccessPeakLabelSettings(int& nLabelXYType, bool bGet = true);
	///------ End NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
	virtual	bool		UpdatePeaksPropertiesAfterSorting(const vector<uint>& vnIndices)	{ ASSERT_AND_RETURN_FALSE }
	
	virtual void 		CalculateFitCurvePoints(TreeNode& trGraph1){ASSERT(0);}
	///------ Folger 10/28/09 QA81-14552 WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA
	bool				IsChangeParam()
	{
		return m_pFitWizCore->IsChangeParam();
	}
	bool				IsRecalculate()
	{
		return m_pFitWizCore->IsRecalculate();
	}
	///------ End WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA
private:
	///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	///// Iris 11/15/2008 v8.0972 QA80-12584_P7 FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
	////virtual void 	beforeExecuteOperation(const GraphLayer& gl, const TreeNode& trGetN, TreeNode& trOp);
	//virtual void 	beforeExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode& trOp);
	/////end FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
	
	//virtual void 	afterExecuteOperation(TreeNode& trGetN, TreeNode& trOp){}
	virtual	void 	beforeExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode& trOp, TreeNode& trUID);
	virtual	void 	afterExecuteOperation(TreeNode& trGetN, TreeNode& trOp, TreeNode& trUID)		{}
	///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	
	///Jasmine 06/12/09 VIRTUAL_FOR_NANOSIZER
	virtual void 	updatePrivateSettings(TreeNode& trGUI){}
	///End VIRTUAL_FOR_NANOSIZER

protected:
	virtual int				getNumBaselineParams();
	
	int		getPeaksOffset();
	
	void 	copyValueByID(TreeNode trSrc, TreeNode& trDst, LPCSTR lpcszSrcAttribName, LPCSTR lpcszDstAttribName, LPCSTR lpcszNode = NULL);
	
	//------ Folger 12/03/08 QA80-12701 v8.0982 THEME_SETTING_CONTROL_FOR_BASELINE_FUNCTION_APPLIED_IN_PA_FIT
	void			AccessPFMTreeFunctions(TreeNode& trPFM, vector<string>& vsFunctions, bool bGet = true);
	//------
	
	virtual bool IsSingleFuncFit(){ ASSERT_AND_RETURN_FALSE }
	
	PeakParamInitHelperBase*		GetParamInitHelper()		{ return m_pParamInitHelper; }
	
protected:
	//bool					m_bInitDone;
	//bool					m_bDeleteFitSession;
	//bool					m_bOperationHasFitSession;		///Jasmine 04/15/08 HARD_TO_CHECK_FITSESSION_POINTER_IN_OPERATION
	
	string 					m_strOperation;	
	string 					m_strCategory;
	string					m_strDefaultFunction;
		
	OperationPtr			m_pnlOp;		///Jasmine 04/10/08 KEEP_OPERATION_IN_PEAK_FITHELPER
	
	NLFitSession			*m_pFitSession;
	PeakFitPreviewCtrl		*m_pPreviewCtrl;
	///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	PreviewCtrlInfo			m_prevCtrlInfo;
	bool					m_bPlotCurveOptionChanged;
	///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	
	//------ Folger 11/05/08 QA80-12509 v8.0965 SUPPORT_BOTH_PEAKS_SORTING_AND_REORDERING_FOR_MULTIPLE_PEAKS_FITTING
	bool					m_bPeakReorderingEnable;
	//------
	
	PeakFitOperationOutputHelper*		m_pOpOutputHelper;		///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	
private:
	
	///------ Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT
	#define		ASSERT_AND_RETURN_NULL			\
			ASSERT(false);						\
			return NULL;
			
	virtual	PeakParamInitHelperBase*		createParamInitHelper()			{ ASSERT_AND_RETURN_NULL }
	virtual	LPCSTR							getBaselineFuncCategory()		{ ASSERT_AND_RETURN_NULL }
	///------ End NANOSIZER_FITTING_BASED_SUPPORT
	
private:	
	//in private since the derived class will convert this pointer as it need
	FitWizCoreBase			*m_pFitWizCore; /// Iris 9/18/2008 NEED_ACCESS_PAWIZCORE_IN_PEAKFITHELPER
	
	///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE
	vector<int>				m_vnUIDs;		//------ Folger 11/21/08 v8.0977 CORRECT_WIZOPERATION_OUTPUT_RANGE_BEFORE_PA_EXIT
	///End NANOSIZER_NEED_CENTRALIZE
	
	///------ Folger 12/22/08 v8.0990 CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
	FitFunctionInfo			m_cacheFitFunctionInfo;		
	///------ End CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
	
	///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	XFEventStatus			m_xfEventStatus;
	///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	
	Tree					m_trParamHide;		///------ Folger 01/05/09 v8.0993d REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG
	
	int						m_nInitRuntimeError;
	
	PeakParamInitHelperBase	*m_pParamInitHelper;
	
	PFParamDlg				*m_pPFDlg;		//------ Folger 10/28/08 v8.0962 CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES
};



/////////////////////////////////////////////////////////
/////////////////	PeakFitHelperBase	/////////////////
///////////////////////////////////////////////////////// 


///Jasmine 04/10/08 KEEP_OPERATION_IN_PEAK_FITHELPER
/// Iris 9/18/2008 NEED_ACCESS_PAWIZCORE_IN_PEAKFITHELPER
//PAFitHelper::PAFitHelper(bool bCreateOp)//(LPCSTR lpcszCategory)
PeakFitHelperBase::PeakFitHelperBase(FitWizCoreBase *pFitWizCore, bool bCreateOp)
///end NEED_ACCESS_PAWIZCORE_IN_PEAKFITHELPER
{
	ResetOperationPtr();
		
	m_pPFDlg = NULL;		//------ Folger 10/28/08 v8.0962 CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES
	
	/// Iris 9/18/2008 NEED_ACCESS_PAWIZCORE_IN_PEAKFITHELPER
	m_pFitWizCore = pFitWizCore;
	///end NEED_ACCESS_PAWIZCORE_IN_PEAKFITHELPER
	
	createFitSessionAndPAParamInitHelper();
	
	createPreivewCtrl();	
	
	m_pOpOutputHelper = NULL;		///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	
	///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	m_prevCtrlInfo.bComputeCumulativeCurve =
	m_prevCtrlInfo.bPlotIndividualPeak =
	m_prevCtrlInfo.bPlotCumulativeCurve = true;
	
	m_bPlotCurveOptionChanged = false;
	///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
}

///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE, move from PA
//#ifndef _DEBUG ///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
//------ Folger 11/21/08 v8.0977 CORRECT_WIZOPERATION_OUTPUT_RANGE_BEFORE_PA_EXIT
static	void	_update_wizoperation_output_ranges_in_fitpeak(const vector<int>& vnUIDs, DWORD dwWizOp = 0)
{
	if ( vnUIDs.GetSize() == 0 )
		return;
	
	DataRange rng;
	int		nn = 0;
	do
	{
		rng = (DataRange)Project.GetObject(vnUIDs[nn++]);
	} while ( nn < vnUIDs.GetSize() && !rng );
	
	if ( !rng )		/// we assume it will be always OK here
	{
		ASSERT(false);
		return;
	}
	
	int nDummyIndex = 0;
	OperationBase*	pOpWiz = NULL;
	OperationBase& opWizard = rng.GetIncomingOperation(TRUE, nDummyIndex);
	if ( opWizard )
		pOpWiz = &opWizard;
	else
	{
		OperationBase& opWizard2 = Project.GetOperationObject(dwWizOp);
		if ( opWizard2 )
			pOpWiz = &opWizard2;
	}
	
	if ( pOpWiz == NULL )
		return;
	
	///------ Folger 02/06/09 PA_FITTING_RECALCULATION_FAILS_SINCE_WIZOP_REMOVES_ALL_EMPTY_RANGES
	/////------ Folger 01/19/09 QA80-12963 PA_FITTING_FAILS_TO_OUTPUT_PROPERLY_WHEN_CHANGE_OUTPUT_IN_CHANGE_PARAM
	///*
	//for ( int ii=opWizard.GetOutputCount()-1; ii>=0; --ii )
	//{
		//opWizard.GetOutput(rng, ii);
		//if ( rng )
			//opWizard.RemoveOutput(rng);
	//}
	//
	//for ( ii=0; ii<vnUIDs.GetSize(); ++ii )
	//{
		//rng = (DataRange)Project.GetObject(vnUIDs[ii]);
		//if ( rng )
			//opWizard.SetOutput(rng, ii);
	//}
	//*/
	//int		nPos = 0;
	//for ( ; nPos < pOpWiz->GetOutputCount(); ++nPos )
	//{
		//pOpWiz->GetOutput(rng, nPos);
		//if ( rng.GetName().Compare(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME) == 0 )
			//break;
	//}
	//
	//for ( int ii=pOpWiz->GetOutputCount()-1; ii>=nPos ; --ii )
	//{
		//pOpWiz->GetOutput(rng, ii);
		//if ( rng.GetNumRanges() > 0 )
		//{
			//int		jj = ii - nPos;
			//if ( jj >= vnUIDs.GetSize() )
			//{
				//pOpWiz->RemoveOutput(rng);
				//continue;
			//}
			//else if ( rng.GetUID() != vnUIDs[jj] )
			//{
				//rng = (DataRange)Project.GetObject(vnUIDs[jj]);
				//pOpWiz->SetOutput(rng, ii);
			//}
		//}
		//rng.SetName(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME, FALSE);
	//}
	/////------ End PA_FITTING_FAILS_TO_OUTPUT_PROPERLY_WHEN_CHANGE_OUTPUT_IN_CHANGE_PARAM
	
	for ( int ii=pOpWiz->GetOutputCount()-1; ii>=0; --ii )
	{
		pOpWiz->GetOutput(rng, ii);
		if ( rng.GetName().Compare(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME) != 0 )
			break;
		pOpWiz->RemoveOutput(rng);
	}
	for ( int jj=0; jj<vnUIDs.GetSize(); ++jj )
	{
		rng = (DataRange)Project.GetObject(vnUIDs[jj]);
		if ( !rng.IsValid() )
		{
			rng.Create();
			rng.GetUID(TRUE);
			Project.AddDataRange(rng);
		}
			
		rng.SetName(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME, FALSE);
		pOpWiz->SetOutput(rng, ++ii);
	}
	
	///------ End PA_FITTING_RECALCULATION_FAILS_SINCE_WIZOP_REMOVES_ALL_EMPTY_RANGES
}
//------ End CORRECT_WIZOPERATION_OUTPUT_RANGE_BEFORE_PA_EXIT
//#endif ///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE	
///End NANOSIZER_NEED_CENTRALIZE

PeakFitHelperBase::~PeakFitHelperBase()
{
	///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE, move from PA
	//#ifndef _DEBUG ///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
	//------ Folger 11/21/08 v8.0977 CORRECT_WIZOPERATION_OUTPUT_RANGE_BEFORE_PA_EXIT
	_update_wizoperation_output_ranges_in_fitpeak(m_vnUIDs, m_pFitWizCore->GetXFWizOp());
	//------
	//#endif ///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE	
	///End NANOSIZER_NEED_CENTRALIZE
	
	//ERR_MSG("~PAFitHelper");
	//
	//if ( m_pnlOp )
	//{		
		//int nAutoUpdate = 0;
		//
		//if(AU_NONE == nAutoUpdate)
			//m_pnlOp->DestroyInternal();
		//else
			//m_pnlOp->OnKeepOpAfterExecute();		
		//
		//m_pnlOp = NULL;
		//
		/////Jasmine 04/15/08 HARD_TO_CHECK_FITSESSION_POINTER_IN_OPERATION
		//if(m_bOperationHasFitSession)
			//m_bDeleteFitSession = true;
		/////End HARD_TO_CHECK_FITSESSION_POINTER_IN_OPERATION
	//}
	//
	//if(!m_bDeleteFitSession)
	//{
		//ERR_MSG("delete m_pFitSession in ~PAFitHelper");
		//delete m_pFitSession;
		//m_pFitSession = NULL;
		//m_bDeleteFitSession = true;
	//}
	
	if ( m_pnlOp != NULL )
	{
		///------ Folger 01/07/09 QA80-12925-P1 v8.0994b ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
		m_pnlOp->SetHelperClass(NULL);
		///------ End ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
		m_pnlOp->DestroyInternal();
		ResetOperationPtr();
		///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
		if ( m_pOpOutputHelper != NULL )
			m_pOpOutputHelper->RestoreWizOpOutputs();
		///------ End PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	}
	
	///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	if ( m_pOpOutputHelper != NULL )
		delete m_pOpOutputHelper;
	///------ End PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	destroyPreivewCtrl();

	destroyFitSessionAndPAParamInitHelper();
}
///Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION, move from PA
bool PeakFitHelperBase::createOperation()
{
	if(m_pnlOp)
		return false;
	
	/// Iris 4/24/2008 HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA, want to show Inner and Outer Limits in Nanosizer and hide in PA
	string 		strSetInfoFromXF;
	StringArray	saOptions, saNames;
	bool		bHasSpacInfo = hasSpecInfo(saOptions, strSetInfoFromXF);
	int			nOption = get_fit_type(strSetInfoFromXF);
	////end HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA
	
	bool bInitOK = false;	
	/// Iris 4/23/2008 HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA
	//Operation& op = (Operation &)op_create(m_strOperation, bInitOK); 		
	Operation& op = (Operation &)op_create(m_strOperation, bInitOK, nOption); 
	///end HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA
	if(NULL == op)
		return false;	
	if(!bInitOK)
	{	
		op_destroy_on_cancel(op);
		return false;
	}
	
	m_pnlOp = &op;

	/// YuI 04/11/08 
	// if this is not set, bool	FitNL::GetCategoryFuncNames
	// will return true, which is indication that category may change
	// FitNL::OperationtoGUI the local bool bIsCategoryAllowedChange will be true
	// and vsCatsFilterList will not get populated
	//	call to mySelFunc.Init will be with empty vsCatsFilterList
	// so inside NLFitSelFunction::Init
	// instead of removing all categories that are not in  the list
	// it will remove all "non-pro" categories, including PFW
	// which resets category in the operation tree to Origin Basic Functions - arghhhhh
	// 
	///Jasmine 04/14/08 BOTH_PFW_AND_NANOSIZER_NEED_SET_SPEC_INFO
	/*trOp.SpecInfo.FitType.nVal = NLFIT_GENERAL_XY_FITTING;
	tree_check_get_node(trOp.SpecInfo, "ClassName"); 
	tree_check_get_node(trOp.SpecInfo, "Option");
	trOp.SpecInfo.Categ.strVal = m_strCategory;*/
	
	/// Iris 4/23/2008 HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA
	/*
	int			nOption = 0;
	string 		strSetInfoFromXF;
	StringArray	saOptions, saNames;
	if( hasSpecInfo(saOptions, strSetInfoFromXF) )
	*/	
	if(bHasSpacInfo)
	///end HIDE_INNER_OUTER_LIMITS_FOR_XYFIT_AND_PA
		m_pnlOp->SetInfoFromXF(nOption, strSetInfoFromXF, saOptions, saNames, m_strCategory);
	///End BOTH_PFW_AND_NANOSIZER_NEED_SET_SPEC_INFO
	/// end YuI
	
	Tree trOp;
	m_pnlOp->GetTree(trOp);
	
	trOp.GUI.FunctionSelection.CategoryList.strVal = m_strCategory;
	
	///Iris 4/10/2008 PEAK_FIT_REPORT_PEAK_CHARACTERISTICS_TO_SEPARATE_SHEET
	// in order to call GUIPrepareOutputBranch
	m_pnlOp->OperationtoGUI(trOp, true, NULL, false); 
	///end PEAK_FIT_REPORT_PEAK_CHARACTERISTICS_TO_SEPARATE_SHEET
	
	m_pnlOp->SetTree(trOp);
	
	return true;
}
///End NANO_CENTRIALIZE_FUNCTION
virtual void PeakFitHelperBase::initSessionSettingsFromGetN(const TreeNode& trGetN)
{	
	//doing...
	ASSERT(0);
}

virtual void PeakFitHelperBase::initGetN(TreeNode& trGetN)
{
	///Jasmine 07/02/09 PA_AND_NANOSIZER_NEED_UPDATE_DATA_TYPE
	ASSERT( GetFitSession() );
	
	TreeNode trGraph1 = tree_get_node_by_tagname(trGetN.result, "Graph1", true);
	TreeNode trInputData = tree_get_node_by_tagname(trGetN.trAdv, "InputData", true);
	if(trGraph1 && trInputData)
		GetFitSession()->UpdateDataTypeBranch(trGraph1, trInputData, m_pFitWizCore->IsAutoUpdated() );
	else
		ASSERT(0);
	///End PA_AND_NANOSIZER_NEED_UPDATE_DATA_TYPE
}


//int PeakFitHelper::resetInputDataWithNewGraph(const GraphLayer gl, const TreeNode trGetN, TreeNode& trGUI, bool bHasBaselinePeak)
///Sophy 10/9/2008 FIX_FAIL_TO_GET_OUTPUT_MANAGER_AND_OPERATION_POINTER_IN_OUTPUT_EVENT
bool PeakFitHelperBase::updateOperationAndOutManagerPointer( const TreeNode& trGUI, TreeNode& trResult )
{
	TreeNode trOutManagerPtr = trGUI.Output.GetNode("OutManagerPointer");
	TreeNode trOperationPtr = trGUI.Output.GetNode( "OperationPointer" );
	ASSERT( trOutManagerPtr && trOperationPtr );
	
	TreeNode trGetNOutMngrPtr = tree_check_get_node( trResult.Output, "OutManagerPointer" );
	TreeNode trGetNOpPtr = tree_check_get_node( trResult.Output, "OperationPointer" );
	trGetNOutMngrPtr.Replace( trOutManagerPtr.Clone() );
	trGetNOpPtr.Replace( trOperationPtr.Clone() );
	
	trGetNOutMngrPtr.SetAttribute(STR_DATAID_ATTRIB, IDE_OUTPUT_MANAGER_POINTER);
	trGetNOpPtr.SetAttribute(STR_DATAID_ATTRIB, IDE_OPERATION_POINTER);
	
	return true;
}
///end FIX_FAIL_TO_GET_OUTPUT_MANAGER_AND_OPERATION_POINTER_IN_OUTPUT_EVENT

virtual void PeakFitHelperBase::copySettingsToOperation(const TreeNode& trGetN, TreeNode& trGUI)
{
	//doing...
	ASSERT(0);	
}

virtual void PeakFitHelperBase::setBaselineRangeToOperation(TreeNode& trGUI)
{
	ASSERT(0);	
}

virtual void PeakFitHelperBase::prepareOutputGraph(GraphLayer& gl, TreeNode& trGUI, const TreeNode& trGetN, bool bHasBaselinePeak)
{
	ASSERT(0);
}

/// Iris 02/24/2009 QA80-13170 NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
void PeakFitHelperBase::checkUpdateParamSettingsOnBaselineParamsNumber(TreeNode& trOneCol, int numBaselineParams, int nBaselineParamNumInTheme)
{
	vector<double>  vValues;
	if( trOneCol.TypeID == TNVAL_TYPE_INT_VECTOR )
	{
		vValues = trOneCol.nVals;
	}
	
	if( trOneCol.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
	{
		vValues = trOneCol.dVals;
	}				
	
	if( nBaselineParamNumInTheme < numBaselineParams )
	{
		vValues.InsertAt(0, 0, numBaselineParams - nBaselineParamNumInTheme);
	}		
	if( nBaselineParamNumInTheme > numBaselineParams )
	{
		vValues.RemoveAt(numBaselineParams, nBaselineParamNumInTheme - numBaselineParams);
	}		
	
	if( nBaselineParamNumInTheme != numBaselineParams )
	{
		if( trOneCol.TypeID == TNVAL_TYPE_INT_VECTOR )
			trOneCol.nVals = vValues;
		
		if( trOneCol.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
			trOneCol.dVals = vValues;					
	}	
}
///end NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM

/// Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
void PeakFitHelperBase::checkUpdateParamSettingsOnBaselineFunctionChanged(TreeNode& trOneCol, const vector& vBaselineParamVals, int nBaselineParamNumInTheme, bool bIsParamValNode)
{
	vector<double>  vValues;
	if( trOneCol.TypeID == TNVAL_TYPE_INT_VECTOR )
	{
		vValues = trOneCol.nVals;
	}
	
	if( trOneCol.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
	{
		vValues = trOneCol.dVals;
	}	
	
	vValues.RemoveAt(0, nBaselineParamNumInTheme);
	
	vector<double>  vValuesNew;
	if(bIsParamValNode)
		vValuesNew = vBaselineParamVals;
	else
	{
		vValuesNew.SetSize(vBaselineParamVals.GetSize());
		vValuesNew = 0;
	}	
	vValuesNew.Append(vValues);
	
	if( trOneCol.TypeID == TNVAL_TYPE_INT_VECTOR )
		trOneCol.nVals = vValuesNew;
	
	if( trOneCol.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
		trOneCol.dVals = vValuesNew;	
}
///end FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL

bool PeakFitHelperBase::applyParamsOnTheme(TreeNode& trGetN)
{
	DWORD dwParamsToSkip = 0;
	//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
	TreeNode trParams = trGetN.PFMParams;
	
	///------ Folger 02/12/09 SHOULD_USE_PARAMS_SAVED_IN_GETN_IF_EXISTS_FOR_CHANGE_PARAM
	//if ( m_pFitWizCore->IsAutoUpdated() )
	if ( m_pFitWizCore->IsAutoUpdated() && !trParams.GetAttribute(STR_IS_PARAMS_SAVED_IN_GETN_ATTRIB, 1) )
	///------ End SHOULD_USE_PARAMS_SAVED_IN_GETN_IF_EXISTS_FOR_CHANGE_PARAM
	{
		trParams = trGetN.FitWorkArea.Parameters;
		/// Folger, 02/02/09, wrong fix, skip value apply should be based on auto param init status
		//dwParamsToSkip |= NLPARAMETERSETTINGS_VALUE;		///Kyle 01/24/2009 SHOULD_NOT_APPLY_PARAMETER_VALUES_WHEN_AUTO_UPDATE_IS_ON
	}
	/// Iris 02/24/2009 QA80-13170 NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
	// if parameter settings from change parameter, also need to check current baseline parameter number is identify with baseline parameter in theme or change parameter tree.
	// if not identify, need correct the current baseline param number to the number in theme.
	/*
	else
	{
	*/	
	///end NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
	//------ End CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
		if( trParams.FixedValues && !trParams.FixedValues.IsEmpty() && trParams.Values.IsEmpty() )
		{
			trParams.Values.dVals = trParams.FixedValues.dVals;
			dwParamsToSkip |= NLPARAMETERSETTINGS_VALUE;
		}
		
		/// Iris 02/24/2009 QA80-13170 NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
		/*
		/// Iris 12/24/2008 v8.0990c FIX_APPLY_SHARE_TO_BASELINE_PARAM_IF_CHANGED_FUNC_IN_BASECREATE_PAGE
		if( trParams.Share && !trParams.Share.IsEmpty() )
		{
			/// Iris 2/19/2009 FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG_MORE_CHANGE
			// according to change /// Iris 2/17/2009 FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG
			//int numBaselineParams = 0;
			int numBaselineParams = 1; // at least have y0, so default should be 1 not 0
			///end FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG_MORE_CHANGE
			
			string strBaselineFitFunciton;
			//--- Iris 01/16/2009 FIX_APPLY_SHARE_TO_INCORRECT_PARAM_IF_HAS_BASELINE_FUNC_WITHOUT_FIT
			//if(m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0) // if has baseline fit functioin
			/// Iris 02/13/2009 NOT_CORRECT_APPLY_PARAM_SHARE_STATUS_FOR_CONSTANT_BASELINE
			// when baseline mode is constant, this is one case of m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0, 
			// and also PA_BM_CONSTANT != m_pFitWizCore->GetBaseMode() is not a correct condition here, so remove it.
			//if(PA_BM_CONSTANT != m_pFitWizCore->GetBaseMode() && m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0)
			if(m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0)
			///end NOT_CORRECT_APPLY_PARAM_SHARE_STATUS_FOR_CONSTANT_BASELINE
			//---
			{			
				numBaselineParams = nlsf_get_number_of_params(strBaselineFitFunciton, STR_PA_NLSF_CAT_BASELINE);
			}
			
			vector<int> vnShare;
			vnShare = trParams.Share.nVals;
			int nBaselineParamNumInTheme = trParams.BaselineParameters.nVal;
			if( nBaselineParamNumInTheme < numBaselineParams )
			{
				vnShare.InsertAt(0, 0, numBaselineParams - nBaselineParamNumInTheme);
			}		
			if( nBaselineParamNumInTheme > numBaselineParams )
			{
				vnShare.RemoveAt(0, nBaselineParamNumInTheme - numBaselineParams);
			}

			/// Iris 2/19/2009 FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG_MORE_CHANGE
			// to fix: choose data and open PA without theme, goal is Fit Peaks, baseline mode is User Defined, function is Line, choose Fit Baseline,
			// go to parameter gird to share w_1 and w_2. Back to baseline treatment step, uncheck Fit Baseline then go to parameter grid, --> w_1 and w_2 shared; 
			// then back to baseline treatment step AGAIN, choose Fit Baseline then go to parameter grid, ==> NOT w_1 and w_2 shared.
			if( nBaselineParamNumInTheme != numBaselineParams)
				trParams.BaselineParameters.nVal = numBaselineParams;
			///end FIX_LOAD_THEME_INCLIDE_SHARE_PARAMS_BUG_MORE_CHANGE
				
			if( trParams.Share.nVals.GetSize() != vnShare.GetSize() )
				trParams.Share.nVals = vnShare;
		}
		///end FIX_APPLY_SHARE_TO_BASELINE_PARAM_IF_CHANGED_FUNC_IN_BASECREATE_PAGE
	}	//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
	*/
	/// Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	//if( trParams.BaselineParameters && !trParams.BaselineParameters.IsEmpty() ) 
	if( trParams.BaselineFunction ) // no BaselineFunction node in previous version, so if not this node will keep old logic here, below "else if" logic will NOT used any more.
	{
		if( isBaselineFunctionChanged(trParams) )
		{
			int nBaselineParamNumInTheme = trParams.BaselineParameters.nVal;		
			if ( nBaselineParamNumInTheme < 1 )
				nBaselineParamNumInTheme  = 1;

			vector vBLParamVals;
			int numBaselineParams = getBaselineParams(&vBLParamVals);
			if( numBaselineParams > 0 )
			{
				trParams.BaselineParameters.nVal = numBaselineParams;
				
				foreach(TreeNode trN in trParams.Children)
				{
					bool bIsParamValNode = 0 == trN.tagName.Compare("Values") ? true : false;
					if( trN.TypeID == TNVAL_TYPE_INT_VECTOR || trN.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
					{				
						checkUpdateParamSettingsOnBaselineFunctionChanged(trN, vBLParamVals, nBaselineParamNumInTheme, bIsParamValNode);
					}
				}	
			}
		}
	}
	else if( trParams.BaselineParameters && !trParams.BaselineParameters.IsEmpty() )  
	///end FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	{
		int numBaselineParams = 1; // at least have y0, so default should be 1 not 0
		string strBaselineFitFunciton;
		if(m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0)
		{			
			numBaselineParams = nlsf_get_number_of_params(strBaselineFitFunciton, getBaselineFuncCategory());
		}
		
		int nBaselineParamNumInTheme = trParams.BaselineParameters.nVal;		
		///------ Folger 03/09/09 BASELINE_PARAMETER_NUMBER_SAVE_IN_THEME_OF_SR4_NOT_APPLICABLE_IN_SR5
		/// if use theme came from SR4, then nBaselineParamNumInTheme may be 0, which is not correct in new design of
		/// SR5 : peak parameters will have at least one baseline parameter, no matter fitting with baseline or not
		if ( nBaselineParamNumInTheme < 1 )
			nBaselineParamNumInTheme  = 1;
		///------ End BASELINE_PARAMETER_NUMBER_SAVE_IN_THEME_OF_SR4_NOT_APPLICABLE_IN_SR5
		if( nBaselineParamNumInTheme != numBaselineParams)
		{
			trParams.BaselineParameters.nVal = numBaselineParams;
			
			foreach(TreeNode trN in trParams.Children)
			{
				if( trN.TypeID == TNVAL_TYPE_INT_VECTOR || trN.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
				{				
					checkUpdateParamSettingsOnBaselineParamsNumber(trN, numBaselineParams, nBaselineParamNumInTheme);
				}
			}	
		}
	}
	///end NOT_CORRECT_APPLY_BASELINE_PARAM_WHEN_CHANGE_PARAM
		
	
	//------ Folger 11/15/08 v8.0972 SHOULD_NOT_APPLY_PARAMETER_VALUES_WHEN_AUTO_INIT_IS_ON
	///------ Folger 02/13/09 IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM
	/// Seems we can only do this to fix #12765, although this will make back-and-forth in PA has different behavior
	/// between (Open dialog directly) and (ChangeParam), since ChangeParam will always ignore auto init status here ...
	//if ( GetFitSession()->GetAutoInitParams() )
	if ( GetFitSession()->GetAutoInitParams() && !m_pFitWizCore->IsChangeParam() )
	///------ End IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM
		dwParamsToSkip |= NLPARAMETERSETTINGS_VALUE;
	//------

	/// Hong 06/26/09 QA80-13846 AUTO_INIT_PARAMETER_IF_USER_HAVE_NOT_EDITED_PARAMETER_WHEN_CHANGE_DATA
	//return getParamsMngr()->SetParamSettings(trParams, dwParamsToSkip);
	return GetFitSession()->SetParamSettings(trParams, dwParamsToSkip);
	/// end AUTO_INIT_PARAMETER_IF_USER_HAVE_NOT_EDITED_PARAMETER_WHEN_CHANGE_DATA
}

/// Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
bool PeakFitHelperBase::isBaselineFunctionChanged(TreeNode& trParams)
{
	TreeNode trBLFunc = trParams.BaselineFunction;
	ASSERT(trBLFunc);
	
	// Not changed: current baseline fit function same as the baseline fit function in theme tree
	string strBaselineFitFunciton;
	if( m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFitFunciton) >= 0 && !trBLFunc.IsEmpty())
	{
		if( 0 == strBaselineFitFunciton.Compare(trBLFunc.strVal) )
			return false;
	}
	
	// Not changed: current has NOT baseline fit, and NOT baseline fit function in theme tree
	if( !m_pFitWizCore->GetBaselineFitMode() && trBLFunc.IsEmpty() ) 
	{
		return false;
	}
	
	// Changed, return true
	// NOT baseline fit function in theme tree, but current has baseline fit function, see as function changed.
	// has baseline fit function in theme tree, but current has NOT baseline fit function, see as function changed.
	return true;
}
///end FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL

void PeakFitHelperBase::applyAutoParamsInitOnTheme(const TreeNode& trGetN)
{
	if(trGetN.PFMParams.AutoParamsInit && !trGetN.PFMParams.AutoParamsInit.IsEmpty()) // if save AutoParamsInit setting to Theme
	{
		GetFitSession()->SetAutoInitParams(trGetN.PFMParams.AutoParamsInit.nVal);
	}	
}
///Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION, move code to PA
bool PeakFitHelperBase::setParams(bool bOnInit, TreeNode& trGetN)
{
	ASSERT_AND_RETURN_FALSE
}
///End NANO_CENTRIALIZE_FUNCTION
bool PeakFitHelperBase::setFunctions(bool bOnInit, TreeNode& trGetN)
{
	vector<string>		vsFunctions;
	prepareFunctions(vsFunctions, bOnInit, trGetN, true);
	
	return SetFunctions(vsFunctions);
}

bool PeakFitHelperBase::setData(TreeNode& trGetN)
{
	TreeNode trInput;
	if ( (trInput = prepareData(trGetN)) )
	{
		return UpdateData(trInput);
	}
	
	return false;
}

void PeakFitHelperBase::prepareFunctions(vector<string>& vsFunctions, bool bOnInit, TreeNode& trGetN, bool bIncludeBaselineFunction/* = false*/)
{
	//doing...
	ASSERT(0);
}
virtual TreeNode PeakFitHelperBase::prepareData(TreeNode& trGetN)
{
	TreeNode trJunk;
	ASSERT(false);
	return trJunk;
}

bool PeakFitHelperBase::createFitSessionAndPAParamInitHelper()
{
	////------ Folger 04/23/08 SUPPORT_GROUP_SHARED_IN_NANOSIZER
	////if( NULL == m_pFitSession && 0 == m_strOperation.CompareNoCase("FitNL"))
	//if( NULL == m_pFitSession && 0 == m_strOperation.CompareNoCase("FitPeak"))
	////------
	//{
		//if(m_strCategory.IsEmpty())
			//m_pFitSession = new MulFuncsFitSession(bPreview);
		//else
			//m_pFitSession = new MulFuncsFitSession(bPreview,  m_strCategory);
	//}
	//
	//if(NULL == m_pFitSession)
		//return error_report("fail to new m_pFitSession");

	///Jasmine 05/05/09 NANO_CENTRIALIZE_FUNCTION
	//bool	bSingleFunc = false;
	//m_pFitSession = new NLFitSession(bSingleFunc);
	m_pFitSession = new NLFitSession( IsSingleFuncFit() );
	///End NANO_CENTRIALIZE_FUNCTION
	
	GetFitSession()->SetDisableUpdate(true);
	GetFitSession()->SetAutoInitParams(true);
	
	///------ Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT
	//m_pParamInitHelper = new PAParamInitHelper(GetFitSession());
	m_pParamInitHelper = createParamInitHelper();
	///------ End NANOSIZER_FITTING_BASED_SUPPORT
	
	return true;
}

void	PeakFitHelperBase::destroyFitSessionAndPAParamInitHelper()
{
	ASSERT(m_pParamInitHelper);
	delete m_pParamInitHelper;
	m_pParamInitHelper = NULL;
	
	ASSERT(m_pFitSession);
	delete m_pFitSession;
	m_pFitSession = NULL;
}


virtual bool 	PeakFitHelperBase::createPreivewCtrl()
{
	if(NULL == m_pPreviewCtrl)
		m_pPreviewCtrl = new PeakFitPreviewCtrl(m_pFitSession);
	
	ASSERT(m_pPreviewCtrl);
	if(NULL == m_pPreviewCtrl)
		return false;
	return true;
}

virtual void 	PeakFitHelperBase::destroyPreivewCtrl()
{
	//----- Iris 9/11/2008 PA_PREVIEW
	ASSERT(m_pPreviewCtrl);
	delete m_pPreviewCtrl;
	m_pPreviewCtrl = NULL;
	//-----
}

PeakFitPreviewCtrl*	PeakFitHelperBase::getPreivewCtrl()
{
	ASSERT( m_pPreviewCtrl );
	return m_pPreviewCtrl;
}

NLParametersManager* PeakFitHelperBase::getParamsMngr()
{
	NLParametersManager*	pNLParamsMngr = GetFitSession()->GetNLParamsMngr();
	ASSERT(pNLParamsMngr);
	return pNLParamsMngr;
}

/////------ Folger 12/22/08 v8.0990 CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT
//void	PeakFitHelperBase::checkUpdateCacheFitFunctionInfo(LPCSTR lpcszFunction)
//{
	//check_update_fit_function_info(m_cacheFitFunctionInfo, lpcszFunction);
//}
/////------ End CACHE_FIT_FUNCTION_IN_PA_FOR_BOTH_SET_FUNCTION_AND_PARAM_INIT

NLFitSession* PeakFitHelperBase::GetFitSession()
{
	ASSERT( m_pFitSession );
	return m_pFitSession;
}

bool PeakFitHelperBase::InitParams(	PEAKINFOARGUMENTSLISTPARAMS*		pstPEAKINFOARGUMENTSLISTPARAMS/* = NULL*/,
									PEAKINFOARGUMENTSLISTFUNCTIONS*		pstPEAKINFOARGUMENTSLISTFUNCTIONS/* = NULL*/,
									PEAKINFOARGUMENTSLISTBASE*			pstPEAKINFOARGUMENTSLISTBASE/* = NULL*/,
									PEAKINFOARGUMENTSLISTBASELINE*		pstPEAKINFOARGUMENTSLISTBASELINE/* = NULL*/,
									bool*								pbHasBaselinePeak/* = NULL*/,
									bool								bLoadValuesFromFDFOnly/* = false*/)
{	
	ASSERT(GetParamInitHelper());
	NOTIFY_NLFSESSION_ON_PARAMETERS_CHANGED
	//----- Iris 11/27/2008 v8.0980 NOT_KEEP_FIX_IF_FIX_BASELINE_PARAMS_IN_BASETREAT
	//return GetParamInitHelper()->InitParamsMngr(pstPEAKINFOARGUMENTSLISTPARAMS, pstPEAKINFOARGUMENTSLISTFUNCTIONS, pstPEAKINFOARGUMENTSLISTBASE, pstPEAKINFOARGUMENTSLISTBASELINE, pbHasBaselinePeak, bLoadValuesFromFDFOnly);
	return GetParamInitHelper()->InitParamsMngr(pstPEAKINFOARGUMENTSLISTPARAMS, pstPEAKINFOARGUMENTSLISTFUNCTIONS, pstPEAKINFOARGUMENTSLISTBASE, pstPEAKINFOARGUMENTSLISTBASELINE, pbHasBaselinePeak, bLoadValuesFromFDFOnly, m_pFitWizCore->GetBaseParamFixMode());
	//-----
}

bool	PeakFitHelperBase::ReinitParamsOnFuncChange(const vector<int>&	vnPeakIndecies,
										PEAKINFOARGUMENTSLISTFUNCTIONS*	pstPEAKINFOARGUMENTSLISTFUNCTIONS/* = NULL*/,
										bool							bLoadValuesFromFDFOnly/* = false*/)
{
	ASSERT(GetParamInitHelper());
	NOTIFY_NLFSESSION_ON_PARAMETERS_CHANGED
	return GetParamInitHelper()->ReinitParamsMngrOnFuncChange(vnPeakIndecies, pstPEAKINFOARGUMENTSLISTFUNCTIONS, bLoadValuesFromFDFOnly);
}

bool	PeakFitHelperBase::ReinitParamsOnPeakChange(const vector<int>&	vnPeakIndecies,
										PEAKINFOARGUMENTSLISTPARAMS&	stPEAKINFOARGUMENTSLISTPARAMS,
										LPCSTR							lpcszDefaultFunction,
										bool							bLoadValuesFromFDFOnly/* = false*/,
										bool							bRemovePeak/* = false*/
										)
{
	ASSERT(GetParamInitHelper());
	NOTIFY_NLFSESSION_ON_PARAMETERS_CHANGED
	return GetParamInitHelper()->ReinitParamsMngrOnPeakChange(vnPeakIndecies, stPEAKINFOARGUMENTSLISTPARAMS, lpcszDefaultFunction, bLoadValuesFromFDFOnly, bRemovePeak);
}

string PeakFitHelperBase::GetDefaultFunction()
{ 
	return m_strDefaultFunction; 
}
void PeakFitHelperBase::SetDefaultFunction(LPCSTR lpcszFunc)
{
	m_strDefaultFunction = lpcszFunc; 
}
///Jasmine 04/27/09 NANO_CENTRIALIZE_FUNCTION
virtual bool PeakFitHelperBase::SetFunction(string strFunction, int nFunc/* = 0*/, bool bResetFunction/* = true*/)
{
	ASSERT_AND_RETURN_FALSE
}
///End NANO_CENTRIALIZE_FUNCTION

///Jasmine 06/12/09 VIRTUAL_FOR_NANOSIZER
virtual bool PeakFitHelperBase::SetFunctions(const vector<string>& vsFunctions, bool bSkipBaseline/* = false*/)
///End VIRTUAL_FOR_NANOSIZER
{
	ASSERT(GetFitSession());
	
	//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
	int nFuncsNum = vsFunctions.GetSize();
	string strTitle = _L("Loading Fitting Functions......");
	string strTips;
	progressBox pb("", PBOX_TOPMOST, nFuncsNum < NLFIT_NUM_PEAKS_THRESHOLD_TO_SHOW_PROGRESSBOX? true:false);
	pb.SetText(strTitle, PBOXT_TITLE);
	pb.SetRange(0,nFuncsNum);
	//--end ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW


	int nPeakOffset = bSkipBaseline ? getPeaksOffset() : 0;
	for ( int nFunc=0; nFunc<vsFunctions.GetSize(); ++nFunc )
	{
		//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        strTips.Format(_L("Loading fitting functions, current peak = %d......"), nFunc);
        if(pb.Set(nFunc))
        {
            pb.SetText(strTips, PBOXT_MIDCENTER);
        }
        else
        {
        	 return error_report("User abort!");
            //out_str("User abort!");
            //break;
        }
        //SetStatusBarText(str);  
        //--endADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        
        	if ( !SetFunction(vsFunctions[nFunc], nFunc + nPeakOffset, nFunc == 0 ? true : false) )
				return false;
	}
	
	return true;
}
	
bool PeakFitHelperBase::UpdateData(TreeNode& trInputData)
{
	ASSERT(GetFitSession() && trInputData);
	
	if ( !okutil_is_fitter_data_node_ready(&trInputData) )
		return false;
	
	return m_pFitSession->SetData(trInputData);
}

virtual void PeakFitHelperBase::InitPreview(const TreeNode& trGetN)
{
	//doing...
	ASSERT(false);
}

/// Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION
bool PeakFitHelperBase::IsReadyIterations(bool *pbChiSqrReady)
{
	if(NULL != m_pFitSession)
	{
		return m_pFitSession->IsReadyIterations(pbChiSqrReady);	
	}
	return false;
}
///end CORRECT_ENABLE_FIT_BUTTON_CONDITION
			
///Jasmine 03/11/08 SHOW_FITCONTROL_BRANCH_IN_XF_NOT_IN_PARAMDLG_BY_CP_REQUEST
void PeakFitHelperBase::SetLinearConstraints(TreeNode& trLinearConstraints, bool bConstraints)
{
	GetFitSession()->SetEnableLinearConstraints(trLinearConstraints, bConstraints);
	NOTIFY_NLFSESSION_ON_PARAMETERS_CHANGED	
}
void PeakFitHelperBase::SetTolerance(double dTolerance)
{
	GetFitSession()->SetTolerance(dTolerance);
	GetFitSession()->ResetFitOutCome();
}

void PeakFitHelperBase::SetNumMaxIter(int nMaxIter)
{
	GetFitSession()->SetMaxNumIter(nMaxIter);
	GetFitSession()->ResetFitOutCome();
}
///End SHOW_FITCONTROL_BRANCH_IN_XF_NOT_IN_PARAMDLG_BY_CP_REQUEST
///Jasmine 06/06/08 QA80-11656 PA_FIT_HAS_NOT_UPDATED_LCL_SETTING
void PeakFitHelperBase::SetIsGetParamsConf(const TreeNode& trQuantities)
{
	Tree trOp;
	if(m_pnlOp)
		m_pnlOp->GetTree(trOp);
	
	TreeNode trGUI = trOp.GUI;
	if(!trGUI || NULL == m_pFitSession || !trQuantities)
	{
		ASSERT(false);
		return;
	}
	
	m_pFitSession->SetIsGetParamsConf(trQuantities.Parameters, trQuantities.SummaryTable, trGUI.Fit.CIMethod);
}
///End PA_FIT_HAS_NOT_UPDATED_LCL_SETTING

///Jasmine 02/01/08 FITCURVE_POINTS_PER_PEAR
//void PeakFitHelper::UpdateFitCurveOptions(TreeNode& trGraph1)
//void PeakFitHelper::UpdateFitCurveOptions(TreeNode& trGraph1, Page& pg)///Sandy 2008-4-9 ADD_PG_TO_GET_AVG_WIDTH_FOR_ESTIMATE_FITTING_NPTS 
void PeakFitHelperBase::UpdateFitCurveOptions(TreeNode& trGraph1, bool bUpdateXDataMinMaxByAuto)//false	///Jasmine 05/17/08 UPDATE_X_DATA_MIN_MAX_BY_AUTO
{
	if(!trGraph1)
		return;
	
	if(bUpdateXDataMinMaxByAuto)	///Jasmine 05/17/08 UPDATE_X_DATA_MIN_MAX_BY_AUTO
		m_pFitSession->UpdateXDataMinMaxByAuto(trGraph1.XDataType);		
	
	if(NULL != m_pFitSession)
		getPreivewCtrl()->SetFitCurveOptions(trGraph1);
}
///End FITCURVE_POINTS_PER_PEAR

bool PeakFitHelperBase::UpdateSettingOnChange(TreeNode& trGetN)
{
	ASSERT(trGetN);
		
	TreeNode trParams = trGetN.PFMParams;
	if( !trParams )
		return error_report("Invalid trGetN.PFMParams in PeakFitHelper::UpdateSettingOnChange");		
	
	Tree		trPFM;
	//TreeNode	trPFM = tr.AddNode("PFM"); // this name not important
	getParamsMngr()->GetParamSettings(trPFM);	
	foreach(TreeNode trN in trPFM.Children)
	{
		TreeNode trDest = trParams.GetNode(trN.tagName);
		if(trDest)
		{
			//--- Iris 10/06/2008 temp code to copy value since Replace and tree_copy_values fail to copy vector value with new format
			//trDest.Replace(trN.Clone(), true, true, true);
			//tree_copy_values(trN, trDest, TREE_COPY_BY_NAME_AND_ORDER);
			if( trN.TypeID == TNVAL_TYPE_INT_VECTOR )
			{
				trDest.nVals = trN.nVals;
			}
			if( trN.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
			{
				trDest.dVals = trN.dVals;
			}
			if( trN.TypeID == TNVAL_TYPE_CSTRING_VECTOR )
			{
				trDest.strVals = trN.strVals;
			}	
			//---
		}
		//else  // just for debug
		//{
			//string str;
			//str.Format("Not find parameter settings node %s to save in theme", trN.tagName);
			//error_report(str);
		//}
	}
	
	if ( trParams.FixedValues && trParams.Values )
		trParams.FixedValues.dVals = trParams.Values.dVals;
	
	if( trParams.AutoParamsInit )
		//------ Folger 10/29/08 v8.0962 CORRECTLY_SET_AUTO_INIT_STATUS_INTO_PARAMS_TREE
		//trParams.AutoParamsInit.nVal = getParamInitHelper()->IsAutoRunInitParams();
		trParams.AutoParamsInit.nVal = GetFitSession()->GetAutoInitParams();
		//------
		
	
	vector<string> vsFunctions;			
	GetFitSession()->GetAllFunctions(vsFunctions);
	if( trParams.Functions )
		//------ Folger 12/03/08 QA80-12701 v8.0982 THEME_SETTING_CONTROL_FOR_BASELINE_FUNCTION_APPLIED_IN_PA_FIT
		//trParams.Functions.strVals = vsFunctions;
		AccessPFMTreeFunctions(trParams, vsFunctions, false);
		//------
	
	if( trParams.BaselineParameters )
		trParams.BaselineParameters.nVal = getNumBaselineParams();		
		
	/// Iris 11/04/2008 v8.0965b SAVE_DEFAULT_FUNC_TO_THEME	
	if( trParams.DefaultFunction )
		trParams.DefaultFunction.strVal = GetDefaultFunction();
	///end SAVE_DEFAULT_FUNC_TO_THEME
	
	trParams.SetAttribute(STR_IS_PARAMS_SAVED_IN_GETN_ATTRIB, 1);		///------ Folger 02/12/09 SHOULD_USE_PARAMS_SAVED_IN_GETN_IF_EXISTS_FOR_CHANGE_PARAM
	
	return true;
}

void PeakFitHelperBase::SetPFWTree(const TreeNode& trGetN, const TreeNode& trPFWTree)
{
	if( !trPFWTree || trPFWTree.IsEmpty() )
		return;
	
	bool bRet = getParamsMngr()->SetFuncsAndParamsMultiFuncsPeakFitting(trPFWTree);
		ASSERT(bRet);
}
void PeakFitHelperBase::GetPFWTree(const TreeNode& trGetN, TreeNode& trPFWTree)
{
	if( !trPFWTree )
		return;
	
	bool bRet = getParamsMngr()->GetFuncsAndParamsMultiFuncsPeakFitting(trPFWTree);
		ASSERT(bRet);
}

//virtual 
///Sophy 9/23/2008 NEW_PA
bool PeakFitHelperBase::Init(TreeNode& trGetN)
{
	if ( !trGetN )
	{
		ASSERT_AND_RETURN_FALSE
	}
	///------ Folger 01/07/09 QA80-12925-P1 v8.0994b ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
	m_pnlOp->SetHelperClass(this);
	///------ End ORIGIN_CRASH_IN_PA_FITTING_WHEN_NEW_PROJECT
	m_nInitRuntimeError = CER_NO_ERROR;
	
	///Jasmine 05/05/09 SetFitType_WAS_ONCE_DONE_IN_InitFromOperationTree
	Tree trOp;
	m_pnlOp->GetTree(trOp);	
	GetFitSession()->SetFitType(trOp.SpecInfo);
	///End SetFitType_WAS_ONCE_DONE_IN_InitFromOperationTree
	
	/// Iris 2/25/2009 QA80-13180 FIX_NOT_APPLY_CORRECT_DEFAULT_FUNC_FOR_NEWLY_ADD_PEAK
	// if op PA with two peaks data, choose Peak Function combobox to choose Voigt functioin and do report.
	// Clear source worksheet and input 5 peaks data and do recalculate, for last 3 peaks, should fit with Voigh function,
	// but current function is Gauss.
	
	// init default function by GetN
	TreeNode trDefaultFunction = trGetN.PFMParams.DefaultFunction;
	if( trDefaultFunction && !trDefaultFunction.IsEmpty() )
		SetDefaultFunction(trDefaultFunction.strVal);
	///end FIX_NOT_APPLY_CORRECT_DEFAULT_FUNC_FOR_NEWLY_ADD_PEAK
	
	// set function, set data and init parameters
	if( !setFunctions(true, trGetN) )
	{
		m_nInitRuntimeError = XFERR_PA_FIT_SET_FUNCTION_FAIL;
		///------ Folger 03/05/09 QA80-12821-P2 CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
		//return error_report("Fail to set function in PeakFitHelperBase::Init");
		error_report("Fail to set function in PeakFitHelperBase::Init");
		///------ End CANCEL_SET_FUNCTIONS_IN_PA_FITTING_CAUSE_ORIGIN_CRASH
	}
	
	if( !setData(trGetN) )
	{
		error_report("Fail to set data in PeakFitHelperBase::Init");
	}
		
	if( !setParams(true, trGetN) )
	{
		error_report("Fail to set Params in PeakFitHelperBase::Init");
	}
	
	// init GetN
	initGetN(trGetN);	
	
	initSessionSettingsFromGetN(trGetN);	
	
	// update fit session by operation tree from theme
	/// Iris 9/22/2008 NEW_PA
	//PrepareOperationTree(trOp, trGetN, trPFM);//copy setting from trGetN and do other preparation	
	PrepareOperationTree(trOp, trGetN);
	///end NEW_PA
	
	// copy pointers from GUI tree to GetN tree
	updateOperationAndOutManagerPointer( trOp.GUI, trGetN.result );	///Sophy 10/9/2008 FIX_FAIL_TO_GET_OUTPUT_MANAGER_AND_OPERATION_POINTER_IN_OUTPUT_EVENT
	
	///Jasmine 05/05/09 OPENRATION_TREE_IS_CHANGED_AND_SHOULD_SET_IN_OPENRATION
#ifdef FIX_SET_OPERATION_TREE_AFTER_CHANGE
	m_pnlOp->SetTree(trOp);
#endif//FIX_SET_OPERATION_TREE_AFTER_CHANGE
	///End OPENRATION_TREE_IS_CHANGED_AND_SHOULD_SET_IN_OPENRATION
	
	// init preview control
	/// Iris 10/31/2008 V8.0963d MOVE_2ND_DERVITIVE_PLOT_CODES_TO_PAWIZCORE
	//GraphLayer gl;
	//m_pPAWizCore->GetPreviewLayer( gl );
	//InitPreview( trGetN.result.gpconfig.Graph1, gl );
	InitPreview( trGetN );
	///end MOVE_2ND_DERVITIVE_PLOT_CODES_TO_PAWIZCORE

	/// Iris 10/20/2008 CLEAN_INIT_SESSION_CODES
	/*
	FITCONTROL		stFITCONTROL;
	stFITCONTROL.nMaxNumIter = trGetN.FitControl.MaxNum.nVal;
	stFITCONTROL.rTolerance = trGetN.FitControl.Tolerance.dVal;
	UpdateFitControlSettings(stFITCONTROL);
	*/
	///end CLEAN_INIT_SESSION_CODES  

	//bool bHasFitGood = false, bParamsReady = false;
	//if( !m_pFitSession->InitFromOperationTree(trOp, bHasFitGood, bParamsReady))//, false, bool bAutoInitParams = false, bool bInitData = false, bool bLoadFDF = true);
		//return false;	
		
	/// Iris 9/22/2008 NEW_PA, no need, paWizCore has save baseline data range 
	//initBaselineData(pg, trPFM);//should after InitFromOperationTree
	///end NEW_PA
	
	//updatefitSessionParameterSettingsFromTree(trGetN.PFMParams, trPFM, (-1 == nBaselineFixed)? NULL : &nBaselineFixed);///Jasmine 01/22/08 NEW_OPTION_OF_FIX_BASELINE_FOR_EACH_PARA_USING_ITS_OWN_SETTING	
	//UpdateSettingOnChange(trGetN);
	//setParamValToPFMTree(pg, trGetN, trPFM);
	
	//------ Folger 11/05/08 QA80-12509 v8.0965 SUPPORT_BOTH_PEAKS_SORTING_AND_REORDERING_FOR_MULTIPLE_PEAKS_FITTING
	SetPeakReorderingEnable(false);
	//------
	
	return true;
}
///end NEW_PA

///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE, move from PA
static	void	_get_output_range(/*DataRange& range, int& nIndex*/vector<int>& vnUIDs, const Operation* pOp)
{
	//------ Folger 11/13/08 QA80-12488 v8.970 PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	/*
	while ( nIndex < OUTPUT_RESULT_RNG_INDEX_END )
	{
		DataRange rng;
		pOp->GetOutput(rng, nIndex++);
		
		if ( rng )
		{
			int nUID = rng.GetUID();
			for ( int jj=0; jj<rng.GetNumRanges(); ++jj )
			{
				int			r1, c1, r2, c2;
				Datasheet	ds;
				string		strName;
				rng.GetRange(jj, r1, c1, r2, c2, ds, &strName);
				rng.SetRange(jj, ds, r1, c1, r2, c2, _composite_subrange_name((string)nUID, strName));
				break;
			}
			range = rng;
			break;
		}
	}
	*/
	for ( int ii=0; ii<pOp->GetOutputCount(); ++ii )
	{
		DataRange rng;
		pOp->GetOutput(rng, ii);
		
		vnUIDs.Add(rng ? rng.GetUID() : 0);
		
		if( rng )
			pOp->RemoveOutput(rng, FALSE); /// YuI
	}
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
}
///End NANOSIZER_NEED_CENTRALIZE

//virtual
///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE, move from PA
//int PeakFitHelper::ExecuteOperation(GraphLayer& gl, Page& pg, const TreeNode& trGetN)
/// Iris 11/15/2008 v8.0972 QA80-12584_P7 FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
//int PeakFitHelper::ExecuteOperation(const GraphLayer& gl, const TreeNode& trGetN, /*DataRange& range1, DataRange& range2, DataRange& range3*/TreeNode &trUID)
int PeakFitHelperBase::ExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode &trUID)
///end FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
///end NEW_PA
{	
	/// Iris 9/17/2008 NEW_PA
	//if(!pg)
	//	return CER_INVALID_PAGE;
	///end NEW_PA
	
#ifdef _DEBUG
	Profiler  junk;
#endif

	bool	bInitOK = false; //output to know if do init gui ok
	int		nOption = 0;
	int		nAutoUpdate = 0; //output to get recalculation mode
	
	///Jasmine 04/10/08 KEEP_OPERATION_IN_PEAK_FITHELPER	
	//Operation& op = (Operation &)op_create(m_strOperation, bInitOK); 
	if(!m_pnlOp)
		return XFERR_FAIL_TO_CREATE_OPERATION;	
	
	Tree 	trOp;
	m_pnlOp->GetTree(trOp);	
	/// Iris 9/17/2008 NEW_PA
	//beforeExecuteOperation(gl, pg, trGetN, trOp);	
	///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	//beforeExecuteOperation(gl, trGetN, trOp);
	beforeExecuteOperation(gl, trGetN, trOp, trUID);
	///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	///end NEW_PA
	m_pnlOp->SetTree(trOp);
	
	m_pnlOp->OnNoEdit(nOption, nAutoUpdate); //save GUI settings to last used theme	

	/// Hong 01/12/10 QA80-14948 NLFIT_SUPPORT_OK_BTN_WHICH_DONOT_FIT_AGAIN
	/*
	BOOL bUserAskNotToDoMoreFit = false;
	if(trGetN.nofit && trGetN.nofit.nVal > 0)
	{
		/// Hong 10/27/08 v8.0961 FIX_GENERATE_REPORT_WITHOUT_ITERATE_FAIL_GET_PARAM_SETTINGS
		//------ Folger 12/10/08 QA80-12751 v8.0984d SUPPORT_ALWAYS_GENERATE_OUTPUTS_REGARDLESS_OF_INTERATION_IN_PA_FITTING
		//m_pFitSession->GetChiSqr();
		m_pFitSession->GetChiSqr(NULL, m_pFitSession->GetNumberItersPerformed() == 0 ? true : false);
		//------ End SUPPORT_ALWAYS_GENERATE_OUTPUTS_REGARDLESS_OF_INTERATION_IN_PA_FITTING
		/// end FIX_GENERATE_REPORT_WITHOUT_ITERATE_FAIL_GET_PARAM_SETTINGS
		bUserAskNotToDoMoreFit = true;
	}
	
	DWORD dwExeCntrl = bUserAskNotToDoMoreFit? OPEXEC_NO_FIT_AGAIN : 0;	
	*/
	DWORD 	dwExeCntrl = 0;
	if ( trGetN.nofit && trGetN.nofit.nVal > 0 )
		dwExeCntrl |= OPEXEC_NO_FIT_AGAIN | OPEXEC_FORCE_CALCUTE_OUTPUT;
	/// end NLFIT_SUPPORT_OK_BTN_WHICH_DONOT_FIT_AGAIN
	dwExeCntrl |= OPEXEC_NO_INIT_FROM_OP_AGAIN;	///Jasmine 04/08/08 NO_INIT_FIT_SESSION_FROM_OP_TREE_AGAIN
	dwExeCntrl |= OPEXEC_NO_PARAM_INIT;			///Jasmine 04/15/08 PEAK_FIT_NO_PARAM_INIT_AGAIN
	
	///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	/*
	///------ Folger 01/19/09 QA80-12969 PA_FITTING_SUPPORT_ANALYSIS_TEMPLATE
	DWORD	dwWizOp = m_pPAWizCore->GetXFWizOp();
	if ( dwWizOp > 0 )
	{
		Operation& opWiz = (Operation&)Project.GetOperationObject(dwWizOp);
		_update_range_uids_by_wiz_op(trUID.range_uid, &opWiz);
	}
	///------ End PA_FITTING_SUPPORT_ANALYSIS_TEMPLATE
	
	//------ Folger 11/13/08 QA80-12488 v8.970 PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	////------ Folger 11/12/08 QA80-12488 v8.0969 PA_FITTING_AUTO_UPDATE_SUPPORT
	////_get_output_range(m_pnlOp, 0, range1);
	////_get_output_range(m_pnlOp, 1, range2);
	////_get_output_range(m_pnlOp, 2, range3);
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT
	vector<int>		vnUIDs;
	vnUIDs = trUID.range_uid.nVals;
	/// YuI 11/14/08 NEED_TO_REMOVE_AND_THEN_RESTORE_OUTPUTS
	vector<int> vWizardOutputUIDs;
	int nWizardOperationUID;
	_remove_wizard_operation_outputs(vnUIDs, vWizardOutputUIDs, nWizardOperationUID);
	/// end NEED_TO_REMOVE_AND_THEN_RESTORE_OUTPUTS
	_set_output_range(m_pnlOp, vnUIDs);
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	*/
	///------ End PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	
	//------ Folger 11/15/08 QA80-12488 v8.0972 NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
	vector<uint>		vnGraphUIDs;
	///------ Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
	if ( trGetN.trUID.graph_uid )
		trUID.graph_uid.nVals = trGetN.trUID.graph_uid.nVals;
	///------ End REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
	vnGraphUIDs = trUID.graph_uid.nVals;
	m_pnlOp->SetIdsToUIDsMap(vnGraphUIDs);
	//------ End NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
	
	///------ Folger 03/16/09 QA80-13279 REMINDER_MESSAGE_FOR_SWITCH_TO_REPORT_SHEET_SHOULD_NOT_BE_SHOWN_DURING_AUTO_UPDATE
	//if( !m_pnlOp->Execute(OEXEM_ON_CREATE, dwExeCntrl))
	///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	//if( !m_pnlOp->Execute(m_pFitWizCore->IsAutoUpdated() ? OEXEM_ON_AUTOUPDATE_MANUAL : OEXEM_ON_CREATE, dwExeCntrl))
	int		nExecuteMode = OEXEM_ON_CREATE;
	if ( m_pFitWizCore->IsChangeParam() )
		nExecuteMode = OEXEM_ON_CHANGEPARAM;
	else if ( m_pFitWizCore->IsRecalculate() )
		nExecuteMode = OEXEM_ON_AUTOUPDATE_MANUAL;
	if( !m_pnlOp->Execute(nExecuteMode, dwExeCntrl))
	///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	///------ End REMINDER_MESSAGE_FOR_SWITCH_TO_REPORT_SHEET_SHOULD_NOT_BE_SHOWN_DURING_AUTO_UPDATE
	{
		return XFERR_FAIL_TO_DO_CALC_OR_REPORT;
	}	
	
	m_pnlOp->GetTree(trOp);
	///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	//afterExecuteOperation(trGetN, trOp);
	afterExecuteOperation(trGetN, trOp, trUID);
	///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	
	//------ Folger 11/13/08 QA80-12488 v8.970 PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	////------ Folger 11/12/08 QA80-12488 v8.0969 PA_FITTING_AUTO_UPDATE_SUPPORT
	////int			nIndex = 0;
	////_set_output_range(range1, nIndex, m_pnlOp);
	////_set_output_range(range2, nIndex, m_pnlOp);
	////_set_output_range(range3, nIndex, m_pnlOp);
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT
	m_vnUIDs.RemoveAll();
	_get_output_range(m_vnUIDs, m_pnlOp);
	trUID.range_uid.nVals = m_vnUIDs;
	//------ End PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
	
	//------ Folger 11/15/08 QA80-12488 v8.0972 NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
	m_pnlOp->GetIdsToUIDsMap(vnGraphUIDs);
	trUID.graph_uid.nVals = vnGraphUIDs;
	//------ End NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
	
	/// YuI 11/14/08 NEED_TO_REMOVE_AND_THEN_RESTORE_OUTPUTS
	//_restore_wizard_operation_outputs(vWizardOutputUIDs, nWizardOperationUID);		///------ Folger 01/22/09 PEAK_FITTING_OUTPUTS_HELPER_CLEANUP
	/// end NEED_TO_REMOVE_AND_THEN_RESTORE_OUTPUTS
	
	m_pnlOp->DestroyInternal();
	ResetOperationPtr();
	
	//------ End TESTING_ON_OPERATION_OUTPUT_SAVING
	
	/// Iris 9/17/2008 NEW_PA, no need
	//m_bOperationHasFitSession = true;		///Jasmine 04/15/08 HARD_TO_CHECK_FITSESSION_POINTER_IN_OPERATION
	///end NEW_PA
	
	///End KEEP_OPERATION_IN_PEAK_FITHELPER
	return CER_NO_ERROR;
}
///End NANOSIZER_NEED_CENTRALIZE

/// Iris 9/22/2008 NEW_PA
//bool PeakFitHelper::PrepareOperationTree(TreeNode& trOp, const TreeNode& trGetN, const TreeNode& trPFM)
bool PeakFitHelperBase::PrepareOperationTree(TreeNode& trOp, const TreeNode& trGetN)
///end NEW_PA
{
	if(!trOp)
		return false;
	
	TreeNode trGUI = trOp.GUI;
	if(!trGUI)
		return false; 
	
	copySettingsToOperation(trGetN, trGUI);	
	
	///------ Folger 07/13/09 QA80-12142 FITTED_CURVE_GRAPH_IS_MISSING_IN_PA_REPORT
	#ifndef		FIX_SET_OPERATION_TREE_AFTER_CHANGE
	tree_set_attribute_to_all_nodes(trGUI, STR_SHOW_ATTRIB, "0", true);
	#endif		/// !FIX_SET_OPERATION_TREE_AFTER_CHANGE
	///------ End FITTED_CURVE_GRAPH_IS_MISSING_IN_PA_REPORT
	//trGUI.FitControl.Show = true;
		
	// setNumberMultiplicity(trPFM, trGUI);	 /// Iris 9/22/2008 NEW_PA, talk with Hong, replica is unmeaning for multi func fit, Replica node should be disable in pa fit, so comment out
	
	trOp.FitWorkArea.ID = 1; //create FitWorkArea with ID same in NLFitSession.h
	trOp.FitWorkArea.Parameters.ID = 2;

	return true;
}

//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
bool		PeakFitHelperBase::UpdateFitWorkArea(TreeNode& trFitWorkArea)
{
	TreeNode trParams = trFitWorkArea.Parameters;
	if ( !trParams )
		return false;
	
	Tree		trPFM;
	getParamsMngr()->GetParamSettings(trPFM);	
	foreach ( TreeNode trN in trPFM.Children )
	{
		TreeNode trDest = trParams.GetNode(trN.tagName);
		if(trDest)
		{
			if( trN.TypeID == TNVAL_TYPE_INT_VECTOR )
			{
				trDest.nVals = trN.nVals;
			}
			if( trN.TypeID == TNVAL_TYPE_DOUBLE_VECTOR )
			{
				trDest.dVals = trN.dVals;
			}
			if( trN.TypeID == TNVAL_TYPE_CSTRING_VECTOR )
			{
				trDest.strVals = trN.strVals;
			}	
		}
	}
	
	///------ Folger 02/24/09 FITWORKAREA_SHOULD_CONTAIN_BASELINE_PARAMETERS_NUMBER_INFO_INORDER_TO_CORRECTLY_APPLY
	/// would be used in PeakFitHelperBase::applyParamsOnTheme
	if( trParams.BaselineParameters )
		trParams.BaselineParameters.nVal = getNumBaselineParams();
	///------ End FITWORKAREA_SHOULD_CONTAIN_BASELINE_PARAMETERS_NUMBER_INFO_INORDER_TO_CORRECTLY_APPLY
	
	/// Iris 3/30/2009 QA80-13362 FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	if( trParams.BaselineFunction )
	{
		string strBaselineFunc;
		if( m_pFitWizCore->GetBaselineFitMode() && m_pFitWizCore->GetBaselineFitFunc(strBaselineFunc) >= 0 )
		{
			trParams.BaselineFunction.strVal = strBaselineFunc;
		}
	}
	///end FIX_CHANGE_BASELINE_FUNC_FIT_STATUS_FROM_NONE_TO_FIT_INSERT_0_FOR_REDUNDANT_BASELINE_PARAM_VAL
	
	return true;
}
//------ End CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING

/// Iris 9/17/2008 NEW_PA
//virtual void PeakFitHelper::beforeExecuteOperation(GraphLayer& gl, Page& pg, const TreeNode& trGetN, TreeNode& trOp)
/// Iris 11/15/2008 v8.0972 QA80-12584_P7 FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
//virtual void PeakFitHelper::beforeExecuteOperation(const GraphLayer& gl, const TreeNode& trGetN, TreeNode& trOp)
///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
//virtual void PeakFitHelperBase::beforeExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode& trOp)
/// virtual
void PeakFitHelperBase::beforeExecuteOperation(const GraphLayer& gl, TreeNode& trGetN, TreeNode& trOp, TreeNode& trUID)
///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
///end FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
///end NEW_PA
{
	///------ Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
	m_pFitWizCore->UpdateGetNFromWizOp(trGetN);
	///------ End REUID_PA_OUTPUTS_FOR_AUTO_UPDATE

	// store PFM tree to trOp
	Tree	trPFM;
	GetPFWTree(trGetN, trPFM);
	TreeNode	trOpPFM = trOp.AddNode("PFWTree");
	trOpPFM.Replace(trPFM.Clone(), true, true);
	
	if( NULL != m_pFitSession )
	{		
		TreeNode	trFitWork = tree_check_get_node(trOp, "FitWorkArea" ); // id of this node is not important, it just used to pass into Operation ///Sophy, Hong said no need to pass ID to it...
		/// Iris 9/17/2008 NEW_PA, replace with PeakFitHelperBase::applyParamsOnTheme
		//TreeNode	trOpParams = tree_check_get_node(trFitWork, "Parameters");
		//m_pFitSession->GetParams(trOpParams);
		///end NEW_PA
		
		TreeNode 	trFitPointer = tree_check_get_node(trFitWork, STR_FIT_POINTER);
		DWORD dw = (DWORD)m_pFitSession;
		trFitPointer.nVal = dw;		
	}
		
	TreeNode 	trGUI = trOp.GUI;
	if(!trGUI)
		return;

	
	copySettingsToOperation(trGetN, trGUI);
	
	setBaselineRangeToOperation(trGUI);	///Jasmine 06/12/09 NANOSIZER_NEED_CENTRALIZE
	
	TreeNode trGraph1 = tree_get_node_by_tagname(trGetN.result, "Graph1", true);
	if(trGraph1)
		CalculateFitCurvePoints(trGraph1);
	
	// Not support Auto Update until pfwiz support AU
	trGUI.AutoUpdate.nVal = AU_NONE;	
	trOp.Operation.AutoUpdate.nVal = AU_NONE;
	
	bool bHasBaselinePeak = GetFitSession()->GetBaselineFitMode();
	/// Iris 3/09/2009 CLEANUP_TODO_CODES
	//updatePrivateSettings(gl, trGUI, trGetN, bHasBaselinePeak); /// Iris 9/17/2008 NEW_PA
	updatePrivateSettings(trGUI);
	///end CLEANUP_TODO_CODES
	
	prepareOutputGraph(gl, trGUI, trGetN, bHasBaselinePeak);	///Jasmine 06/15/09 NANOSIZER_NEED_CENTRALIZE
	
	//------ Folger 11/26/07 PFW_OTHER_INFORMATION_TABLE
	addOtherInformation(trOp);
	//------
	
	//------ Folger 05/07/08 SHOULD_NOT_GENERATE_OPERATION_THEME_WHEN_RUN_FROM_PA
	trOp.SetAttribute(STR_NO_OPERATION_THEME_ATTRIB, 1);
	//------
	
	///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
	/// move to PeakFitHelper::beforeExecuteOperation
	///// Iris 12/01/2008 v8.0981 FIX_CHANGE_PARAM_ALWAYS_REPLOT_ON_SOURCE_GRAPH
	//TreeNode trSourceGraphIDMap = trGetN.trAdv.GetNode("SourceGraphIDMap");
	//TreeNode trSourceGraphUID = trGetN.trAdv.GetNode("SourceGraphUID");
	//if(trSourceGraphIDMap && !trSourceGraphIDMap.IsEmpty() && trSourceGraphUID && !trSourceGraphUID.IsEmpty())
	//{
		//trOp.Operation.SourceGraphIDMap.nVals = trSourceGraphIDMap.nVals;
		//trOp.Operation.SourceGraphUID.nVals = trSourceGraphUID.nVals;
	//}	
	/////end FIX_CHANGE_PARAM_ALWAYS_REPLOT_ON_SOURCE_GRAPH
	///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA

}

//virtual 
int	PeakFitHelperBase::getNumBaselineParams()
{
	return 0;
}

int	PeakFitHelperBase::getPeaksOffset()
{
	return IsBaselineFitWithPeaks() ? 1 : 0;
}

///Jasmine 05/06/09 NANO_CENTRIALIZE_FUNCTION, move from PA
void PeakFitHelperBase::copyValueByID(TreeNode trSrc, TreeNode& trDst, LPCSTR lpcszSrcAttribName, LPCSTR lpcszDstAttribName, LPCSTR lpcszNode)// = NULL)
{
	vector<string> vstagNames = {"Quantities", "Graph1", "Output", "PeakReport", "PeakReportField", "PasteResultTable"};
	if(lpcszNode)
	{
		vstagNames.RemoveAll();
		vstagNames.Add(lpcszNode);
	}
	for(int ii = 0; ii < vstagNames.GetSize(); ii++)
	{
		TreeNode trSource = tree_get_node_by_tagname(trSrc, vstagNames[ii], true);
		TreeNode trDestination = tree_get_node_by_tagname(trDst, vstagNames[ii], true);
		if(trSource && trDestination)
		{
			octree_copy_values_by_id(&trSource, &trDestination, false, lpcszSrcAttribName, lpcszDstAttribName);
			tree_node_copy_attribute(trSource, trDestination, STR_USE_ATTRIB);
			tree_node_copy_attribute(trSource, trDestination, STR_COMBO_ATTRIB);
			if(!trSource.FirstNode && !trDestination.FirstNode)
				trDestination.strVal = trSource.strVal;
		}
	}
}
///End NANO_CENTRIALIZE_FUNCTION

//------ Folger 12/03/08 QA80-12701 v8.0982 THEME_SETTING_CONTROL_FOR_BASELINE_FUNCTION_APPLIED_IN_PA_FIT
void		PeakFitHelperBase::AccessPFMTreeFunctions(TreeNode& trPFM, vector<string>& vsFunctions, bool bGet/* = true*/)
{
	if ( !trPFM )
	{
		ASSERT(false);
		return;
	}
	
	if ( bGet )
	{
		vsFunctions = trPFM.Functions.strVals;
		if ( trPFM.BaselineParameters.nVal > 0 )
			vsFunctions.InsertAt(0, trPFM.BaselineFunction.strVal);
	}
	else
	{
		vector<string>	vsFunctionsTmp;
		vsFunctionsTmp = vsFunctions;
		if ( IsBaselineFitWithPeaks() )
		{
			trPFM.BaselineFunction.strVal = vsFunctionsTmp[0];
			vsFunctionsTmp.RemoveAt(0);
		}
		trPFM.Functions.strVals = vsFunctionsTmp;
	}
	
}
//------ End THEME_SETTING_CONTROL_FOR_BASELINE_FUNCTION_APPLIED_IN_PA_FIT

///------ Folger 01/05/09 v8.0993d REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG
void		PeakFitHelperBase::SetGetParamHideTree(TreeNode& trParamHide, bool bSet/* = true*/)
{
	if ( bSet )
	{
		///------ Folger 07/14/09 NANOSIZER_FAILS_TO_UPDATE_PARAMETERS_HIDE_GUI_AFTER_CHANGE_FUNCTION
		if ( NULL == trParamHide )
			m_trParamHide.Reset();
		else
		///------ End NANOSIZER_FAILS_TO_UPDATE_PARAMETERS_HIDE_GUI_AFTER_CHANGE_FUNCTION
			m_trParamHide.Replace(trParamHide);
	}
	else
		trParamHide.Replace(m_trParamHide);
}
///------ End REMEMBER_HIDE_GETN_DIALOG_STATUS_IN_PARAMETER_DIALOG

///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
void		PeakFitHelperBase::SetUpdatePreviewInfo(bool bPlotIndividualPeak, bool bPlotCumulativeCurve)
{
	m_prevCtrlInfo.bPlotIndividualPeak = bPlotIndividualPeak;
	m_prevCtrlInfo.bPlotCumulativeCurve = bPlotCumulativeCurve;
	
	m_bPlotCurveOptionChanged = true;
}
///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM

//------ Folger 10/28/08 v8.0962 CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES
///------ Folger 09/27/09 QA80-14380 FIT_PEAK_PARAMETERS_DIALOG_FAILS_TO_BE_MODALESS_WHEN_SWITCH_TO_OTHER_PAGES
// bool		PeakFitHelperBase::GetPreviewLayer(GraphLayer& gl)
// {
// 	return GetFitWizCoreBase()->GetPreviewLayer(gl);
// }
bool		PeakFitHelperBase::GetPreviewLayer(GraphLayer& gl,  bool bSetActive/* = true*/)
{
	return GetFitWizCoreBase()->GetPreviewLayer(gl, bSetActive);
}
///------ End FIT_PEAK_PARAMETERS_DIALOG_FAILS_TO_BE_MODALESS_WHEN_SWITCH_TO_OTHER_PAGES
void			PeakFitHelperBase::SetPeakFitDlgPointer(PFParamDlg* pPFDlg)
{
	m_pPFDlg = pPFDlg;
}

PFParamDlg*		PeakFitHelperBase::GetPeakFitDlgPointer()
{
	return m_pPFDlg;
}
//------ End CORRECTLY_UPDATE_PEAK_FIT_DIALOG_WHEN_SWITCH_PAGES

bool			PeakFitHelperBase::IsFitConverged()
{
	return GetFitSession()->IsFitConverged();
}

LPCSTR			PeakFitHelperBase::GetPeakFuncCategory()
{
	return GetParamInitHelper()->GetPeakFuncCategory();
}

LPCSTR			PeakFitHelperBase::GetBaselineFuncCategory()
{
	return GetParamInitHelper()->GetBaselineFuncCategory();
}

///------ Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
bool			PeakFitHelperBase::AccessPeakLabelSettings(int& nLabelXYType, bool bGet/* = true*/)
{
	return GetFitWizCoreBase()->AccessPeakLabelSettings(nLabelXYType, bGet);
}
///------ End NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
#endif	//_PEAK_FIT_HELPER_BASE_H
