/*---------------------------------------------------------------------------------

Hit ctrl-enter to execute.

Description:

	This script will let the user change the units that and image is calibrated in.
	it handles cm, µm, nm, and Å.  It will take an image calibrated in any of these
	units and convert the calibration (and thus the scale bar also) to new units.
	Install the script in a menu with the Install Script command in the File menu

	Samantha Cooper June 17, 2000
	Annotated by Paul Thomas March 2001 

	Copyright © 2000 Gatan Inc.

---------------------------------------------------------------------------------*/


/*	This method, as indicated by 'number' before the method name,
	returns a numerical value corresponding to the exponent of the input units
	when given a string as input.
	e.g. supplied with cm, the method returns -2 to denote 
	the units are 10e-2m
	Note this method is called twice; once to calulate the old units 
	and also the new units.  Hence if either the entered units are not recognised
	or if the image calibration is not in known units
	then the routine will throw the unknown units error message.	*/

number GetUnitsExponent( string units )
{
	number exp
	if (units == "m")
		exp = 0
	else if (units == "cm")
		exp = -2
	else if (units == "mm")
		exp = -3
	// Note the '||' is an OR operator
	else if (units == "µm" || units == "um" )					
		exp = -6
	else if (units == "nm")
		exp = -9
	else if (units == "Å" || units == "A")
		exp = -10
	else
		Throw( "Unknown units.\nEnsure the input and image calibration are in SI units.")
	return exp
}


/*	This method changes the calibration units of image 'img'
	to the units specified by the string 'newunits'
	As indicated by the use of 'void', the method doesn't return anything */

void ChangeImageUnits( image img, string newunits )
{
	//NDimen is the number of dimensions of image img
	number nDimen = img.ImageGetNumDimensions()	
	
	// Index is the dimension index number    
	// Loop nDimen times, changing the units of each dimension.
	number index 				
	for (index=0; index<nDimen; index++)       									
	{	
		// Get the existing dimension unit string for dimension 'index', denoted here as oldUnits															
		string oldUnits = img.ImageGetDimensionUnitString( index )
		
		// Call the method GetUnitsExponent to get the exponent corresponding to the inputted newUnits string 
		// and also for the exisiting old units 
		number newExp = GetUnitsExponent( newUnits )				
		number oldExp = GetUnitsExponent( oldUnits )

		// Now calulate the conversion factor 'convFactor'			
		number convFactor = 10**( oldExp-newExp )
							
		// Get the old scale 'cal' of dimension 'index'  
		number cal = img.ImageGetDimensionScale( index )
		
		// Set the scale of dimension 'index' to cal*convfactor and set the units of dimension 'index' as the string 'newUnits'			
		img.ImageSetDimensionScale( index, cal*convFactor )			
		img.ImageSetDimensionUnitString( index, newUnits )			
	}
}


/*	This function is the main part of the procedure, and from here
	the other functions are called (hence it is placed after the above functions).
	Again, the use of void denotes that nothing is returned when called */

void MenuChangeImageUnits()
{	
	// Grab the front image; note the use of ':=' to ensure changes		
	// to img also affects the front image by implication 
	image img := GetFrontImage()
									
	// Prompt the user to enter the string 'units'/  Note if nothing returned, the procedure ends
	string prompt = "Please enter the units for the scale bar.\n Examples: um for micron, A for Angstroms"
	string units 
	if (!GetString( prompt, units, units ))							 
		exit(0)	
		
	// Call the ChangeImageUnits method, passing in the input image and the desired units													
	ChangeImageUnits( img, units )									
}


// Finally, call the MenuChangeImageUnits method to start the procedure
MenuChangeImageUnits( )												

