
/******************************************************************
Interface
******************************************************************/
interface clusterInterface
{
void StopSelection(object self);
image getMask(object self);
void getEllipseCoordinates(object self,number &x1P,number &y1P,number &x2P,number &y2P,number &eccent);
}

/****************************************************
Clustering LUNCHER
****************************************************/
class lunchClustering: MSA112_UIFrame
{

number sparsity
number elipsePoints
number gap
number MaskCubed
string MSAlabel	

number ElipseID		//to find out the selecting instanse (ellipse)
number scatterID	//to find out the scatterPlot in work among 'new', 'cancel' and 'confirm'
number WaitingID
number MSAID

number enablingState


TagGroup ControlTags	//keeps ID of open Scatter plots
image cluster			//currently edited cluster image
number scattN		//number of scatter plots
number ClusterN		//number of clusters
number currCluster	//currently edited cluster, needed as global because it is not tranmitted among 'new', 'cancel' and 'confirm'
number correction 	//correction flag needed to block creation of a new cluster

TagGroup CreateHead(object self)
	{
	TagGroup Dialog = DLGCreateDialog("display results")
	//Dialog.DLGTableLayout(4,1,0)
	
		TagGroup Upper = DLGCreateDialog("display results")
		Upper.DLGTableLayout(3,1,0)
	Upper.DLGAddElement(DLGCreateLabel(""+MSA112_Version()+"    "))
	Upper.DLGAddElement(self.InfoButton(20,210))	
	Upper.DLGAddElement(self.settingsButton(20,210,"Settings").DLGanchor("East"))
		TagGroup Lower = DLGCreatedialog("")
		Lower.DLGTableLayout(2,1,0)
	Lower.DLGAddElement(DLGCreateLabel("               "))		
	Lower.DLGAddElement(DLGcreateLabel("hold ALT for info").DLGAnchor("East"))
	

	Dialog.DLGAddElement(Upper)
	Dialog.DLGAddElement(Lower)
	
	return Dialog
	}
	
TagGroup ColoredPanel(object self)
	{
	number colors = 6	
	number height = 24
	number narr = 8
	
	number width = narr*colors
	
	taggroup Pan = DLGCreateGraphic(width,height)
	rgbimage color := rgbImage("",4,width,height)
	
	for(number i=1;i<=colors;i++)
		{
		color[0,(i-1)*narr,height,i*narr] = MSA112_ClusterColor(i)
		}
		
	Pan.DLGAddBitmap(color)	
	
	return Pan
	}
	
TagGroup CreateView(object self)
	{
	TagGroup Dialog = DLGCreateDialog("")
	Dialog.DLGTableLayout(2,1,0)
	
	Dialog.DLGAddElement(DLGCreatePushButton("design clusters","Design").DLGIdentifier("Design").DLGAnchor("West"))
	Dialog.DLGAddElement(DLGCreatePushButton("  load old ","Load").DLGIdentifier("Load").DLGAnchor("East"))	
	return Dialog
	}

TagGroup Create_Plot(object self)
	{
	TagGroup Dialog = DLGCreateDialog("").DLGIdentifier("scatter")
	Dialog.DLGTableLayout(3,1,0)
	
	Dialog.DLGAddElement(DLGCreatePushButton(" add plot X-Y   ","PlotScatter").DLGIdentifier("AddScatter").DLGanchor("West"))	
	Dialog.DLGAddElement(DLGCreateIntegerField(3,4).DLGIdentifier("compF").DLGanchor("West"))
	Dialog.DLGAddElement(DLGCreateIntegerField(2,4).DLGIdentifier("compS").DLGanchor("West"))

	return Dialog
	}
	
TagGroup CreateClusteringBox(object self)
	{
	TagGroup Dialog = DLGCreateBox("manage clusters").DLGIdentifier("design")

	
	TagGroup Dialog1 = DLGCreateDialog("").DLGTableLayout(3,1,0)
	Dialog1.DLGAddElement(DLGCreatePushButton("  new  ","NewCluster").DLGIdentifier("NewCluster"))
	Dialog1.DLGAddElement(DLGCreatePushButton("cancel","CancelSelection").DLGIdentifier("Cancel"))
	Dialog1.DLGAddElement(DLGCreatePushButton("confirm","ConfirmSelection").DLGIdentifier("ConfirmSelection").DLGanchor("West"))

	TagGroup Dialog2 = DLGCreateDialog("").DLGTableLayout(3,1,0)
	Dialog2.DLGAddElement(DLGCreatePushButton("delete","DeleteCluster").DLGIdentifier("Delete"))
	Dialog2.DLGAddElement(DLGCreatePushButton("append","CorrectCluster").DLGIdentifier("Correct"))
		Dialog2.DLGAddElement(self.ColoredPanel().DLGanchor("West"))	
	
	Dialog.DLGAddElement(Dialog1)
	Dialog.DLGAddElement(Dialog2)
		
	return Dialog
	}	

TagGroup CreateAutoClusteringBox(object self)
	{
	TagGroup Dialog = DLGCreateBox("auto clustering").DLGIdentifier("AutoBox")
	Dialog.DLGTableLayout(3,1,0)
	Dialog.DLGAddElement(DLGCreatePushButton("auto","FindAutoClusters").DLGIdentifier("NewCluster"))
	Dialog.DLGAddElement(DLGCreateLabel("clusters number").DLGIdentifier("Cancel"))
	Dialog.DLGAddElement(DLGCreateIntegerField(2,3).DLGIdentifier("numberClusters").DLGanchor("West"))

	return Dialog
	}
	
TagGroup Create_Finalize(object self)
	{
	TagGroup Dialog = DLGCreateDialog("").DLGIdentifier("finalize")
	Dialog.DLGTableLayout(3,1,0)

	Dialog.DLGAddElement(DLGCreatePushButton("maps","BuildMaps").DLGIdentifier("ShowMaps").DLGanchor("West"))
	Dialog.DLGAddElement(DLGCreatePushButton("close","eraseControl").DLGIdentifier("erase").DLGanchor("West"))	
	Dialog.DLGAddElement(DLGCreatePushButton(" store ","StoreClusters").DLGIdentifier("storeTableau").DLGanchor("West"))
		
	return Dialog
	}
	
TagGroup CreateAll(object self)
	{
	TagGroup Dialog = DLGCreatedialog("")

	Dialog.DLGAddElement(self.CreateHead())	
	Dialog.DLGAddElement(self.CreateView())	
	Dialog.DLGAddElement(self.Create_Plot())
	Dialog.DLGAddElement(self.CreateAutoClusteringBox())	
	Dialog.DLGAddElement(self.CreateClusteringBox())
	Dialog.DLGAddElement(self.Create_Finalize())	
	
	return Dialog	
	}

void Selecting(object self,number state)
	{
	self.SetElementIsEnabled("NewCluster",!State)
	self.SetElementIsEnabled("Delete",!State)
	self.SetElementIsEnabled("Correct",!State)
	self.SetElementIsEnabled("Replot",!State)	
	self.SetElementIsEnabled("Cancel",State)
	self.SetElementIsEnabled("ConfirmSelection",State)
	}


void EnablingButtons(object self,number state) //standard name used for INFO-mode
	{
	self.SetElementIsEnabled("scatter",State)
	self.SetElementIsEnabled("tuned",State)
	self.SetElementIsEnabled("AutoBox",State)	
	self.SetElementIsEnabled("design",State)	
	self.SetElementIsEnabled("finalize",State)
	
	self.SetElementIsEnabled("Design",!State)	
	self.SetElementIsEnabled("Load",!State)
	
	enablingState = state
	}	

number EnablingAll(object self)	//This is needed for INFO-mode
	{
	self.SetElementIsEnabled("scatter",1)
	self.SetElementIsEnabled("tuned",1)	
	self.SetElementIsEnabled("finalize",1)
	self.SetElementIsEnabled("AutoBox",1)
	self.SetElementIsEnabled("View",1)

	self.SetElementIsEnabled("design",1)
	self.SetElementIsEnabled("Load",1)
	
	return enablingState
	}

			
object init(object self,string Package,string Name)
	{
	MSAlabel = MSA112_Label() 
	
	self.MSA112_initUIFrame(self.CreateAll(),Package,Name)	
	
	try{self.EnablingButtons(0);}
	catch{break;}
		
	sparsity = self.MSA112P_sparsity()
	gap =  self.MSA112P_gap()
	elipsePoints = self.MSA112P_ellipsePoints()
	MaskCubed = self.MSA112P_MaskCubed()
	
	MSA112_reset()
	
	return self
	}

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

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

	taggroup tg1 =	self.AddSettingsLine_Int(SettingList,self.MSA112P_sparsity(),6)
	taggroup tg2 =	self.AddSettingsLine_Int(SettingList,self.MSA112P_gap(),6)
	taggroup tg3 =	self.AddSettingsLine_Int(SettingList,self.MSA112P_ellipsePoints(),6)
	taggroup tg4 =	self.AddSettingsLine_Check(SettingList,self.MSA112P_MaskCubed())
	
	MSA112_reset()
	
	object SettingsFrame = Alloc(UIframe).init(SettingList)
	if(SettingsFrame.Pose())
		{
		sparsity = self.SettingNumberParameter(tg1)
		elipsePoints = self.SettingNumberParameter(tg2)
		gap = self.SettingNumberParameter(tg3)
		MaskCubed = self.SettingNumberParameter(tg4)
		}
	}


void CreateControlTags(object self)
	{	
	ControlTags = NewTagGroup()
	ControlTags.TagGroupSetTagAsTagGroup("ScatterPlots",NewTagList())	
	}


image GetScatterPlot(object self, number scattN)
	{
	number ID = ControlTags.MSA112_getNumberfromList("ScatterPlots",scattN,"Scatter ID","L")

	return getImageFromID(ID)
	}


number CheckIfScatterExist(object self,number first,number second) 
	{
	for (number i = 0;i<scattN;i++)
		{
		number Comp1 = ControlTags.MSA112_getNumberfromList("ScatterPlots",i,"Comp 1","S")
		number Comp2 = ControlTags.MSA112_getNumberfromList("ScatterPlots",i,"Comp 2","S")
//result("\nscatter "+i+" "+Comp1+"-"+Comp2+ " new "+first+"-"+second)		
		number exist = ((comp1==first)&&(comp2==second)) || ((comp1==second)&&(comp2==first))
//result(" exist "+exist)		
		if(exist)	return 0
		}
		
	return 1
	}
	
void AddScatterPlot(object self,number first,number second) 
	{
	self.MSA112_Info("add Plot X-Y",0,70,\
	"adding extra"+\
	"\nscatter plot"+\
	"\nwith indicated"+\
	"\ncomponent indexes"+\
	"\nin addition to"+\
	"\ndefault '1-2'plot")
	
	//add new scatter plot
//result("\nSP first "+first+" second "+second)	
	if(self.CheckIfScatterExist(first,second)) 
		{
//result("\nadd scatterplot "+first +"-"+second)
		image MSAimage:= getImageFromID(MSAID)	
		TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,0)
	
		//create a copy with current cluster image
		TagGroup MatrixtagsCurr = NewTagGroup()
		TagGroupCopyTagsFrom(MatrixtagsCurr,Matrixtags)
		if(cluster.ImageIsValid()) MatrixtagsCurr.TagGroupSetTagAsArray(MSAlabel+":Cluster Mask",cluster)
											//replace cluster mask for temporary one
		//create scatterPLot	
		string Method = "PCA"	
		number ChosenCluster =-1		//all data points, not clustered
		rgbimage scatter := MSA112_PlotXY(MatrixTagsCurr,ChosenCluster,Method,first,second,sparsity)
		scatter.setName(MSAimage.getName()+" SP 1-2("+currCluster+")")	//(plot from MatrixTags doesnot set name)
		scatter.showimage()
	
		//wrap into Frame112
		imageDocument Scatdoc = scatter.ImageGetOrCreateImageDocument()
		Scatdoc.ImageDocumentShow()
		
		DocumentWindow Win = Scatdoc.ImageDocumentGetWindow()
		number closeID = Win.WindowAddWindowListener(self,"window_closed:ScatterClosed")
		
		alloc(MSA_ClusteringScatter).init(Scatdoc,MSA112_MSApath()+":EndMembers",first,second,self.ScriptObjectGetID())
//result(" - ScatterPlot "+first+"-"+second)	
			
		//make scatter tags
		ControlTags.MSA112_setNumberinList("ScatterPlots",scattN,"Scatter ID","L",scatter.imageGetID())
		//ControlTags.MSA112_setNumberinList("ScatterPlots",scattN,"Listener ID",closeID)
		ControlTags.MSA112_setNumberinList("ScatterPlots",scattN,"Comp 1","S",first)
		ControlTags.MSA112_setNumberinList("ScatterPlots",scattN,"Comp 2","S",second)
		
		scattN ++
result("\nscatter number "+scattN);
//ControlTags.TagGroupOpenBrowserWindow(0)		
		}
	else OKdialog("scatter plot "+first+"-"+Second+" already exists !!")	
	}

void scatterClosed(object self, number e_fl, DocumentWindow Win)
    {
	scattN --
result ("\nnumber of clusters "+clusterN)
	if(scattN==0) self.EnablingButtons(0)
	}	



image CheckMSAimage(object self)
	{
	image MSAimage:=getFrontImage()

	//Check if it is MSA container	
	TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,0)
	if(!MatrixTags.TagGroupIsValid()) exit(0)

	//Check if there are enough PCA components
	number chosenCluster = 0	//all data points
	number CompN =MSA112_ReadNumberComponents(MatrixTags,chosenCluster,"PCA")
	if(CompN<2)
		{
		OKdialog("At least 2 PCA components must be extracted !!")
		exit(0)		
		}
	
	return MSAimage
	}
	
void Design(object self)
	{
	self.MSA112_Info("design clusters",10,70,\
	"press this button"+\
	"\nto cluster data"+\
	"\nin front-most"+\
	"\nMSA container")
	
	image MSAimage :=self.CheckMSAimage()
	MSAID =MSAimage.ImageGetID()
	
	TagGroup MatrixTags = MSAimage.MSA112_GetMatrixTags(0)
	cluster := MSA112_GetCluster(MatrixTags)
	
	ClusterN =MatrixTags.MSA112_getNumberFromTags(MSAlabel+":clusters number","S")
//result ("\nnumber of clusters "+clusterN)

	if(clusterN>0)
		{
		if(OKCancelDialog("There are already clusters in MSA container.\nDesign from scratch ?")) 
			{
			cluster =0
			clusterN =0
			}
		else exit(0)	
		}
		
	self.CreateControlTags()
	
	self.AddScatterPlot(1,2)
	
	self.EnablingButtons(1)
	}

void PlotScatter(object self)
	{
	number First = self.LookUpElement("compF").DLGgetValue()
	number Second = self.LookUpElement("compS").DLGgetValue()
	
	self.AddScatterPlot(First,Second)		
	}
	
		
void NewCluster(object self)
	{
	self.MSA112_Info("new",10,200,\
	"create a new"+\
	"\ncluster by"+\
	"\nmanual selection"+\
	"\nof datapoints"+\
	"\nin front-most"+\
	"\nscatter plot")
		
	image scatter := getFrontImage()
	scatterID = scatter.ImageGetID()
//result("\nscatterID "+scatterID)

	TagGroup ScatterTags = MSA112_getScatterTags(scatter)
	CurrCluster = ClusterN +1
result("\nCurrent Cluster "+CurrCluster)
		
	object Elipse = alloc(MSA_EllipseSelector)
	ElipseID = Elipse.init(elipsePoints,gap).ScriptObjectGetID()

	self.Selecting(1)
//result("\nElipseID "+ElipseID)
	}

void CancelSelection(object self)
	{
	self.MSA112_Info("cancel",180,280,\
	"cancel current"+\
	"\nselection of"+\
	"\ndatapoints"+\
	"\n(ellipse selector"+\
	"\nwill disappear)")
	
	object Ellipse =  GetScriptObjectFromID(ElipseID)
	
	image mask := ellipse.getMask()
	mask.deleteImage()
	
	if(Ellipse.ScriptObjectIsValid()) Ellipse.StopSelection()  
	ElipseID = 0
	
	//restore global parameters
	scatterID   = 0
	currCluster = 0
	correction =0
	
	Ellipse.selectScatterPlot()
	self.Selecting(0)
	}
	
	
void RepaintAllScatterPlots(object self,image mask,number clusterC)
	{
	for(number i=0;i<scattN;i++)
		{
		try{
			image scatter :=self.GetScatterPlot(i)
			TagGroup ScatterTags = MSA112_getScatterTags(scatter)	
			
			//update mask in scatterPlot
			image StoredMask := MSA112_GetImageFromTags(ScatterTags,"mask")
			StoredMask = tert(Mask==1,clusterC,StoredMask)
			ScatterTags.MSA112_setImageInTags("mask",StoredMask)
			
			//repaint scatterPlot				
			image coorX := MSA112_GetImageFromTags(ScatterTags,"Coordinates-X") 
			image coorY := MSA112_GetImageFromTags(ScatterTags,"Coordinates-Y") 	

			MSA112_RepaintCluster(scatter,StoredMask,coorX,coorY,clusterC)
			}
		catch
			{
			break
			//scatter plot was deleted somehow without registration in list
			}			
		}
	}
		
void ConfirmSelection(object self)
	{
	self.MSA112_Info("confirm",340,200,\
	"confirm current"+\
	"\nselection of"+\
	"\ndatapoints"+\
	"\n(selected points"+\
	"\n(will be painted"+\
	"\nin sequential colors"+\
	"\naccording pallet")
	
	//currCluster needed as global parameters because it is not transmitted among 'new', 'cancel', 'confirm'

	object Ellipse =  GetScriptObjectFromID(ElipseID)
	if(!Ellipse.ScriptObjectIsValid()) exit(0)

	//update cluster 
	image mask := ellipse.getMask()
	
	//get scatter and its tags
	image scatter := scatterID.FindImageByID()
	TagGroup ScatterTags = MSA112_getScatterTags(scatter)	
						//thrown if scatterPlot was closed	
	//update cluster
	
	number width =ScatterTags.MSA112_GetNumberFromTags("width","L")
	//number height =ScatterTags.MSA112_GetNumberFromTags("height","L")	
	image clusterNew = imageclone(cluster)
	clusterNew[0,irow*width + icol] = Mask
	cluster = tert(clusterNew==1,CurrCluster,cluster)

	//repaint all scatterPlots		
	self.RepaintAllScatterPlots(mask,currCluster)

	//delete displayed mask image
	mask.deleteImage()
//result("\n"+mask.ImageisValid()+" "+storedmask.ImageisValid());
	
	//clean up ellipse
	Ellipse.StopSelection()  
	ElipseID = 0	
	
	//end ellipse
	Ellipse.selectScatterPlot()
	self.Selecting(0)
	
	if(!correction) ClusterN ++	//otherwise it was a correction of existing cluster
result("\nClusterN "+ClusterN)	
	//reset global parameters
	scatterID = 0
	currCluster = 0	
	correction = 0
//cluster.MatrixTranspose().showimage()	
	}	
	
void DeleteCluster(object self)
	{	
	self.MSA112_Info("delete",80,320,\
	"delete last"+\
	"\npreviously "+\
	"\ndesigned"+\
	"\ncluster")
	
	if(ClusterN<=0) {OKdialog("no clusters !! ");exit(0);}

	if(OKcanceldialog("delete last cluster ("+MSA112_ColorString(ClusterN)+") ?"))
		{		
		number ClusterD = ClusterN
//result("\nto delete "+ClusterD);
		
		//delete in cluster
		cluster = tert(cluster==ClusterD,0,cluster)
//cluster.matrixTranspose().showimage()	
	
		//delete in mask
		image scatter0 := self.GetScatterPlot(0)
		
		image mask := MSA112_GetImageFromTags(MSA112_getScatterTags(scatter0),"mask")
		mask = tert(Mask==ClusterD,1,0)
		
		self.RepaintAllScatterPLots(mask,0)		
		
		ClusterN--
		}
		
	}	

number ChooseCluster(object self,number clusters)
	{
	if(clusters<=0) throw("no clusters !! ")

	TagGroup dialog = DLGCreateDialog("")
	dialog.DLGAddElement(DLGCreateLabel("choose cluster:"))
	
    TagGroup entries
    TagGroup choice = DLGCreateChoice(entries)
    dialog.DLGAddElement(choice).DLGExpand("X").DLGFill("X")
    for(number i=1;i<=clusters;i++) 
		{
        string clusterLabel ="cluster "+i+" ("+MSA112_ColorString(i)+")"
        entries.DLGAddChoiceItemEntry(clusterLabel)
		}
		
	object frame = alloc(uiframe).init(dialog)
    if(!frame.Pose()) exit(0)
    number chosen = choice.DLGGetValue() 

	return (Chosen+1)	//choice item are 0,1,2... clusters are 1,2,3...
	}
	
void CorrectCluster(object self) 
	{
	self.MSA112_Info("correct",220,320,\
	"correct one of"+\
	"\npreviously"+\
	"\ndesigned"+\
	"\ncluster")
	
	image scatter := getFrontImage()
	scatterID = scatter.ImageGetID()
	TagGroup ScatterTags = MSA112_getScatterTags(scatter) //this is needed to ensure that scatter plot is in-front

	CurrCluster = self.ChooseCluster(clusterN)
//result("\ncorrecting cluster "+currCluster)	

	correction =1
	
	object Elipse = alloc(MSA_EllipseSelector)
	ElipseID = Elipse.init(elipsePoints,gap).ScriptObjectGetID()
	
	self.Selecting(1)
	}

		
void FindAutoClusters(object self)
	{
	self.MSA112_Info("find",-10,120,\
	"automatic clustering"+\
	"\nof data using the"+\
	"\nk-mean algorithm")
	
	}

	
	//display previously calculated spectra and masks
											//may be ControlTags or "temDM MSA:" in MatrixTags
void ShowMasksAndSpectra(object self,TagGroup GivenTags,image AvSpecGlobal,image MaskTemplate,string DataName,number clusterN)
	{
	number width,height
	MaskTemplate.getSize(width,height)
		
	image CubeMask
	if(MaskCubed)
		{	
		CubeMask := integerimage(DataName+" masks",2,0,width,height,clusterN)
		
		//transfer calibration
		number ScaleX,ScaleY,originX,originY
		string unitX,unitY
		MaskTemplate.ImageGetDimensionCalibration(0,OriginX,ScaleX,unitX,1)
		MaskTemplate.ImageGetDimensionCalibration(1,OriginY,ScaleY,unitY,1)	
		CubeMask.ImageSetDimensionCalibration(0,OriginX,ScaleX,unitX,1)	
		CubeMask.ImageSetDimensionCalibration(1,OriginY,ScaleY,unitY,1)		
		}

	//check if Average spectra were calculated
	number SpecCalculated
	image AvSpecLast :=GivenTags.MSA112_getImagefromList("clusters",clusterN,"Average Spectrum")
	if(AvSpecLast.ImageIsValid()) SpecCalculated =1
	
	imagedisplay imdisp
	if(SpecCalculated)
		{
		AvSpecGlobal.showimage()
		AvSpecGlobal.setName(DataName+" average spectra")
		AvSpecGlobal.showimage()
		imdisp = ImageGetImageDisplay(AvSpecGlobal,0)
		imdisp.LinePlotImageDisplaySetLegendShown(1)
		ImageDisplaySetSliceLabelByID(imdisp,ImageDisplayGetSliceIDByIndex(imdisp,0),"average")
		}
		
	//check if clusters are stored in the new format
	number OldVersion
	image MaskClusterTest :=GivenTags.MSA112_getImagefromList("clusters",1,"Mask")	
	if(!MaskClusterTest.ImageIsValid())	//reserve path for old versions
					{
					OldVersion =1
result("\nreserve path for older version");
					number Npoints = GivenTags.MSA112_getNumberFromTags("pixels","L")

					image mask1D :=integerImage("",2,0,1,Npoints)			
					GivenTags.TagGroupGetTagAsArray("Cluster Mask",mask1D)	//the clustering info from global cluster array

					MaskClusterTest :=integerimage("",2,0,width,height)
					for(number j=0;j<height;j++)
						{
						MaskClusterTest[irow,j] = mask1D[j*width,0,(j+1)*width,1]
						}				
					}		
	
	for(number currCluster = 1;currCluster <= clusterN; currCluster++)
		{
result("\ncurrCluster "+currCluster)		
		//getCluster mask
		image MaskCluster :=imageClone(MaskTemplate)
		
		if(!OldVersion) MaskCluster :=GivenTags.MSA112_getImagefromList("clusters",currCluster,"Mask")	
		else
					{
					//reserve path	
					
					MaskCluster =tert(MaskClusterTest==currCluster,1,0)			
					}
			
		if(MaskCubed) CubeMask[0,0,currCluster-1,width,height,currCluster] =MaskCluster
		else
			{
			MaskCluster.setName(DataName+" cluster "+currcluster+" mask")
			MaskCluster.showimage()
			}			
		//get cluster Average spectrum	
		image AvSpec
		if(SpecCalculated) AvSpec :=GivenTags.MSA112_getImagefromList("clusters",currCluster,"Average Spectrum")	
		
		if(!AvSpec.ImageIsValid())	
					{
					//reserve path
			
					AvSpec :=AvSpecGlobal.imageClone()
			
					GivenTags.TagGroupGetTagAsArray("clusters:["+currCluster+"]:Average Spectrum",AvSpec)
					tagGroup MatrixTags =newTagGroup()
					MatrixTags.TagGroupSetTagAsTagGroup(MSA112_Label(),givenTags)
					AvSpec =AvSpec.MSA112_RestoreWeightedSpectrum(MatrixTags,currCluster)
					}
		else result("\nWARNING: Average spectrum in cluster "+currCluster +" was not calculated !!")
	
		if(AvSpec.ImageIsValid())
			{
			//add to plot
			imdisp.imageDisplayAddImage(AvSpec,"cluster "+currCluster)
			}
		}
	
	if(MaskCubed) CubeMask.showimage() 	
	}
	
image MakeCalibratedMask(object self, TagGroup MatrixTags)
	{
	//read size info 
	number N,depth,width,height
	MatrixTags.MSA112_GETSISizes(N,depth,width,height)
	
	
	//read calibration
	number ScaleX,ScaleY,originX,originY
	string unitX,unitY
	MatrixTags.MSA112_GetCalibration(ScaleX,originX,unitX,"X")
	MatrixTags.MSA112_GetCalibration(ScaleY,originY,unitY,"Y")
	
	image Mask := integerimage(" mask",2,0,width,height)
	Mask.ImageSetDimensionCalibration(0,OriginX,ScaleX,unitX,1)	
	Mask.ImageSetDimensionCalibration(1,OriginY,ScaleY,unitY,1)
	
	return Mask
	}
	
	
	//makes spectra and masks, put it into ControlTags
void MakeMasksAndSpectra(object self)
	{	
	image MSAimage := MSAID.FindImageByID()
	string DataName = MSAimage.getName()
	TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,0)

	//check if clustered
	if(ClusterN==0) {OKdialog("data are not clustered !!");self.EndThread("ShowClusters",WaitingID);exit(0);}	

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

	//get global average
	image AvSpecGlobal:= MSA112_GetAverageSpectrum(MatrixTags)
	
	//make mask
	image Mask := self.MakeCalibratedMask(MatrixTags)

	
	//recast cluster into mask
	for(number j=0;j<height;j++)
		{
		Mask[irow,j] = Cluster[j*width,0,(j+1)*width,1]
		}

	//prepare a list of clusters in ControlTags
	TagGroup tg
	if(ControlTags.TagGroupGetTagAsTagGroup("clusters",tg))	TagGroupDeleteAllTags(tg)	//delete previous clusters
	ControlTags.TagGroupSetTagAsTagGroup("clusters",NewTagList())
	ControlTags.TagGroupGetTagAsTagGroup("clusters",tg)
	TagGroup NullCluster = NewTagGroup()
	tg.TagGroupAddTagGroupAtEnd(NullCluster)	//fictive 0-cluster
	
	image DataMatrix = MSA112_GetMSAMatrix(MatrixTags,0)
	
	//set cluster masks and calculate average Spectra
	try{
		for(number currCluster = 1;currCluster <= clusterN; currCluster++)
			{
			string ClusterLabel = MSA112_GetClusterLabel(currCluster)
			image AvSpec
			number kPoint	
			MSA112_TakeCluster(dataMatrix,cluster,currCluster,0,AvSpec,kPoint)//return redDataMatrix (NOT used)
//result("\n"+currCluster +" "+kN)

			//restore weighting
			Avspec = AvSpec.MSA112_RestoreWeightedSpectrum(MatrixTags,0)

			image MaskCluster =Mask
			MaskCluster =tert(MaskCluster == currCluster,1,0)
			
			//store AvSpectrum and mask in ControlTags 
			ControlTags.MSA112_setNumberInList("clusters",currCluster,"pixels","L",kPoint)	//this extends a list
			ControlTags.MSA112_setImageinList("clusters",currCluster,"Average Spectrum",AvSpec)
			ControlTags.MSA112_setImageinList("clusters",currCluster,"Mask",MaskCluster)			
			}		
//ControlTags.TagGroupOpenBrowserWindow(0)
	
		self.ShowMasksAndSpectra(ControlTags,AvSpecGlobal,Mask,DataName,clusterN)
		}
	catch {self.EndThread("MakeMaps",WaitingID);}
	
	self.EndThread("MakeMaps",WaitingID)		
	}
	
void BuildMaps(object self)
	{
	self.MSA112_Info("make maps",80,360,\
	"generate"+\
	"\nmaps and average"+\
	"\nspectra of designed"+\
	"\nclusters")
		
	WaitingID = self.StartThreadFromDLG("MakeMasksAndSpectra","MakeMaps")
	}

void Load(object self)
	{
	self.MSA112_Info("load",340,70,\
	"press this button"+\
	"\nto load previously"+\
	"\ndesigned clusters"+\
	"\nin front-most"+\
	"\nMSA container")
	
	image MSAimage := getFrontImage()
	MSAID =MSAimage.ImageGetID()
	string DataName = MSAimage.getName()
	TagGroup MatrixTags = MSA112_GetMatrixTags(MSAimage,0)
	
	cluster := MSA112_GetCluster(MatrixTags)
	
	clusterN =MatrixTags.MSA112_getNumberFromTags(MSAlabel+":clusters number","S")	
	if(clusterN==0) 
		{
		OKdialog("there are no clusters\n in MSA container !!")
		exit(0);
		}
		
	//get global average
	image AvSpecGlobal:= MSA112_GetAverageSpectrum(MatrixTags)
	
	//make mask
	image Mask := self.MakeCalibratedMask(MatrixTags)
		
	TagGroup GivenTags	//"temDM MSA:" tags"
	MatrixTags.TagGroupGetTagAsTagGroup(MSAlabel,GivenTags)
	//GivenTags.TagGroupOpenBrowserWindow(0)
	
	try{
	self.ShowMasksAndSpectra(GivenTags,AvSpecGlobal,Mask,DataName,clusterN)	
		}
	catch break
	
	self.CreateControlTags()

	self.AddScatterPlot(1,2)
	
	for(number currCluster;currCluster<=clusterN;currCluster++) self.RepaintAllScatterPlots(mask,currCluster)	 
	
	self.EnablingButtons(1)
		
	}

	
void StoreClusters(object self)
	{	
	self.MSA112_Info("store",270,360,\
	"store currently"+\
	"\ndesigned clusters"+\
	"\nin MSA container")
	
	image MSAimage := MSAID.FindImageByID()

	TagGroup MatrixTags = MSAimage.MSA112_GetMatrixTags(0)
	MSAimage.MSA112_setCluster(cluster)	//this deletete old clusters and set empty new ones in cluster list

	TagGroup ClusterList 
	MatrixTags.TagGroupGetTagAsTagGroup(MSAlabel+":clusters",ClusterList)
	
//ClusterList.TagGroupOpenBrowserWindow(0)

	//store new cluster information	FOR THE MOMENT NOT FOUND A SMOOTH WAY TO COPY ITEMS INTO ANOTHER LIST
	for(number currCluster =1 ;currCluster<= clusterN; currCluster++)
		{
result("\ncurrCluster "+currCluster)		
		TagGroup NewTags = NewTagGroup()
		number kPoints =ControlTags.MSA112_getNumberfromList("clusters",currCluster,"pixels","L")
		if(kPoints==0)	//average spectar were not calculated
			{
			image clusterTemp = cluster.ImageClone()
			clusterTemp =tert(clusterTemp==currCluster,1,0)
			kPoints = sum(clusterTemp)
			}
		ClusterList.MSA112_setNumberInTags("["+currCluster+"]:pixels","L",kPoints)
		
		image AvSpec :=ControlTags.MSA112_getImagefromList("clusters",currCluster,"Average Spectrum")
		if(AvSpec.ImageIsValid()) ClusterList.MSA112_setImageinTags("["+currCluster+"]:Average Spectrum",AvSpec)

		image Mask :=ControlTags.MSA112_getImagefromList("clusters",currCluster,"Mask")
		if(Mask.ImageIsValid()) ClusterList.MSA112_setImageinTags("["+currCluster+"]:Mask",Mask)	
		}
//ClusterList.TagGroupOpenBrowserWindow(0)		
	}
	
	
void CloseScatterPlots(object self)
	{
	//make scatter tags
	number ScattToDelete = scattN 
	for(number i=0;i<ScattToDelete;i++)
		{
		number ScattID = ControlTags.MSA112_getNumberfromList("ScatterPlots",i,"Scatter ID","L")
//result("\n"+i+" ScattID "+ScattID)		
		image scatter := ScattID.GetImageFromID()
		scatter.deleteImage()
		}
	ControlTags.TagGroupDeleteAllTags()
	
	self.EnablingButtons(0)
	}
	
void eraseControl(object self)
	{
	self.MSA112_Info("erase",190,360,\
	"stop designing"+\
	"\ncluster and close"+\
	"\nall scatter plots"+\
	"\nwithout saving")
	
	if(OKcancelDialog("do you want to close\ncurrent clustering\nwithout storing ?")) 
		{	
		self.CloseScatterPlots()
		}
	}
	
	

		
}

void createAll()
{
alloc(lunchClustering).init(MSA112_MSApath(),"MSA clustering") 

}

createAll()
