# 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++)
{
}

// 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_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");

// 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();
}