{
This program will evaluate all images with filenames and parameters given in the file:
YYYYMMDD_GeneralAVG_REJ.ini
and create Average and Standard Deviation and Standard Error Images in the selected directory <Path>/Mean/
Input Parameters in the ini file:
Delay# 			 --> enter the file header convention <FILE HEADER><_><Index>.tif
FirstFrame#		 --> enter the index number for start
LastFrame# 		 --> enter the index number for end
Nmax#			 --> threshold for saturated pixels or pixels with anomalously high amplitude

Program requires ANY image of the same size as processed images (usually some mask image)

Program DO NOT require initialization file
After processing the temp directory MUST be deleted 

File names for temporary files in temp directory are

<"M"><Fle header><_><index>.tif
<"B"><Fle header><_><index>.tif 
Sum.tif
AB.tif


The input parameters requested from operator:

- 'Select IMAGE for size definition' --> select the file header 
- Browse and select directory where images are stored
- Select the appropriate ini file

Parameters hard coded into the script:
- 'Enter the NUMBER of LOOPS' 	   --> number of circles of rejection 
- 'Enter the REJECTION CRITERIA'   --> rejection criteria in sigmas 


All averaged and standard deviation images stored for each loop
Naming convention for output files:
<File header><"_"><av><loop index> 	--> averaged file
<File header><"_"><sd><loop index>	--> standard deviation file

Created by Vladimir Lobastov 13.01.2002
Update by Andreas Gahlmann 06.27.20009}



const
  	 	  CommonDlgsLib = 'VppCommonDlgs.dll' ;	 	{DLL for common dialog} 
		  P ='D:\Data\UED4_Data_processed\Utilities_UED4\Delays\*.ini'; 		 	  //default directory for INI file
		  InPath='D:\Data\UED4_Data_processed\28082003\';			 	{default path for images}
		  Path2='D:\Data\UED4_Data_processed\Utilities_UED4\';		{default path for initial mask image}
		  Qwst='Do you want to use Patch for saturated pixels?';
		  		  
		  function BrowseFolders( Path:pointer ) : integer ; external CommonDlgsLib ;
		  

var 
	CR;		  							{rejection criteria}
	ind, jnd, k;						{indices}
	Loops;
	First, Last;						{first and last filenames to process}
	delay, FirstFrame, LastFrame, Nmax; {handles}
	im;	   								{filename counter}
	F,N;		  						{first and last number of images to process}
	FHead;	  							{file header}
	xSize, ySize;						{sizes of the images}	
	Img;								{image for size definition}
	CH;
	Path;								{path for images}
	TR;
	Stdev, SEM;							{standard deviation and standard error image}
	Sel;
	

function FieldedFileName(FName, ind);
  begin
    FieldedFileName:= FName+'_'+ReplaceStr(Str(ind:4),' ','0',rs_ReplaceAll);		//Attach the index count (with leading zeros) to the file name 
  end; 
	
{
******************************************************************
********************** function Select ***************************
******************************************************************
This function return a full file name for a file 
}	 	 
function SELECT;											
		var
   		   nName; Name, ix;
   		   Choice, nDIR;
		begin
	 		 Name:=FindFirstFile(P, fa_Archive);				  	 	 		//Find the first ini file in the delays directory 
	 		 nName:=ExtractFileName(Name);										//Convert the file name and the extension to a string
	 		 nDIR:= ExtractFilePath(Name);										//Return the drive and directory portions of a file name including the trailing backslash
			 ix:=0;																//initialize the variable ix to value of zero
	  		 
			 while StrLen(Name) > 0 do											//If there is a file in the directory, do

	  		 	   begin
	  	   		   		Name:=ExtractFileName(FindNextFile) ;					//Finde the next ini file in the delays directory
		   				nName:=nName+';'+Name;									//Augment the nName string with the next file name
					 if ix>100 then halt('Too many Files in Directory');   		//Stop, if there are more than 100 files
					 	ix:=ix+1;			  	   		 						//Increase the counter ix by 1
	 				end; 

	 			 if SelectString( 'Select File',nName , Choice ) >= 0 then		//If a selection among nName strings is made from the dialog box, then
	 			 	begin
			 			 SELECT:=nDIR+Choice;		  		   	 	  			//Initialize SELECT to the selected ini file
	 				end	
	 			else
	 				begin 
	 	 	  			  WriteInfo('No Selection made! Restart program! ');	//Inform the user that no selection was made
		 	  			  halt;					  						 		//abort the program
	 				end; 
		end;
//----------------------> end of function SELECT <-----------------------------------		
	
	
{************************************************************************}
{ ***	                      Procedure InitMASK	   				  ***}									   
{************************************************************************}
{This procedure will create array of mask and new data images }
procedure InitMASK;
var
	MI0, BI;
	ind;
	i;	  
 
  begin
  	   	  	{if Query(Qwst) = id_Yes then  
			begin			   
			   Open( Path2+'SpotPatch.tif', MI0) ; 	   		   			  			//Use a mask image to reject pixels from the start
			end   
			else}
			   Open( Path2+'BlankBinaryInvUED4.tif', MI0) ;    			   			//Read a inverse blank mask image from disk (all pixels 1)   
			   
{---->}	for ind:=F to N do	   
		   begin
			   i:=FieldedFileName('',ind);											//Convert expression (ind) to a string (with leading zeros)
   			   CreateDir(Path+'temp\');			 		  				  	   	 	//create subdirectory for output
			   Save(MI0, Path+'temp\'+'M'+FHead+i+'.tif');  		   				//Save the ith sample mask image	
			   Open(Path+FHead+i+'.tif',BI);										//Read the ith sample image from disk
			   Save(BI, Path+'temp\'+'B'+FHead+i+'.tif');							//Save the ith sample image
			   WriteStatus('Initiating... '+Str(ind));								//Display a message in the status bar
			   Delete(BI);				  											//Delete the image BI from the desktop
			   Delete(i); 															//Delete the string i		   					
		   end;
			   Delete(MI0);	   		   												//Delete the image MIO from the desktop
  end;		   					
  {-----------------------> end of procedure InitMASK}

{************************************************************************}
{ ***	                      Procedure ABI	  		   				  ***}									   
{************************************************************************}
{This procedure calculates mean image}
procedure ABI(k);
var 
   AB,AVG;
   NI,MI,BI;
   i;		  
   Zeros;
   FNAME;
begin
	 	 Open( Path2+'BlankDoubleUED4.tif', AB) ; 						  			//open blank Single image (all pixels 0)
		
{---->}for ind:=F to N do
		begin
			   i:=FieldedFileName('',ind);											//Convert expression (ind) to a string (with leading zeros)
 					Open(Path+'temp\'+'B'+FHead+i+'.tif',BI);						//Read the ith sample image from disk			
			   		AB:=AB+BI;														//Add the blank image and the sample images
					WriteStatus('Summed...  '+ Str(ind));							//Display a message in the status bar
			   	   //	Show(AB, 'Summing');											//Display the image variable AB on the desktop
			//     Delete(BI); 														//Delete the image BI from the desktop
				 Delete(i);															//Delete the string i
		end;
				 Save(AB,Path+'temp\'+'AB'+'.tif');									//Save the sum of sample images
				 Delete(AB);														//Delete the image AB from the desktop

	 	 Open( Path2+'BlankShortIntUED4.tif', NI) ; 								//Open blank ShortInt image (all pixels 0)
{---->}
	for ind:=F to N do
		begin		 
			   i:=FieldedFileName('',ind);	  	  									//Convert expression (ind) to a string (with leading zeros)
					Open(Path+'temp\'+'M'+FHead+i+'.tif',MI);						//Read the ith sample mask image from disk
					NI:=NI+MI;														//Add the sample mask images
				//	Show(NI,'NI');													//Display the image variable NI on the desktop
			   		WriteStatus(Str(ind));		
			    // Delete(MI);														//Delete the image NI from the desktop
				 Delete(i);															//Delete the string i							   
		end;			
					Zeros:= ((NI)= 0);												//Identify the zero pixels in the mask image
				Open(Path+'temp\'+'AB'+'.tif',AB);									//Read the sum sample image from disk				
				AVG:=Double(AB/(NI+Zeros))*(not Zeros);								//Calculate the average of all pixels except the zero pixels in the mask image
			    Save(AVG, Path+'temp\'+FHead+'_av'+Str(k)+'.tif');					//Save the output average files
		
			Delete(AVG);															//Delete the variable AVG 	
			Delete(Zeros);															//Delete the variable Zeros
			Delete(AB);																//Delete the variable AB
			Delete(NI);																//Delete the variable NI
	end;
{------------------------------------>end of procedure --ABI--}  		
	
{************************************************************************}
{ ***	                      Procedure STD	  		   				  ***}									   
{************************************************************************}
{This procedure calculates standard deviation image}	
procedure STD(k);
var
		  A;
		  i;
		  NI,BI,MI,SD, SE;
		  Sum;
		  Zeros;		 
  begin

  	    Open( Path2+'BlankDoubleUED4.tif', Sum) ; 						  			//open blank Single image (all pixels 0)
    	Open(Path+'temp\'+FHead+'_AV'+Str(k)+'.tif',A);								//open the average file				
{---->}								   				  
	for ind:=F to N do
		begin
			   i:=FieldedFileName('',ind);			  								//Convert expression (ind) to a string (with leading zeros)
			   WriteStatus(i);														//Display a message in the status bar
			   	     		  Open(Path+'temp\'+'B'+FHead+i+'.tif',BI);				//Read the sample images from disk
			   	     		  Sum:=Sum+(BI-A)*(BI-A);								//Calculate the sum of residuals			
					Delete(BI);														//Delete the variable BI
					Delete(i);														//Delete the variable i
		end;
					Delete(A);														//Delete the variable A
				 Save(Sum,Path+'temp\'+'Sum'+'.tif');								//Save the sum of residuals image
				 Delete(Sum);		  												//Delete the variable Sum


	 	 Open( Path2+'BlankShortIntUED4.tif', NI) ; 								//Open blank ShortInt image (all pixels 0)
{---->}
	for ind:=F to N do		
		begin
			   i:=FieldedFileName('',ind);	  	  									//Convert expression (ind) to a string (with leading zeros)
				   	 		  Open(Path+'temp\'+'M'+FHead+i+'.tif',MI);				//Read the ith sample mask image from disk	
				   			  NI:=NI+MI;	 										//Add the sample mask images, holds the number of pixels contributing to the average 
					 Delete(MI);													//Delete the variable MI
					 Delete(i);														//Delete the variable i
		end;	
				Open(Path+'temp\'+'Sum'+'.tif',Sum);								//Open the sum of residuals
			Zeros:= ((NI-1) <= 0);													//Identify the pixels values <=1 in the mask image NI							
			CH:=((NI+Zeros-1) <=0);													//Identify the pixels values <=0 in the mask image NI
			SD:=Double(sqrt(Sum/((NI+Zeros-1+CH)))*(not Zeros)); 					//Calculate the standard deviation of all pixels except the zero pixels in the mask image.  ---> {floating point error}
			    Save(SD, Path+'temp\'+FHead+'_sd'+Str(k)+'.tif');					//Save the output standard deviation files
			SE:=Double(SD/Sqrt(NI+CH));
				Save(SE, Path+'temp\'+FHead+'_se'+Str(k)+'.tif');					//Save the output standard error of the mean files
				Save(NI, Path+'temp\'+FHead+'_ni'+Str(k)+'.tif');					//Save the output standard error of the mean files
			Delete(SD);	 															//Delete the variable SD
			Delete(SE);
			Delete(Sum);															//Delete the variable Sum
			Delete(Zeros);															//Delete the variable Zeros
			Delete(NI);																//Delete the variable NI
			Delete(CH);																//Delete the variable CH
  end;
{------------------------------------>end of procedure --STD--}  	

{************************************************************************}
{ ***	                      Procedure Reject 		   				  ***}									   
{************************************************************************}
{This procedure will reject pixels not satisfying chosen criteria of CR*sigma}

procedure Reject(k);
var
		  A,S;
		  j;
		  MI,BI,RJ;
begin
{---->}	
	for ind:=F to N do	
		begin
			   j:=FieldedFileName('',ind);		  		 		  	   		  	   	//Convert expression (ind) to a string (with leading zeros)
   		 		Open(Path+'temp\'+'B'+FHead+j+'.tif',BI);							//Read the sample images from disk
			    Open(Path+'temp\'+FHead+'_SD'+Str(k)+'.tif',S);						//Read the standard deviation image from disk					
			    Open(Path+'temp\'+FHead+'_AV'+Str(k)+'.tif',A);						//Read the average image from disk								   
			   		ConvertType( BI,typ_Double ) ;
					RJ:= ((A-CR*S) < BI) and (BI< (A+CR*S)) and ( BI < TR );			//Identify which pixels to keep in each sample image
					Delete(A);		  				 		   	   	 	 			//Delete the variable A
					Delete(S);						   								//Delete the variable S
			   		   WriteStatus('Frame= ' + Str(ind)+'   Total rejected pixels=  '+ Str(SumOf(not RJ)));	   //Display a message in the status bar
			   		BI:=BI*RJ;			   	   					  		   			//Reject pixels in the sample image
			   			   Save(BI, Path+'temp\'+'B'+FHead+j+'.tif'); 				//Save updated sample images 
					Delete(BI);														//Delete the image BI from the desktop
			   				Open(Path+'temp\'+'M'+FHead+j+'.tif',MI);				//Read the mask images from disk
			   		MI:=MI and RJ;													//Reject the same pixels in the mask image as well
			   			   Save(MI, Path+'temp\'+'M'+FHead+j+'.tif');				//Save updated mask images    
					Delete(MI);														//Delete the variable MI
					Delete(RJ);														//Delete the variable RJ
					Delete(j);														//Delete the variable j
		end;
end;
{------------------------------------>end of procedure --Reject--}  	


{************************************************************************}
{ ***	                      Function GetFolder	   				  ***}									   
{************************************************************************}

  
function GetFolder( InitPath ) ;
{ Opens the folder browse dialog and returns a folder path }
{ InitPath may be used to set the initial folder (set to '' otherwise) }
{ Returns a null string if Cancel is pressed }

const
  BufSize = 255 ;
  
var
  FolderName ;

begin
  FolderName := InitPath + StringOfChar( ' ',BufSize - Length( InitPath ) ) ;		//Initialize the variable Folder Name
  if BrowseFolders( FolderName ) <> 0 then 			   		   			  	 		//If a folder is selected
    GetFolder := Trim( FolderName )	  												//Return the folder path
else
    GetFolder := '' ;			  													//Return the Null String
end;  { GetFolder }

{------------------------------------>end of Function --GetFolder--}  	

{
 ************************************************************************
 ************************************************************************
 ***                                                                  ***
 ***	                      Main program							  ***
 ***																  ***
 ************************************************************************ 
 ************************************************************************
}

var
  Avg ;	
begin
		CR:=3;								//rejection criteria in sigma's to satisfy Chauvenets condition, see an Introduction to Error analysis.
		F:=1;								//the first frame to process
		N:=100;								//the last frame to process
		Loops:=2;							//selection of number rejection runs
		FHead:='C_';						//file header
		TR:=60000;							//upper threshold for rejection
		xSize:=512;							//size of image in pixel in x dimension					  
		ySize:=512;							//size of image in pixel in y dimension
				
                if GetNumImages = 0 then halt( 'This program requires a desktop image for size definition' ) ;	  //Return the number of images on the desktop
                   SelectImage( 'Select IMAGE for size definition',Img ) ;			   	 			  //Select an image from a list of desktop images
                if IsNull( Img ) then halt( 'No image was selected' ) ;	 							  //Return true if the variable Img is uninitialized

				   Path:=GetFolder( InPath )+'\';	  	  			  								  //Use the default directory or select a new one
                if ( Path = '\' ) then halt( 'Directory not selected' ) ;
		//WriteInfo(Path);					   
                          xSize:=GetXSize(Img);						  	 							  //Return the x-dimension of the size definition image
                          ySize:=GetYSize(Img);														  //Return the y-dimension of the size definition image
						  Free(Img);																  //Release the memory used by the variable Img

	 		Sel:=SELECT;												  			// selector for initialization file
			First:=Val(ReadPrivateINIString( Sel, 'TotalDelays', 'First'));	   			//first filename to process, Convert a string expression into a numerical value
			Last:=Val(ReadPrivateINIString( Sel, 'TotalDelays', 'Last'));	   			//last filename to process, Convert a string expression into a numerical value
			  for im:=First to Last do														//for all filenames to process, do
   	   		   	   begin       
				   	   delay:='delay'+Str(im);   								//index the handles with consecutive numbers
					   FirstFrame:='FirstFrame'+Str(im);
					   LastFrame:='LastFrame'+Str(im);
					   Nmax:='Nmax'+Str(im);
	   		   		   FHead:=ReadPrivateINIString( Sel, 'FileNames', delay);					  //read the imth image name		 	   		
					   F:=Val(ReadPrivateINIString( Sel, 'FileNames', FirstFrame));				  //the first frame to average
   					   N:=Val(ReadPrivateINIString( Sel, 'FileNames', LastFrame));				  //the last frame to average
					   TR:=Double(Val(ReadPrivateINIString( Sel, 'FileNames', Nmax)));				  	  //the rejection threshold

					  {GetString('Enter the FILE HEADER',FHead);									  //Display a dialog box and prompt the user to enter a string
						  GetNumber('Enter the FIRST frame',F);						  				  //Display a dialog box and prompt the user to enter a number
						  GetNumber('Enter the LAST frame',N);				   
						  GetNumber('Enter the NUMBER of LOOPS',Loops);
						  GetNumber('Enter the REJECTION CRITERIA',CR);						  						  
						  GetNumber('Enter the REJECTION TRESHOLD',TR);			
						  }	
						  InitMASK;		   	   			  				{This procedure will create array of mask and new data images}
		for k:=0 to Loops do
			begin
				ABI(k);													{This procedure calculates the mean image}	
				STD(k);													{This procedure calculates standard deviation image}
			if not (k=Loops	) then
				Reject(k);	  	  										{This procedure will reject pixels not satisfying chosen criteria of CR*sigma}
			end;
					CreateDir(Path+'Mean\');			 		  				  	   	  		   	 //create subdirectory for output
					Open(Path+'temp\'+FHead+'_AV'+Str(k)+'.tif',Avg);								 //Read the average image from disk
					//Show(Avg, 'Avg');																 //Display the image variable Avg on the desktop
			        Open(Path+'temp\'+FHead+'_sd'+Str(k)+'.tif',Stdev);								 //Read the standard deviation image from disk
				    //Show(Stdev, 'Stdev');															 //Display the image variable Stdev on the desktop
					Open(Path+'temp\'+FHead+'_se'+Str(k)+'.tif',SEM);								 //Read the standard deviation image from disk
				    //Show(SEM, 'SEM');															 //Display the image variable SEM on the desktop
					Save(Avg,Path+'Mean\'+FHead+'_av'+Str(k)+'.tif');								 //Save the final avarge image in the mean directory
				    Save(Stdev, Path+'Mean\'+FHead+'_sd'+Str(k)+'.tif');							 //Save the final standard deviation image in the mean directory
					Save(SEM, Path+'Mean\'+FHead+'_se'+Str(k)+'.tif');							 //Save the final standard deviation image in the mean directory
					Free(Avg);																  		 //Release the memory used by the variable Avg
		end	  ;
					
					PlaySound( 'C:\Program Files\Digital Optics\V++\autorun.wav' ) ;		 		 //Play a sound
					WriteInfo('Frame averaging  for '+ Str(Last)+' filenames completed');		   				 //Display a message in the status bar
end

