home *** CD-ROM | disk | FTP | other *** search
- /**********************************************
- *
- *
- we create a new menu, called 'Fit', that appears
- after 'data' in the menu bar
- *
- *
- **********************************************/
-
- NumPeaks = 1;/* default to single peak for peak related functions */
-
- menu -plot /* make sure plot window menu */
-
- menu 7 F&it
-
- /* this macro is used below as well as
- * for the apparent linear fit menu
- */
- def ShowLinearFit {
- /* no need to have "" except if there is '=' involved */
- type "Param\tValue\tsd";
- type "A\t$(LR.A)\t$(LR.sdA)";
- type "B\t$(LR.B)\t$(LR.sdB)";
- type "R = $(LR.r)";
- type "SD = $(LR.sd), N = $(LR.N)";
- df=LR.N-2;TINY=1e-20;
- t = LR.r*sqrt(df/((1-LR.r+TINY)*(1+LR.r+TINY)));
- P=incbeta(df/(df+t*t),0.5*df,0.5);
- type "P = $(P)";
- }
-
- /* this macro is used in initializing various
- * fitting functions
- * The parameters in limit.??? is assumed
- * set x0, y0 accordingly
- */
-
- def SetXYoffset {
- minoffset = 0.05;
- /* consider zero offset if 5% from zero */
- x0 = limit.xmin;
- if(abs(x0/(limit.xmax-x0)) < minoffset) {
- x0 = 0
- };
-
- y0 = limit.ymin;
- if(abs(y0/(limit.ymax-y0)) < minoffset) {
- y0 = 0
- };
- }
-
- def TypeBasicParam { /* type out Chisqr and x0,y0 */
- ty -a "Chisqr = $(Chisqr)";
- type "X offset (x0) = $(x0)";
- type "Y offset (y0) = $(y0)";
- Separator 3;
- }
-
- def FitGuess {/* a rough fit to get init guess */
- NoFitCurve = -1;/* do not generate fit curve */
- nlsf -H %C;
- nlsf -1;
- nlsf -2;
- nlsf -5;
- nlsf -t;/* terminate fit */
- }
-
- def KineticInit {
- limit %C;
- /* find max/min in both X and Y for the data */
-
- SetXYoffset;
- /* set y0 and x0 based on limit.###
- * will set y0 or x0 to zero if
- * they are close to zero
- */
-
- /* next we need to find the time constant(t1) and amplitude (A1) */
- del dummy;/* incase it was not deleted from other parts */
-
- copy -s 20 %C dummy;
- /* we interpolate the data with 20 points and put into
- * a temporary data set called dummy
- */
-
- set dummy -f 0;/* this remove any possible offset in x */
- dummy-y0; /* also remove y offset */
- dummy = ln(dummy);
- LR -B dummy;
- /* linear regression on the beginning */
- del dummy;/* we are interested only in the parameters */
-
- t1=-1/LR.B;t1=$(t1,*3);
- A1=exp(LR.A);A1=$(A1,*3);/* limit them to 3 sig digits */
- if(y0==0) (pv1=0);/* hold y0 if it is zero */
- if(x0==0) (pv2=0);/* hold x0 if it is zero */
- A2=0;A3=0;/* to disable the other two exponentials */
- }
-
- menu (&Linear Regression) {
- %W=%[%C,'_'];%B=%[%C,>'_'];
- del %W.%B_LINE;/* resulting curve of LR is in wksName.colName_LINE */
- LR %C; /* linear Regression */
- type -a; /* open the script window is it is not */
- type Linear Regression for %C:;
- type "Y = A + B * X";
- ShowLinearFit;
- #Linear fit to %C
- }
-
-
- def CheckPRName {
- if(%[%C,>"Polyfit"] != "") {/* > for beyond */
- ty -N "Are you sure you want to do
- polynomial regression on %C.
- which is already a polynomial fit?";
- };
- }
-
- /* The next menu is for polynomial fit
- * we will initialize some parameters
- * here, so they will not be init as
- * zero
- */
- menu (&Polynomial Regression..) {
- CheckPRName;/* to make sure we are not doing a PR on a PR fit curve */
- CheckVar order 2;/* see if order is defined, if not set it to 2 */
- CheckVar PR.Fit 1; /* 1 = create fit curve, 0 = no fit curve */
- CheckVar PR.Formula 0;
-
- limit %C;fitx1=limit.xmin;fitx2=limit.xmax;
-
- GetNumber [Order (1-9, 1 = linear)] order
- [Show Formula on Plot?] PR.Formula:2
- /* :2 for binery check box instead of edittext */
- [Create Fit Curve?] PR.Fit:2s
- /* s for show items below if yes */
- [Fit curve # pts] fitnpts
- [Fit curve Xmin] fitx1
- [Fit curve Xmax] fitx2
- [Polynomial Fit to %C];
- /* user can cancel, otherwise we will continue */
-
- if(order<=0 || order>9 || fitnpts < 2 || fitx1==fitx2) {
- type -b Parameters invalid; break 1;
- };
-
- /* if no more cancel button, any
- * error must be cause by
- * the DLL routine
- */
- def DLLError {
- type -b Polynomial fit failed! Please check parameters and try again.
- };
-
- PR.A=data(0,0,30);/* dataset to hold parameters */
- dll orgmath PR $(order) PR.A xof(%C) %C;
- /* Polynomial Regression is in the ORGMATH.DLL */
-
- layer -c %C;/* Position of %C in the layer, result in count */
-
- if(PR.Fit){
- GetCuvName PR$(order);
- /* %B is the name of the fit curve */;
-
- (%B)=data(0,0,fitnpts);
- /* (%B) instead of %B, otherwise just the content of %B
- * will be set instead of the name in %B be assigned
- */
- SetDataRange %B;/* use fitx1, fitx2 and fitnpts */
- /* the fitted curve is now ready */
-
- (%B)=poly(xof(%B),PR.A); /* get the y values for the fit */
-
- graph %B;/* show it in the current layer */
- set %B -c 2;/* color red */
- };
-
- Para2ScriptWindow PR.A order;
- /* Output to the script window is always enabled */
- if(PR.Formula){
- %Z="$(PR.A[1])";/* string could be very long, use Z */
- for(i=2;i<=order+1;i+=1) {
- if(PR.A[i]<0)
- {%K="$(PR.A[i])"}
- else
- {%K="+$(PR.A[i])"};
-
- if(i>2)
- {%Z="%Z%K x\+($(i-1))"}
- else
- {%Z="%Z%K x"};
- };
- label -s -n PR.F.$(count) "y=%Z";
- /* -s = string substitution, -n = name */
- };
- #Polynomial fit to %C
- }
-
- /*
- * %1 = coeff data set
- * %2 = order
- */
- def Para2ScriptWindow {
- type -a "Polynomial Regression on %C";
- type "y = A0 + A1 x + A2 x^2 + A3 x^3 +...";
-
- Separator 4;/* macro defined in ORGSYS.CNF */
- type -o Tab 55;/* set tab to 10 chars */
- ty Parameter\tValue\tsd;
-
- Separator 4;
-
- for(i=1;i<=%2+1;i+1) {
- ty "A$(i-1)\t$(%1[i],*8)\t$(%1[i+10])";
- };/* The $() notation with *8 means 8 significant digits */
-
- Separator 4;
-
- ty "R =$(%1[21])";
- ty "R^2=$(%1[23])";
- ty "SD =$(%1[22])";
- }
-
- Menu
-
- Menu "Apparent Linear Fit" {
- del %C.LINE;/* resulting curve of LR is in %C.LINE */
- LR -S %C; /* linear Regression on linearized scales */
- type -a; /* open the script window is it is not */
- type Linear Fit for %C on linearized scales;
- type "yscale(Y) = A + B * xscale(X)";
- type where scale() is the current axis scale function;
- ShowLinearFit;
- #Linear fit to %C on linearized X Y scales.
- }
-
- Menu
-
- Menu "1 &Exponential Decay" {
- nlsf -f ExpDecay 4;
- /* ExpDecay function can be triple exponential
- * so we restrict it to single by
- * using only the first 4 parameters.
- * params:y0 x0 A1 t1. Must define function first
- */
-
- KineticInit;
- for(i=5;i<=8;i+=1) {/* turn off 2nd and 3rd exp */
- p$(i)=0;/* the parameters */
- pv$(i)=0;/* the vary flag */
- };
- lsqfit;/* the generic fitting macro */
- queue {
- ty -a Fit y0+Ae^(-(x-x0)/t) to %C;
- TypeBasicParam;
- ty "t=$(t1)\tA=$(A1)";
- };#Fit y0+Ae^(-x/t) to %C
- }
-
- Menu "2 &Exponential Decay" {
- nlsf -f ExpDecay 4;
- /* ExpDecay function can be triple exponential
- * so we restrict it to single by
- * using only the first 4 parameters.
- * params:y0 x0 A1 t1 A2 t2. Must define function first
- */
-
- KineticInit;
- FitGuess;/* the generic fitting macro for init guess */
- t1 = prec(t1,1);/* just the order of magnitude */
- A2=0.5*A1;t2=10*t1;
- GetNum
- [First Decay Time(t1)] t1
- [Second Decay Time(t2)] t2
- [Initial Time] x0
- [Init Time vary?] pv2:2
- [Y Offset] y0
- [Y Offset Vary?] pv1:2
- [Verify initial guesses];
- pv5=1;pv6=1;/* turn on A2 and t2 variables */
- lsqfit;/* the generic fitting macro */
- queue {
- ty -a Fit y0 + A1e^(-x/t1) + A2e^(-x/t2) to %C;
- TypeBasicParam;
- ty "t1=$(t1,*4)\tA1=$(A1,*4)";
- ty "t2=$(t2,*4)\tA2=$(A2,*4)";
- };#Fit y0 + A1e^(-x/t1) + A2e^(-x/t2) to %C
- }
-
- Menu "3 &Exponential Decay" {
- nlsf -f ExpDecay 4;
- /* ExpDecay function can be triple exponential
- * so we restrict it to single by
- * using only the first 4 parameters.
- * params:y0 x0 A1 t1 A2 t2. Must define function first
- */
-
- KineticInit;
- FitGuess;/* the generic fitting macro for init guess */
- t1 = prec(t1,1);/* just the order of magnitude */
- A2=0.5*A1;t2=10*t1;A3=0.5*A2;t3=10*t2;
- GetNum
- [First Decay Time(t1)] t1
- [Second Decay Time(t2)] t2
- [Third Decay Time(t3)] t3
- [Initial Time] x0
- [Init Time vary?] pv2:2
- [Y Offset] y0
- [Y Offset Vary?] pv1:2
- [Verify initial guesses];
-
- pv5=1;pv6=1;/* turn on A2 and t2 variables */
- pv7=1;pv8=1;/* turn on A3 and t3 variables */
- lsqfit;/* the generic fitting macro */
-
- queue {
- ty -a Fit y0 + A1e^(-x/t1) + A2e^(-x/t2) + A3e^(-x/t3) to %C;
- TypeBasicParam;
- ty "t1=$(t1,*4)\tA1=$(A1,*4)";
- ty "t2=$(t2,*4)\tA2=$(A2,*4)";
- ty "t3=$(t3,*4)\tA3=$(A3,*4)";
- };#Fit y0 + A1e^(-x/t1) + A2e^(-x/t2) + A3e^(-x/t3) to %C
- }
-
- Menu
-
- Menu "1 &Exponential Growth" {
- nlsf -f ExpGrow 4;
- /* ExpGrow function can be double exponential
- * so we restrict it to single by
- * using only the first 4 parameters.
- * params:y0 x0 A1 t1. Must define function first
- */
-
- KineticInit;
- t1 = -t1;/* see above, it was for decay */
-
- lsqfit;/* the generic fitting macro */
- queue {
- ty -a Fit y0+Ae^(x/t) to %C;
- ty "y0=$(y0), A=$(A1), t=$(t1)";
- };#Fit y0+Ae^(-x/t) to %C
- }
-
- /* The Fit1Peak macro is used for both Gaussian and
- * Lorentzian fit. The macro does not need to be defined
- * before the menu, but it is clearer to put them
- * together.
- */
-
- def Fit1Peak {
- NumPeaks = 1;/* Gauss,Lorentz functions are multi-peaks functions */
-
- integ %C;nlsf -func %1;
- /* %1 is the argument passed to the macro */
-
- if(integ.dx < 0) (integ.dx *=-1;integ.area *= -1;);
- /* if x is in descending order, we need to turn these around */
-
- limit %C;
-
- SetXYoffset;
- /* see Kinetic above */
- /* paramters
- * y0 = P1
- * xc = P2
- * w = P3
- * A = P4
- */
- if(y0==0) (pv1=0);/* y0 is the 1st parameter, hold it if zero */
-
- P2=integ.x0;
- P4=integ.Area;
- P3=integ.dx;
- /* parameter initialization from the
- * integration result(integ.x0,integ.area,integ.dx).
- */
- lsqfit;
- /* the generic macro for iterating 10 times */
- queue {
- x = P4/(P3*sqrt(pi/2));/* peak height */
- ty -a %1 fit to %C;
- ty "Area\tCenter\tWidth\tOffset\tHeight";
- ty "$(P4,*5)\t$(P2,*5)\t$(P3,*5)\t$(P1,*5)\t$(x,*5)"
- /* *5 if a formatting statement for 5 significant digits */
- };
- /* using a queue command will
- * ensure proper windows updating.
- */
- }
-
- Menu (1 &Gaussian) {
- Fit1Peak Gaussian;#Gaussian fit to %C
- }
-
- Menu (1 &Lorentzian) {
- Fit1Peak Lorentz;#Lorentzian fit to %C
- }
-
- Menu Sig&moidal {
- axis -pget X Scale ScaleType;
- if(ScaleType==1) (%S = Logistic) else (%S = Boltzman);
- nlsf -f %S;
- lsqfit;
- /* the generic macro for iterating 12 times */
- queue {
- ty -a Sigmoidal(%S) fit to %C;
- ty " Chisqr = $(Chisqr)";
- Separator 3;
- ty " Init(A1) = $(A1,*5)\t$(PE1,*3)";
- ty "Final(A2) = $(A2,*5)\t$(PE2,*3)";
- ty "XatY50(x0) = $(x0,*5)\t$(PE3,*3)";
- if(ScaleType==1) {/* log scale, must be logistic */
- ty "Power(p) = $(p,*5)\t$(PE4,*3)";
- Separator 3;
- ty " XatY20 = $( x0*(0.2/0.8)^(1/p) )";
- ty " XatY80 = $( x0*(0.8/0.2)^(1/p) )";
- }
- else {
- ty "Width(dx) = $(dx,*5)\t$(PE4,*3)";
- Separator 3;
- ty " XatY20 = $( x0+dx*ln(0.2/0.8) )";
- ty " XatY80 = $( x0+dx*ln(0.8/0.2) )";
- };
- /* *5 if a formatting statement for 5 significant digits */
- };
- /* using a queue command will
- * ensure proper windows updating.
- */
-
- }
-
- /* assume fit to %C and all fitting parameters are in place */
- def MakePeaks {
- %B=xof(%C);
- if(%B=="")
- return 1;/* no x column, can not work */
- nlsf.funcx$=%B;
-
- %W=%[%C,'_'];/* get wks name */
- /* del fit and all peak columns */
- del %W_fit;
- for(i=1;i<=12;i+=1) (del %W_peak$(i)) /* max 12 peaks */
-
- /* put columns back to wks */
- win -o %W {
- work -v fit;
- for(i=1;i<=NumPeaks;i+=1) (work -v peak$(i));
- };
- break -b Generating curves...;
- break -r 0 (numPeaks+1);
- nlsf.funcCol$=%W_Fit;
- nlsf.make(func);
-
- break -p 1;
- layer -i %W_Fit;
-
- set %W_Fit -c color(red);
-
- for(i=1;i<=NumPeaks;i+=1) {
- break -p (i+1);
- nlsf -p Save;/* save copy of parameters */
- nlsf -y 0 3 3;/* value=0, init = 3(0,1,2), inc = 3 */
- y = A$(i);
- p$(1+3*i)= y;
-
- nlsf.funcCol$=%W_peak$(i);
- nlsf.make(func);
-
- nlsf -p Restore;
- layer -i %W_peak$(i);
- set %W_peak$(i) -c 4;/* blue */
- set %W_peak$(i) -d 2;/* dotted */
- };
- break -e;
- }
-
- def FitNPeaks {
- GetNumber -s [Number of Peaks] NumPeaks;
- if(NumPeaks > 12) {ty -b Too many peaks;break 1};
-
- del _Peak_Y;
- create _Peak_Y -X 20;
-
- integ %C;nlsf -func %1;
- /* %1 is the argument passed to the macro */
-
- if(integ.dx < 0) (integ.dx *=-1;integ.area *= -1;);
- /* if x is in descending order, we need to turn these around */
-
- def QuitFit [del _Peak_Y];
-
- limit %C;
- SetXYoffset;
- /* integration was carried out from zero, we need
- * to remove the offset */
- integ.area -= y0*(limit.xmax-limit.xmin);
- integ.area/=NumPeaks;
- integ.dx/=NumPeaks;
- GetNumber -s [Initial half width estimate] integ.dx;
- for(i=1;i<=NumPeaks;i+=1) {
- A$(i)=integ.area;
- w$(i)=integ.dx
- };
-
- if(y0==0) (pv1=0);/* y0 is the 1st parameter, hold it if zero */
- def EndToolbox {
- doTool 0;/* reset toolbox */
- for(i=1;i<=NumPeaks;i+=1) { XC$(i)=_Peak_A[i] };
- nlsf -H %C;
- noFitCurve=-1;/* we will generate the fit cureves by script */
- nlsf -v 0 1 3;/* hold all xc's constant */
- step*=2;
- nlsf -2;step/=2;nlsf -2;/* carry out four iterations */
- step/=2;nlsf -2;
-
- nlsf -v 1 1 3;/* release all holds on xc's */
- step*=2;
- nlsf -2;step/=2;
- nlsf -5;
- nlsf -t;/* terminate fit */
- queue {
- ty -a %1($(NumPeaks)) fit to %C;
- ty "Peak\tArea\tCenter\tWidth\tHeight";
- for(i=1;i<=NumPeaks;i+=1) {
- x = A$(i);y=Xc$(i);t=w$(i);
- z = x/(t*sqrt(pi/2));/* peak height */
- ty "$(i)\t$(x,*5)\t$(y,*5)\t$(t,*5)\t$(z,*5)";
- };
- ty "Yoffset = $(y0)";
- MakePeaks;/* macro defined above */
- };
- };
- GetPts -n _Peak_Y NumPeaks {Double-click(or Enter) to set Peak$(1+count)};
- }
-
- Menu
- Menu (Multiple &Gaussian) {
- FitNPeaks Gaussian;#Multiple Gaussian fit to %C
- }
-
- Menu (Multiple &Lorentzian) {
- FitNPeaks Lorentz;#Multiple Lorentzian fit to %C
- }
- menu
-
- Menu "&Select Fitting Function.." {
- nlsf -f;
- #Select one of the built-in \
- fitting functions, or enter your own.
- }
-
- Menu "Start &Fitting Session.." {
- nlsf %C;
- def QuitFit (doTool -wc nlsf);
- doTool -w nlsf;/* load the nlsf toolbar */
- #Start the user controlled \
- non-linear least square fitting session
- }
-
- Menu "&Parameters/Simulate.." {
- fitX1=X1;fitX2=X2;
- nlsf -e;
- #Open the Fitting Function dialog box
- }
-
- /* End of Fit menu */
-