// Filename:    LR.ogs
// Creation:    by Joe Przechocki, 7/27/95
// Purpose:     Modularized Code for performing Linear Regression 
//              from Menu or LR Toolbar.
// Modifications:
// RKM 12/11/98 v6.0141 REPORT_TO_OUTPUTLOG
// SDB 1/7/99 v6.0148 REPORT_TO_OUTPUTLOG
// LAS 1/10/02 v6.9174 added support for FindX and FindY
////////////////////////////////////////////////////////////////////////////////
// Main Code which is run based on if user hits FIT or SAVE on toolbar
////////////////////////////////////////////////////////////////////////////////


[Tab.Settings.OnInit]
	LR!Tab.Settings.Points.v1=20;
	LR!Tab.Settings.RangeMargin.v1=10;
	LR!Tab.Settings.Confidence.v1=95;
	LR!Tab.Settings.Simple=1;

[Tab.Operation.OnInit]
	LR!Tab.Operation.FixedSlope.v1=1;
	LR!Tab.Operation.FindXedit.enable=0;
	LR!Tab.Operation.FindYedit.enable=0;
	LR!Tab.Operation.FindXButn.enable=0;
	LR!Tab.Operation.FindYButn.enable=0;

[Tab.Operation.Fit.OnClick]

	if (exist(%H)==3 && Layer.is3D==1)
	{
		type -b $general.2DGraphsOnly;
		return 1;
	}

	stat.reset();				//Reset the LabSts40.DLL

	if (LR!Tab.Settings.FitAllCurves==1 && exist(%H)==3)
	{
		//Concatenate a list of Y datasets
		count=0;%Z="";doc -e DY {%Z=%Z %C;count++;};
		loop (ii,1,count)
		{
			%A=%[%Z,#ii];
		}
	}
	else
	{
		%Z=%C;
		count=1;
	}
	loop (ii,1,count)
	{
		%A=%[%Z,#ii];
		if (run.section(,SelectionCk,%A)==0 && run.section(,OptionsCk)==0) 
		{
			run.section(,MakeFit,%A);        //If Options are OK then fit
			run.section(,Columns);        //Now insert data into raw wks
		}
		else
			return 1;
	}


	if (LR!Tab.Settings.FitAllCurves==0 && LR!Tab.Settings.ApparentFit==0)
	{
	
		LR!Tab.Operation.StaticText$=$Regression.ForDataSet;
		LR!Tab.Operation.FindXedit.enable=1;
		LR!Tab.Operation.FindYedit.enable=1;
		LR!Tab.Operation.FindXButn.enable=1;
		LR!Tab.Operation.FindYButn.enable=1;
		
	}
	else
	{
	
		LR!Tab.Operation.StaticText$=$Regression.Calculate;
		LR!Tab.Operation.FindXedit.enable=0;
		LR!Tab.Operation.FindYedit.enable=0;
		LR!Tab.Operation.FindXButn.enable=0;
		LR!Tab.Operation.FindYButn.enable=0;
		
	}
		
	return 0;
	
	
[ReportError]
	type -b;			//BEEP!
	type -b %1;			//Type out the appropriate error message or a general one
	type -q "";                     //Clear up Status Bar

	
////////////////////////////////////////////////////////////////////////////////
// Menu LR Code
////////////////////////////////////////////////////////////////////////////////
[FitLinear]

	stat.reset();				//Reset the LabSts40.DLL
	//Call SimpleFit using 1st token calling this section
	//If first token is 1 then regression line will span entire X-axis range
	if (run.section(,SelectionCk,%C)==0 && run.section(,SimpleFit,%1)==0)
		run.section(,MenuLROutput);


////////////////////////////////////////////////////////////////////////////////
// Modular Code for performing Linear Regression follows
////////////////////////////////////////////////////////////////////////////////

[SelectionCk]
	/* check user settings                                          */
	/* -------------------------------------------------------------*/
	/* Check the users data selection                               */

	if (exist(%H)!=3 && exist(%H)!=2)
	{
		run.section(,ReportError,$General.2DGraphsOrWks);
		return 1;
	}

	if (exist(%H)==3)
	{
		if (%1=="") 
		{
			run.section(,ReportError,$Regression.NoData);
			return 1;
		}
		else
		{
			stat.data$=%1;
			%B=errof(%1)$;
			if (exist(%B)==1)
				stat.errbarData$=%B;
			else
				stat.errbarData$="";
		}
	}
	
	if (exist(%H)==2 && %(%H,@Y#,2)>1)
	{
		run.section(,ReportError,$General.Only1YColumn);
		return 1;
	}

	if (exist(%H)==2)
	{
		if ((wks.sel<=1)||((wks.col$(wks.c1).type==4)&&(wks.sel&16==16))) 
		{
			run.section(,ReportError,$Regression.BadOptions);
			return 1;
		}
		else
		{
			switch (wks.col$(wks.c1).type)
			{
				case 1://Y column is first select
					stat.data$=%(%H,wks.c1);        
					break;
				case 4://X column is first selected
					stat.data$=%(%H,%(%H,@YS,1));
					break;
				default:
					run.section(,ReportError,$Regression.BadOptions);
					return 1;
			};
			%A=stat.data$;%B=errof(%A)$;
			if ((exist(%B)==1)&&(colnum(%B)<=wks.c2)) 
				stat.errbarData$=%B;
			else
				stat.errbarData$="";
			
		}
	}

////////////////////////////////////////////////////////////////////////////////
// Check/Update Options Settings on SETTINGS page of toolbar
////////////////////////////////////////////////////////////////////////////////
[OptionsCk]

	//User can specify any number for fit POINTS or CONFIDENCE level
	//Toolbar only displays integer however remembers entered number
	//therefore we need to set the actual number to the nearest integer.

	//If user has Error-Bars-As-Weight OFF we definitely do not use error Bars
	if (LR!Tab.Operation.ErrorAsWeight==0)
		stat.ErrBarData$="";

	if (LR!Tab.Settings.RangeMargin<0)
	{
		run.section(,ReportError,$Regression.BadMargins);
		return 1;
	}

	if ((exist(%H)==2)&&(LR!Tab.Settings.ApparentFit))
	{
		run.section(,ReportError,$Regression.ApparentWks);
		return 1;
	}

	// Through (0,0) requires both axes to be linear               
	if (LR!Tab.Operation.ThroughZero)
	{
		if ((exist(%H)==3)&&(layer.x.space!=1)||(layer.y.space!=1))
		{
			run.section(,ReportError,$Regression.ThroughZeroGr);
			return 1;
		}
			
		if (LR!Tab.Operation.FixSlope)
		{
			run.section(,ReportError,$Regression.ThroughZeroFixSlope);
			return 1;
		}
	
	}

	if (LR!Tab.Settings.Confidence.v1<=0 || LR!Tab.Settings.Confidence.v1>=100)
	{
		run.section(,ReportError,$Regression.BadConfidence);
		return 1;
	}

	LR!Tab.Settings.Confidence.v1=int(LR!Tab.Settings.Confidence.v1*10+.5)/10;

	// Need at least 2 pts to create a line  

	if (LR!Tab.Settings.Points.v1<2)
	{
		run.section(,ReportError,$Regression.BadNoOfPts);
		return 1;
	}
	
	%B=stat.errbarData$;
	if (LR!Tab.Operation.ErrorAsWeight && %B=="")
	{
		run.section(,ReportError,$Regression.NoErrBars);
		return 1;
	}
	
	// Insert Residual Column requires a new column to be in existance before lr() 
	%A=stat.data$;
	
	if (LR!Tab.Settings.ResidualData && exist(%[%A,'_'])!=2)
	{
		run.section(,ReportError,$General.NoRawWks);
		return 1;
	}

	if (LR!Tab.Settings.ResidualData)
		win -o %[%A,'_']
		{
			wks.col=colnum(%A);
			for (;1;)
			{
				if (wks.col$(wks.col+1).type==3 || wks.col$(wks.col+1).type==5)
					wks.col+=1;
				else
					break;
			}
			if (LR!Tab.Operation.ErrorAsWeight && wks.col<colnum(%B))
				wks.col=colnum(%B);		//if no error-bar designations found, force to be dataset MAPPED AS error

			wks.col+=1;     			//Insert after Y or any Error Bar data...

			wks.insert(Residual);
			wks.Insert(Fit);        		//Insert with automatic enumeration of columns
			stat.resData$=%(%H,wks.col+1);
			LR!Tab.Operation.StoreResidual.v1=wks.col+1;//Store location of Residuals
		};
		
	
	/* -------------------------------------------------------------*/
	return 0;						// return Ok
	

////////////////////////////////////////////////////////////////////////////////
// Fitting Module
////////////////////////////////////////////////////////////////////////////////

[MakeFit]
	/* Perform LR */
	/* -------------------------------------------------------------*/
	if (exist(%H)==2)
	{
		/* plot approved wks selection*/
		worksheet -p 201 scatter;
		if (LR!Tab.Operation.ErrorAsWeight)
		{
			%A=stat.ErrBarData$;	//Ensure inclusion of bars
			layer -i %A;
		}
	
		//Note! Place code here to modify plot if desired.
	}

	if (LR!Tab.Operation.ErrorAsWeight)
		stat.ChiSqrErr=LR!Tab.Operation.UseChiSquare;
	else
		stat.ChiSqrErr=1;
	
	layer -i;                       /* to clear style templates */
	
	// Setup the Fit Curve
	%A=stat.data$;				//Set %A to be the RAW DATASET

	create.wksName$="LinearFit";
	create.wksLabel$=$Regression.LinearFit;
	create.template$="CREATE";
	%B=LR!Tab.Settings.Points.v1;
	create.npts=%B;
	create.enumwks=1;			//Enumerate the worksheet
	create.numtypes=1;			
	create.type1=4;				//Only explicitly specify 1st type as X
	create.typen=1;				//Set TypeN=Y column type

	if (LR!Tab.Operation.ConfidenceBands==0 && LR!Tab.Operation.PredictionBands==0)
		create.wks(A %A);

	if (LR!Tab.Operation.ConfidenceBands==1 && LR!Tab.Operation.PredictionBands==0)
	{
		create.wks(A %A UCL LCL);
		%B=create.data3$;
		stat.UCLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRUpperConf);
		%B=create.data4$;
		stat.LCLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRLowerConf);
	}
	if (LR!Tab.Operation.ConfidenceBands==0 && LR!Tab.Operation.PredictionBands==1)
	{
		create.wks(A %A UPL LPL);
		%B=create.data3$;
		stat.UPLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRUpperPred);

		%B=create.data4$;
		stat.LPLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRLowerPred);
	}
	if (LR!Tab.Operation.ConfidenceBands==1 && LR!Tab.Operation.PredictionBands==1)
	{
		create.wks(A %A UCL LCL UPL LPL);
		%B=create.data3$;
		stat.UCLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRUpperConf);

		%B=create.data4$;
		stat.LCLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRLowerConf);

		%B=create.data5$;
		stat.UPLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRUpperPred);

		%B=create.data6$;
		stat.LPLdata$=%B;
		run.section(Origin,SetWksLabel,%B $Regression.LRLowerPred);
	}

	%B=create.data1$;	
	stat.fitXdata$=%B;

	%B=create.data2$;
	stat.fitYdata$=%B;
	run.section(Origin,SetWksLabel,%B $Regression.LinearFit);
	stat.confLevel=LR!Tab.Settings.Confidence.v1/100;

	stat.Apparent=LR!Tab.Settings.ApparentFit;
		
	/* New codes, CPY v3.74 */
	stat.MakeX.FitNpts=LR!Tab.Settings.Points.v1;

	%A=stat.data$;				//Set %A to be the RAW DATASET
	limit %A;				//Get some limiting values on the raw dataset	
	if(LR!Tab.Operation.ThroughZero)
	{
		if(Limit.xmin > 0)
			Limit.xmin=((layer.x.from<0)&&LR!Tab.Settings.SpanXAxis)?layer.x.from:0;
		if(Limit.xmax < 0)
			Limit.xmax=((layer.x.to>0)&&LR!Tab.Settings.SpanXAxis)?layer.x.to:0;
	}
	if (LR!Tab.Settings.SpanXAxis)
	{
		if (LR!Tab.Operation.ThroughZero)
		{
			stat.MakeX.FitX1=limit.xmin;
			stat.MakeX.FitX2=layer.x.to;
		}
		else
		{
			stat.MakeX.FitX1=layer.x.from;
			stat.MakeX.FitX2=layer.x.to;
		}
	}
	else
	{
		stat.MakeX.FitX1=limit.xmin;
		stat.MakeX.FitX2=limit.xmax;
	}
	
	stat.makeX.margin=LR!Tab.Settings.SpanXAxis?0:LR!Tab.Settings.RangeMargin;
	stat.makex();
	
	%B=errof(%A)$;						//Get the error dataset of the raw dataset
	if (LR!Tab.Operation.ErrorAsWeight)
		Stat.ErrBarData$=%B;                        	//Use error bars if asked to do so
	else
		Stat.ErrBarData$="";
		
	if(LR!Tab.Operation.ThroughZero)
		err=stat.LR(Z);
	if(LR!Tab.Operation.FixSlope)
	{
		stat.lr.b=LR!Tab.Operation.FixedSlope.v1;
		err=stat.LR(B);
	}
	if(LR!Tab.Operation.ThroughZero==0 && LR!Tab.Operation.FixSlope==0)
		err=stat.LR();					// Linear Regression without line 
		
	// Check to see if the DLL reports bad calculation due to error bars 
	if (err==6)
	{
		type -b;                                	//BEEP!
		type -b $regression.badErrBar;  	 	//Error!
		return 1;                       		//Return Error
	}

	// Check to see if the DLL reports bad calculation due to not enough data
	if (err==1)
	{
		type -b;				//BEEP!
		type -b $general.BADCalculation;	
		return 1;
	}	

	/* Prepare the plot to receive datasets                 */
	/* ---------------------------------------------------- */
	if (LR!Tab.Settings.SpanXAxis)
	{
		LR!Tab.Operation.StoreRescale=layer.x.rescalemargin;
		layer.x.rescalemargin=0;
	}

	%B=create.data2$;
	layer -i200 %B;		                     		// plot into layer
	set %B -c 2;                        			// set to red
	
	// Include green confidence line curves 
	if(LR!Tab.Operation.ConfidenceBands)
	{
		%B=stat.UCLdata$;
		layer -i200 %B;
		set %B -c 3;
	
		%B=stat.LCLdata$;
		layer -i200 %B;
		set %B -c 3;
	}
	// Include blue confidence line curves 
	if(LR!Tab.Operation.PredictionBands)
	{
		%B=stat.UPLdata$;
		layer -i200 %B;
		set %B -c 4;
	
		%B=stat.LPLdata$;
		layer -i200 %B;
		set %B -c 4;
	}
	legend;
	
	if (LR!Tab.Settings.SpanXAxis)
	{
		layer.x.rescalemargin=LR!Tab.Operation.StoreRescale;
	}
	
	/* ---------------------------------------------------- */
	/*   Output Parameters and ANOVA Table (optional)       */
	/* ---------------------------------------------------- */
	SaveRedirection=type.Redirection(16,3);	// SDB 1/7/99 REPORT_TO_OUTPUTLOG
	type.BeginResults();		/// RKM 12/10/98 v6.0141 REPORT_TO_OUTPUTLOG
	%B=stat.errbardata$;
	if (LR!Tab.Settings.ApparentFit)
	{
		type $regression.LRApparent;
		type $regression.LREqnApparent;
		type $regression.LRmsgApparent;
		if (LR!Tab.Operation.ErrorAsWeight)
			type $regression.UsingWeight;
	}
	if(LR!Tab.Operation.ThroughZero==0 && LR!Tab.Settings.ApparentFit==0)
	{
		type $regression.performLR;
		type $regression.EqnforLR;
		if (LR!Tab.Operation.ErrorAsWeight)
			type $regression.UsingWeight;
	}
	%A=%1;
	if(LR!Tab.Operation.ThroughZero==1 && LR!Tab.Settings.ApparentFit==0)
	{
		type $regression.performLRZ;
		type $regression.EqnForLRZ;
		if (LR!Tab.Operation.ErrorAsWeight)
			type $regression.UsingWeight;
	}
	
	type;
	
	if (LR!Tab.Settings.Simple==1)
	{
		type $regression.ShortParaHeader1;
		separator 4;
		type "A\t$(Stat.LR.A)\t$(stat.LR.Ase)";
		type "B\t$(Stat.LR.B)\t$(stat.LR.Bse)";
		separator 4;
		
		type;
		type $regression.ShortParaHeader2;
		separator 4;
		if (stat.pValue<0.0001) %A="<0.0001"; else %A=$(stat.pValue);
		type "$(Stat.R)\t$(Stat.SD)\t$(stat.npts)\t%A";
		separator 4;
		type;
	}
	else
	{
		type $regression.LongParaHeader1;
		separator 5;
		if (stat.LR.Ap<0.0001) %A="<0.0001"; else %A=$(stat.LR.Ap);
		type "A\t$(Stat.LR.A)\t$(stat.LR.Ase)\t$(stat.LR.A/stat.LR.Ase)\t%A";
		if (stat.LR.BP<0.0001) %A="<0.0001"; else %A=$(stat.LR.BP);
		type "B\t$(Stat.LR.B)\t$(stat.LR.Bse)\t$(stat.LR.B/stat.LR.Bse)\t%A";
		separator 5;
		
		type;
		type $regression.LongParaHeader2;
		separator 5;
		type "$(Stat.R)\t$(stat.COD)\t$(stat.AdRSq)\t$(Stat.SD)\t$(stat.npts)";
		separator 5;
		/* ---------------- Type out the Confidence Intervals...------- */
		type;
		%A=LR!Tab.Settings.Confidence$;
		type $regression.ConfHeader;
		separator 5;
		type "A\t$(Stat.LR.A-(Stat.LR.ASE*Stat.LR.t))\t$(Stat.LR.A+(Stat.LR.ASE*Stat.LR.t))";
		type "B\t$(Stat.LR.B-(Stat.LR.BSE*Stat.LR.t))\t$(Stat.LR.B+(Stat.LR.BSE*Stat.LR.t))";
		/* ---------------- Type out the ANOVA Table...---------------- */
		separator 5;
		type;
		type $regression.AnovaHeader;
		separator 5;
		type $regression.AnovaDesc1;
		type $regression.AnovaDesc2;
		separator 5;
		type -l $regression.model;                       //The word MODEL in current language
		type "\t$(stat.df1)\t$(stat.ssr)\t$(stat.msr)\t$(stat.fvalue)";
		type -l $regression.error;                       //The word ERROR in current language
		type "\t$(stat.df2)\t$(stat.sse)\t$(stat.mse)";
		type -l $regression.total;                       //The word TOTAL in current language
		type "\t$(stat.df3)\t$(stat.SSto)";
		separator 5;
		type;
	
		type $regression.AnovaDesc3;
		separator 5;
		if (stat.pValue<0.0001) %A="<0.0001"; else %A=$(stat.pValue);
		type  "%A";
		separator 5;
		type;
	}

////////////////////////////////////////////////////////////////////////////////
// Output Fit and Residual into new columns of the Raw Data Worksheet
////////////////////////////////////////////////////////////////////////////////
[Columns]
	/* Calculate Fit & Residual Data based on experimental X values */
	/* -------------------------------------------------------------*/
	
	%A=stat.data$;

	if (LR!Tab.Settings.ResidualData)
	{
		type -qp 0;                                     //Disable Origin arithmetic progress msg
		win -o %[%A,'_']
		{						//Fit=Raw Data - Residual
			wks.col=colnum(%A);
			wcol(LR!Tab.Operation.StoreResidual.v1-1)=wcol(wks.col)-wcol(LR!Tab.Operation.StoreResidual.v1);
			set %H -ue;				//Update worksheet if Excel
		};

		type -qp 1;                                     //Enable Origin arithmetic progress msg

		%A=%[%A,'_'];
		type $regression.SavedFit&Res;
	}
	type.EndResults();
	type.Redirection=SaveRedirection; // restore previous redirection.
	delete -v SaveRedirection;
	
	return 0;						//Return OK
	
	/* -------------------------------------------------------------*/
	
////////////////////////////////////////////////////////////////////////////////
// Simplistic LR Fitting
////////////////////////////////////////////////////////////////////////////////
[SimpleFit]
	/* Perform LR */
	/* -------------------------------------------------------------*/
	if (exist(%H)==2)
	{
		/* plot approved wks selection*/
		worksheet -p 201;
		if (LR!Tab.Operation.ErrorAsWeight)
		{
			%A=stat.ErrBarData$;//Ensure inclusion of bars
			layer -i %A;
		}
	
		//Note! Place code here to modify plot if desired.
	}
	
	%A=Stat.ErrBarData$;
	if(exist(%A)==1)
		stat.ChiSqrErr=0;
	else
		stat.ChiSqrErr=1;

	layer -i;/* to clear style templates */
	
	/* setup the fit curve */
	%A=%C;
	create.wksName$="LinearFit";
	create.wksLabel$=$Regression.LinearFit;
	create.template$="CREATE";
	create.npts=20;
	create.enumwks=1;					//Enumerate the worksheets
	create.enumerate=1;
	create.numtypes=1;					//Only explicitly specify 1st type as X
	create.type1=4;
	create.typen=1;						//Set TypeN=Y column type
	
	create.delete(%C);
	create.wks(A %C);

	%B=create.data1$;
	stat.fitXdata$=%B;
	%B=create.data2$;
	stat.fitYdata$=%B;
	%A=%C;			//%A is used in the definition of $Regression.LinearFit
	run.section(Origin,SetWksLabel,%B $Regression.LinearFit);		//Set Label

	stat.Apparent=1;					//Always Apparent
	stat.MakeX.FitNpts=20;
	
	stat.data$=%C;
	limit %C;

	if (%1==1)
	{
		stat.MakeX.FitX1=layer.x.from;
		stat.MakeX.FitX2=layer.x.to;
		stat.MakeX.Margin=0;
	}
	else
	{
		stat.MakeX.FitX1=limit.xmin;
		stat.MakeX.FitX2=limit.xmax;
		stat.MakeX.Margin=10;				//Default Margin is 10%
	}
	
	stat.makex();
	
	err=stat.LR();/* Linear Regression without line */

	/* Check to see if the DLL reports bad calculation due to error bars */
	if (err==6)
	{
		type -b;                                	//BEEP!
		type -b $regression.badErrBar;   		//Error!
		return 1;                       		//Return Error
	} 
	// Check to see if the DLL reports bad calculation due to not enough data
	if (err==1)
	{
		type -b;				//BEEP!
		type -b $general.BADCalculation;	
		return 1;
	}	

	if (%1==1 || %[%1,1:1]=="S")		
	{
		i=layer.x.rescalemargin;
		layer.x.rescalemargin=0;
	}
	
	%A=create.data2$;
	layer -i200 %A;						// plot into layer
	set %A -c 2;		                       	 	// set to red

	if (%1==1 || %[%1,1:1]=="S")		
		layer.x.rescalemargin=i;
	
	legend;
	return 0;

////////////////////////////////////////////////////////////////////////////////
// Menu LR Simple Output - no possibility of Through Zero
////////////////////////////////////////////////////////////////////////////////

[MenuLROutput]
	SaveRedirection=type.Redirection(16,3);	// SDB 1/7/99 REPORT_TO_OUTPUTLOG
	type.BeginResults();		/// RKM 12/10/98 v6.0141 REPORT_TO_OUTPUTLOG
	%A=Stat.Data$;
	if (layer.x.space==1 && layer.y.space==1)
	{	
		type $regression.performLR;
		type $regression.EqnForLR;
	}
	else
	{
		type $regression.LRApparent;
		type $regression.LREqnApparent;
		type $regression.LRmsgApparent;
	} 
	
	/* Now check to see if there is error data and if it is in plot */
	%A=stat.data$;
	%B=errof(%A)$;
	if (exist(%B)==1)
		type $regression.UsingWeight;
	type;
	type $regression.ShortParaHeader1;
	separator 4;
	type "A\t$(Stat.LR.A)\t$(stat.LR.Ase)";
	type "B\t$(Stat.LR.B)\t$(stat.LR.Bse)";
	separator 4;

	type;
	type $regression.ShortParaHeader2;
	separator 4;
	if (stat.pValue<0.0001) %A="<0.0001"; else %A=$(stat.pValue);
	type "$(Stat.R)\t$(Stat.SD)\t$(stat.npts)\t%A";
	separator 4;
	type.EndResults();
	type.Redirection=SaveRedirection; // restore previous redirection.
	delete -v SaveRedirection;
	return 0;

[Tab.Operation.ErrorAsWeight.OnClick]
	LR!Tab.Operation.UseChiSquare=LR!Tab.Operation.ErrorAsWeight==0?1:0;

	
[Tab.Operation.FindXButn.Onclick]
	
	//type -b "Find X";
	if(LR!Tab.Operation.FindYedit.v1 == 0/0)
		run.section(,ReportError,$Regression.LRNoY);
	else
		LR!Tab.Operation.FindXedit.v1=(LR!Tab.Operation.FindYedit.v1-stat.lr.a)/stat.lr.b;
	
[Tab.Operation.FindYButn.Onclick]
	
	//type -b "Find Y";
	if(LR!Tab.Operation.FindXedit.v1 == 0/0)
		run.section(,ReportError,$Regression.LRNoX);
	else
		LR!Tab.Operation.FindYedit.v1=stat.lr.a+(stat.lr.b*LR!Tab.Operation.FindXedit.v1);
	

[OnCancel]

	LR!Tab.Operation.StaticText$=$Regression.Calculate;
	LR!Tab.Operation.FindXedit.enable=0;
	LR!Tab.Operation.FindYedit.enable=0;
	LR!Tab.Operation.FindXButn.enable=0;
	LR!Tab.Operation.FindYButn.enable=0;
	LR!TAB.OPERATION.FINDXEDIT.V1$="";
	LR!TAB.OPERATION.FINDYEDIT.V1$="";
	return 0;
	
