	
	//FOR THE MOMENT default weighting & centering can be changed only from persistent tags
	/*
	number Weight = self.LookUpElement("Weighting").DLGgetValue()-1
	number Cent = self.LookUpElement("Centering").DLGgetValue()
	number SVD = self.LookUpElement("SVD").DLGgetValue()
	self.StoreParameter(Weight,WeightName)
	self.StoreParameter(Cent,CentName)
	self.StoreParameter(SVD,SVDName)
	*/


/****************************************************
MSA proceed LAUNCHER
****************************************************/
class MSAlauncherD: MSA112_UIFrame
{
number MinSpar
number converg,deviaSpec,maxItPCA
	
string MSAlabel
string HisName
number t
number WaitingID
number enablingState
number MatrixSemaphore
number runningPCA,runningRec
roi energyRange
number maxRange

number ConfirmFrameID

TagGroup CreateMatrixBox(object self)
	{
	TagGroup Dialog = DLGCreateBox("prepare container")
	
	TagGroup Dialog1 = DLGCreateDialog("")
	Dialog1.DLGTableLayout(4,1,0)
	Dialog1.DLGAddElement(DLGCreatePushButton("container","RunMatrix").DLGIdentifier("runMatrix"))
	Dialog1.DLGAddElement(DLGCreateLabel("      "))		
	Dialog1.DLGAddElement(DLGCreateLabel("      "))	
	Dialog1.DLGAddElement(DLGCreateLabel("      "))	
	
	TagGroup Dialog2 = DLGCreateDialog("")
	Dialog2.DLGTableLayout(2,1,0)
	Dialog2.DLGAddElement(DLGCreateLabel("   weighting").DLGAnchor("East"))
	TagGroup WItems
	Dialog2.DLGAddElement(DLGCreatePopUp(WItems,2).DLGIdentifier("Weighting"))
		WItems.DLGAddPopUpItemEntry("  no  ")
		WItems.DLGAddPopUpItemEntry("E & X,Y")
		WItems.DLGAddPopUpItemEntry("E only ")
		WItems.DLGAddPopUpItemEntry("Anscombe")
		
	Dialog.DLGAddElement(Dialog1)
	Dialog.DLGAddElement(Dialog2)
	
	return Dialog
	}
	
TagGroup CreatePCABox(object self)
	{	
	TagGroup Dialog1 = DLGCreateDialog("")
	Dialog1.DLGTableLayout(3,1,0)	//3 collumn, 1 rows	
	Dialog1.DLGAddElement(DLGCreatePushButton(" PCA","RunPCA").DLGIdentifier("runPCA"))	
	Dialog1.DLGAddElement(DLGCreateCheckBox("center",1,"ChangeCenter").DLGIdentifier("Centering").DLGAnchor("East"))
	Dialog1.DLGAddElement(DLGCreatePushButton("stop","StopPCA").DLGIdentifier("stopPCA").DLGEnabled(0))	

	TagGroup Dialog2 = DLGCreateDialog("")
	Dialog2.DLGTableLayout(2,1,0)	//2 collumn, 1 rows	
	Dialog2.DLGAddElement(DLGCreateCheckBox("use SVD",0).DLGIdentifier("SVD").DLGAnchor("East"))
	Dialog2.DLGAddElement(DLGCreateLabel("                    "))	
	
	TagGroup Dialog3 = DLGCreateDialog("")
	Dialog3.DLGTableLayout(2,1,0)	//2 collumn, 1 rows
	Dialog3.DLGAddElement(DLGCreateLabel("number components"))
	Dialog3.DLGAddElement(DLGCreateIntegerField(2,5).DLGIdentifier("componentsPCA").DLGanchor("West"))
	
	TagGroup Dialog = DLGCreateBox("extract PCA components")
	Dialog.DLGAddElement(Dialog1)
	Dialog.DLGAddElement(Dialog2)
	Dialog.DLGAddElement(Dialog3)
	
	return Dialog
	}

void ChangeCenter(object self, TagGroup tg)
	{
	self.MSA112_InfoBox(tg,"center",270,200,\
	"check this box"+\
	"\nwhen you desire" +\
	"\nto center dataset" +\
	"\n(count from mean)" +\
	"\nprior PCA" )	
	}

	

TagGroup CreateReconstructionBox(object self)
	{
	TagGroup Dialog = DLGCreateBox("reconstruct DataCube")
	
	TagGroup Dialog1 = DLGCreateDialog("")
	Dialog1.DLGTableLayout(3,1,0)
	Dialog1.DLGAddElement(DLGCreatePushButton("k?","Adviser").DLGIdentifier("Adviser"))
	Dialog1.DLGAddElement(DLGCreatePushButton("reconstruct","RunRec").DLGIdentifier("RunRec"))	
	Dialog1.DLGAddElement(DLGCreatePushButton("stop","StopRec").DLGIdentifier("stopRec").DLGEnabled(0))	

	TagGroup Dialog2 = DLGCreateDialog("")
	Dialog2.DLGTableLayout(2,1,0)
	Dialog2.DLGAddElement(DLGCreateLabel("number components").DLGAnchor("East"))
		number defRECcomp = 2	//this is before initialization of proceed tool, cannot be loaded
	Dialog2.DLGAddElement(DLGCreateIntegerField(defRECcomp,5).DLGIdentifier("componentsRec").DLGanchor("West"))
	
	Dialog.DLGAddElement(Dialog1)
	Dialog.DLGAddElement(Dialog2)
	
	return Dialog
	}	

TagGroup CreateCompressionBox(object self)
	{
	TagGroup Dialog = DLGCreateBox("compress Data")
	Dialog.DLGTableLayout(2,1,1)

	Dialog.DLGAddElement(DLGCreatePushButton("  compress ","CompressDataCube"))	
	Dialog.DLGAddElement(DLGCreatePushButton("  extract  ","RunExtraction").DLGIdentifier("RunExtract"))	
	
	return Dialog
	}	

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 CreateAllBoxes(object self)
	{		
	TagGroup Dialog = DLGCreatedialog("")
	Dialog.DLGAddElement(self.CreateProgress())
	Dialog.DLGAddElement(self.CreateMatrixBox())
	Dialog.DLGAddElement(self.CreatePCABox())
	Dialog.DLGAddElement(self.CreateReconstructionBox())
	Dialog.DLGAddElement(self.CreateCompressionBox())
	
	string BottomLabel = MSA112_HisName()
	if(len(BottomLabel)<6) BottomLabel += " "	//GMS3 bug with display labels
	Dialog.DLGAddElement(DLGCreateLabel(MSA112_HisName()))
	
	return Dialog
	}

void EnablingButtons(object self,number state)
	{
	self.SetElementIsEnabled("stopPCA",state)
	self.SetElementIsEnabled("stopRec",state)	
	}
	
number EnablingAll(object self)	//This is needed for INFO-mode
	{
	self.SetElementIsEnabled("stopPCA",1)
	self.SetElementIsEnabled("stopRec",1)
	
	return enablingState
	}
			
object init(object self,string Package,string Name,string MSAlabelP)
	{
	MSAlabel = MSAlabelP	
	
	self.MSA112_initUIFrame(self.CreateAllBoxes(),Package,Name)
	
	//FOR THE MOMENT default weighting,centering,SVD,numbers of PCA and REC components can be changed only from persistent tags
	number Weight = self.MSA112P_Weight()	//default : E & X,Y
	number Cent = self.MSA112P_Cent()		//default : do centering
	number SVD = self.MSA112P_SVD()			//default do SVD
	number defPCAcomponents = self.MSA112P_defPCAcomponents()	//default 2
	number defRECcomponents = self.MSA112P_defRECcomponents()	//default 2
	MinSpar = self.MSA112P_MinSpar()
	
	//set default visible settings
	try{	//if tool is already opened, objectID mismatch and setting fail
	self.LookUpElement("Weighting").DLGValue(Weight+1)
	self.LookUpElement("Centering").DLGValue(Cent)
	self.LookUpElement("SVD").DLGValue(SVD)
	self.LookUpElement("componentsPCA").DLGValue(defPCAcomponents)
	self.LookUpElement("componentsRec").DLGValue(defRECcomponents)
	}
	catch{break;}
	
	//load tunable parameters
	converg = self.MSA112P_converg()
	deviaSpec = self.MSA112P_deviaSpec()
	maxItPCA = self.MSA112P_MaxIttPCA()

	MSA112_reset()
		
	return self
	}

void CloseUIFrame(object self)
	{
	//add some actions if neccesary
	}
		
/*********************Setting****************************/
void Settings(object self)
	{	

	TagGroup SettingList = DLGCreateBox("Settings").DLGTableLayout(1,3,1)
	
	//convergence cannot be shortcut
		TagGroup ConvergItems
	TagGroup tg1 = DLGCreatePopup(ConvergItems, self.MSA112P_converg()+1)// Converg 0->1
		ConvergItems.DLGaddPopupItemEntry("angular")
		ConvergItems.DLGaddPopupItemEntry("by value")
	string ConvergName = MSA112_DOWN()	
	Tg1.DLGIdentifier(ConvergName).DLGAnchor("East")
	SettingList.DLGaddElement(self.SettingsLine(ConvergName.right(11),Tg1))
	//end converg tag
	taggroup tg2 =	self.AddSettingsLine_Real(SettingList,self.MSA112P_deviaSpec(),7,5)
	taggroup tg3 =	self.AddSettingsLine_Int(SettingList,self.MSA112P_MaxIttPCA(),5)
	
	MSA112_reset()
	
	object SettingsFrame = Alloc(UIframe).init(SettingList)
	if(SettingsFrame.Pose())
		{
		//convergence cannot be shortcut
		converg = tg1.DLGGetValue()-1	// Converg 1->0
		self.MSA112_StoreParameter(converg,ConvergName)	
		//end converg
		deviaSpec = self.SettingNumberParameter(tg2)
		maxItPCA = self.SettingNumberParameter(tg3)
		}
	}

/*********************Matrix****************************/

void ConfirmRange(object self, number e_fl, DocumentWindow Win)
	{		
	object ConfirmFrame =ConfirmFrameID.GetScriptObjectFromID()
	try{ConfirmFrame.OKconfirm();}
	catch break
	}


void ConfirmAction1(object self)
	{	
	number Estart,Eend
	energyRange.ROIGetRange(Estart,Eend)
	Eend = Estart +(Eend-Estart)/2
	
	number minRange =128
	if(Eend<(Estart+minRange)) Eend = Estart +minRange
	energyRange.ROISetRange(Estart,Eend)	
	}
	
void ConfirmAction2(object self)
	{
	number Estart,Eend
	energyRange.ROIGetRange(Estart,Eend)
	Eend = Estart +(Eend-Estart)*2
	
	if(Eend>maxRange) Eend =maxRange
	
	energyRange.ROISetRange(Estart,Eend)	
	}

void RunMatrix(object self)
	{
	self.MSA112_Info("make container",0,90,\
	"prepare container"+\
	"\nto keep MSA results"+\
	"\nfrom front-most"+\
	"\nspectrum-image"+\
	"\n(weighting option"+\
	"\nmust be specified)")
		
	WaitingID = self.StartThreadFromDLG("ProceedMatrix","makeMatrix")		
	}
	
void ProceedMatrix(object self)
{	
number weighting
number WeightingCode = self.LookUpElement("Weighting").DLGgetValue()-1
number WeightSpecOnly,Anscombe

weighting =WeightingCode
if(WeightingCode==2) 
	{
	weighting =1
	WeightSpecOnly =1
	}	
result("\nWeighting "+Weighting+" WeightSpecOnly "+WeightSpecOnly+" Anscombe "+Anscombe)

	//check if 3D datacube
	image DataCube
	try{
	DataCube := getFrontImage()	
		}
	catch
		{
		OKdialog("It should be data cube in front !!")
		self.EndThread("makeMatrix",WaitingID)
		exit(0)		
		}
	if(DataCube.ImageGetNumDimensions()!=3) 
		{
			TagGroup ConfirmTags1 = DLGCreatedialog("")
			ConfirmTags1.DLGAddElement(DLGCreateLabel("wrong format for data cube !!"))
			number left =-50
			number top =160
		MSA112_Confirm(self,ConfirmTags1,"check your datacube","  OK  ","Cancel",left,top)
		self.EndThread("makeMatrix",WaitingID)
		exit(0)
		}	


try
	{
	//check Sparsity
	number spar = MSA112_Sparsity(DataCube)
result("\nsparcity "+spar)	
	if(weighting>0) if(spar<minspar)	//too much sparsity make weighting crazy
		{
			TagGroup ConfirmTags2 = DLGCreatedialog("")
			ConfirmTags2.DLGAddElement(DLGCreateLabel("dataCube is too sparse ("+spar+\
			").\nConsider binning or filtering prior PCA."+\
			"\nOtherwise press OK to proceed further."))
			number left =-50
			number top =160
		if(!MSA112_Confirm(self,ConfirmTags2,"Warning","  OK  ","Cancel",left,top)) throw("")
		}
	
	//make average spectrum, show the range selection	
	image AvSpec
		
		number Estart=0, Eend =	DataCube.ImageGetDimensionSize(2)	
		maxRange =Eend
		image OverView :=MSA112_MakeAverageSpectrum(DataCube)
		AvSpec :=OverView
		OverView.showimage()
		imageDisplay disp = OverView.ImageGetImageDisplay(0)
		energyRange  = NewRoi()
		energyRange.ROISetName("Selected range")
		energyRange.ROISetLabel("Selected range")
		energyRange.ROISetVolatile(0)
		energyRange.ROISetColor(1,0,0)	
		energyRange.ROISetRange(Estart,Eend) 
		disp.ImageDisplayAddRoi(energyRange)
		
		//add window closing listener	
		DocumentWindow SpecWin =MSA112_GetLoadingWindow(OverView)	
		number Listener =SpecWin.WindowAddWindowListener(self,"window_closed:ConfirmRange")
		
	//select energy range
	number left =-50
	number top =160
			TagGroup ConfirmTags3 = DLGCreatedialog("")
			ConfirmTags3.DLGAddElement(DLGCreateLabel("select the energy range\nfor MSA treatment."))
			TagGroup ChangeTags = DLGCreatedialog("").DLGTableLayout(2,1,0)
			ChangeTags.DLGAddElement(DLGCreatePushButton("reduce twice","ConfirmAction1").DLGIdentifier("reduceRange"))			
			ChangeTags.DLGAddElement(DLGCreatePushButton("increase twice","ConfirmAction2").DLGIdentifier("increaseRange"))
			ConfirmTags3.DLGAddElement(ChangeTags)	

	if(!MSA112_Confirm(self,ConfirmFrameID,ConfirmTags3,"select energy range","Confirm","Cancel",left,top)) throw("")	

	try
		{
		//when overview is closed, ROI can be still red ?	
		energyRange.ROIGetRange(Estart,Eend)	
		AvSpec :=Overview[0,Estart,1,Eend]	
		}
	catch break	

		
	//make MSA image
	image AvImage
	image MSAimage := MSA112_MakeMSAimage(dataCube,AvImage,Estart,Eend) //AvImage returned because it is costly

	//convert to matrix	
	image dataMatrix := MSA112_ConvertCubeToMatrix(DataCube,Estart,Eend)
	
	//weighting
	if(weighting>0) 
		{
		if(WeightSpecOnly==1) AvImage =1	//needed for consistancy of further operations	

		if(weighting==3)//Anscomb
			{
			dataMatrix =2*sqrt(dataMatrix+3/8)
			dataMatrix =tert(dataMatrix>0,dataMatrix,0)	
			}
		else	MSA112_Weighting(dataMatrix,AvSpec,AvImage)
		}
		
	MSAImage.showimage()	
	try{OverView.deleteImage();} catch{break;}
	
	MSA112_AttachImages(MSAimage,dataMatrix,AvSpec,AvImage,weighting,WeightSpecOnly)
		
//end of what should be done in background
	}
	catch
		{
		self.EndThread("makeMatrix",WaitingID) 
		break
		}
	
self.EndThread("makeMatrix",WaitingID) 
}

	
/*********************PCA****************************/
void RunPCA(object self)
	{
	self.MSA112_Info("make PCA",-10,200,\
	"decompose data"+\
	"\nfrom front-most"+\
	"\nMSA container on" +\
	"\nPCA components")
	
	self.RunThreadFromDLG("ProceedPCA",runningPCA,"runPCA","stopPCA")
	//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
	}
	
void StopPCA(object self)	//stop after closing a step
	{
	self.MSA112_Info("stop",380,160,\
	"press this button"+\
	"\nif something goes" +\
	"\nwrong or if you"+\
	"\nfeel it takes" +\
	"\ntoo much time")
	
	self.StopThreadFromDLG(runningPCA,"stopPCA")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}	

void TerminatePCA(object self)	//immediate stop
	{
	self.TerminateThreadFromDLG(runningPCA,"runPCA","stopPCA")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}
	
	
	
void ProceedPCA(object self)
{
//read checkboxes
number CompN = self.LookUpElement("componentsPCA").DLGgetValue()
number makeCent = self.LookUpElement("Centering").DLGgetValue()

self.MSA112_UpdateProgress("running",0)

//convert devia spec from rad into close to 1 cosinus	
number minCos = cos(deviaSpec)

number interrupted = 0					
try
{	
//this is what should be done in background

result("\nproceed PCA ")	

//check MSAimage
image MSAimage := getFrontImage()
string DataName = MSAimage.getName()

TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,1)
if(!MatrixTags.TagGroupIsValid()){ throw("");}


//read basic parameters
number Points,Depth,width,height
MatrixTags.MSA112_GetSISizes(Points,Depth,width,height)

	
number disp,origin
string units
MatrixTags.MSA112_GetCalibration(disp,origin,units,"E")


//define treated clusters
number clusterN =MatrixTags.MSA112_getNumberFromTags(MSAlabel+":clusters number","S")
number clusterS = 0
if(clusterN!=0)
	{
		clusterS = 0
		TagGroup Message1T = DLGCreateLabel("Data are clustered !!\nChose your target cluster")
		TagGroup TreatedClusterT = DLGCreateDialog("").DLGTableLayout(2,1,0)
			TagGroup ClusterNoT = DLGCreateIntegerField(ClusterS,2)
			TagGroup ClusterDescrT = DLGCreateLabel("treat only this cluster")
			TreatedClusterT.DLGaddElement(ClusterNoT)
			TreatedClusterT.DLGaddElement(ClusterDescrT)
		TagGroup TreatAllT = DLGCreateCheckBox("treat all clusters         ",0)
		TagGroup Message2T = DLGCreateLAbel("cluster 0 means 'no clustering'")
			
		TagGroup ClusterDialog = DLGCreateDialog("")
		ClusterDialog.DLGaddElement(Message1T)
		ClusterDialog.DLGaddElement(TreatedClusterT)
		ClusterDialog.DLGaddElement(TreatAllT)
		ClusterDialog.DLGaddElement(Message2T)		

	number left =-80
	number top =280	
	if(!MSA112_Confirm(self,ClusterDialog,"old components","Extract","Cancel",left,top)) throw("")
	ClusterS = ClusterNoT.DLGgetValue()
	if(DLGGetValue(TreatAllT)) clusterS = (-1)	
	}
	
number cluster0,clusterF	//initial and final clusters
MSA112_ClustersRange(ClusterS,ClusterN,Cluster0,ClusterF)


//get MSAimage and cluster mask
image IniMatrix := MSA112_GetMSAMatrix(MatrixTags)
image Cluster:= MSA112_GetCluster(MatrixTags)

result("clusters:"+Cluster0+"-"+ClusterF+"; number of PCA components:"+CompN)

//evaluate steps
number steps,linear,quadr,ext
steps = 1+(ClusterF-Cluster0+1)*(1+CompN)  //assumed takeCluster = each compnent extraction		
number stepped = 0		
	
		
//prepare cluster list	
tagGroup ClusterList = MSA112_EnsureClusterList(MatrixTags)	

image dataMatrix	//prepare a copy of iniMatrix, iniMatrix is not changed	

//Proceed clusters chain
for(number currCluster = Cluster0;currCluster <= ClusterF;currCluster++)
	{	
	//check cluster
	string ClusterLabel = MSA112_GetClusterLabel(currCluster)
	number kPoints
	if( !MatrixTags.TagGroupGetTagAsLong(ClusterLabel+":pixels",kPoints))
		{	//this is used as check whether [i]-cluster exists or not
		ClusterList.TagGroupCreateGroupTagAtEnd()
		}


	//set convergence criteria
	string ConvCrit
	if(converg!=0) ConvCrit = "by value"
	else ConvCrit = "angular"	//this is default and can be override only if converg!=0
				
result("\nmaxIt "+maxItPCA+ " convergence criteria: "+ConvCrit)
			
	//take cluster	
stepped++ 
self.MSA112_ThreadMarkStart(stepped/steps,"CL:"+currCluster,"\ncluster "+currCluster,t)

	image AvSpec := realimage("Average spec",4,Depth,1)
	
	dataMatrix := MSA112_TakeCluster(IniMatrix,cluster,currCluster,makeCent,AvSpec,kPoints)

	if(!dataMatrix.imageIsValid() ) OKdialog("cluster "+currCluster+" consists of no points !!")
		
	number uncentered = !makeCent
result(": "+kPoints+" points")
	
	
	//prepare all images
	image Tvec:= realimage("T-vector",4,1,kPoints)
	image Pvec:= realimage("P-vector",4,1,Depth)	
	image EVs := MSA112_PCAimageEigens(maxItPCA,deviaSpec,converg)
	image devia:= MSA112_PCAimageDevia(maxItPCA,mincos)
	image spikes:= MSA112_PCAimageSpikes(maxItPCA,0)
	
	//makes many components images from one-component ones
	image Tall:= MSA112_PCAimagesAll(Tvec,CompN)
	image Pall:= MSA112_PCAimagesAll(Pvec,CompN)
	image EVsAll := MSA112_PCAimagesAll(EVs,CompN)
	image deviaAll:= MSA112_PCAimagesAll(devia,CompN)
	image spikesAll:= MSA112_PCAimagesAll(spikes,CompN)
	
	//row-images of size: CompN x 1
	image finEVs := realimage(DataName+" cluster_"+currCluster+" Eigenvalues",4,CompN,1)
	image Iterations := integerimage("Iterations",2,0,CompN,1)
	
self.MSA112_ThreadMarkEnd(runningPCA," taken",t)		

	//check previously extracted components
	number CompNold =MSA112_ReadNumberComponents(MatrixTags,currCluster,"PCA")
	if(CompNold>0)
		{
		number maxItOld =MatrixTags.MSA112_getNumberFromTags(ClusterLabel+":PCA:max iterations","I")
				result("\npreviously extracted "+CompNold+ " PCA components"+ " maxIterations "+maxItOld)
		if(maxItOld==maxItPCA) result(" (same as curently)")
		else 	result(" (changed)")
		
		number uncenteredOld =MatrixTags.MSA112_getNumberFromTags(ClusterLabel+":uncentered","S")
		if(uncenteredOld) result( "\nuncentered")
		else 	result("\ncentered")	
		if(uncentered==uncenteredOld) result(" (same as curently)")
		else 	result(" (changed)")	

		
		//if there are old useful components, confirm their overwritting	
		if((maxItOld==maxItPCA)&&(uncentered==uncenteredOld)) 
			{
				TagGroup ConfirmTags1 = DLGCreatedialog("")
				ConfirmTags1.DLGAddElement(DLGcreateLabel(CompNold +" PCA components were already extracted"+\
				"\nYou can overwrite them or add new\ncomponents while keeping old ones"))		
				TagGroup radio_items
				TagGroup OverWriteBox =DLGCreateRadioList(radio_items,0)
				radio_items.DLGAddRadioItem("overwrite", 1)
				radio_items.DLGAddRadioItem("add new", 0)			
				ConfirmTags1.DLGAddElement(OverWriteBox)
			number left =-80
			number top =280	
			if(!MSA112_Confirm(self,ConfirmTags1,"old components","Confirm","Cancel",left,top)) throw("")
			if(DLGGetValue(OverWriteBox)) CompNold=0	//overwrite chosen
			else if(CompN<=CompNold) {result("\nno extra components to extract");throw("");}	//add chosen but not possible
	
			if(CompNold>0)
				{
				//take old components
				//currently their calculation time is not accounted properly in steps					
				image PallOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Loadings")	
				image TallOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Scores")				
				image EVsAllOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Valuesflow")	
				image DeviaAllOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Precisions")	
				image finEVsOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Variance")	
				image IterationsOld :=MatrixTags.MSA112_getImageFromTags(ClusterLabel+":PCA:Iterations")

				//attach to the new ones
				Tall[0,0,kPoints,CompNold] = TallOld[0,0,kPoints,CompNold]	
				Pall[0,0,depth,CompNold] = PallOld[0,0,depth,CompNold]	

				EVsAll[0,0,maxItPCA+1,CompNold] = EVsAllOld[0,0,maxItPCA+1,CompNold]
		
				if(finEVsOld.imageIsValid()) finEVs[0,0,1,CompNold] =finEVsOld[0,0,1,CompNold]
				if(iterationsOld.imageIsValid()) iterations[0,0,1,CompNold] = iterationsOld[0,0,1,CompNold]
					
				//reduce matrix		
				image TallCapt, PallCapt

				TallCapt =Tall[0,0,kPoints,CompNold]	//equal, not assign, otherwise Python doesnot find image
				PallCapt =Pall[0,0,depth,CompNold]
					
					
				dataMatrix -= MSA112_matrixMultiply(TallCapt,MatrixTranspose(PallCapt)) 
		//dataMatrix.imageclone().showimage()
			
				}
			}
			
		else CompNold =0	//overwritting forced as parameters were changed
		}

	
	number CurrEV
	
		
		for(number i=CompNold;i<CompN;i++)
			{
stepped++
self.MSA112_ThreadMarkStart(stepped/steps,"CL:"+currCluster+" PC:"+(i+1),"\ncomponent "+(i+1)+":",t)

					//curently not used initializations:
								//initial loading
								//Pvec.setPixel(0,0,1) 
								//Pvec = MSA112_RandomVector(depth)
			Pvec = MatrixTranspose(AvSpec) //initialization as an average
	
			devia[1,0,maxItPCA+1,1] = 0	//all except zero-pixel
			EVs[1,0,maxItPCA+1,1]   = 0	//all except zero-pixel	
			
/*
if(EVs.imageisValid()) {EVs.showimage();result("\nEVs");}
if(devia.imageisValid()) {devia.showimage();result("\ndevia");}
if(spikesXY.imageisValid()) {spikesXY.showimage();result("\nspikesXY");}
*/
			
	// head NIPALS COMMAND	
	number Nitt = MSA112_FindNIPALS(dataMatrix,Pvec,Tvec,EVs,devia)
		
				
			//write output in arrays
			Iterations.setpixel(i,0,Nitt)
			deviaAll[0,i,Nitt+1,i+1]=devia[0,0,Nitt+1,1]


			Tall[0,i,kPoints,i+1]=Tvec
			Pall[0,i,depth,i+1]  =Pvec
				
				
			//values of final iteration				
			CurrEV = EVs.getPixel(0,Nitt)
			currEV /= kPoints
			finEVs.setPixel(i,0,CurrEV)

			number CurrDevia = devia.getPixel(0,Nitt)
result(" itt:"+nItt+ "; EV:"+ CurrEV+ " log(EV) "+log(currEV)+ "; devia:"+CurrDevia)	
				

	//reduce DataMatrix
	dataMatrix -= matrixMultiply(Tvec,MatrixTranspose(Pvec)) //reduce also quadrant garbadge
							
self.MSA112_ThreadMarkEnd(runningPCA," ",t)
			}	
			
		
		
	
//dataMatrix.imageclone().showimage()
	
	//resort with decreasing singular values
	Pall = MSA112_ResortDescending(Pall,finEVs)
	Tall = MSA112_ResortDescending(Tall,finEVs)	
	deviaAll = MSA112_ResortDescending(deviaAll,finEVs)
	EVsAll = MSA112_ResortDescending(EVsAll,finEVs)
	Iterations = MSA112_ResortDescending(Iterations,finEVs)
	finEVs = MSA112_ResortDescending(finEVs,finEVs)

	//Scree plot
	image components  //it is a dummy image in this case
	MSA112_DisplayEigenValues(log(finEVs),"Cluster "+CurrCluster+" "+"Variance","PCA",Components)
		
	//Plot Loadings
	DataName = left(DataName,len(DataName)-4)
	AvSpec.ImageSetName("cluster_"+currCluster)		
	AvSpec.ImageSetDimensionCalibration(0,origin,disp,units,1)
	number mplot = CompN
	number maxLoadings = self.MSA112_LoadParameter(10,"max displayed loadings")
	if(mplot>maxLoadings) mplot = maxLoadings //not overload display
	MSA112_DisplayLoads(AvSpec,Pall,1,mplot,DataName+" LOAD("+CurrCluster+")","PCA",components)

	// store PCA tags
	number quadrant =0
	MatrixTags.MSA112_StorePCAtags(currCluster,uncentered,kPoints,AvSpec,quadrant)
	MatrixTags.MSA112_StorePCAtags(currCluster,CompN,maxItPCA,deviaSpec)	//basic parameters
	MatrixTags.MSA112_StorePCAtags(currCluster,Pall, Tall, finEVs)	//main PCA results
	MatrixTags.MSA112_StorePCAtags(currCluster,EVsAll,DeviaAll,spikesAll,Iterations) //iterations info

	//Plot two 1-2 components Scatterplot 
	number sparsity = self.MSA112_LoadParameter(20,"sparsity in X-Y plot")

	rgbimage scatter := MSA112_PlotXY(MSAimage,currCluster,"PCA",1,2,sparsity)
	
	scatter.setName(DataName+" SP 1-2("+currCluster+")")
	scatter.showimage()
	}

self.MSA112_UpdateProgress("performed",0)

//end of what should be done in background
}
catch 
	{
	self.MSA112_UpdateProgress("stopped",0)
	interrupted = 1
	break
	}

self.TerminatePCA()

if(!interrupted)  MSA112_ToAdvanced()
}


/********************* Adviser ****************************/


void Adviser(object self)
	{
	self.MSA112_Info("advaiser",-20,300,\
	"consult on how many"+\
	"\nPCA components (k)"+\
	"\nare recomended to use" +\
	"\nin reconstruction")

	}	

	
/*********************Reconstruction****************************/

void RunRec(object self)
	{
	self.MSA112_Info("reconstruct",0,300,\
	"reconstruct denoised"+\
	"\nspectrum-image from"+\
	"\nfront-most MSA container"+\
	"\nusing indicated number" +\
	"\nof PCA components")
	
	self.RunThreadFromDLG("ProceedRec",runningRec,"RunRec","stopRec")
	//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
	}
	
void StopRec(object self)	//stop after closing a step
	{
	self.MSA112_Info("stop",380,240,\
	"press this button"+\
	"\nif something goes" +\
	"\nwrong or if you"+\
	"\nfeel it takes" +\
	"\ntoo much time")
	
	self.StopThreadFromDLG(runningRec,"stopRec")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}	
	
void TerminateRec(object self)	// immediate stop
	{
	self.TerminateThreadFromDLG(runningRec,"RunRec","stopRec")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	}	

void RunExtraction(object self)
	{
	self.MSA112_Info("extract",350,380,\
	"reconstruct denoised"+\
	"\nspectrum-image from"+\
	"\nfront-most compressed"+\
	"\nMSA container using"+\
	"\npreviously applied" +\
	"\nnumber of PCA" +\
	"\ncomponents")
	
	self.RunThreadFromDLG("ExtractDataCube",runningRec,"RunExtract","stopRec")
	//Thread name (no parameters);GLOBAL thread running number;start/stop button IDENTIFIERS
	
	self.SetElementIsEnabled("RunRec",0)
	//additionally disable Reconstruction button
	}
	
	
void TerminatExtraction(object self)
	{
	self.TerminateThreadFromDLG(runningRec,"RunExtract","stopRec")
	//GLOBAL thread running number; start/stop button IDENTIFIERS
	
	self.SetElementIsEnabled("RunRec",1)
	//additionally enable Reconstruction button
	}	

	
image Reconstruction(object self,TagGroup MatrixTags,image AllComponents)
{
//dimensions of reconstruction
number ClusterN = AllComponents.ImageGetDimensionSize(0)-1//clusterF-cluster0 

number CompN = AllComponents.ImageGetDimensionSize(1)-1
number cluster0,clusterF //= ClusterN	
if(ClusterN!=0) MSA112_ClustersRange(-1,ClusterN,Cluster0,ClusterF)	//all clusters used
else 	MSA112_ClustersRange(0,ClusterN,Cluster0,ClusterF)			//zero cluster used
			
//steps
number steps = ClusterN + 4	//assume that 	weighting = each cluster 
							//				cubing = 2*each cluster 
							//				add mean = 0.5 each cluater
if(steps==4) steps = 5 //no clustering, then cluster 0 is treated
number stepped = 0
//result("\nsteps "+steps)


number weighting =MatrixTags.MSA112_getNumberFromTags(MSAlabel+":weighted","S")

image Cluster:= MSA112_GetCluster(MatrixTags)
if(clusterN==0) Cluster=0

//read size info 
number Points,Edepth,width,height
MatrixTags.MSA112_GetSISizes(Points,Edepth,width,height)

//reconstruction main unit
image RecMatrix :=realImage("",4,Edepth,Points)	
image AvSpec2D =realimage("Average spectrum",4,Edepth,Points)

for(number currCluster = Cluster0;currCluster <= ClusterF;currCluster++)
	{

stepped++
self.MSA112_ThreadMarkStart(stepped/steps,"cluster "+currCluster,"\ncluster "+currCluster,t)
	string ClusterLabel = MSA112_GetClusterLabel(currCluster)
	
	//check if PCA was uncentered
	number uncentered =MatrixTags.MSA112_GetNumberFromTags(ClusterLabel+":uncentered","S")	
	
	//get local Average Spectrum
	image AvSpec = MSA112_GetAverageSpectrum(MatrixTags,currCluster)  	

	//read PCA components 
	string method = "PCA"
	image Tall = MSA112_GetScores(MatrixTags,method,currCluster)
	image Pall = MSA112_GetLoadings(MatrixTags,method,currCluster)	

	//ensure that only selected clusters and components are accounted
	image ClusterComponents := AllComponents[1,currCluster,CompN+1,currCluster+1] //ONLY currCluster components
	image ClusterComponentsT :=ClusterComponents.MatrixTranspose()
		//make mask to supressed unchosen components
	number PointsC,CompNC 
	Tall.GetSize(CompNC,PointsC)
	image TallComp :=integerImage("",1,0,CompNC,PointsC)
	TallComp = ClusterComponentsT[icol,0]	
	Tall *=TallComp	//unchosen clusters and components should show zero scores 
	
//Tall.MatrixTranspose().showimage()	
//Pall.MatrixTranspose().showimage()	

	//full scores, not clastered
	image RTall
	if(currCluster!=0) RTall = MSA112_ProjectClusteredScore(MatrixTags,Tall,currCluster)
	else RTall = Tall
//RTall.MatrixTranspose().showimage()
	
	//reconstruct	
	image RTallCapt =RTall[0,0,Points,CompN]	//equal, not assign, otherwise Python doesnot find image	
	image loadingsT =MatrixTranspose(Pall[0,0,Edepth,CompN]) //direct incorparation in MSA112_matrixMultiply dangerous 
	RecMatrix += MSA112_matrixMultiply(RTallCapt,loadingsT)

	//add local cluster mean-spectrum
	if(!uncentered) if(sum(ClusterComponents)>0)
		{	
		image mask = cluster.imageclone()
		mask = tert(cluster==CurrCluster,1,0)

		AvSpec2D += (AvSpec[icol,0]*mask[0,irow])//AvSpec - real;mask int2
		}
	//if uncentered, AvSpec2D = 0
	
self.MSA112_ThreadMarkEnd(runningRec," ",t)	
	}
	//end cluster

//add accumulated mean-spectrum 	
stepped +=0.5
self.MSA112_ThreadMarkStart(stepped/steps,"add mean","\nadd mean",t)
		
RecMatrix += AvSpec2D
//RecMatrix.showimage()

self.MSA112_ThreadMarkEnd(runningRec," done",t)

//restore weighting  
if(weighting==1)
	{
	stepped ++
	self.MSA112_ThreadMarkStart(stepped/steps,"restore weighting","\nrestore weighting",t)

		image AverSpec = MSA112_GetAverageSpectrum(MatrixTags)
		image AverImage = MSA112_GetAverageImage(MatrixTags)
		MSA112_DeWeighting(RecMatrix,AverSpec,AverImage)
		
	self.MSA112_ThreadMarkEnd(runningRec," done",t)
	}
	
if(weighting==3) //Anscomb
	{
	RecMatrix =(RecMatrix/2)**2 -3/8
	}
		
//set out-clusterPixels
if(ClusterN!=0)RecMatrix = MSA112_SetOutClusterPixels(MatrixTags,RecMatrix,-1)
	
//RecMatrix.showimage()


//converting to datacube		
stepped +=2
self.MSA112_ThreadMarkStart(stepped/steps,"converting to cube","\nconverting to cube",t)
image RecCube = MSA112_Convert2Dto3D(RecMatrix,width,height)
RecCube.showimage()	
		
self.MSA112_ThreadMarkEnd(runningRec,"done",t)

//calibrate rec cube
MatrixTags.MSA112_CalibrateRecCube(RecCube)

//copy tags
TagGroup FinTags = MatrixTags.TagGroupClone()	//allacquisition tags ae copied
FinTags.TagGroupDeleteTagWithLabel(MSAlabel)	//all MSA tags deleted incl. DataMatrix
TagGroup ImTags = RecCube.ImageGetTagGroup()
TagGroupCopyTagsFrom(ImTags,FinTags)

//set selected MSA tags in RECcube
ImTags.MSA112_setStringInTags(MSAlabel+":type","reconstructed datacube")
ImTags.MSA112_setNumberInTags(MSAlabel+":clusters number","S",clusterN)
ImTags.MSA112_setNumberInTags(MSAlabel+":number components","S",CompN)
ImTags.MSA112_setImageInTags(MSAlabel+":Components List",Allcomponents)
ImTags.MSA112_setNumberInTags(MSAlabel+":weighted","S",weighting)

self.MSA112_UpdateProgress("performed",0)

return RecCube
}
	 

void ProceedRec(object self)
{
number CompN = self.LookUpElement("componentsRec").DLGgetValue()

self.MSA112_UpdateProgress("running",0)
try
{	
//this is what should be done in background

image MSAimage := getFrontImage()
string DataName = MSAimage.getName()
TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,0)
if(!MatrixTags.TagGroupIsValid()) throw("")

//define the number of used clusters and components
number clusterN =MatrixTags.MSA112_GetNumberFromTags(MSAlabel+":clusters number","S")
number cluster0,clusterF
if(clusterN!=0)
	{
		TagGroup ConfirmTags1 = DLGCreatedialog("")
		ConfirmTags1.DLGAddElement(DLGcreateLabel("Data are clustered\nUse clusters ?"))
	number left =-80
	number top =320
	if(MSA112_Confirm(self,ConfirmTags1,"dialog","clustered ","no clusters",left,top))
		{
		result("\nconfirmed clustered")
		MSA112_ClustersRange(-1,ClusterN,Cluster0,ClusterF)
		}	
	else
		{
		result("\nrejected ClusterN "+ClusterN+" "+Cluster0+" "+ClusterF)
		MSA112_ClustersRange(0,ClusterN,Cluster0,ClusterF)
		}
	result("\nclusters "+cluster0+"..."+clusterF)	
	}
else MSA112_ClustersRange(0,ClusterN,Cluster0,ClusterF)

result("\nclusters "+cluster0+"..."+clusterF)

//confirm the components list
image AllComponents := MSA112_ConfirmComponents(Cluster0,ClusterF,CompN,MatrixTags,MSAlabel,"use")
//AllComponents.showimage()

//fire reconstruction	
image RecCube := self.Reconstruction(MSAimage.ImageGetTagGroup(),AllComponents)	
DataName = left(DataName,len(DataName)-4)	//remove MSA
RecCube.ImageSetName(DataName+" REC("+CompN+")")	
RecCube.showimage()	

MatrixTags.MSA112_setImageInTags(MSAlabel+":Components List",AllComponents)	//COmponnet list in MSAimage
}
catch 
	{
	self.MSA112_UpdateProgress("stopped",0)
	break
	}

self.TerminateRec()
}

void CompressDataCube(object self) 
	{
	self.MSA112_Info("compress",-10,380,\
	"create a copy"+\
	"\nof MSA container"+\
	"\ncontaining only PCA"+\
	"\ncompressed data" +\
	"\n(much smaller size)")
		
	image MSAimage := getFrontImage()
	string DataName = MSAimage.getName()

	image Compressed := imageClone(MSAimage)
	TagGroup MatrixTags = MSA112_GetMatrixTags(Compressed,1)
	if(!MatrixTags.TagGroupIsValid()) exit(0)

	MatrixTags.TagGroupDeleteTagWithLabel(MSAlabel+":Matrix")	//delete DataMatrix
	MatrixTags.MSA112_SetStringInTags(MSAlabel+":type","MSA compressed")

	//check if reconstruction was done
	image AllComponents :=MatrixTags.MSA112_GetComponentList()
	
	if(!AllComponents.ImageIsValid())
		{
		OKdialog("Reconstruction should be done at least once before compression !!")
		
		exit(0)
		}
	
	DataName = left(DataName,len(DataName)-4)	//remove MSA
	Compressed.ImageSetName(DataName+" COMP")	

	Compressed.showimage()	
	}


void ExtractDataCube(object self) 
{
self.MSA112_UpdateProgress("running",0)
try
{	
//this is what should be done in background
image Compessed := getFrontImage()
string DataName = Compessed.getName()

TagGroup MatrixTags = MSA112_GetMatrixTags(Compessed,0)
if(!MatrixTags.TagGroupIsValid()) throw("")

//read stored component list
image AllComponents :=MatrixTags.MSA112_GetComponentList()
result("\nMARKER ");
number CompN =AllComponents.ImageGetDimensionSize(1) -1
//AllComponents.showimage()

//fire reconstruction	
image RecCube := self.Reconstruction(Compessed.ImageGetTagGroup(),AllComponents)
DataName = left(DataName,len(DataName)-4)	//remove MSA	
RecCube.ImageSetName(DataName+" REC("+CompN+")")	
RecCube.showimage()
}
catch 
	{
	self.MSA112_UpdateProgress("stopped",0)
	break
	}
	
self.TerminatExtraction()	
}


number MSA112_AboutToCloseUIFrame(object self,number verify) 
	{
	self.SetInfoMode(0)

	try{self.EndThread("makeMatrix",WaitingID);}
	catch{break;}	
	
	try{self.TerminatePCA();}
	catch{break;}	

	try{self.TerminateRec();}
	catch{break;}	

	return 1
	}	
}

void createAll()
{
alloc(MSAlauncherD).init(MSA112_MSApath(),"PCA proceed",MSA112_Label()) 

}

createAll()
