Change calibration units
DigitalMicrograph Script
Switch dimension calibration units in an image (demonstrate simple custom dialog).
Preview
/////////////////////////////////////////////////////////////////////
// (c) Gatan Inc.
/////////////////////////////////////////////////////////////////////
// This script will let the user change the units that an image is calibrated in.
// it handles km, m, cm, µm, nm, pm, 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.
// The script has two alternative main methods. A simple text-input version
// and a method building a custom dialog for more convenience.
/////////////////////////////////////////////////////////////////////
// last modified 08-July-2014 BS
/* 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 calculate 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 == "km")
exp = 3
else 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 if (units == "pm" )
exp = -12
else
Throw( "Unknown units.\nEnsure the input and image calibration are in SI units.")
return exp
}
/* This method, as indicated by 'string' before the method name,
returns a string value. It replaces the 'easy' format of A and um
by the nice Å or µm, respectively. Other unites are returned unchanged. */
string GetNiceUnit( string units )
{
if (units == "um" )
return "µm"
if (units == "A")
return "Å"
return units
}
/* 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, GetNiceUnit(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 )
}
/* This function is a more UI based variant of the procedure above.
It performs the same functionality, but prompts the user with a customized dialog
for better convenience. */
void MenuChangeImageUnitsByDialog()
{
// Grab the front image; note the use of ':=' to ensure changes
// to img also affects the front image by implication
image img := GetFrontImage()
// Build a dialog-description tagGroup
taggroup dlg, dlgItems
dlg = DLGCreateDialog( "Select units", dlgItems )
// Build a radio list in the dialog. Each entry has a displayed string and an
// according (unique) value. We simply use the value as 'index' in the list.
// Addign the 'side' attribute formats the radio list horizontally.
TagGroup radioListTG = DLGCreateRadioList( )
radioListTG.DLGAddRadioItem( "km", 0 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "m", 1 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "cm", 2 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "mm", 3 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "µm", 4 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "nm", 5 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "Å", 6 ).DLGSide("Left")
radioListTG.DLGAddRadioItem( "pm", 7 ).DLGSide("Left")
// Add the radio list entry to the dialog
dlgItems.DLGAddElement( radioListTG )
// Pre-Initialize the dialog with the value of the current unit (X direction).
// If the radioList has an item of according value, it will be selected.
// Otherwise no item will be selected.
string oldXUnits = img.ImageGetDimensionUnitString( 0 )
radioListTG.DLGValue(GetUnitsExponent(oldXUnits))
// Create a dialog-object (UIframe) and initialize it with our built custom dialog
object dialog = Alloc(UIframe).init(dlg)
// Display the dialog as modal dialog (i.e. with OK/CANCEL button.)
// If the user clicks Cancel, the method returns 0 and the script will stop
// Changing the value in the dialog will be reflected in the value change
// of the dialog tagGroup, i.e. the value of radioListTG will be changed.
if ( !dialog.Pose() ) exit(0)
// Read out the value of the radioList.
number index = radioListTG.DLGGetValue()
// Find the string associated with the value.
// Because our value is the 'index' of the whole list, we can directly
// use it to find the according string.
string units
radioListTG.DLGGetNthLabel(index,units)
// 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
// Hint: Install the script in a menu with the Install Script command in the File menu
// MenuChangeImageUnits( ) // --> simple version
MenuChangeImageUnitsByDialog( ) // --> custom dialog version