// Filename:    Smooth.ogs
// Creation:    by Ree Migliozzi, 7/27/95  DLL by Santanu Bhattacharya
// Purpose:     Modularized Code for smoothing using three different methods
//              (Savitzsky-Golay, Adjacent Averaging and FFT
//		from the Menu or Smoothing Toolbar.//
// Modification log
// CPY v3.83 9/17/95, need to fix selection range smooth, modified
//      much of the codes
// CPY v3.83 9/20/95, change MenuSmooth operation to use selection range to 
//     replace origin, undo ML's earlier change
// CPY v3.83 ADD_UNDO
// CPY v3.85 CHECK_SMOOTH_DATA_X
// RKM v4.161 1/30/97 IMPORT_TO_GRAPH; allow smoothing to be performed when the 
// 		data was imported into the graph window 
// LAS v6.906 8/1/01, Apply button added for GetN added for SG, AA and FFTFilter
//      but was not added for Diff/Smooth
// LAS V7.0226 2/25/02 MINIMIZE_FORCE_ACTIVATE
/////////////////////////////////////////////////////////////
// Main Code which is run based on if user hits one of the 
// Smooth Buttons on the Toolbar
/////////////////////////////////////////////////////////////


[Tab.Settings.OnInit]
	Smooth!Tab.Settings.StoreResults=2;

	Smooth!Tab.Settings.PolyDegSpin.Min=1;
	Smooth!Tab.Settings.PolyDegSpin.Max=9;
	Smooth!Tab.Settings.PolyDegSpin.Value=2;

	Smooth!Tab.Settings.PtsLeftSpin.Min=0;
	Smooth!Tab.Settings.PtsLeftSpin.Max=25;
	Smooth!Tab.Settings.PtsLeftSpin.Value=5;

	Smooth!Tab.Settings.PtsRightSpin.Min=0;
	Smooth!Tab.Settings.PtsRightSpin.Max=25;
	Smooth!Tab.Settings.PtsRightSpin.Value=5;

	Smooth!Tab.Settings.NumPoints.v1=5;

[Initialize]
	/// load DLL and initialized dataset and assign %W to wks name
	if(curve.error==0/0)
	{
		type -b $smooth.dllLoadFailure;
		return 1;
	}
	if(Layer.is3D==1)
	{
		type -b $general.2DGraphsOnly;
		return 1;
	}

	curve.reset();				/*init all parameters*/ 
	if(exist(%C)!=1)
		type -b $smooth.Noactivedata;
	else
		curve.data$=%C;			/*active dataset window has data*/

	%W=%[%C,'_'];				/*worksheet name*/

	return 0;

[OptionsCk]
	/// set %A to result dataset name and set curve.smoothpts
	///--------------------------------------------------------///
	/// called from button script, thus index contains the current
	/// button number with index=1,2,3 for SG,AA,FT, index=4 for DiffSmooth
	/// CPY change to take argument to make this work for both
	/// toolbar and menu
	/// when called from botton:
	/// %1=Smooth!Tab.Settings.StoreResults,%2=total or Smooth!Tab.Settings.NumPoints
	curve.smoothpts=%2;
	if(%1==1)/// put result back to Original data
	{
		curve.result$=%C; 
		/// CPY v3.83 ADD_UNDO
		undo %C;
	}
	if(%1==2)
	{
		switch(index)
		{
			case 1:
				%K=$Smooth.SG;
				break;
			case 2:
				%K=$Smooth.AA;
				break;
			case 4:
				%K=$Smooth.SGDeriv;
				break;
			default:
				%K=$Smooth.FFT;
				break;
		}

		///RKM 1/29/97 IMPORT_TO_GRAPH begin
		///We have to do this because the dll requires a worksheet for curve methods
		%B=curve.data$;
		if(exist(%[%B,'_'])!=2)
		{
			edit %B;
			win -i;
		}
		///RKM 1/29/97 IMPORT_TO_GRAPH end

		run.section(,CreateWks);	//Create new wks to hold result data
		%A=create.wksname$;
		%A=curve.data$;		//Set %A to original data
		%B=xof(%A);		//Get the X column of original data
		%A=create.data1$;	//Set %A to the X column of smoothed data
		(%A)=%B;		//Copy the X column of the original data
		%A=create.data2$;	//Set %A to the smoothed data column
		run.section(Origin,SetWksLabel,%A "%K");
		curve.result$=%A;
	}
	return 0;

[CreateWks]

	stat.data$=%C;		//use stat object to create dataset name
	%A=stat.data$;		

	create.wksName$="Smoothed";
	create.wksLabel$="%K";		//%K is set in [OptionsChk]
	create.template$="CREATE";
	create.npts=fitnpts;
	create.enumwks=1;
	create.numtypes=1;			
	create.type1=4;				//Only explicitly specify 1st type as X
	create.typen=1;				//Set TypeN=Y column type
	create.wks(A %A);
	%A=create.wksname$;
	%A!wks.colwidth=27;

[MakeCurve]
	layer -i200 %a;
	checkvar cc 2;
	set %a -c cc;  
	delete -v cc;  //delete variable
	return 0;

	
[Tab.Operation.SavGol.OnClick]
	if(run.section(,Initialize))
		return 1;
	else
	{
		curve.smoothleftpts=Smooth!Tab.Settings.PtsLeftSpin;
		curve.smoothrightpts=Smooth!Tab.Settings.PtsRightSpin;
		total=Smooth!Tab.Settings.PtsLeftSpin+Smooth!Tab.Settings.PtsRightSpin+1;
		curve.polydeg=Smooth!Tab.Settings.PolyDegSpin;
		if(total<3)
		{
			type -b $Smooth.MorePoints;
			return 1;
		}
		else
		{
			index=1;
			run.section(,OptionsCk,Smooth!Tab.Settings.StoreResults total);
			if(curve.sgsmooth()==0/0)
			{
				type -b $calculus.DiffSmoothResErr;
				if(Smooth!Tab.Settings.StoreResults==2)
				{
					%A=create.wksname$;
					win -o %A {page.closebits=2;win -ca;}
					legend;plot -c;
				}
				return 1;
			}
			if(Smooth!Tab.Settings.StoreResults==2) 
			{
				run.section(,MakeCurve);
			}
		}
	}
	legend;
	return 0;
	
	
[Tab.Operation.AdjAve.OnClick]
	if(run.section(,Initialize))
		return 1;
	else
	{
		index=2;
		run.section(,OptionsCk,Smooth!Tab.Settings.StoreResults Smooth!Tab.Settings.NumPoints.v1);
		curve.adjave();
		if(Smooth!Tab.Settings.StoreResults==2) 
		{
			run.section(,MakeCurve);
		}
	}
	legend;
	return 0;
	
[Tab.Operation.FFTOp.OnClick]
	if(run.section(,Initialize))
		return 1;
	else
	{
		index=3;
		run.section(,OptionsCk,Smooth!Tab.Settings.StoreResults Smooth!Tab.Settings.NumPoints.v1);
		curve.fftsmooth();	
		if(Smooth!Tab.Settings.StoreResults==2) 
		{
			run.section(,MakeCurve);
		}
	}
	legend;
	return 0;	


////////////////////////////////////////////////////////////////////
// Smooth code from Menu
////////////////////////////////////////////////////////////////////
[MenuInit]
	/// usage MenuInit index
	/// resulting smooth points in jj
	/// resulting choice to replace or insert in ii=1,2
	if(%1==1 || %1 ==4) ///CPY add index=4 for DiffSmooth
	{
		curve.polydeg=2;curve.smoothleftpts=3;curve.smoothrightpts=3;
		%K=$Smooth.Order9;
		%B=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25;
		GetNumber 
		$Smooth.MenuInitPolyDeg	curve.polydeg:K
		$Smooth.MenuInitNumpointsL curve.smoothleftpts:B
		$Smooth.MenuInitNumpointsR curve.smoothrightpts:B
		$Smooth.MenuInitSmoothPoints;
		curve.smoothleftpts=curve.smoothleftpts-1;
		curve.smoothrightpts=curve.smoothrightpts-1;
		jj=curve.smoothleftpts+curve.smoothrightpts+1;	//This will be passed to curve.smoothpts
		if(jj<3)
		{
			type -b $Smooth.MorePoints;	//Total # of points considered must be at least 3
			run.section(,MenuInit,index);	
		}

	}
	else
	{
		jj=5;
		getnum -s $Smooth.MenuInitEnterNum jj $Smooth.MenuInitSmoothPoints;
	}
	return 0;

[MenuSG]
	index = 1;/// Buttons use index to determine button number, we are similating that
	if(run.section(,Initialize))
		return 1;
		
	run.section(,MenuIndex);
	
		
	for(done=0;done==0;)
	{
		def OnApply {
			curve.smoothleftpts=curve.smoothleftpts-1;
			curve.smoothrightpts=curve.smoothrightpts-1;
			jj=curve.smoothleftpts+curve.smoothrightpts+1;	//This will be passed to curve.smoothpts
			if(jj<3)
				type -b $Smooth.MorePoints;	//Total # of points considered must be at least 3
			else
				run.section(,MakeSG);
		}
		
		if(run.section(,GetNSG)==0)
		{
			curve.smoothleftpts=curve.smoothleftpts-1;
			curve.smoothrightpts=curve.smoothrightpts-1;
			jj=curve.smoothleftpts+curve.smoothrightpts+1;	//This will be passed to curve.smoothpts
			if(jj<3)
			{
				type -b $Smooth.MorePoints;	//Total # of points considered must be at least 3
			}
			else
			{
				if (run.section(,MakeSG) == 1)
				{
					%A=create.wksname$;
					win -o %A {page.closebits=2;win -ca;}
				}
				legend;
				done=1;
			}
		}
		else
		{
			%A=create.wksname$;
			win -o %A {page.closebits=2;win -ca %H;}
			done=1;
		}
	}	
	delete -v done;		
	return 0;

[GetNSG]

	cc=2;curve.polydeg=2;curve.smoothleftpts=3;curve.smoothrightpts=3;
	%K=$Smooth.Order9;
	%B=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25;
	GetNumber 
	$Smooth.MenuInitPolyDeg	curve.polydeg:K
	$Smooth.MenuInitNumpointsL curve.smoothleftpts:B
	$Smooth.MenuInitNumpointsR curve.smoothrightpts:B
	$Smooth.SmoothedLineColor cc:@C
	$Smooth.MenuInitSmoothPoints;
	
	return 0;


[MakeSG]
		
	run.section(,makecommon,$Smooth.SG);  //same code for all three smooth options
		
	if(curve.sgsmooth()==0/0)
	{
		type -b $calculus.DiffSmoothResErr;
		curve.smoothleftpts=curve.smoothleftpts+1;
		curve.smoothrightpts=curve.smoothrightpts+1;
		return 1;
	}
	else
	{
  		run.section(,MakeCurve);
		curve.smoothleftpts=curve.smoothleftpts+1;
		curve.smoothrightpts=curve.smoothrightpts+1;
		return 0;
	}

[MenuMovingWindow]
	/// Adjacent Averaging
	index = 2;/// Buttons use index to determine button number, we are similating that
	if(run.section(,Initialize))
		return 1;
	
	run.section(,MenuIndex);
	
	def OnApply {
		run.section(,MakeAA);
	}
	if(run.section(,GetNAA) == 0)
	{
		if(run.section(,MakeAA)==1)
		{
			%A=create.wksname$;
			win -o %A {page.closebits=2;win -ca %H;}
		}
	}
	else
	{
		%A=create.wksname$;
		win -o %A {page.closebits=2;win -ca %H;}
	}
	legend;			
	return 0;

[GetNAA]

	jj=5;cc=2;
	//getnum -s $Smooth.MenuInitEnterNum jj $Smooth.MenuInitSmoothPoints;
	getnum $Smooth.MenuInitNumpoints jj 
	$Smooth.SmoothedLineColor cc:@C
	$Smooth.MenuInitSmoothPoints;
	
	return 0;
		

[MakeAA]

	run.section(,makecommon,$Smooth.AA);
	
	if(curve.adjave()==0/0)
	{
		type -b $calculus.DiffSmoothResErr;
		return 1;
	}
	else
	{
		run.section(,MakeCurve);
		return 0;
	}




[MenuFFTFilter]
	index = 3;/// Buttons use index to determine button number, we are similating that
	if(run.section(,Initialize))
		return 1;

	run.section(,MenuIndex);
	
	def OnApply {
		run.section(,MakeFFTFilter);
	}
	if(run.section(,GetNFFTFilter) == 0)
	{
		if (run.section(,MakeFFTFilter)==1)
		{
			%A=create.wksname$;
			win -o %A {page.closebits=2;win -ca %H;}
		}
	}
	else
	{
		%A=create.wksname$;
		win -o %A {page.closebits=2;win -ca %H;}
		legend;plot -c;
	}
	legend;			
	return 0;

[GetNFFTFilter]

	jj=5;cc=2;
	//getnum -s $Smooth.MenuInitEnterNum jj $Smooth.MenuInitSmoothPoints;
	getnum 	$Smooth.MenuInitNumpoints jj 
	$Smooth.SmoothedLineColor cc:@C
	$Smooth.MenuInitSmoothPoints;
	
	return 0;


[MakeFFTFilter]
	run.section(,makecommon,$Smooth.FFT);

	get %C -e ii;
	if(curve.fftsmooth()==0/0 || curve.smoothpts>ii)
	{
		type -b $smooth.NumPointsErr;
		return 1;
	}
	else
	{
		run.section(,MakeCurve);
		return 0;
	}
		
[MenuDiffSmooth]
	index = 4;/// Buttons use index to determine button number, we are similating that
	/// button 4 does not exist yet on toolbar, we are just using it to reuse the
	/// codes in OptionsCk
	if (run.section(,Initialize))
		return 1;
	else
	{
		if (run.section(,MenuInit,index)) /// result smooth npts in jj, result choice in ii
			return 1;
		run.section(,OptionsCk,2 jj);     /// ii forced to 2 since diff must create new data

		if (curve.derivdeg<1 || curve.derivdeg>2)
			curve.DerivDeg=1;
		//If curve.polydeg==1, then curve.derivdeg must also equal 1
		if(curve.polydeg!=1)
		{
			switch (curve.polydeg)
			{
				case 2:
					%A=$Smooth.Order2;
					break;
				case 3:
					%A=$Smooth.Order3;
					break;
				case 4:
					%A=$Smooth.Order4;
					break;
				case 5:
					%A=$Smooth.Order5;
					break;
				case 6:
					%A=$Smooth.Order6;
					break;
				case 7:
					%A=$Smooth.Order7;
					break;
				case 8:
					%A=$Smooth.Order8;
					break;
				case 9:
					%A=$Smooth.Order9;
					break;
			}
			GetNum $Smooth.MenuDiffSmoothOrder curve.derivdeg:A $Smooth.MenuDiffSmoothDeriv;
		}
		if (curve.sgDeriv()==0/0)
		{
			type -b $calculus.DiffSmoothResErr;
			%A=create.wksname$;
			win -o %A {page.closebits=2;win -ca;}
			legend;plot -c;
			return 1;
		}
		list -sn DerivPlot B;
		getnamedwin %B;
		page.label$=%K;
		page.title=3;
		%A=create.data2$;	
		graph %A;
		rescale;
	}
	legend;
	return 0;

[Tab.Settings.StoreResults.OnClick]
	// CPY 7/26/00 t8248 v6.1008
	//type -b $Smooth.ReplaceData;
	if(Tab.Settings.StoreResults==1)
		type -b $Smooth.ReplaceData;


/////////////////////////////////////////////
//SG,AA and FFTFilter all use this same code
/////////////////////////////////////////////

[MakeCommon]

	///RKM 1/29/97 IMPORT_TO_GRAPH begin
	///We have to do this because the dll requires a worksheet for curve methods
	%B=curve.data$;
	if(exist(%[%B,'_'])!=2)
	{
		edit %B;
		//win -i;
		win -ia;  //LAS 2/25/02 MINIMIZE_FORCE_ACTIVATE
		//minimize AND force activation of the  previously active window
	}
	///RKM 1/29/97 IMPORT_TO_GRAPH end
	
	
	curve.smoothpts=jj;
	
	//need to update the wks label and column label
	%A=create.wksName$;
	%A!page.label$=%1;

	%A=create.data2$;
	%K=%1;
	run.section(Origin,SetWksLabel,"%A" "%K");
	//each time the Apply button is clicked
	
	return 0;
	
[MenuIndex]

//index=1 for SG


	switch(index)
	{
		case 1:
			%K=$Smooth.SG;
			break;
		case 2:
			%K=$Smooth.AA;
			break;
		case 4:
			%K=$Smooth.SGDeriv;
			break;
		default:
			%K=$Smooth.FFT;
			break;
	}

	run.section(,CreateWks);
	%A=curve.data$;		//Set %A to original data
	%B=xof(%A);		//Get the X column of original data
	%A=create.data1$;	//Set %A to the X column of smoothed data
	(%A)=%B;		//Copy the X column of the original data
	%A=create.data2$;	//Set %A to the smoothed data column
	curve.result$=%A;
	run.section(Origin,SetWksLabel,%A "%K");
	return 0;	
