1.12.3.4 Non-linear Fitting

NLFit is the new fitter starting with Origin version 8. This new fitter handles the fitting process with a copy of the data while performing iterations. This results in faster operation compared to older versions where the fitter directly accessed data repeatedly from the worksheet.

There are two classes available to perform nonlinear fitting:

NLFit
This is the Origin C class that wraps the low level API from the new fitting engine. This class has no knowledge of Origin and works with copies of data in buffers. In order to use this class, you will be responsible in preparing all necessary buffers (pointers). This separation prepares for the future implementation of performing fitting as a background process.
NLFitSession
This is a higher level Origin C class with a friendly interface that wraps the NLFit class to Origin objects. This class is the kernel in the new NLFit Dialog. We recommend that you use this class in your Origin C code, as the process to interface to Origin is rather complicated and the NLFitSession classtakes care of this complexity for you.

Nonlinear Fitting

Before you use the NLFitSession class, you need to include a specific header file:

#include <..\originlab\NLFitSession.h>

You also need to include and compile the OriginC\Originlab\nlsf_utils.c file to your current workspace. Run the Labtalk command below in the Command window, or from your script file, to programmatically add the file:

Run.LoadOC(Originlab\nlsf_utils.c, 16)

Define an NLFitSession object, and set the fitting function as Gauss:

// Set Function
NLFitSession nlfSession;
if ( !nlfSession.SetFunction("Gauss") )
{
	out_str("Fail to set function!");
	return;
}

// Get parameter names and number:
vector<string>  vsParamNames;
int nNumParamsInFunction = nlfSession.GetParamNamesInFunction(vsParamNames);

Set two XY datasets with DATA_MODE_GLOBAL mode, to perform global fitting with sharing of parameters:

int nNumData = 2;
// Set the first dataset
if ( !nlfSession.SetData(vY1, vX1, NULL, 0, nNumData) )
{
	out_str("Fail to set data for the first dataset!");
	return;
}    	

// Set the second dataset
if ( !nlfSession.SetData(vY2, vX2, NULL, 1, nNumData, DATA_MODE_GLOBAL) )
{
	out_str("Fail to set data for the second dataset!");
	return;
}

Run parameter initialization code to initialize parameter values:

// Parameter initialization
if ( !nlfSession.ParamsInitValues() )
{
	out_str("Fail to init parameters values!");
	return;
}

Alternately, you can directly set parameter values one by one:

vector vParams(nNumParamsInFunction*nNumData);
// set parameter value for the first dataset
vParams[0] = 5.5; // y0
vParams[1] = 26; // A
vParams[2] = 8; // xc
vParams[3] = 976; // w

// set parameter value for the second dataset
vParams[4] = 2.3; // y0
vParams[5] = 26; // A
vParams[6] = 10.3; // xc
vParams[7] = 102; // w

int nRet = nlfSession.SetParamValues(vParams);
if(nRet != 0) // 0 means no error
    return;

Share xc parameter between the two datasets:

int nSharedParamIndex = 1; // 1, the index of xc in Gauss function
nlfSession.SetParamShare(nSharedParamIndex);

Perform the fit and output status message:

// Do fit
int nFitOutcome;
nlfSession.Fit(&nFitOutcome);    

string strOutcome = nlfSession.GetFitOutCome(nFitOutcome);
out_str("Outcome of the fitting session : " + strOutcome);

Get fit statistic result:

int nDataIndex = 0;
RegStats        fitStats;
NLSFFitInfo     fitInfo;
nlfSession.GetFitResultsStats(&fitStats, &fitInfo, false, nDataIndex);
printf("# Iterations=%d, Reduced Chisqr=%g\n", fitInfo.Iterations,
 fitStats.ReducedChiSq);

Get final fit parameter values:

vector          vFittedParamValues, vErrors;
nlfSession.GetFitResultsParams(vFittedParamValues, vErrors);

// The parameter xc is shared in two input data.
// So the value of xc is same for all data sets, and it only appears one time
// in the fitted parameter values - vParamValues.	
// vsParamNames contains the parameter names in Gauss function - y0, xc, w, A.
// The following to add parameter names for the second dataset without xc.
vsParamNames.Add("y0");
vsParamNames.Add("w");
vsParamNames.Add("A");

for( int nParam = 0; nParam < vFittedParamValues.GetSize(); nParam++)
{    	
    printf("%s = %f\n", vsParamNames[nParam], vFittedParamValues[nParam]);
}

Calculate fit curve Y values using the final fit parameters:

vector vFitY1(vX1.GetSize()), vFitY2(vX2.GetSize());
// Get fitted Y for the first dataset
nlfSession.GetYFromX(vX1, vFitY1, vX1.GetSize(), 0);
// Get fitted Y for the second dataset
nlfSession.GetYFromX(vX2, vFitY2, vX1.GetSize(), 1);

Accessing FDF File

Fitting function settings stored in an FDF file can be loaded into a tree variable. You will need to include the OriginC\system\FDFTree.h file:

#include <FDFTree.h>

Then use the nlsf_FDF_to_tree function:

string strFile = GetOpenBox("*.FDF");
Tree tr;
if(nlsf_FDF_to_tree(strFile, &tr))
{
	out_tree(tr);
}