/*------------------------------------------------------------------------------* * File Name: Internal.c * * Creation: CPY 3/5/2001 * * Purpose: Support for using Origin C from inside Origin * * This is used primarily in places like NLSF, Set Matrix Values and * * function plotting and etc. * * Copyright (c) OriginLab Corp.2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 * * All Rights Reserved * * * * Modification Log: * * Bill Liang,1/16/02 * Bill Liang,1/17/02 * CPY v7.0365 QA70-2583 LABTALK_AND_OC_ABS_CONSISTENT * LAS 1/31/03 commented out the NLSFCntrl * using NLSF = LabTalk.NLSF can be used instead * CPY 7/7/03 changed to include only origin.h to take advantage of PCH *------------------------------------------------------------------------------*/ #include // main Origin C header that is precompiled and already include most headers // add your additional include files here // *************************** // functions that accept scalars and return a scalar // *************************** //------- CPY v7.0365 QA70-2583 LABTALK_AND_OC_ABS_CONSISTENT // we need to provide this function such that the labtalk verison of abs // will work the same as in Origin C. The C library function abs(n) would // still be called if you are passing in an integer argument. double abs(double x) { return fabs(x); } //------- // returns max of two doubles double max(double da, double db) { return (da > db ? da : db); } // returns min of two doubles double min(double da, double db) { return (da < db ? da : db); } // returns max of two floats float max(float fa, float fb) { return (fa > fb ? fa : fb); } // returns min of two floats float min(float fa, float fb) { return (fa < fb ? fa : fb); } // returns max of two ints int max(int ia, int ib) { return (ia > ib ? ia : ib); } // returns min of two ints int min(int ia, int ib) { return (ia < ib ? ia : ib); } // returns max of two uints uint max(uint na, uint nb) { return (na > nb ? na : nb); } // returns min of two uints uint min(uint na, uint nb) { return (na < nb ? na : nb); } // returns max of two shorts short max(short na, short nb) { return (na > nb ? na : nb); } // returns min of two shorts short min(short na, short nb) { return (na < nb ? na : nb); } // returns max of two ushorts ushort max(ushort wa, ushort wb) { return (wa > wb ? wa : wb); } // returns min of two ushorts ushort min(ushort wa, ushort wb) { return (wa < wb ? wa : wb); } // *************************** // functions that accept a dataset and return values from its properties // *************************** // returns min value of dataset double min(Dataset &aa) { BasicStats stat; stat.min = -1; Data_sum(&aa, &stat); return stat.min; } // returns max value of dataset double max(Dataset &aa) { BasicStats stat; stat.max = -1; Data_sum(&aa, &stat); return stat.max; } // returns 25th percentile value of dataset double y25(Dataset &aa) { double perc, result; BOOL interp = false; perc=25; Data_percentiles(&aa, &perc, &result, 1,interp); return result; } // returns 50th percentile value of dataset double y50(Dataset &aa) { double perc, result; BOOL interp = false; perc=50; Data_percentiles(&aa, &perc, &result, 1,interp); return result; } // returns 75th percentile value of dataset double y75(Dataset &aa) { double perc, result; BOOL interp = false; perc=75; Data_percentiles(&aa, &perc, &result, 1,interp); return result; } // *************************** // functions that accept a curve and return values from its properties // *************************** // this function is used only for the two functions below, so must be set to static // so that it is invisible outside this file static int minmax(Dataset &aa, BOOL bGetMin=TRUE) { BasicStats stat; stat.iMin =0; stat.iMax =0; Data_sum(&aa, &stat); return bGetMin? stat.iMin:stat.iMax; } // returns x value corresponding to minimum in y value double xatymin(Curve &cc) { return Curve_x(&cc, minmax(cc)); } // returns x value corresponding to minimum in y value double xatymax(Curve &cc) { return Curve_x(&cc, minmax(cc,FALSE)); } double yatxmax(Curve &cc) { if (cc.HasX()) { Dataset xdata(); cc.AttachX(xdata); double xmax = max(xdata); return Curve_yfromX(&cc, xmax); } else { // GetUpperIndex returns the index immediately after the last point int n = cc.GetUpperBound(); return cc[n-1]; } } double yatxmin(Curve &cc) { if (cc.HasX()) { Dataset xdata(); cc.AttachX(xdata); double xmin = min(xdata); return Curve_yfromX(&cc, xmin); } else { return cc[0]; } } //returns x value correpsonding to mid y value double xaty50(Curve &cc) { double ymiddle = (max(cc) + min(cc))/2.0; return Curve_xfromY(&cc, ymiddle); } //returns x width of dataset corresponding to half the max value in y //double fwhm(Curve &cc, double yoffset = 0) double fwhm(Curve &cc, double yoffset) { Curve ccLocal(cc); ccLocal -= yoffset; IntegrationResult result; BOOL ipass = Curve_integrate(&ccLocal, &result); return result.dxPeak; } //returns area under the curve //double area(Curve &cc, double yoffset = 0) double area(Curve &cc, double yoffset) { Curve ccLocal(cc); ccLocal -= yoffset; IntegrationResult result; BOOL ipass = Curve_integrate(&ccLocal, &result); return result.Area; } // sorts the curve BOOL sort(Curve &cc) { cc.TrimLeft(TRUE); cc.Sort();// missing values are sorted to the end cc.TrimRight(); return true; } // smooth the curve //BOOL smooth(Curve &cc, int method=0, int leftpts = 3, int rightpts = 3, int polydeg = 2) BOOL smooth(Curve &cc, int method, int leftpts , int rightpts, int polydeg) { string ydataname; cc.GetName(ydataname); if(method == 0) // perform adjacent averaging { _LT_Obj { curve.reset(); curve.data$ = ydataname; curve.result$ = ydataname; curve.smoothPts = leftpts; curve.adjave(); } return true; } else if (method == 1) // perform fft filtering { _LT_Obj { curve.reset(); curve.data$ = ydataname; curve.result$ = ydataname; curve.smoothPts = leftpts; curve.FFTSmooth(); } return true; } else // perform Savitzky-Golay filtering { _LT_Obj { curve.reset(); curve.data$ = ydataname; curve.result$ = ydataname; curve.smoothLeftPts = leftpts; curve.smoothRightPts = rightpts; curve.smoothPts = leftpts + rightpts + 1; curve.polyDeg = polydeg; curve.SGSmooth(); } return true; } } //-------- Bill Liang,1/16/02 // return the asymtoptic y value as follow: // double-branch: (yatxmax+yatxmin)/2 // single-branch: yatxmax or yatxmin with the smaller slope double yatasymt(Curve &cc) { Dataset xd; cc.AttachX(xd); if(fabs(xatymax(cc)-xatymin(cc))<(max(xd)-min(xd))*2.0/3) { // double-branch return (yatxmin(cc)+yatxmax(cc))/2.0; } else { // single-branch double dy1=Curve_yfromX(&cc,0.9*min(xd)+0.1*max(xd))-yatxmin(cc); double dy2=yatxmax(cc)-Curve_yfromX(&cc,0.1*min(xd)+0.9*max(xd)); if(fabs(dy1)(max(xd)-min(xd))*1.0/3) { // y-symemtric double-branch if(fabs(min(cc)-yatasymt(cc))iupper || ibeg>=iend) return false; cc.SetLowerIndex(ibeg); cc.SetUpperIndex(iend); fitpoly(cc,ipolyorder,coeff); // restore original indics cc.SetLowerIndex(ilower); cc.SetUpperIndex(iupper); return true; } //----------------- end Bill Liang,1/16/02 // fit polynomial to curve and return coefficients BOOL fitpoly(Curve &cc, int ipolyorder, double *coeff, int inumer, int idenom) { string strYdata; cc.GetName(strYdata); int ilower, iupper, ilen, iseg, ibeg, iend; if ( (idenom != 0) ) { if (inumer > idenom) return false; ilower = cc.GetLowerBound(); iupper = cc.GetUpperBound(); ilen = iupper - ilower; if (ilen <= idenom) return false; iseg = ilen / idenom; ibeg = iseg * (inumer - 1); iend = ibeg + iseg; cc.SetLowerIndex(ibeg); cc.SetUpperIndex(iend); } _LT_Obj { stat.reset(); stat.apparent=0; stat.pr.order = ipolyorder; stat.data$ = strYdata; stat.pr(); coeff[0] = stat.pr.a; } for( int i = 1; i <= ipolyorder; i++ ) { string str; str.Format("stat.pr.b%d", i); LT_get_var(str, &coeff[i]); } if ( (idenom != 0) ) { cc.SetLowerIndex(ilower); cc.SetUpperIndex(iupper); } return true; } // the following is no longer needed and users should use // using NLSF = LabTalk.NLSF; // Point to the NLSF object // perform initialization of NLSF and set all control strucutre variables to sensible values //BOOL initNLSF(NLSFCntrl &control) //{ // _LT_Obj // { // nlsf.init(); // lstrcpy(control.szYdataName, nlsf.y$); // lstrcpy(control.szFuncName, nlsf.func$); // lstrcpy(control.szWtDataName, nlsf.w$); // control.Tolerance = nlsf.tolerance; // control.Confidence = nlsf.conf; // control.Prediction = nlsf.pred; // control.imaxIter = nlsf.maxIter; // control.idataBegin = nlsf.dataBegin; // control.idataEnd = nlsf.dataEnd; // control.idataStep = nlsf.dataStep; // control.iwType = nlsf.wType; // // for(int ii=0; ii <200; ii++) // { // control.Par[ii] = 0; // control.Err[ii] = 0; // control.Dep[ii] = 0; // control.ConfIntv[ii] = 0; // } // // control.openGraph = true; // control.createCurve = true; // control.confBands = false; // control.predBands = false; // control.createWks = false; // control.pasteToPlot = true; // control.pasteToResults = true; //control.sameXasData = true; // // // } // return true; //} // // perform NLSF fitting using the NLSFControl structure //BOOL fitNLSF(NLSFCntrl &control) //{ // _LT_Obj // { // nlsf.msgPrompt = 0; // suppress error messages! // nlsf.func$ = control.szFuncName; // set fitting function // nlsf.fitdata$ = control.szYdataName; // set dependent variable // // // Dataset dWeight(control.szWtDataName); // create dWeight dataset variable // // if( (control.iwType > 0) && (control.iwType < 5) ) // { // nlsf.wType = control.iwType; // set weight method // if( (dWeight.IsValid()) && (nlsf.wType != 0 && nlsf.wType !=2) ) // { // nlsf.w$ = control.szWtDataName; // set weighting dataset // } // } // // // nlsf.execute("parainit"); // initialize parameters // // if (control.imaxIter > 0) nlsf.iterateEX(control.imaxIter); // else nlsf.iterateEX(100); // iterate // // if(control.openGraph) // { // if(control.confBands) // { // nlsf.createCurves("C"); // create confidence bands // } // if(control.predBands) // { // nlsf.createCurves("P"); // create prediction bands // } // if(control.pasteToPlot) // { // nlsf.pasteParams("Plot"); // create fit label on graph // } // if(control.createCurve) // { // nlsf.end(12); // create fit curve on graph // } // } // if(control.pasteToResults) // { // nlsf.pasteParams("Results"); // create results in Results Log // } // if(control.createWks) // { // nlsf.paramWKS("Parameters"); // create Parameters worksheet // } // // // assign nlsf object properties to NLSFCntrl structure // control.ChisqDoF = nlsf.chiSqr; // control.SSR = nlsf.ssr; // control.Correlation = nlsf.cor; // control.COD = nlsf.cod; // control.MuFinal = nlsf.muMin; // control.Mu = nlsf.mu; // control.DerivStep = nlsf.derivStep; // control.Tolerance = nlsf.tolerance; // control.Confidence = nlsf.conf; // control.Prediction = nlsf.pred; // control.inPara = nlsf.nPara; // control.inParaVary = nlsf.nParaVary; // control.imaxIter = nlsf.maxIter; // control.idataBegin = nlsf.dataBegin; // control.idataEnd = nlsf.dataEnd; // control.idataStep = nlsf.dataStep; // control.inPoints = nlsf.nPoints; // /* // control.ixBegin = nlsf.xBegin; // control.ixEnd = nlsf.xEnd; // control.ixPoints = nlsf.xPoints; // */ // control.iDOF = nlsf.dof; // control.inConstr = nlsf.nConstr; // control.inConstrEff = nlsf.nConstrEff; // control.iwType = nlsf.wType; // // // set values of results from fit // for(int ii = 1; ii <= nlsf.nPara; ii++) // { // control.Par[ii-1] = nlsf.p$(ii); // control.Err[ii-1] = nlsf.e$(ii); // control.Dep[ii-1] = nlsf.d$(ii); // control.ConfIntv[ii-1] = nlsf.c$(ii); // } // } // return true; //} // overloaded fitNLSF function to allow for quick fitting with weighting //double fitNLSF(string strYData, string strFitFunc, int iwType, string strWtData) //{ // NLSFCntrl control; // instantiate structure variable // initNLSF(control); // initialize fit // // lstrcpy(control.szYdataName, strYData); // initialize dependent variable // lstrcpy(control.szFuncName, strFitFunc); // initialize fitting function // // control.iwType = iwType; // initialize weight type // lstrcpy(control.szWtDataName, strWtData); // initialize weighting dataset name // // fitNLSF(control); // fit // return control.ChisqDoF; // //}