// Filename:	grAnaly.ogs
// Creation:	CPY v3.8 7/1/95	
// Purpose:	    Graph Analysis Menus, only some of the functions
// Modifications:
// CPY v3.83 9/16/95 rewrite DiffSmooth to use LabCurve, move it to smooth.ogs
// CPY v3.83 9/18/95 DIFF_RANGE, REMOVE_DOTS
// RKM for v5.0 11/09/96 added [Simple]
// JMP for v5.0 01/30/97 added FFT_FILTERING
// JMP for v5.0 05/29/97 USE_EXCHAGEXY_PROPERTY Use layer.exchangeXY to dynamically handle exchanged axes when translating
// JMP for v5.0 06/20/97 INSERT_DERIVATIVE_COLUMN Ensure that the raw data worksheet exists, and insert the column to the right of raw data
// SDB for v6.0 Beta 3/16/98 added Threshold filter
// RKM 12/11/98 v6.0141 REPORT_TO_OUTPUTLOG
// SDB 1/7/99   v6.0148 REPORT_TO_OUTPUTLOG
// RKM 10/11/99	v6.0233	Modified [Diff] so that it only differentiates on plotted range
//			Previously it was only looking at datamakers
// ML 1/31/2002 QA70-630 MUST_USE_DIFFERENT_GLOBAL_STRING
// GJL 11/26/2002 QA70-#3131 v7.0445 USE_ORIGINAL_GRAPH_NAME
////////////////////////////////////////////////////////////////////////////////
//
// Differentiate
//
////////////////////////////////////////////////////////////////////////////////

[Derivative]
	#Take the derivative of %C and put the result into a new window
	get %C -b begin;
	get %C -e end;
	/// CPY v3.83 9/18/95 DIFF_RANGE
	i1=-1;
	if(MKS1>=0) /// if selected
	{
		i1=MKS1;
		i2=MKS2;
	}
	// JMP for v5.0 06/20/97 INSERT_DERIVATIVE_COLUMN
	%W=%[%C,'_'];
	%A=%C;

	create.wksName$="Derivative";
	create.wksLabel$=$Granaly.DerivLabel;
	create.template$="CREATE";
	create.npts=20;
	create.enumwks=1;					//Enumerate the worksheets
	create.enumerate=0;
	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.data2$;
	undo %C;
	deriv %C;
	copy -x %C %B;
	undo;
	%A=%C;
	run.section(Origin,SetWksLabel,%B $Granaly.DerivLabel);		//Set Label

	if(i1>=0)
	{
		set %B -b i1;
		set %B -e i2;
	}
	else 
	{
		set %B -b begin;
		set %B -e end;
	}
	/// end DIFF_RANGE

	/// ML 1/31/2002 QA70-630 MUST_USE_DIFFERENT_GLOBAL_STRING
	//list -sn DerivPlot B;
	//getnamedwin %B;
	list -sn DerivPlot L;
	getnamedwin %L;
	/// end MUST_USE_DIFFERENT_GLOBAL_STRING

	page.label$=$Granaly.DerivLabel;
	page.title=3;
	queue 
	{
		layer -a;
		if (legend.show)
			legend;
	};
	layer -i200 %B;
	delete -v begin;delete -v end;
	return 0;

////////////////////////////////////////////////////////////////////////////////
//
// Integrate
//
////////////////////////////////////////////////////////////////////////////////

[Integrate]
	#Integrate %C (from zero)
	/// ML v3.83 9/18/95 MAKE_IT_C_COMPLIANT
	//if (MkS1>=0) (i1=MkS1;i2=MkS2)
	//else (get %C -b i1;get %C -e i2);
	%A=%C;
	%W=%H;
	create.wksName$="Integral";
	create.wksLabel$=$Granaly.IntegLabel;
	create.template$="CREATE";
	create.npts=20;
	create.enumwks=1;					//Enumerate the worksheets
	create.enumerate=0;
	create.numtypes=1;					//Only explicitly specify 1st type as X
	create.type1=4;
	create.typen=1;						//Set TypeN=Y column type
	create.wks(A %C);
	%B=create.data2$;
	integ %C;
	copy -x _Integ_Area %B;
	run.section(Origin,SetWksLabel,%B $Granaly.IntegLabel);		//Set Label
	if (MkS1>=0) 
	{
		i1=MkS1;
		i2=MkS2;
	}
	else 
	{
		get %C -b i1;
		get %C -e i2;
	}
	list -sn IntegPlot L;
	getnamedwin %L;
	/// end MUST_USE_DIFFERENT_GLOBAL_STRING

	page.label$=$Granaly.IntegLabel;
	page.title=3;
	layer -i200 %B;
	layer -a;
	if (legend.show)
			legend;
	SaveRedirection=type.Redirection(16,3);	// SDB 1/7/99 v6.0148 REPORT_TO_OUTPUTLOG
	// GJL 11/26/2002 QA70-#3131 v7.0445 USE_ORIGINAL_GRAPH_NAME
	win -o %W 
	{
		type.BeginResults();		/// RKM 12/10/98 v6.0141 REPORT_TO_OUTPUTLOG
	}
	/// end MAKE_IT_C_COMPLIANT
	ty $granaly.IntegFromZero; // Changed %C to %A in Origin.OMG
	// End USE_ORIGINAL_GRAPH_NAME
	ty "i = $(i1) --> $(i2)";
	ty "x = $(integ.x1) --> $(integ.x2)";
	ty "Area	Peak at	Width	Height";
	separator 4;
	ty "$(integ.area)	$(integ.x0)	$(integ.dx)	$(integ.y0)";
	type.EndResults();
	type.Redirection=SaveRedirection; // restore previous redirection.
	delete -v SaveRedirection;

////////////////////////////////////////////////////////////////////////////////
//
// Subtract Ref Data...
//
////////////////////////////////////////////////////////////////////////////////

[SubRef]

	#Subtract one data set from another
	//undo %C; this is done inside the dialog for whichever dataset selected	
	math -o -; // open simple math dialog and choose subtract, source and ref data is whatever last used
	rescale;
	
////////////////////////////////////////////////////////////////////////////////
//
// Subtract Straight Line
//
////////////////////////////////////////////////////////////////////////////////

[SubLine]

	#Pick two screen pts and subtract %C from the line formed
	create _line -M 3;set _line -l 1;
	def EndToolbox (;undo %C;%C --O _Line;del _line;rescale);	
	GetPts -n _line 2 
	[Double-click to set straight line begin..]
	[Double-click to set straight line end..];


////////////////////////////////////////////////////////////////////////////////
//
// Y Translate
//
////////////////////////////////////////////////////////////////////////////////

[TransY]
	#Pick one pt as ref and move curve to a new pt vertically
	// JMP for v5.0 05/29/97 USE_EXCHAGEXY_PROPERTY
	if (layer.ExchangeXY)
		run.section(Granaly,TransXAction);
	else
		run.section(Granaly,TransYAction);
	return 0;


[TransYAction]
	def EndToolbox
	{		
	y_last=y;;
	def EndToolbox {y-y_last;undo %C;%C + y;};	
	GetPts -Y 1 (Move cursor to new location, hit ENTER)
	}; 
	GetPts 1 $EXEmessage.Pick1Pt;
	
	
////////////////////////////////////////////////////////////////////////////////
//
// X Translate
//
////////////////////////////////////////////////////////////////////////////////

[TransX]
	#Pick one pt as ref and move curve to a new pt horizontally
	// JMP for v5.0 05/29/97 USE_EXCHAGEXY_PROPERTY
	if (layer.ExchangeXY)
		run.section(Granaly,TransYAction);
	else
		run.section(Granaly,TransXAction);
	return 0;

[TransXAction]
	def EndToolbox
	{
		x_last = x;;
		def EndToolbox 
		{
			x - x_last;
			if (hasx(%C)) 
			{
				undo xof(%C);
				xof(%C)+=x;x=0;
			}
			else 
				undo -dx %C;
			 
			get %C -f v1;
			v1+x;
			set %C -f v1;
		}; 
		GetPts -X 1 (Move cursor to a new location, hit Enter);
	}; 
	GetPts 1 $EXEmessage.Pick1Pt;
	

////////////////////////////////////////////////////////////////////////////////
//
// Averaging Multiple Curves..
//
////////////////////////////////////////////////////////////////////////////////

[AveCurves]

	#Creates averaged data by summing up all of the data in the current layer
	layer -c;
	%W=%H;					//Save the graph window name
	if (count<2) 
	{
		type -b $general.AveCurvesTooFew;
		return 1;
	}
	create.wksName$="Average";
	create.wksLabel$=$Granaly.AveMultLabel;
	create.template$="Create";
	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 Mean$(count)Cuv);

	%A=create.wksname$;
	%(%A,1)=xof(%C);
	%A=create.data2$;
	get %(1,@D) -e ii;
	set %A -e ii;
	(%A)=Data(0,0,ii);
	run.section(Origin,SetWksLabel,%A $Granaly.AveMultLabel);
	loop(ii,1,count)
	{ 
		%A+%(ii,@D);
	}
	%A/count;
	layer -i200 %A;				//Include the Average dataset into the layer
	set %A -c $(count+1);			//Set the color of the Average curve
		
	del -v end;		

////////////////////////////////////////////////////////////////////////////////
//
// Inter/extrapolate..
//
////////////////////////////////////////////////////////////////////////////////
	
[Interpolate]

	#Interpolate or extrapolate %C into a new curve, depending on %C's line connection type
	limit %C;fitx1=limit.xmin;fitx2=limit.xmax;
	layer -c %C;
	stat.data$=%C;
	%B=stat.data$;
	
	%A=%C;
	create.wksName$="InterExtrap";
	create.wkslabel$=$Granaly.InterpolLabel;
	create.template$="CREATE";
	create.npts=30;
	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 %B);
	%B=create.data2$;
	run.section(Origin,SetWksLabel, %B $Granaly.InterpolLabel);
	
	for(done=0;done==0;)
	{
	
		def OnApply {
			if(fitnpts<3)
				type -b $Regression.BadNoOfPts;	
			else
				run.section(,makeinterpolate);
		}
	
		if(run.section(,GetNInterpolate) == 0)
		{
			if(fitnpts<3)
				type -b $Regression.BadNoOfPts;	
			else
			{
				run.section(,makeinterpolate);
				done=1;
			}
		}
		else
		{
	   		%A=create.wksName$;
	   		win -o %A {page.closebits=2; win -ca %H;};
	   		done=1;
		}
	
	}
	legend;
	delete -v cc;
	delete -v done;
	
[GetNInterpolate]

	cc=2;
	GetNumber
	$granaly.InterpolateCurveXmin fitx1
	$granaly.InterpolateCurveXmax fitx2
	$granaly.InterpolateCurvepts  fitnpts
	$granaly.InterpolateCurveColor cc:@C
	$granaly.InterpolateMakeCurve;
	
	return 0;	
	
[MakeInterpolate]
	
	%A=create.data1$;
	%B=create.data2$;
	
	(%A)=0/0;
	(%B)=0/0;
	set %A -e 0;
	set %B -e 0;
		
	(%A)=data(fitx1,fitx2,(fitX2-fitX1)/(fitnpts-1));
	(%B)=data(0,0,fitnpts);
	%A=%C;
	%B +-O %C;
	set %B -s 1;
	layer -i200 %B;
	checkvar cc 2;
	set %B -c cc;
	return 0;

[Simple]
	undo %C;
	math %C %C;


	//////////////////////////////////////////////////////////////////////
	// FFT Filtering - LowPass, HighPass, BandPass, BandBlock
	// JMP 01/30/97 FFT_FILTERING
	//////////////////////////////////////////////////////////////////////

[FFTFilters]
	switch(%1)
	{
		case 1:
			run.section(,HighPass);
			break;
		case 2:
			run.section(,BandPass);
			break;
		case 3:
			run.section(,BandBlock);
			break;
		case 4:
			run.section(,Threshold);
			break;
		default:
			run.section(,LowPass);
			break;
	};
	return 0;

[CreateWks]
	
	create.template$="CREATE";
	create.wksName$="FFTfilter";
	create.wksLabel$="";
	create.npts=30;
	create.enumwks=1;
	create.numtypes=2;			
	create.type1=4;				//Only explicitly specify 1st type as X
	create.type2=1;				//Set TypeN=Y column type

	create.wks(Time %C);

	return 0;
	
[CreateWksLabel]

	%B=%1;
	%B=%B %C;
	create.wksLabel$=%B;
	%A=create.data1$;
	run.section(Origin,SetWksLabel,"%A" $General.Independent);
	%A=create.data2$;
	%B=%1;
	%B=%B %C;
	run.section(Origin,SetWksLabel,"%A" "%B");
	
	return 0;

[LowPass]
	if(run.section(Granaly,FFTFilterInit) == 1)
		return 1;
	run.section(Granaly,CreateWks);  //LAS added this section
	run.section(Granaly,CreateWksLabel,$FFTfilter.LowPass);
	def OnApply {
		run.section(Granaly,MakeLowPass);
	}

	if (run.section(Granaly,GetNLowPass)==0)
		run.section(Granaly,MakeLowPass);
	else
	{
		%A=create.wksName$;
		win -o %A {page.closebits=2; win -ca %H;};
	}								
	legend;	
	delete -v cc;
	return 0;

[GetNLowPass]

	cc=2;
	Fc=Fc==0/0?int(10/(limit.xmax-limit.xmin)):Fc;		//Initialize to 10 times lowest frequency
	getnumber 
	(Fc) Fc 
	($FFTFilter.Color) cc:@C
	($FFTfilter.FreqCutOff);
	return 0;

[MakeLowPass]
	//need to update the wks label and column label
	%A=create.wksName$;
	%B=$FFTfilter.LowPass;
	%B=%B %C;
	%A!page.label$=%B;

	%A=create.data2$;
	run.section(Origin,SetWksLabel,"%A" "%B");
	//each time the Apply button is clicked


	if (Fc<0)
	{
		type -b;
		type -b $FFTFilter.BadInput;		
		return 1;
	}

	if (run.section(Granaly,FFTfilterFoward))
		return 1;								
	ii=xindex(Fc,%W_Real);
	run.section(Granaly,SetFilter,$(1) $(ii));
	run.section(Granaly,SetFilter,$(fft.NextPowerOf2-ii+2) $(fft.NextPowerOf2));
	run.section(Granaly,FFTfilterBackward);				// Backward FFT
	run.section(Granaly,PlotFilter);
	return 0;

[HighPass]
	run.section(Granaly,FFTFilterInit);
	run.section(Granaly,CreateWks);  //LAS added this section
	run.section(Granaly,CreateWksLabel,$FFTfilter.HighPass);
	def OnApply {
		run.section(Granaly,MakeHighPass);
	}

	if (run.section(Granaly,GetNHighPass)==0)
		run.section(Granaly,MakeHighPass);
	else
	{
		%A=create.wksName$;
		win -o %A {page.closebits=2; win -ca %H;};
	}	
	legend;	
	delete -v cc;
	return 0;
	
[GetNHighPass]

	cc=2;
	Fc=Fc==0/0?int(10/(limit.xmax-limit.xmin)):Fc;		//Initialize to 10 times lowest frequency
	getnumber 
	(Fc) Fc 
	($FFTfilter.Shift) HPshift:2
	($FFTFilter.Color) cc:@C
	($FFTfilter.FreqCutOff);
	
	return 0;
	
[MakeHighPass]	
	
	//need to update the wks label and column label
	if (Fc<0)
	{
		type -b;
		type -b $FFTFilter.BadInput;		
		return 1;
	}
	%A=create.wksName$;
	%B=$FFTfilter.HighPass;
	%B=%B %C;
	%A!page.label$=%B;

	%A=create.data2$;
	run.section(Origin,SetWksLabel,"%A" "%B");
	//each time the Apply button is clicked

	if (run.section(Granaly,FFTfilterFoward))
		return 1;								// Foward FFT

	ii=xindex1(Fc,%W_Real);

	run.section(Granaly,SetFilter,$(ii) $(fft.NextPowerOf2/2));
	run.section(Granaly,SetFilter,$(fft.NextPowerOf2/2+1) $(fft.NextPowerOf2-ii+2));				//Account for 1st row containing 0 frequency info and subtraction +1

	run.section(Granaly,FFTfilterBackward);					// Backward FFT
	run.section(Granaly,PlotFilter);
	
	return 0;

[BandPass]

	run.section(Granaly,FFTFilterInit);
	run.section(Granaly,CreateWks);  //LAS added this section
	run.section(Granaly,CreateWksLabel,$FFTfilter.BandPass);
	def OnApply {
		run.section(Granaly,MakeBandPass);
	}

	if (run.section(Granaly,GetNBand)==0)
		run.section(Granaly,MakeBandPass);
	else
	{
		%A=create.wksName$;
		win -o %A {page.closebits=2; win -ca %H;};
	}	
	legend;	
	delete -v cc;
	return 0;

[MakeBandPass]

	//need to update the wks label and column label
	%A=create.wksName$;
	%B=$FFTfilter.BandPass;
	%B=%B %C;
	%A!page.label$=%B;

	%A=create.data2$;
	run.section(Origin,SetWksLabel,"%A" "%B");
	//each time the Apply button is clicked
	
		
	if (Fl<0 || Fh<Fl)
	{
		type -b;
		type -b $FFTFilter.BadInput;		
		return 1;
	}

	if (run.section(Granaly,FFTfilterFoward))
		return 1;									// Foward FFT

	ii=xindex1(Fl,%W_Real);
	jj=xindex(Fh,%W_Real);

	run.section(Granaly,SetFilter,$(ii) $(jj));
	run.section(Granaly,SetFilter,$(fft.NextPowerOf2-jj+2) $(fft.NextPowerOf2-ii+2));		//Account for 1st row containing 0 frequency info and subtraction +1

	run.section(Granaly,FFTfilterBackward);					// Backward FFT
	run.section(Granaly,PlotFilter);

	return 0;



[BandBlock]
	run.section(Granaly,FFTFilterInit);
		
	run.section(Granaly,CreateWks);  //LAS added this section
	run.section(Granaly,CreateWksLabel,$FFTfilter.BandBlock);
	def OnApply {
		run.section(Granaly,MakeBandBlock);
	}

	if (run.section(Granaly,GetNBand)==0)
		run.section(Granaly,MakeBandBlock);
	else
	{
		%A=create.wksName$;
		win -o %A {page.closebits=2; win -ca %H;};
	}	
	legend;
	delete -v cc;
	return 0;


[MakeBandBlock]
	//need to update the wks label and column label
	%A=create.wksName$;
	%B=$FFTfilter.BandBlock;
	%B=%B %C;
	%A!page.label$=%B;

	%A=create.data2$;
	run.section(Origin,SetWksLabel,"%A" "%B");
	//each time the Apply button is clicked
	
		
	if (Fl<0 || Fh<Fl)
	{
		type -b;
		type -b $FFTFilter.BadInput;		
		return 1;
	}
	
	if (run.section(Granaly,FFTfilterFoward))
		return 1;									// Foward FFT

	ii=xindex1(Fl,%W_Real);
	jj=xindex1(Fh,%W_Real);

	run.section(Granaly,SetFilter,$(1) $(ii-1));
	run.section(Granaly,SetFilter,$(jj+1) $(fft.NextPowerOf2/2));
	run.section(Granaly,SetFilter,$(fft.NextPowerOf2/2+1) $(fft.NextPowerOf2-jj+2-1));
	run.section(Granaly,SetFilter,$(fft.NextPowerOf2-ii+2+1) $(fft.NextPowerOf2));				//Account for 1st row containing 0 frequency info and subtraction +1

	run.section(Granaly,FFTfilterBackward);					// Backward FFT
	run.section(Granaly,PlotFilter);

	return 0;

[Threshold]
	run.section(Granaly,FFTFilterInit);
// Return Error if CANCEL
	if (run.section(Granaly,FFTfilterFoward))
		return 1;		
	set %W_r -e fft.NextPowerOf2/2;
	run.section(Granaly,SetFilter,$(1) $(fft.NextPowerOf2));
	%K=%H;
	getenumwin Threshold Threshold;
	store.v1$=%W;
	store.v2$=%K;
	store.v3$=%H;
	layer -i200 %W_r;
	rescale;
	hline.y=(abs(y2)-abs(y1))/2;
	hline.x=(abs(x2)-abs(x1))/2;
	return 0;

[FFTFilterInit]
	//////////////////////////////////////////////////////////////////////
	// Initialize FFT and get some inital values
	//////////////////////////////////////////////////////////////////////
	fft.reset();
	limit %C;							//Get some limiting values
	get %C -b i1;get %C -e i2;
	i1--; 						//i1 and i2 must be in C-convention where counting starts from 0, and loop variable is < i2
	
	%A=xof(%C);
	%B=%C;
	fft.forward.timedata$=%A;
	fft.forward.realdata$=%B;
	
	if(fft.chkres())
	{
		if (run.section(Granaly,GetDeltaT)) 
			return 1;
	}
	
	return 0;

[GetFc]
	Fc=Fc==0/0?int(10/(limit.xmax-limit.xmin)):Fc;							//Initialize to 10 times lowest frequency
	if ("%1"=="shift")
		getnumber (Fc) Fc ($FFTfilter.Shift) HPshift:2 ($FFTfilter.FreqCutOff);
	else
		getnumber (Fc) Fc ($FFTfilter.FreqCutOff);
	if (Fc<0)
	{
		type -b;
		type -b $FFTFilter.BadInput;		
		return 1;
	}
	return 0;

[GetNBand]
	//////////////////////////////////////////////////////////////////////
	// Get Cut-Off Frequency Range
	//////////////////////////////////////////////////////////////////////
	cc=2;
	Fl=Fl==0/0?int(10/(limit.xmax-limit.xmin)):Fl;							//Initialize to 10 times lowest frequency
	Fh=Fh==0/0?int(20/(limit.xmax-limit.xmin)):Fh;							//Initialize to 10 times lowest frequency
	getnumber 
	($FFTfilter.Low) Fl
	($FFTfilter.High) Fh
	($FFTfilter.Shift) HPshift:2 
	($FFTFilter.Color) cc:@C
	($FFTfilter.FreqRange);

	return 0;

[GetDeltaT]
	getnumber ($FFTfilter.Deltat) FFT.forward.tdelta ($FFTfilter.DeltatPrompt);
	return 0;

[SetFilter]
	#!type -a "Setting filter from %1 to %2";
	set %W_H -b (%1);
	set %W_H -e (%2);
	%W_H=1;				//Set to 1 for rows 1 to row where Fc
	set %W_H -b 1;			//Reset to full Range
	set %W_H -e fft.NextPowerOf2;
	return 0;

[FilterThreshold]
	%W=store.v1$;
	%L=store.v2$;
	%K=store.v3$;
	th=ThVal.v1;			//Set global var for threshold
	set %W_r -e fft.NextPowerOf2;
	stat.name(1,FFTtemp);
	%A=stat.name.worksheet$;
	create.wksName$="%A";
	create.template$="CREATE";
	create.npts=fft.NextPowerOf2;
	create.type1=4;			//Only explicitly specify 1st type as X
	create.typen=1;			//Set TypeN=Y column type
	create.wks(r Freq Real Imag);
	%A=create.wksname$;
	copy %W_Freq %A_Freq;		//Copy Frequencies to new temp FFT wks
	copy %W_r %A_r;			//Copy Amplitudes to new temp FFT wks
	sort -w %A %(%A,1);		//Sort worksheet by 4th column
	ii=xindex(th,%(%A,2));		//Find index value at Threshold
	win -c %K;			//Close Threshold window		
	win -a %L;
	%A_r=1;
	set %A_r -e ii;			//Set end index value to Threshold
 	%A_r=0;				//Assign values lower than Threshold to 0
	set %A_r -e fft.NextPowerOf2;	//Reset worksheet to full range
	sort -w %A %(%A,2);		//Sort worksheet by frequencies 
	copy %A_r %W_H;
	win -ca %A;			//Close temp FFT worksheet
	run.section(Granaly,CreateWks);  //LAS added this section
	run.section(Granaly,CreateWksLabel,$FFTfilter.Threshold); 
	run.section(Granaly,FFTfilterBackward);
	run.section(Granaly,PlotFilter);	
	legend;
	return 0;

[FFTfilterFoward]
	
	fft.reset();
	
	delete temp;
	delete temp_A;

	create temp -wd 30 A B;
	temp_B=%C;
   	if(exist(xof(%C))==0)
   	{
		get %C -i fftdt;
		temp_A=data(0,1,1/(limit.size-1));			//Create X data ranging from 0 to 1
   	}
	else
	{
		temp_A=xof(%C);
		temp_A-=limit.xmin;					//Subtract off any time offset
	}

	fft.forward.timedata$=temp_A;
	fft.forward.realdata$=temp_B;
	fft.forward=1;
	fft.real=1;
    	fft.windowing=1;
	fft.normalize=0;
	fft.shifted=0;
	fft.unwrap=0;

//las moved fft.chkres() to fftfilterinit section

	fft.chkres();
	
	//////////////////////////////////////////////////////////////////////
	// Setup invisible output worksheet
	//////////////////////////////////////////////////////////////////////
	stat.name(1,FFTfilter,Freq,Real,Imag,H);
	%W=stat.name.worksheet$;
	create %W -wd 30 Freq Real Imag H r;
	fft.output.samplingdata$=%W_freq;
	fft.output.Realdata$	=%W_real;
	fft.output.Imagdata$	=%W_imag;
	fft.output.ampdata$	=%W_r;
	fft.output.phasedata$	="";
	fft.output.powerdata$	="";
	//////////////////////////////////////////////////////////////////////
	

	//////////////////////////////////////////////////////////////////////
	// Perform FFT on rows i1 to i2
	//////////////////////////////////////////////////////////////////////
	fft.forward(i1,i2);	//i1,i2 are in C-convention where counting starts at 0, loop variable < i2
	run.section(Ffttool,FFToutputDataset);

	delete temp_A;		//Delete temporary datasets by deleting the X dataset
	%W_H=%W_Freq;		//Initialize Filter function to 0
	%W_H*=0;
	return 0;


[FFTfilterBackward]
	//Since frequency is not shifted from -fmax to +fmax, but rather it is 0 to fmax, with mirror image from fmax+1 to 2fmax

	if (HPshift)
		%W_H[1]=1;	// Enable zero frequency information
	%W_Real*=%W_H;
	%W_Imag*=%W_H;

	//////////////////////////////////////////////////////////////////////
	// Backward FFT
	///////////////////////////////////////////////////////////////////////

	fft.reset();

	fft.forward.timedata$=%W_Freq;
	fft.forward.realdata$=%W_Real;
	fft.forward.imagdata$=%W_Imag;

	if(fft.chkres())
		type -b $FFT.badResolution;

	fft.backward.fdelta=fft.forward.tdelta;
	fft.backward.freqdata$=%W_Freq;
	fft.backward.realdata$=%W_Real;
	fft.backward.imagdata$=%W_Imag;

	fft.forward=0;
	fft.real=0;
   	fft.windowing=1;
	fft.normalize=0;
	fft.shifted=0;
	fft.unwrap=0;

	fft.forward.tdelta=1.0;
	fft.forward.timedata$="";
	fft.forward.realdata$="";
	fft.forward.imagdata$="";

	
	fft.output.samplingdata$=create.data1$;
	fft.output.Realdata$	=create.data2$;
	fft.output.Imagdata$	="";
	fft.output.ampdata$	="";
	fft.output.phasedata$	="";
	fft.output.powerdata$	="";

	fft.backward(fft.chkres.i1,fft.chkres.i2);	//Do not re-use i1 i2 variables, since we will need to preserve original size information
	
	%A=create.data1$;
	%A+=limit.xmin;					//Translate according to raw data

	//////////////////////////////////////////////////////////////////////
	// Clean up Forward FFT datasets by deleting the X dataset of invisible worksheet
	///////////////////////////////////////////////////////////////////////
	%A=fft.backward.freqdata$;
	delete %A;					//Delete temporary datasets by deleting the X dataset
	return 0;

[PlotFilter]
	%A=fft.output.RealData$;
	layer -i200 %A;
	checkvar cc 2;
	set %A -c cc;
	set %A -e (i2-i1);					//Set Filtered Data to same size as Original which is (End-Beg+1) but here i1 and i2 are in C convention so gives i2-i1 as the end
	return 0;
