1.12.3.1 Linear Fitting

To perform a linear fitting routine in Origin C, you can use the ocmath_linear_fit function. With this function, you can do linear fitting with weight, and then you can get the fitting results, including parameter values, statistical information, etc.

The following procedure will show how to perform linear fitting in Origin C by using this function, and the results will output to the specified windows and worksheet.

Perform Linear Fitting

Before starting linear fitting, please import the desired data, here need one independent and one dependent.

Now, begin the Origin C routine. Three steps are needed.

  1. New a c file and add an empty function as the below. Copy the codes from the following steps into this function.
    #include <GetNBox.h> // used for GETN_ macros
    void linearfit()
    {
    }
  2. Get the data from the worksheet for linear fit. Both independent and dependent are using vector variables.
    // Get XY data from worksheet window
    Worksheet wks = Project.ActiveLayer();
    if(!wks)
        return;  // need to activate a worksheet with data
    WorksheetPage wp = wks.GetPage();
     
    DataRange dr;
    dr.Add("X", wks, 0, 0, -1, 0);  // x column
    dr.Add("Y", wks, 0, 1, -1, 1);  // y column
     
    vector vX;  
    dr.GetData(&vX, 0);  // get data of x column to vector
     
    vector vY;
    dr.GetData(&vY, 1);  // get data of y column to vector
  3. Show GetN dialog to control fit options and call ocmath_linear_fit function to do linear fit with these options.
    // Prepare GUI tree to show fit options in GetN dialog
    GETN_TREE(trGUI)	
    GETN_BEGIN_BRANCH(Fit, _L("Fit Options")) 
    GETN_ID_BRANCH(IDST_LR_OPTIONS) GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
    	GETN_CHECK(FixIntercept, _L("Fix Intercept"), 0) 
    		GETN_ID(IDE_LR_FIX_INTCPT)
    	GETN_NUM(FixInterceptAt, _L("Fix Intercept at"), 0) 
    		GETN_ID(IDE_LR_FIX_INTCPT_AT)
    	GETN_CHECK(FixSlope, _L("Fix Slope"), 0) 
    		GETN_ID(IDE_LR_FIX_SLOPE)
    	GETN_NUM(FixSlopeAt, _L("Fix Slope at"), 1) 
    		GETN_ID(IDE_LR_FIX_SLOPE_AT)
    	GETN_CHECK(UseReducedChiSq, STR_FITTING_CHECKBOX_USE_RED_CHI_SQR, 1) 
    		GETN_ID(IDE_FIT_REDUCED_CHISQR)
    GETN_END_BRANCH(Fit)	
    if( !GetNBox(trGUI) )
    {
    	return; // clicked Cancel button
    }	
    LROptions stLROptions;
    stLROptions = trGUI.Fit; // assign value from GUI tree to struct
    
    // Do linear fit with the above input dataset and fit option settings
    int nSize = vX.GetSize();  // data size
    FitParameter psFitParameter[2];  // two parameters	 
    RegStats stRegStats;  // regression statistics
    RegANOVA stRegANOVA;  // anova statistics	
    
    int nRet = ocmath_linear_fit(vX, vY, nSize, psFitParameter, NULL, 
                            0, &stLROptions, &stRegStats, &stRegANOVA);	
    if(nRet != STATS_NO_ERROR)
    {
        out_str("Error");
        return;
    }

Result to Output Window

Once the computation is finished, the fitting results can be output to the specified windows. Here the values of parameters will output to the Script Window and the statistical information will output to the Result Log window as a tree.

void put_to_output_window(const FitParameter* psFitParameter, 
			const RegStats& stRegStats, const RegANOVA& stRegANOVA)
{	
	// Output analysis result to Script window, Result Log and Worksheet
	// print the values of fitting parameters to the Script Window
	vector<string> vsParams = {"Intercept", "Slope"};
	for(int iPara = 0; iPara < vsParams.GetSize(); iPara++)
	{
	    printf("%s = %g\n", vsParams[iPara], psFitParameter[iPara].Value);
	}
	
	// Put the statistical results to Result Log
	Tree trResults;
	TreeNode trResult = trResults.AddNode("LinearFit");
	TreeNode trStats = trResult.AddNode("Stats");
	trStats += stRegStats;  // add regression statistics to tree node
	 
	TreeNode trANOVA = trResult.AddNode("ANOVA");
	trANOVA += stRegANOVA;  // add anova statistics to tree node
	 
	string strResult;
	tree_to_str(trResult, strResult);  // convert tree to string
	
	Project.OutStringToResultsLog(strResult);  // output to Result Log
}

Result to Worksheet

You can output the fitting result to the specified Worksheet as well. And the results can be organized in normal column format or tree view format in Worksheet window.

The following two ways both used Datasheet::SetReportTree method to put result in Worksheet by tree variable. The difference is the option bit WP_SHEET_HIERARCHY when create worksheet, see the 2nd variable used AddLayer method below.

Output to Normal Worksheet

void output_to_wks(WorksheetPage wp, const FitParameter* psFitParameter)
{
	// prepare report tree		
	int nID = 100; // Each node must have node ID and node ID must be unique
	Tree tr;
	tr.Report.ID = nID++;
	TreeNode trReport = tr.Report;
	trReport.SetAttribute(TREE_Table, GETNBRANCH_TRANSPOSE);		
	
	// column 1
	trReport.P1.ID = nID++;
	trReport.P1.SetAttribute(STR_LABEL_ATTRIB, "Parameter"); // column label
	trReport.P1.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_X);
	
	// column 2
	trReport.P2.ID = nID++;
	trReport.P2.SetAttribute(STR_LABEL_ATTRIB, "Value"); // column label
	trReport.P2.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
	
	// column 3
	trReport.P3.ID = nID++;
	trReport.P3.SetAttribute(STR_LABEL_ATTRIB, "Prob>|t|"); // column label
	trReport.P3.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);	
	
	// prepare the vectors to show in the table
	vector<string> vsParamNames = {"Intercept", "Slope"};  // parameter name
	vector vValues, vProbs;  // parameter value and prob
	for(int nParam = 0; nParam < vsParamNames.GetSize(); nParam++)
	{
	    vValues.Add(psFitParameter[nParam].Value);
	    vProbs.Add(psFitParameter[nParam].Prob);
	}
	
	// assign the vectors to tree node
	trReport.P1.strVals = vsParamNames;
	trReport.P2.dVals = vValues;
	trReport.P3.dVals = vProbs;
	
	// report tree to worksheet
	int iLayer = wp.AddLayer("Linear Fit Params"); 
	Worksheet wksResult = wp.Layers(iLayer);		 
	if(!wksResult.IsValid() || wksResult.SetReportTree(trReport) < 0)
	{
	    printf("Fail to set report tree. \n");
	    return;
	}
	wksResult.AutoSize();	
}

Output to Tree Format Worksheet

void output_to_tree_view_wks(WorksheetPage& wp, const RegStats& stRegStats)
{
	Tree tr;
	int nID = 100; // Each node must have node ID and node ID must be unique
	uint nTableFormat = GETNBRANCH_OPEN	
						| GETNBRANCH_HIDE_COL_HEADINGS 
						| GETNBRANCH_HIDE_ROW_HEADINGS 
						| GETNBRANCH_FIT_COL_WIDTH 
						| GETNBRANCH_FIT_ROW_HEIGHT;
	
	// prepare root table node
	tr.Report.ID = nID++; // add Report treenode and assign node id
	TreeNode trReport = tr.Report; 
	// need set table attribute for table node
	trReport.SetAttribute(TREE_Table, nTableFormat); 
	// the title of root table
	trReport.SetAttribute(STR_LABEL_ATTRIB, "Linear Fit Stats"); 
	
	// prepare stats table node
	trReport.Table.ID = nID++; // add Table treenode and assign node id
	TreeNode trTable = trReport.Table;
	// need set table attribute for table node
	trTable.SetAttribute(TREE_Table, nTableFormat|GETNBRANCH_TRANSPOSE); 
	// the title of stats table
	trTable.SetAttribute(STR_LABEL_ATTRIB, "Regression Statistics"); 
	
	// prepare result node
	trTable.Stats.ID = nID++; // add Stats treenode and assign node id
	TreeNode trStats = trTable.Stats;		
	trStats += stRegStats; // support adding result from sturct to treenode
	
	// set label, those text will show in row header in table
	trStats.N.SetAttribute(STR_LABEL_ATTRIB, "Number of Points");
	trStats.DOF.SetAttribute(STR_LABEL_ATTRIB, "Degrees of Freedom");
	trStats.SSR.SetAttribute(STR_LABEL_ATTRIB, "Residual Sum of Squares");
	trStats.AdjRSq.SetAttribute(STR_LABEL_ATTRIB, "Adj. R-Square");
	
	// to hide other nodes
	trStats.ReducedChiSq.Show = false;
	trStats.Correlation.Show = false;
	trStats.Rvalue.Show = false;
	trStats.RSqCOD.Show = false;
	trStats.RMSESD.Show = false;
	trStats.NormResiduals.Show = false;
	
	// the bits to control the newly created worksheet as hierarchy format
	DWORD   dwOptions = WP_SHEET_HIERARCHY | CREATE_NO_DEFAULT_TEMPLATE; 
	int iLayer = wp.AddLayer("Linear Fit Stats", dwOptions); 
	
	Worksheet wksResult = wp.Layers(iLayer);		 
	if(!wksResult.IsValid() || wksResult.SetReportTree(trReport) < 0)
	{
	    printf("Fail to set report tree.\n");
	    return;
	}
	wksResult.AutoSize();
}