Loading...
 

Tcl-Huygens


This article explains the connection between Tcl and the HuygensSoftware. For a short entry on what Tcl is, see TclTk.



Tcl Tk

What is Tcl/Tk

Tcl is a general purpose scripting language as part of the public domain Tcl Tk package. It is an acronym for Tool Command Language and is pronounced as 'tickle'. Tcl was developed by John Ousterhout at the University of California at Berkeley, starting in 1987. Its purpose is to provide a consistent 'glue' between components of a software library and/or different applications. In short, Tcl is ideally suited to provide an interface between the image processing functions of the Huygens Compute Engine and higher levels such as the graphical user interface. At the same time it provides you with a full fledged, well documented scripting environment.
The Tk-part of the package is the Toolkit, based on Tcl commands, which provides an easy way to build graphical user interfaces which can run on many platforms.

The syntax of Tcl has the simple structure of a shell-style language. A command consists of one or more words separated by spaces or tabs. The first word is the true command and the following words are the arguments. Commands are separated by newlines or semi-colons in the case of more commands on the same line. The only datatype used in Tcl is the string. For an overview of the Tcl basics you can see the Huygens Tcl Manual_Tcl_structure.

All the Tcl core commands are well described in the book Tcl and the Tk by John Ousterhout (Ousterhout, John K., Tcl and the Tk toolkit. ISBN 0-201-63337-Z Addison-Wesley, New York). If you plan to program more than a few lines, be sure
to get Practical Programming in Tcl and Tk, Brent B. Welch. Currently it is in its 4th edition, ISBN: 0-13-038560-3.
Good documentation can also be found also in the internet, see e.g. http://www.tcl.tk/.

Huygens extensions to Tcl Tk


The Huygens Software extends the basic Tcl Tk libraries by adding special commands to handle multidimensional images in a convenient way. Whenever you create or load an image into the Huygens software, a Tcl command is created with the name of the new image. This so-called object oriented approach means that you always specify the image object first and subsequently the operation you want to perform on it. See Huygens Tcl Manual_Image_commands for more details.

The Huygens extensions to Tcl are documented in detail in the Huygens Core Programmer Guide:

  • File and export operations.
  • Reporting and display operations.
  • Image restoration operations.
  • Image manipulation operations.
  • Image analysis operations.
  • Arithmetic operations.
  • Undo operations.
  • Miscellaneous.

Documentation on the Tcl-Huygens commands follow the standard Tcl Notation.

Examples of basic Tcl commands


Assigning variables


As an example let's assign a value to a simple variable:
set x 4.2
=> 4.2

where => means the respond (return value) from Tcl, according to the notation followed from John Ousterhout's book. To the variable called x a string '4.2' is assigned Although erroneous, the command
set 4.2 x
=> x

is also possible, meaning the assignment of string "x" to the value name"4.2".
set a {TCL and the TK Toolkit}
=>TCL and the TK Toolkit


The use of curly braces is needed in order to keep the complete text string as only one string, including the white spaces.

Variable substitution

Variable substitution is invoked by the "$" character:
set a 2
=> 2
set b $a
=> 2
incr b 10
=> 12


Expressions

set a 2.2
set b 3.2
expr ($a + $b)*2
=> 10.8
set x .5
expr 2.1 * cos($x)
=> 1.84292


Control flow

In the examples below the scripts are multi line. We advice you to enter these examples in a separate file.
set message ""
set p 2
foreach k {1 2 3 4} {
    append message "$k to the power $p is [expr pow($k,$p)]\n"
}
set message
=>1 to the power 2 is 1.0
 2 to the power 2 is 4.0
 3 to the power 2 is 9.0
 4 to the power 2 is 16.0


Procedures

proc sum_of_squares {a b} {expr $a*$a + $b*$b}
sum_of_squares 2 5
=> 29
set a 8; set b 9
if {[sum_of_squares $a $b] > 100} {
    set message "result is out of limit"
}
set message
=> result is out of limit


String manipulation

Here is an example how to extract from a list all the names ending with `.ics'.
set list {a.tiff b.ics c d e.ics d.ics}
set new {}
foreach el $list {
    if [string match *.ics $el] {
        lappend new $el
    }
}
set new
=> b.ics e.ics d.ics


Accessing files

Find text lines from a file called HuTclInit containing the string "save".
set dir {/usr/local/svi}
set filename HuTclInit
set f [open $dir/$filename r]
set pattern save
set message "\n"
while {[gets $f line] >= 0} {
   if [regexp $pattern $line] {
      append message "found: $line \n"
   }
}
close $f
set message
=> found: proc hu_saveDef {} {
 found: huOpt saved
 found: proc hu_saveHist filename {


Tcl extensions: image processing commands


Object-oriented programming: images are commands

Whenever you create or load an image into the Huygens System, a Tcl command is created with the name of the new image. This so-called object oriented approach means that you always specify the image object first and subsequently the operation you want to perform on it.

Images in the Huygens System are Tcl commands!!! This allows a very natural syntax. For instance, to add 1 to all pixel values in an image "foo" and place the result in an image "bar" you enter:
foo + 1 -> bar


We have opted for the -> symbol instead of the = symbol because the operations in the Huygens System nearly always have the character of an assignment operation, and are not equations.

Let's see how can we subtract two different images of the same dimensions using Huygens Professional, as a detailed introductory example.

Load the two images. Do this through the top menu (FileOpen) but keep an eye on the TclShell at the bottom right to see the commands that are automatically executed there. When you open an image in Huygens (command: img open), it gets an internal name which is related to the name of the file that contained it. This internal name is returned right after the opening of the image. (In many cases it is the same name, but sometimes some conflictive characters have to be replaced).

I'll call the two images 'data' and 'background', but in your case they will have more complex names depending on your file names.

(Another command is executed by Huygens Pro after 'img open' to generate and show a thumbnail, but this is not important now).

Type now this command in the TclShell:
data - background -> a


(Mind the spaces after each item in that command, and remember to replace 'data' and 'background' with the corresponding internal image names your datasets got. You don't have to type these completely, the TclShell has a nice expander tool: type the first characters of the name and then press TAB, the name will be completed as much as possible among the existing alternatives. Pressing TAB inmediatly again (twice, thus) gives you a list of alternatives, in case multiple images have the same name root).

Press enter to execute the command. In the image 'a' (that is created by default by Huygens at start up, empty) you'll have the difference of the two images. Simple!!! Just one command line subtracts all pixel values one from the other, as long as the images have the same dimensions. You can now save image 'a' with a significative name by going to File → Save As > ICS2 or any other File Format. See what command is executed to actually save the image in the Tcl Shell.

If you need to repeat this operation automatically for multiple images opened in pairs you'll need some further scripting. This is probably just a loop over all the contents of a directory, taking the secondary image from another location but with a related name. It helps if the file names and locations are systematic so that image pairs can be found easily by a syntax rule or so... Tcl provides the control-flow and file-access commands necessary to program all this.

About command names


Notice that some Huygens extensions have names equal to basic Tcl commands, but the context clearly distinguishes their functions, as commands are always at the beginning of the sentence and the rest are parameters.

The following line sets all the VoXels in the existing image named 'a' to a value of 100. It is a Huygens extension to Tcl, and the command here is the image name "a", while set is a so-called method.
a set 100


This other line, on the contrary, sets a variable called 'a' to a value of 100 so you can use substitute it in other expressions later. It uses the basic Tcl command set, and "a" is just a variable name.
set a 100


A complex script

HuygensCore doesn't make questions to the user because it doesn't expect to have an interface to do it, so it takes default alternatives at conflictive points. You can reproduce the same behavior in HuygensProfessional by setting the verbosity to silent with
huOpt verb -mode silent


The only Tcl commands added by Huygens are those concerning image processing functions. For anything else (loops, directory access/creation and so on) you have the basic Tcl commands available. To obtain all the TIFF files in a certain directory you can use for example glob like follows:
glob "/path/to/mydir/*.tif"


That returns the file names as a Tcl list. Lists are one of the fundamental Tcl object types and plenty of commands are used to handle them.

For example, you can 'capture' the output of that command into a variable 'allFiles', and then use a for-each loop to execute something on all those files. To 'capture' the output of any Tcl command into a certain variable you use square brackets to execute the command and embed that into a regular set line, like in this example:
set allFiles [glob  "/path/to/mydir/*.tif"]
foreach file $allFiles {
    huOpt report "Processing file: $file"
    set image [img open $file]

    # Do something with the opened image here:
    $image * 100 -> a
}

In case you need to open two files, not just one, to operate them together, things become slightly more complex. This means that for each file name $file in the previous loop you have to do some string manipulations to generate the name of the secondary file, based on it. That can be tricky, but Tcl provides the functions to do that.

As an example, suppose that each $file in that loop has a name like in -="/path/to/data/myDataFile_0001.tif"+- and that the secondary images are named like in "/path/to/reference/myDataFile_0001_background.tif". This is an easy case: the reference file is stored in another directory, and its file name is like the other file plus a suffix "_background". In this case you would do something like this:
set dataDir "/path/to/data"
set refDIr "/path/to/reference"
set allFiles [glob  "$dataDir/*.tif"]
foreach file $allFiles {
    huOpt report "Processing file: $file"
    set image [img open $file]

    # Finding name of secondary image
    set filename [file tail $file]
    set rootname [file rootname $filename]
    set extension [file extension $filename]

    set scndImgName "${filename}_background$extension"
    set scndImgFullPath "$refDir/$scndImgName"

    set scndImage [img  open $scndImgFullPath]

    # Do something with the opened images here:
    $image - $scndImage -> a

    # Store the result with a meaningful name
    a save "/destination/path/${filename}_difference"
}


Notice that sometimes variables are referred to as ${variable} and not just $variable in the previous script. That's Tcl syntax to avoid ambiguities in concatenated strings. If you want to add the string "_suffix" to whatever is in variable 'txt' and set it into a new variable you can't just do
set new "$txt_suffix"

because that is referring to an unexisting variable named 'txt_suffif". You use the curly braces to limit the reference to the variable name
set new "${txt}_suffix"


This is clearer: you are using the contents of variable 'txt' and appending to it a literal string "_suffix". Usage of {} is only necessary in case of ambiguity, normally you refer to a variable's value just by adding a dollar sign in front of the variable name.


Loading of an image

Suppose there exists an ICS image file-pair named "faba64" (faba64.ics and faba64.ids) in your current directory. You can load the image faba64 by typing:
{CODE()}
img open faba64
=>faba64
{CODE}
If the file is of another type you may need to specify its extension, and if it is in another location also the full path to it.

Image statistics

faba64 stat

will write statistical information of image faba64 to the Task report window.

Restoration

Suppose you have already loaded the image faba64 and you wish to restore it. Now, first you need to load a measured or computed Point Spread Function file, for example the psfNew file.
img open psfNew
img create faba64_ictm
faba64 ictm psfNew -> faba64_ictm -it 30 -rr on


Now delete the created files psfNew and faba64_ictm and the opened file faba64 .
faba64 del; psfNew del; faba64_ictm del


Following the command substitution rule the former comments could be written in one:
[img open faba64] ictm [img open psfNew] -> [img create faba64_ictm] -it 30 -rr on


Save to ICS format

Assuming that faba64_ictm is an existing image
faba64_ictm save foo

will save the image in ICS file pair foo.ids foo.ics

More examples

For more examples see HuTclUsefulProcedures.
Read also more about the tcl fundementals on the Huygens Core user guide.
See also the list of Tutorials under the paragraph Programming.

Libraries


Useful libraries for Tcl Tk can be found, for example, in http://tcl.tk/software/tcllib/ (read about dependencies here).

Contact Information

Scientific Volume Imaging B.V.

Laapersveld 63
1213 VB Hilversum
The Netherlands


Phone: +31 (0)35 64216 26
Fax: +31 (0)35 683 7971
E-mail: info at svi.nl

Image Image Image Image Image Image