3.9.2.1.2 Fit Multiple XY Data in a loop

Version Info

Minimum Origin Version Required: Origin 8 SR6

Need to do before Running Examples

Prior to running the following example, the nlsf_utils.c file need to be loaded and compiled. This can be done from script with the following command or just add this file to your workspace.

run.LoadOC(Originlab\nlsf_utils.c);

Examples

The following code shows how to use the NLFitSesssion to fit many datasets to the same function.

#include <Origin.h>
#include <..\originlab\NLFitSession.h>
// assume active worksheet with XYYYY data, all with a single peak
// so we can fit all of them to gauss function and gnerate a new worksheet to hold the fitting results.
void test1()
{
	Worksheet wks = Project.ActiveLayer();
	if(!wks)
	    return;
	
	Worksheet wksOut;
	wksOut.Create();
	
	fit_all_cols(wks, wksOut);
}

static bool fit_all_cols(Worksheet& wks, Worksheet& wksOutput, string strFunc = "Gauss")
{
	NLFitSession    FitSession;
	int             nDataIndex = 0; // only one set in our case
	DWORD           dwRules = DRR_GET_DEPENDENT | DRR_NO_FACTORS;
	
	// 1. Set fucntion
	if(!FitSession.SetFunction(strFunc, NULL)) // set function, category name can be ignore
	    return error_report("invalid fit function");
	
	vector<string>  vsParamNames;
	int             nNumParamsInFunction = FitSession.GetParamNamesInFunction(vsParamNames);
	int 			nFitOutcome, nFitErr = -1;
	
	for(int nYCol = 1; nYCol < wks.GetNumCols(); nYCol++)
	{
	    DataRange   drInputData;
	    drInputData.Add(wks, 0, "X");
	    drInputData.Add(wks, nYCol, "Y");
	    int         nNumData = drInputData.GetNumData(dwRules);
	    ASSERT(1==nNumData);
	    
	    //2 set the dataset
	    vector  vX1, vY1;
	    drInputData.GetData( dwRules, nDataIndex, NULL, NULL, &vY1, &vX1 );     
	    if(!FitSession.SetData(vY1, vX1, NULL, nDataIndex, nNumData))  
	        return error_report("err setting data");
	
	    // 3. Call parameter init codes to init parameters
	    if(!FitSession.ParamsInitValues())
	        return error_report("err ParamsInitValues");
	    // 4. Iterate with default settings
	    if(!FitSession.Fit(&nFitOutcome))
	    {
        	string strOutcome = FitSession.GetFitOutCome(nFitOutcome);
	        printf("fit failed:%d->%s\n", nFitErr, strOutcome);
	        return false;
	    }
		// 5. success, get results and put to wksOutput
		FitParameter	params[20];// whatever the max possible number of parameters in your function
		RegStats		fitStats;
		NLSFFitInfo		fitInfo;
		FitSession.GetFitResultsStats(&fitStats, &fitInfo, false, nDataIndex);
		FitSession.GetFitResultsParams(params, &fitStats);
		_append_fit_results(wksOutput, vsParamNames, params, fitStats, fitInfo);
	}
	
	return true;
}
static void _append_fit_results(Worksheet& wks, const vector<string>& vsParamNames, const FitParameter* pParams, const RegStats& fitStats, const NLSFFitInfo& fitInfo)
{
	Column	c0Time = wks.Columns(0);
	int		nR1 = c0Time.GetUpperBound();
	// check if empty, then setup cols
	if(nR1 < 0)
	{
		vector<string> vsExtraCols = {"Tick Count", "Adj Rsquare", "Iterations"};
		int nTotalCols = vsParamNames.GetSize() + vsExtraCols.GetSize();
		if(wks.GetNumCols() < nTotalCols)
		{
			wks.SetSize(0, nTotalCols);
			vector<string> vs;vs = vsExtraCols;
			vs.Append(vsParamNames);		
			for(int nCol = 0;nCol < vs.GetSize();nCol++)
			{
				Column cc = wks.Columns(nCol);
				cc.SetLongName(vs[nCol]);
			}
		}
	}
	nR1++; 
	wks.SetCell(nR1, 0, GetTickCount()/1000.0);
	wks.SetCell(nR1, 1, fitStats.AdjRSq);
	wks.SetCell(nR1, 2, fitInfo.Iterations);
	//fit parameters
	for(int ii = 0, nCol = 3; ii < vsParamNames.GetSize(); ii++, nCol++)
	{
		wks.SetCell(nR1, nCol, pParams[ii].Value);
	}
}