
number MSA112_clipping(number sigma,number minTail)
	{
	
	number clipping = (sqrt(-log(minTail))*sigma).trunc()
	
	return clipping
	}
	
/****************************************************
Filtering
****************************************************/
class Filtering_MSA112: MSA112_UIFrame
{
string FilterLabel
number MinTail,MinSpar
number DefBin,DefSigmaX,DefSigmaE,clipX,clipE

number runningBin,runningXFilt,runningEFilt
number t
number WaitingID

TagGroup CreateProgress(object self)
	{
	TagGroup Dialog = DLGCreatedialog("")
		TagGroup Upper = DLGCreatedialog("")
		Upper.DLGTableLayout(3,1,0)
	Upper.DLGAddElement(DLGcreateLabel("  "+MSA112_Version()+"    ").DLGIdentifier("Version"))
	Upper.DLGAddElement(self.InfoButton(20,210))
	Upper.DLGAddElement(self.settingsButton(20,210,"Settings"))
		TagGroup Lower = DLGCreatedialog("")
		Lower.DLGTableLayout(2,1,0)
	Lower.DLGAddElement(DLGcreateLabel("                    ").DLGAnchor("East").DLGIdentifier("Message"))
	Lower.DLGAddElement(DLGcreateLabel("hold ALT for info"))	

	Dialog.DLGAddElement(Upper)
	Dialog.DLGAddElement(Lower)
	Dialog.DLGAddElement(DLGcreateProgressBar("P bar").DLGfill("X"))
	
	return Dialog
	}
	
TagGroup CreateBinningBox(object self)
	{
	TagGroup DialogBinning = DLGCreateBox("binning SI")
	
	DialogBinning.DLGTableLayout(3,3,0)

	DialogBinning.DLGAddElement(DLGCreateLabel(" bin X "))	
	DialogBinning.DLGAddElement(DLGCreateLabel(" bin Y "))
	DialogBinning.DLGAddElement(DLGCreatePushButton("   run   ","RunBinning").DLGIdentifier("runBinning"))	
	
	DialogBinning.DLGAddElement(DLGCreateIntegerField(2,3).DLGIdentifier("BinX"))
	DialogBinning.DLGAddElement(DLGCreateIntegerField(2,3).DLGIdentifier("BinY"))
	DialogBinning.DLGAddElement(DLGCreatePushButton("stop","stopBinning").DLGIdentifier("stopBinning").DLGEnabled(0))	

	return DialogBinning
	}

TagGroup CreateFilteringBox(object self)
	{
	TagGroup DialogFiltering = DLGCreateBox("gaussian filtering SI")
	
	DialogFiltering.DLGTableLayout(3,3,0)

	DialogFiltering.DLGAddElement(DLGCreateLabel("0.6  <"))	
	DialogFiltering.DLGAddElement(DLGCreateLabel("sigma"))
	DialogFiltering.DLGAddElement(DLGCreateLabel("   < 2.6     "))
	
	DialogFiltering.DLGAddElement(DLGCreatePushButton("spatial","runXfiltering").DLGIdentifier("runXfiltering"))
	DialogFiltering.DLGAddElement(DLGCreaterealField(1,6,2).DLGIdentifier("SigmaX"))
	DialogFiltering.DLGAddElement(DLGCreatePushButton("stop","stopXfiltering").DLGIdentifier("stopXfiltering").DLGEnabled(0))	

	DialogFiltering.DLGAddElement(DLGCreatePushButton("energy","runEfiltering").DLGIdentifier("stopEfiltering"))	
	DialogFiltering.DLGAddElement(DLGCreaterealField(1,6,2).DLGIdentifier("SigmaE"))
	DialogFiltering.DLGAddElement(DLGCreatePushButton("stop","stopEfiltering").DLGIdentifier("stopEfiltering").DLGEnabled(0))

	
	return DialogFiltering
	}

	
TagGroup CreateAverageBox(object self)
	{
	TagGroup DialogAverage = DLGCreateBox("show average")
	
	DialogAverage.DLGTableLayout(2,1,0)

	DialogAverage.DLGAddElement(DLGCreatePushButton("spectrum","AverageSpectrum").DLGIdentifier("AverageSpectrum"))	
	DialogAverage.DLGAddElement(DLGCreatePushButton("   image  ","AverageImage").DLGIdentifier("AverageImage"))
	
	return DialogAverage
	}
	
TagGroup CreateAllFrames(object self)
	{
	TagGroup Dialog = DLGCreateDIalog("")
	
	Dialog.DLGAddElement(self.CreateProgress())
	
	Dialog.DLGAddElement(self.CreateBinningBox())
	
	Dialog.DLGAddElement(self.CreateFilteringBox())
	
	Dialog.DLGAddElement(self.CreateAverageBox())
	
	return Dialog
	}
	
object init(object self,string Package,string Name)
	{
	self.MSA112_initUIFrame(self.CreateAllFrames(),Package,Name)
	
	//initialize parameters
	FilterLabel = self.MSA112P_FilterLabel()// this can be changed from GlobTags only
	MinTail = self.MSA112P_MinTail() // this can be changed from GlobTags only
	MinSpar = self.MSA112P_MinSpar()// this can be changed from GlobTags only
	DefBin = self.MSA112P_DefBin()
	DefSigmaX = self.MSA112P_DefSigmaX()
	DefSigmaE = self.MSA112P_DefSigmaE()
	clipX = self.MSA112P_clipX()
	clipE = self.MSA112P_clipE()
	
	MSA112_reset()
	
	//set default visible settings
	try{	//if tool is already opened, objectID mismatch and setting fail
	self.LookUpElement("BinX").DLGValue(DefBin)	
	self.LookUpElement("BinY").DLGValue(DefBin)	
	self.LookUpElement("SigmaX").DLGValue(DefSigmaX)
	self.LookUpElement("SigmaE").DLGValue(DefSigmaE)
		}
	catch{break;}
	
	}

/*********************Setting****************************/
void Settings(object self)
	{
	number NumberLines = 5		//number of adjusted parameters
	TagGroup SettingList = DLGCreateBox("Settings").DLGTableLayout(1,NumberLines,1)

	taggroup tg1 =	self.AddSettingsLine_Int(SettingList,self.MSA112P_DefBin(),3)
	taggroup tg2 =	self.AddSettingsLine_Real(SettingList,self.MSA112P_DefSigmaX(),6,2)
	taggroup tg3 =	self.AddSettingsLine_Real(SettingList,self.MSA112P_DefSigmaE(),6,2)
	taggroup tg4 =	self.AddSettingsLine_Check(SettingList,self.MSA112P_clipX())
	taggroup tg5 =	self.AddSettingsLine_Check(SettingList,self.MSA112P_clipE())	
	
	MSA112_reset()
	
	object SettingsFrame = Alloc(UIframe).init(SettingList)
	if(SettingsFrame.Pose())
		{
		DefBin = self.SettingNumberParameter(tg1)
		DefSigmaX = self.SettingNumberParameter(tg2)
		DefSigmaE = self.SettingNumberParameter(tg3)
		clipX = self.SettingNumberParameter(tg4)
		clipE = self.SettingNumberParameter(tg5)	
		}
	}


	
/*********************binning****************************/
void RunBinning(object self)
	{
	self.MSA112_Info("run binning",300,100,\
	"bin front-most"+\
	"\nspectrum-image"+\
	"\nalong X and Y" +\
	"\nwith indicated" +\
	"\nbinning numbers")
	
	if(runningBin==0)
		{
		self.RunThreadFromDLG("Binning",runningBin,"runBinning","stopBinning")
		//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
		}
	}

void StopBinning(object self)
	{
	self.StopThreadFromDLG(runningBin,"stopBinning")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}

void TerminateBinning(object self)
	{
	self.TerminateThreadFromDLG(runningBin,"runBinning","stopBinning")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}
	
		
void Binning(object self)
	{
	number binX = self.LookUpElement("BinX").DLGgetValue()
	number binY = self.LookUpElement("BinY").DLGgetValue()

	self.MSA112_UpdateProgress("running",0)	
	try
		{
	image cube := getfrontImage()
	string Name = cube.ImageGetName()
	
	//evaluate steps
	number steps = 11 //just divide all on 10 steps, 1 is to show start
	number stepped
		
	image binned  = self.MSA112_binning(cube,binX,binY,runningBin,steps,stepped)//resulted image is real	
				
	binned.showimage()
	binned.ImageSetName(Name+"_"+binX+"x"+binY)
	
	MSA112_TransferCalibration(cube,binned,binX,binY,0)
	TagGroup BinnedTags = MSA112_TransferImageTags(cube,binned)
	BinnedTags.MSA112_SetNumberInTags(FilterLabel+":binning X","S",binX)
	BinnedTags.MSA112_SetNumberInTags(FilterLabel+":binning Y","S",binY)
		
self.MSA112_UpdateProgress(" performed",0)
			
		}
	catch
		{
		self.MSA112_UpdateProgress("stopped",0)
		break
		}	
	
	self.TerminateBinning()
	}


/*********************filtering****************************/
void RunXfiltering(object self)
	{	
	self.MSA112_Info("run spatial filtering",0,220,\
	"smooth front-most"+\
	"\nspectrum-image"+\
	"\nin X,Y-directions"+\
	"\nwith Gaussian curve" +\
	"\nof indicated sigma")
	
	if(runningXFilt==0)
		{
		self.RunThreadFromDLG("Xfiltering",runningXFilt,"runXfiltering","stopXfiltering")
		//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
		}
	}

void StopXfiltering(object self)
	{
	self.StopThreadFromDLG(runningXFilt,"stopXfiltering")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}

void TerminateXfiltering(object self)
	{
	self.TerminateThreadFromDLG(runningXFilt,"runXfiltering","stopXfiltering")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}
	
void RunEfiltering(object self)
	{
	self.MSA112_Info("run spatial filtering",0,240,\
	"smooth front-most"+\
	"\nspectrum-image"+\
	"\nin energy-direction"+\
	"\nwith Gaussian curve" +\
	"\nof indicated sigma")
	
	if(runningEFilt==0)
		{
		self.RunThreadFromDLG("Efiltering",runningEFilt,"runEfiltering","stopEfiltering")
		//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
		}
	}

void StopEfiltering(object self)
	{
	self.StopThreadFromDLG(runningEFilt,"stopEfiltering")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}

void TerminateEfiltering(object self)
	{
	self.TerminateThreadFromDLG(runningEFilt,"runEfiltering","stopEfiltering")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}
	
void Xfiltering(object self)
	{
	number sigma = self.LookUpElement("SigmaX").DLGgetValue()

	self.MSA112_UpdateProgress("running",0)
try
	{
	image cube := getfrontImage()
	string Name = cube.ImageGetName()
	
	//evaluate steps
	number castles = MSA112_CastleClip(sigma,minTail)
	number bishops = MSA112_BishopClip(sigma,minTail)
	number steps = 2*(castles+bishops)+1
	number stepped	
	
	image filtered
	filtered = self.MSA112_Xfiltering(cube,sigma,minTail,runningXFilt,steps,stepped)
	
	image final
	number cl
	if(clipX==1)
		{
self.MSA112_ThreadMarkStart(stepped/steps,"clipping "+clipX,"\nclipping "+clipX,t)
		final = MSA112_Xclipping(filtered,castles)		
stepped++
self.MSA112_ThreadMarkEnd(runningXFilt," ",t)
		}
	else 
		{
		final:= filtered
		}
	
	final.showimage()
	final.ImageSetName(Name+"_"+"xGss")
	
	MSA112_TransferCalibration(cube,final,1,1,0)
	TagGroup FinalTags = MSA112_TransferImageTags(cube,final)
	FinalTags.MSA112_SetNumberInTags(FilterLabel+":spatial sigma","F",sigma)
	

self.MSA112_UpdateProgress(" performed",0)

	}
	catch
		{
		self.MSA112_UpdateProgress("stopped",0)
		break
		}
		
	self.TerminateXfiltering()
	}

void Efiltering(object self)
	{
	number sigma = self.LookUpElement("SigmaE").DLGgetValue()

	self.MSA112_UpdateProgress("running",0)
	try
		{	
	image cube := getfrontImage()
	string Name = Cube.ImageGetName()
		
	//evaluate steps
	number castles = MSA112_CastleClip(sigma,minTail)
	number steps = castles + 1
	number stepped	

	image filtered
	filtered = self.MSA112_Efiltering(cube,sigma,minTail,runningEFilt,steps,stepped)
	
	image final
	number cl
	if(clipE==1)
		{
self.MSA112_ThreadMarkStart(stepped/steps,"clipping "+clipE,"\nclipping "+clipE,t)

		final = MSA112_Eclipping(filtered,castles)
					
stepped++
self.MSA112_ThreadMarkEnd(runningEFilt," ",t)			
		}
	else 
		{
		final:= filtered
		}
		
		final.showimage()
		final.ImageSetName(Name+"_"+"eGss")		
		
		MSA112_TransferCalibration(cube,final,1,1,0)
		TagGroup FinalTags = MSA112_TransferImageTags(cube,final)
		FinalTags.MSA112_SetNumberInTags(FilterLabel+":energy sigma","F",sigma)
	
self.MSA112_UpdateProgress(" performed",0)
		}
		catch
			{
			self.MSA112_UpdateProgress("stopped",0)
			break
			}
		
	self.TerminateEfiltering()
	}

	
void MakeAverageSpectrum(object self)
	{
	try	{
	image cube := getfrontImage()
	
	image AvSpec := MSA112_MakeAverageSpectrum(cube)
	
	AvSpec.showimage()
		}
	catch
		{
		self.EndThread("AverageSpectrum",WaitingID)
		}
		
	self.EndThread("AverageSpectrum",WaitingID)	
	}

void AverageSpectrum(object self)
	{
	self.MSA112_Info("average spectrum",0,300,\
	"extract average"+\
	"\nspectrum (summed "+\
	"\nover all X,Y-pixels)"+\
	"\nfrom front-most" +\
	"\nspectrum-image")
	
	WaitingID = self.StartThreadFromDLG("MakeAverageSpectrum","AverageSpectrum")
	}
	
void MakeAverageImage(object self)
	{
	try	{
	image cube := getfrontImage()

	image MSAimage := MSA112_MakeMeanImage(cube)
	
	MSAimage.showimage()
		}
	catch
		{
		self.EndThread("AverageImage",WaitingID)
		}
	
	self.EndThread("AverageImage",WaitingID)
	}

void AverageImage(object self)
	{
	self.MSA112_Info("average spectrum",330,300,\
	"extract average"+\
	"\nimage (summed "+\
	"\nover all E-channels)"+\
	"\nfrom front-most" +\
	"\nspectrum-image")
	
	WaitingID = self.StartThreadFromDLG("MakeAverageImage","AverageImage")
	}
}



void createAll()
{
alloc(Filtering_MSA112).init(MSA112_MSApath(),"MSA filtering") 

}

createAll()
