When programming in an X-Function or in a normal Origin C function, you may need to call another X-Function which has accomplished the desired purpose.
To call an X-Function in Origin C, class XFBase is needed (add #include <XFbase.h> for the header file).
A typical simple process will include:
XFBase xf(LPCSTR lpcszName = NULL); //Which can declare the class and load the X-Function. //set value for a specific variable for X-Function by variable name or variable index. //var variable below can be other data type like matrix&, int&, string&, double&, DataRange& and so on. xf.SetArg(LPCSTR lpcszName, vector& var); xf.SetArg(int nVarIndex, vector& var); //sequentially set values for the variables for X-Function. //Both the order of the variable in the X-Function variables list and the name can be used. xf.SetArgs(...); //Execute the X-Function ''without'' executing event handling functions. xf.Evaluate(...);
#include <XFbase.h> // XFbase.h is included for accessing the class XFBase. // The example shows how to call an X-Function and get the result via Origin C // A typical process of using XFBase will be the following. void Call_XF_from_OC_Ex1_integ1() { //////// Prepare the input data and put into worksheet //////// vector vX; vector vY; vX.Data(0., 20.0, 0.05); vY.SetSize(vX.GetSize()); double dA = 100.0; double dXc = 8.0; double dW = 2.0; vY = dA * exp(-0.5*(vX-dXc)*(vX-dXc)/dW/dW); Worksheet wks; wks.Create("origin"); while(wks.Columns.Count()<6) wks.AddCol(); wks.SetColDesignations("XY"); wks.Columns(1).SetLongName("Raw"); wks.Columns(3).SetLongName("Integration"); wks.Columns(5).SetLongName("Normalized"); DataRange drIn; drIn.Add(wks,0,"X"); drIn.Add(wks,1,"Y"); if(!drIn.SetData(&vY, &vX)) { out_str("Failed to set the data!"); return; } //////// Call X-Function integ1 to do the integration and plotting.//////// //// Load the X-Function string strXFNameToCall = "integ1"; XFBase xf(strXFNameToCall); if( !xf.IsValid() ) { out_str("Failed to load xfunction."); return; } //// Set the arguments for the X-Function // Prototype for X-Function integ1. // void integ1(const XYRange& iy, const int& baseline, const int& type, // XYRange& oy, const int& plot, double& x1, double& x2, int& i1, int& i2, // double& area, double& y0, double& x0, double& dx, TreeNode& tr, const int& rescale) DataRange drInteg; drInteg.Add(wks, 2, "X"); drInteg.Add(wks, 3, "Y"); double dArea; // DataRange can be directly passed as the arguments though the prototype for the argument is XYRange because class XYRange is derived from class DataRange. // We need get the result of integrated area, so set the 9th argument (area) separately. if ( !xf.SetArgs(drIn, 0, 0, drInteg, 1) || !xf.SetArg(9, dArea) ) { out_str("Failed to set the arguments!"); return; } //// Execute the X-Function if ( !xf.Evaluate()) { out_str("Failed to execute the X-Function!"); return; } //////// Use the result of integ1 to do some calculation. //////// vector vXInteg; vector vYInteg; vector vYNorm; DataRange drNorm; drNorm.Add(wks, 4, "X"); drNorm.Add(wks, 5, "Y"); drInteg.GetData(vXInteg, 0); drInteg.GetData(vYInteg, 1); vYNorm = vYInteg/dArea; if( !drNorm.SetData(&vYNorm, &vXInteg) ) { out_str("Failed to set the normalized data!"); return; } }
#include <XFbase.h> #include <ReportTree.h> void Call_XF_from_OC_Ex2_corrcoef() { //Prepare data ASCIMP ascimp; Worksheet wks; string strFile = GetAppPath(1) + "Samples\\Statistics\\automobile.dat"; wks.Create(); if(AscImpReadFileStruct(strFile,&ascimp)==0) { wks.ImportASCII(strFile, ascimp); } DataRange drIn; for (int i = 2; i < 7; i++) { drIn.Add(wks, i, "X"); } string strXFNameInner = "corrcoef"; XFBase xf(strXFNameInner); if ( !xf ) XF_THROW(XFERR_FAIL_LOAD_XF); Tree trDummy1, trDummy2, trDummy3; ReportData rd(trDummy1); ReportTree rt(trDummy2); ReportTree rtPlot(trDummy3); if ( !xf.SetArgs(drIn, 1, 1, 1, 1, 1, 95, 0, rd, rtPlot, rt) ) XF_THROW(XFERR_FAIL_SET_ARG); //set plot data to destination worksheet for graph in report tree. WorksheetPage wksPage = wks.GetPage(); int nLayer = wksPage.AddLayer(); Worksheet wksReportData = wksPage.Layers(nLayer); rd.SetWorksheet(wksReportData); if ( !xf.Evaluate() ) XF_THROW(XFERR_FAIL_EVAL); // prepare worksheet for hierarchical report tree DWORD dwNewLayerBits = WP_SHEET_HIERARCHY | CREATE_NO_DEFAULT_TEMPLATE | WP_SHEET_THIN_COL_HEADERS | WP_SHEET_MAIN_NAN_AS_BLANK; nLayer = wksPage.AddLayer((LPCSTR)NULL, dwNewLayerBits); Worksheet wksReportTree = wksPage.Layers(nLayer); rt.GenerateReport(wksReportTree, false, false); wksReportTree.AutoSize(); DWORD dwOptions = GETNBRANCH_HIDE_COL_LABELS | GETNBRANCH_FIT_COL_WIDTH | GETNBRANCH_FIT_ROW_HEIGHT; nLayer = wksPage.AddLayer((LPCSTR)NULL, dwNewLayerBits, NULL, dwOptions); Worksheet wksRTPlot = wksPage.Layers(nLayer); rtPlot.GenerateReport(wksRTPlot, false, false); wksReportTree.AutoSize(); }
#include <XFbase.h> void Call_XF_from_OC_Ex3_expGraph() { // Load the X-Function string strXFNameToCall = "expGraph"; XFBase xf(strXFNameToCall); if( !xf.IsValid() ) { out_str("Failed to load xfunction."); return; } // Set the arguments for the X-Function int nType = 7; if( !xf.SetArg("type", nType) ) //7:jpg out_str("Failed to set argument image type"); string strFilename = "abc"; if( !xf.SetArg("filename", strFilename) ) out_str("Failed to set argument filename"); string strPath = "d:\\"; // the page export to if( !xf.SetArg("path", strPath) ) out_str("Failed to set argument path"); string strPages = "Graph1"; //assuming Graph1 is exist if( !xf.SetArg("pages", strPages) ) out_str("Failed to set argument pages"); // Set tree argument for the X-Function Tree tr1; xf.GetXFCreatedTree("tr1", tr1); //get the tree tr1.Width.nVal = 5; //set tree value tr1.Height.nVal = 4; tr1.Unit.nVal = 0; if( !xf.SetArg("tr1", tr1)) out_str("Failed to set argument tr"); // Execute the X-Function, and before_execute is called without dialog. TreeNode trGetN; if( !xf.Run(0, trGetN) ) { out_str("Failed to execute the X-Function!"); return; } }
#include <XFbase.h> void call_XF_getnlr() { // Load the getnlr X-Function XFBase xfGetNLR("getnlr"); if( !xfGetNLR.IsValid() ) { out_str("Failed to load getnlr X-Function."); return; } // Set the output tree argument Tree tnMyFit; if( !xfGetNLR.SetArg("tr", tnMyFit) ) { out_str("Failed to set argument: tr"); return; } // Set the source worksheet argument Worksheet wks; char szWks[MAX_PATH]; if( LT_get_str("__REPORT$", szWks, MAX_PATH) && lstrlen(szWks) ) { wks.Attach(szWks); if( !xfGetNLR.SetArg("iw", wks) ) { out_str("Failed to set argument: iw"); return; } } // Set the notation argument // Allowed values: // 0 = Parameter names // 1 = Abbreviations // 2 = Both int nPNotation = 2; // Parameter names and abbreviations if( !xfGetNLR.SetArg("pnotation", nPNotation) ) { out_str("Failed to set argument: pnotation"); return; } // With arguments set we can now execute the X-Function if( !xfGetNLR.Evaluate() ) { out_str("Failed to evaluate the getnlr X-Function."); return; } // Output the whole tree to the script window out_tree(tnMyFit); // Put the p1 value into a new workbook double p1; if( tnMyFit.p1.GetValue(p1) ) { // Create a new workbook using the default Origin template WorksheetPage wksPgNew; wksPgNew.Create("origin.otw"); // Get the active worksheet Worksheet wksNew = wksPgNew.Layers(-1); // Get the worksheet's first column Column col = wksNew.Columns(0); // Get the column's data values vector &colVals = col.GetDataObject(); // Put the p1 value into the column's data if( colVals.GetSize() < 1 ) colVals.Add(p1); // Add a new row with the p1 value else colVals[0] = p1; // Set first row to the p1 value } }
The following function can be called from Origin C to execute the stats X-Function.
In this example the stats X-Function is called to operate on one column of the specified worksheet, shows how to set vector data type input argument, and how to get double type result after X-Function execute.
#include <XFbase.h> bool callStatsXF(Worksheet& wks, int nCol, double& dMean, double& dSD, int& n, double& dMin, double& dMax, double& dSum, int& nMissing) { //========== Load the stats X-Function XFBase xfStats("stats"); if( !xfStats.IsValid() ) { out_str("Failed to load stats X-Function."); return false; } //========== Set the ix argument // Get stats on the specified column // Create a data range DataRange dr; dr.Add(wks, nCol, "Range1"); // Get the data represented by the data range into a local vector. vector<double> vData; if( !dr.GetData(&vData, 0) ) { out_str("Failed to get data."); return false; } if( 0 == vData.GetSize() ) { out_str("Dataset is empty."); return false; } // Now with the local vector we can set the ix argument. if( !xfStats.SetArg("ix", vData) ) { out_str("Failed to set argument: ix"); return false; } //========== Set the output arguments if( !xfStats.SetArg("mean", dMean) ) { out_str("Failed to set argument: mean"); return false; } if( !xfStats.SetArg("sd", dSD) ) { out_str("Failed to set argument: sd"); return false; } if( !xfStats.SetArg("n", n) ) { out_str("Failed to set argument: n"); return false; } if( !xfStats.SetArg("min", dMin) ) { out_str("Failed to set argument: min"); return false; } if( !xfStats.SetArg("max", dMax) ) { out_str("Failed to set argument: max"); return false; } if( !xfStats.SetArg("sum", dSum) ) { out_str("Failed to set argument: sum"); return false; } if( !xfStats.SetArg("missing", nMissing) ) { out_str("Failed to set argument: missing"); return false; } //========== Execute the X-Function if( !xfStats.Evaluate() ) { out_str("Failed to evaluate the stats X-Function."); return false; } return true; } // Test function for calling the above function. void testCallStatsXF(int nCol = 0) { Worksheet wks = Project.ActiveLayer(); if( !wks ) { out_str("Activate a worksheet and try again."); return; } double dMean, dSD, dMin, dMax, dSum; int n, nMissing; if( callStatsXF(wks, nCol, dMean, dSD, n, dMin, dMax, dSum, nMissing) ) { printf("For Column %d:\ \ndMean = %f\ \ndSD = %f\ \ndMin = %f\ \ndMax = %f\ \ndSum = %f\ \nDataPoints = %d\ \nnMissing = %d\n", nCol + 1, dMean, dSD, dMin, dMax, dSum, n, nMissing); } }
This example shows how to construct XYRange variables and use them as X-Function arguments in Origin C.
To run the following function, a workhseet with 5 columns should be active. Fill the first two columns with XY data, the next two with XY data where the number of point is different but the range of X is similar to the first, and one empty column. The example illustrates the subtract_ref functions ability to interpolate. Note the comments for alternately using Y input as output.
#include <XFbase.h> void run_subtract_ref() { Worksheet wks = Project.ActiveLayer(); if( 5 != wks.GetNumCols() ) { out_str("Please make sure there are 5 columns in worksheet"); return; } XYRange in; in.Add(wks, 0, "X"); // 1st column as X in.Add(wks, 1, "Y"); // 2nd column as Y XYRange ref; ref.Add(wks, 2, "X"); // 3rd column as X ref.Add(wks, 3, "Y"); // 4th column as Y XYRange out; out.Add(wks, 0, "X"); // Use the same X as Input and Output out.Add(wks, 4, "Y"); // Use the empty Y as Output // Comment line above and uncomment line below to overwrite Y data // out.Add(wks, 1, "Y"); // Use the input Y as output XFBase xf("subtract_ref"); // construct X-Function object with X-Function name if( !xf.SetArg("iy1", in) ) { out_str("Failed to set argument: iy1"); return; } if( !xf.SetArg("iy2", ref) ) { out_str("Failed to set argument: iy2"); return; } if( !xf.SetArg("oy", out) ) { out_str("Failed to set argument: oy"); return; } double xmean, ymean; if( !xf.SetArg("xmean", xmean) || !xf.SetArg("ymean", ymean) ) { out_str("Failed to set argument: xmean or ymean"); return; } if( !xf.Evaluate() ) { out_str("Failed to evaluate the subtract_ref X-Function."); return; } printf("xmean = %f, ymean = %f\n", xmean, ymean); }
To check the argument data types of a function, open the X-Function Builder (F10), or type "xfname -h" or "help xfname" in the Command or Script Window.
#include <XFBase.h> bool test_xf_with_theme() { Worksheet wks = Project.ActiveLayer(); if( !wks ) return false; XFBase xf("averagexy"); // use theme name as input, can use STR_LAST_USED to apply last used settings to replace "abc" here. xf.ApplyTheme("abc"); // set XFunctioin input varaible XYRange ry; ry.Add(wks, 0, "X"); ry.Add(wks, 1, "Y"); ry.Add("S", NULL); if (!xf.SetArg("iy", ry)) return false; //// set XFunction output variables int iColx = wks.AddCol(); wks.Columns(iColx).SetType(OKDATAOBJ_DESIGNATION_X); int iColy = wks.AddCol(); Dataset dsOutX(wks, iColx), dsOutY(wks, iColy); if (!xf.SetArg("x", dsOutX)) return false; if (!xf.SetArg("y", dsOutY)) return false; return xf.Evaluate(); }
#include <../Originlab/xfunctionex.h> bool running_xf_with_autoupdate() { Worksheet wks = Project.ActiveLayer(); if( !wks ) return false; // prepare input XY Range XYRange ry; ry.Add(wks, 0, "X"); ry.Add(wks, 1, "Y"); ry.Add("S", NULL); ry.Add(wks, 0, "X"); ry.Add(wks, 2, "Y"); ry.Add("S", NULL); ry.Add(wks, 0, "X"); ry.Add(wks, 3, "Y"); // prepre output X&Y columns int iColx = wks.AddCol(); wks.Columns(iColx).SetType(OKDATAOBJ_DESIGNATION_X); int iColy = wks.AddCol(); Dataset dsOutX(wks, iColx), dsOutY(wks, iColy); // running XFunction "averagexy" with XFunction class XFunction xf; Tree trXF; if ( !xf.Load(&trXF, "averagexy", 0, true, false, true) ) // load a xfunction by name return false; // set XFunctioin input varaible if (!xf.SetArg("iy", ry)) return false; // set XFunction output variables if (!xf.SetArg("x", dsOutX)) return false; if (!xf.SetArg("y", dsOutY)) return false; Tree tr; TreeNode trGetN; xf.GetGUI(tr, trGetN); // AU_AUTO means Auto Update is on. xf.Run(AU_AUTO, trGetN); return true; }