{
This program will evaluate all images with chosen criteria of Standard Deviation
and create Average and Standard Deviation Images in selected directory <Path>

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

Program DO NOT require initialization file
After processing directories MUST be cleaned and 
all temporary files should be deleted 

File names for temporarily files in parent 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' --> enter the file header 
- Browse and select directory where images are stored
- 'Enter the FILE HEADER' --> enter the file header convention <FILE HEADER><_><Index>.tif
- 'Enter the FIRST frame' --> enter the index number for start
- 'Enter the LAST frame' --> enter the index number for end

- 'Enter the NUMBER of LOOPS' 	   --> number of circles of rejection 
- 'Enter the REJECTION CRITERIA'   --> rejection criteria in sigmas 
- 'Enter the REJECTION TRESHOLD'   --> threshold for saturated pixels or 
  		 	 		   			   	   pixels with anomalously high amplitude

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

Usually the last averaged file is used for further processing
									   
Created by Vladimir Lobastov 13.01.2002}



const
  	 	  CommonDlgsLib = 'VppCommonDlgs.dll' ;	 	{DLL for common dialog} 
		  InPath='D:\UED3_Data_processed\20081118_Azobenzene_short\';			 	{default path for images}
		  Path2='D:\UED3_Data_processed\Utilities\';		{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;
	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;

function FieldedFileName(FName, ind);
  begin
    FieldedFileName:= FName+'_'+ReplaceStr(Str(ind:3),' ','0',rs_ReplaceAll);		//Attach the index count (with leading zeros) to the file name 
  end; 
	
{************************************************************************}
{ ***	                      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+'BlankBinaryInv.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
			   //Halt(FHead);
			   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+'BlankSingle.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+'BlankShortInt.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
			     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:=Single(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;
		  Sum;
		  Zeros;		 
  begin

  	    Open( Path2+'BlankSingle.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+'BlankShortInt.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  
					 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:=Single(sqrt(Sum/((NI+Zeros-1+CH)))*(not Zeros)); 					//Calculate the standard deviation of all pixels except the zero and one pixels in the mask image.  ---> {floating point error}
			    Save(SD, Path+'temp\'+FHead+'_sd'+Str(k)+'.tif');					//Save the output standard deviation files
			Delete(SD);	 															//Delete the variable SD
			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								   
			   		   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:=2.5;							//rejection criteria in sigma's
		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' ) ;	 		  //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
						  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
			        Save(Avg,Path+'Mean\'+FHead+'_AV'+Str(k)+'.tif');								 //Save the final avarge image in the mean directory
				    Free(Avg);																  		 //Release the memory used by the variable Avg
					PlaySound( 'C:\Program Files\Digital Optics\V++\Library\Mac.wav' ) ;	 		 //Play a sound
					WriteInfo('Processing completed!!!');							   				 //Display a message in the status bar
end

