// Filename:    Assays.ogs
// Creation:    by Laurie Shea, 5/10/96
// Purpose:     Modularized Code for standard curves
// Calibration Model
// 1.  Linear Fit
// 2.  Quadratic Fit
// 3.  Cubic Fit
// 4.  Spline Fit
// 5.  Boltzmann Fit
// 6.  Logistic Fit
// 7.  ExpDecay Fit
//
// Modifications:
//	RKM 2/12/97 Standard.otw now in buttons directory MOVE_STANDARD
//	JMP 8/05/97 Use COPY commands instead of domenu operations for COPY and PASTE
////////////////////////////////////////////////////////////////////////////////
// Sets the number of replicates to display
////////////////////////////////////////////////////////////////////////////////
[Display]

	if(format.choice==1)
	{

		if (wks.ncols<replicates.value+1)
			worksheet -a replicates.value-wks.ncols+1;

		else
		{
			for(;wks.ncols>(replicates.value+1);)
			{
				delete %(%H,wks.ncols);
			}
		}
		for(ii=2;ii<=wks.ncols;ii++)
		{
			wks.col$(ii).type=1;
		}
		doc -uw;
	}
	else 
	{
		if(wks.ncols/2<replicates.value)
			worksheet -a (replicates.value*2-wks.ncols);
		else
		{
			if(wks.ncols/2>replicates.value)
	   		{
				jj=wks.ncols-(replicates.value*2+1)+1;
				repeat (jj) {delete %(%H,wks.ncols)};
			}
		}
		for(ii=1;ii<=wks.ncols;ii++)
		{
			if(ii/2!=int(ii/2))
				wks.col$(ii).type=4;
		}
		doc -uw;
	}
	


[SelectionCk]


	if(format.choice==2 && datarange.choice==2 && (wks.c2-wks.c1+1)/2 != int((wks.c2-wks.c1+1)/2))
	{
		type -b $calibrate.oddnumofcolumns;
		return 1;
	};

	if(datarange.choice==2 && wks.c1==wks.c2)
	{
		type -b $calibrate.noselection;
		return 1;
	} 

	return 0;


////////////////////////////////////////////////////////////////////////////////
// Code which is called from Standard worksheet
////////////////////////////////////////////////////////////////////////////////
[Standard]

	if (run.section(,selectionck)==0)
	{
		run.section(,worksheetselection);
		if(replicates.v1>1) 
		{
			switch (format.choice) 
	      		{
			case 1:
				run.section(,average1);
				break;
			case 2:
				run.section(,average2);
			break;
			}	
	   	}
		else
	   	{
			///RKM Standard.otw now in buttons directory MOVE_STANDARD
			doc -cw standard; 
			doc -t buttons\standard.otw;
			win -r %H Standard$(count+1);
			///
			%(%H,1)=%(%W,1);
			%(%H,2)=%(%W,2);
		   	delete %H_SD;
			sort -c 1 2 %(%H,1);	//sort in ascending order
		};
	}

////////////////////////////////////////////////////////////////////////////////
// Main Code called from 'Calculations' buttons
////////////////////////////////////////////////////////////////////////////////
[Main]
	
	switch (index)
	{
	case 1:
		run.section(,fit);
		run.section(,predictX);
		layer -a;
		break;
	case 2:
		run.section(,fit);
		run.section(,predictY);
		layer -a;
		break;
	case 3:
		run.section(,clear);
		break;
	case 4:
		run.section(,help);
		break;
	};


////////////////////////////////////////////////////////////////////////////////
//Fit the data to the selected model.
////////////////////////////////////////////////////////////////////////////////

[Fit]


	%W=%H;				//store active window name in %W
	/*    %A holds the name of calibration model		*/

	%A=model.l$(model.choice)$;	//gets the calibration model
	%A=%[%A,#1];			//strips the word fit
	


	doc -cp %A;
	win -t plot standard %A$(count+1);
	
	if (%W!model.choice==6)
		layer1.x.type=2;
	if(exist(%W_SD)==1)
	{
		get %W_SD -e ErrorEnd;
		if(ErrorEnd!=0)
		{
			layer -i (%W_YAve) (%W_SD) (%W_Ynew);
			set %W_SD -o %W_Yave;		//Set as +- error bars
			set %W_SD -c 1;			//Set color to black
		}
		else
		{
			layer -i (%W_YAve) (%W_Ynew);
		}
		delete -v ErrorEnd;
	}
	else
	{
		layer -i (%W_YAve) (%W_Ynew);
	}
	layer -i201 %W_YAve;		//Set type to scatter (just to make sure)
	set %W_YAve -c 1;		//Set color to black
	layer -i201 %W_Ynew;		
	set %W_Ynew -c 4;		//Set color to blue
	layer -a;	//rescale to show all

	switch(%W!model.choice)
	{
   	   case 1 to 3:
		run.section(,commonlinear);
		break;
       	   case 4:
		run.section(,Spline);
	        break;
  	   case 5:
		run.section(,Boltzmann);
	        break;
	   case 6:
		run.section(,Logistic);
	        break;
	   case 7:
		run.section(,ExpDecay);
		break;
	}

////////////////////////////////////////////////////////////////////////////////
//
//Worksheet Selection 
//
////////////////////////////////////////////////////////////////////////////////
[WorksheetSelection]

	//if entire worksheet selected
	if(datarange.choice==1)
	{
		%W=%H;
	}
	else
	{
		%W=%H;
		getenumtempwks origin Selection;	//open hidden worksheet - name is in %A
		NumCols=((%W!wks.c2-%W!wks.c1+1)-%A!wks.ncols)>=0?((%W!wks.c2-%W!wks.c1+1)-%A!wks.ncols):0;
		win -o %A
		{
			worksheet -a NumCols;
		}
		delete -v NumCols;

		for (ii=%W!wks.c1,jj=1;ii<=%W!wks.c2;ii++,jj++)
		{
			copy -b (%W!wks.r1) %(%W,ii) %(%A,jj) -b 1 -e (%W!wks.r2-%W!wks.r1+1);
		}
		%W=%A;
	};





////////////////////////////////////////////////////////////////////////////////
//
// Averages the data when the data is in XYYY Format
// first column assumed to be the X data
////////////////////////////////////////////////////////////////////////////////

[Average1]
// xyyy format

	///RKM Standard.otw now in buttons directory MOVE_STANDARD
	doc -cw standard; 
	doc -t buttons\standard.otw;
	win -r %H Standard$(count+1);
	///
	sum(%W,2,$(%(%W,@#)));
	%(%H,1)=%(%W,1);
	%(%H,2)=_Mean;	
	%(%H,3)=_SD;
	sort -c 1 3 %(%H,1);	//sort in ascending order



////////////////////////////////////////////////////////////////////////////////
// Averages the data when the data is in XYXY Format
//////////////////////////////////////////////////////////////////////////////////

[Average2]
//xyxy
	
		
	//Create 2 scratch worksheets
	//first worksheet averages the X columns

	getenumtempwks origin %WX;

	/*execute script for the named window*/
	win -o %A
	{
		worksheet -a (%W!wks.ncols/2 -2);
		for (ii=1;ii<=%(%W,@#)/2;ii++)
			wcol(ii)=%(%W,(ii-1)*2+1);
		%B=%H;
		page.closebits=2;
	};

	getenumtempwks origin %WY;
	win -o %A
	{
		worksheet -a (%W!wks.ncols/2 -2);
		for (ii=1;ii<=%(%W,@#)/2;ii++)
			wcol(ii)=%(%W,ii*2);
		page.closebits=2;
	};

	///RKM Standard.otw now in buttons directory MOVE_STANDARD
	doc -cw standard; 
	doc -t buttons\standard.otw;
	win -r %H Standard$(count+1);
	///
	
	sum(%B,1,$(%(%B,@#)));
	%(%H,1)=_Mean;
	sum(%A,1,$(%(%A,@#)));
	%(%H,2)=_Mean;	
	%(%H,3)=_SD;
	sort -c 1 3 %(%H,1);	//sort in ascending order
	win -o %A {win -ca};
	win -o %B {win -ca};
	
	
	
////////////////////////////////////////////////////////////////////////////////
//
// Linear Fit, Quadratic Fit, Cubic Fit depending upon the selected model
//
////////////////////////////////////////////////////////////////////////////////

[CommonLinear]

	/*depending upon the calibration model*/
	/*performs a linear regression on the data*/
	/*performs a 2nd order polynomial regression*/
	/*performs a 3rd order polynomial regression*/
	stat.reset();
	stat.data$=%(1,@D);
	%A=stat.data$;
	%B=errof(%A);
	if(exist(%B)==1)
	{
		get %B -e ErrorEnd;
		if(ErrorEnd!=0)
			stat.errbarData$=%B;
		else
			stat.errbarData$="";
		delete -v ErrorEnd;
	}
	else
	{
		stat.errbarData$="";
	}
	if (%W!model.choice==1)
		stat.name(0,%A,A,Line);
	else
		stat.name(0,%A,A,Poly);
	   
	%A=stat.name.worksheet$;
	if (exist(%A)==2)		//Kill the already existing AND open worksheet
		win -o %A {page.closebits=2;win -ca;};
	create %A -wd 1000 XFit YFit;	//create a worksheet with two columns named XFit and YFit
	if (%W!model.choice==2)
		stat.pr.order=2;
	else
	if (%W!model.choice==3)
		stat.pr.order=3;
	stat.fitxdata$=%A_XFit;
	stat.fitYdata$=%A_YFit;
	stat.makeX.fitnpts=1000;
	%A=stat.data$;
	limit %A;
	stat.makex.fitx1=limit.xmin;
	stat.makex.fitx2=limit.xmax;
	stat.makex();
	if (%W!model.choice==1)
		stat.LR();
	else
		stat.PR();	
	%A=stat.name.worksheet$;
	layer -i200 %A_YFit;	
	set %A_Yfit -c 2;

	%A=%A_XFit;	//%A stores the X values for the calibrated curve
	%B=%[%A,'_']_YFit;	//%B stores the Y values for the calibrated curve


////////////////////////////////////////////////////////////////////////////////
// Fits the data to an exponential decay
////////////////////////////////////////////////////////////////////////////////

[ExpDecay]
/* Exponential decay 1 Fit*/
/*Fit y0+A1*e^(-(x-x0)/t1) to %(1,@D) */
	
	nlsf.func$=ExpDecay1;
	//SDB 9/9/04 added section to use old code for ExpDecay1 parameter init
	run.section(assays,KineticInit,0.05);
	run.section(assays,AutoNLSF);


////////////////////////////////////////////////////////////////////////////////
// Sets the data plot line connection method to Spline
////////////////////////////////////////////////////////////////////////////////

[Spline]

	set %(1,@D) -l 9;		//line connection method set to Spline
	stat.name(0,%(1,@D),A,Spline);
	%B=stat.name.worksheet$;
	if (exist(%B)==2)		//Kill the already existing AND open worksheet
		win -o %B {page.closebits=2;win -ca;};
	copy -s 1000 %(1,@D) %B_spline;
	%B=stat.name.worksheet$;
	%B=%B_spline;		//Stores name of associated y column
	%A=xof(%B);		//Stores name of associated x column

	return 0;

////////////////////////////////////////////////////////////////////////////////
// Fits the data to a sigmoidal
////////////////////////////////////////////////////////////////////////////////
[Boltzmann]

//Sigmoidal fit to %(1,@D)
	nlsf.func$ = Boltzmann;
	copy -x %(1,@D) dummy;
	deriv dummy;
	integ -q dummy;
	dx = integ.dx/2; 
	x0 = integ.x0;
	limit %(1,@D);
	if(limit.imax < limit.imin) 
	{
		temp = limit.ymax;
		limit.ymax=limit.ymin;
		limit.ymin=temp;
	}
	A1=limit.ymin;
	A2=limit.ymax;
	run.section(,autoNLSF);
	/* the generic macro for iterating 20 times */

[Logistic]

	nlsf.func$= Logistic;
	limit %(1,@D);
	if (limit.imax<limit.imin) 
	{
		temp = limit.ymax;
		limit.ymax=limit.ymin;
		limit.ymin=temp;
	} 
	A1=limit.ymin;
	A2=limit.ymax;
	P=1;
	X0=limit.xmin*100;
	
	

	run.section(,autoNLSF);
	/* the generic macro for iterating 20 times */

////////////////////////////////////////////////////////////////////////////////
//
// Finds unknown X values from given Y values
//
////////////////////////////////////////////////////////////////////////////////

[PredictX]
	
	%W_Xnew=table(%B,%A,%W_Ynew);



////////////////////////////////////////////////////////////////////////////////
//
// Finds unknown Y values from given X values
//
////////////////////////////////////////////////////////////////////////////////

[PredictY]	
	%W_Ynew=table(%A,%B,%W_Xnew);

	
////////////////////////////////////////////////////////////////////////////////
//
// Clears columns Xnew and Ynew
//
////////////////////////////////////////////////////////////////////////////////
[Clear]
	_temp1=%(%H,1);
	_temp2=%(%H,2);
	if(wks.ncols!=4) 
		_temp3=%(%H,3);
	clearworksheet %H;

	%(%H,1)=_temp1;delete _temp1;
	%(%H,2)=_temp2;delete _temp2;
	if(wks.ncols!=4) 
	{
		%(%H,3)=_temp3;
		delete _temp3;
	}
	worksheet -s (wks.ncols-1) 1 (wks.ncols-1) 1;//place cursor in nice place
////////////////////////////////////////////////////////////////////////////////
// Provides instructions
/////////////////////////////////////////////////////////////////////////////////
[Help]

	type -b $calibrate.help;


////////////////////////////////////////////////////////////////////////////////
// NonLinear Least Squares Fitting
//////////////////////////////////////////////////////////////////////////////////
[AutoNLSF]
	nlsf.cleanupfitdata();
	nlsf.fitdata$=%(1,@D);
	nlsf.tolerance=0;
	nlsf.W$=errof(%(1,@D));		//use error bars as weight
	if (nlsf.w$=="") 
	   nlsf.wtype=0;
	else 
	   nlsf.wtype=1;
	nlsf.xBegin=limit.xmin;
	nlsf.xEnd=limit.xmax;
	xpoints=nlsf.xPoints;		//Save the current nlsf.xPoints
	nlsf.xPoints=1000;
	nlsf.fit(20);			//FIT, 20 iterations
	%B=nlsf.funccol$;		//stores name of calibrated curve
	%A=xof(%B);			//stores name of associated x column
	nlsf.xPoints=xpoints;		//Restore nlsf.xPoints
	delete -v xpoints;

[KineticInit]
/* CPY v3.53 changed to add %1 argument */

//SDB 9/9/04 added section to use old code for ExpDecay1 parameter init
	limit %C;
					/* find max/min in both X and Y for the data */

	run.section(Fit,SetXYoffset,%1);
		/* 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
		changed to simple LR, CPY v3.493 */
	LR -N dummy;
	#! copy dummy test_B;LR.B=;LR.A=;

	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 */
	nlsf.msgprompt=2;		/* No_dependency_msg Cao 5/5/94*/

	return	0;
