The interface is written in Tcl/Tk but only minimal knowledge of Tcl
scripting language should be necessary to write a simple task interface.
You do not need to know anything about the Tk graphics side as this is
all handled by CCP4i library commands. You may find it useful to read a
few chapters of one of the introductory textbooks:
Tcl and the Tk Toolkit by John Ousterhout
Addison-Wesley 1994 ISBN 0-201-63337-X
Practical Programming in Tcl and Tk by Brent Welsh
The man pages for Tcl/Tk are also extremely useful.
Below is an introduction to some features of Tcl which are used in a task
interface .tcl file.
Tcl Data Structures
Tcl treats all data as text strings except in some limited situations
where it 'knows' they should be numerical. A value is assigned to a variable
using the set command:
set NCYCLES 25
set MODE refinement
set TITLE "This is 25 cycles of refinement"
Here the variable NCYCLES is set to '25', MODE is set to
'refinement' and TITLE is set to 'This is 25 cycles of refinement'.
Some features:
As in the third line above, a string which includes white space (spaces,
tabs, new lines etc.) must be enclosed in double quotes.
The variable names are case sensitive: mode is not the same
as MODE.
To access the contents of a variable, put a dollar sign before the variable
name, e.g.:
set last_cycle $NCYCLES
and
set title "This is $NCYCLES cycles of $MODE"
Note that in the second example the values of NCYCLES and MODE
will be substituted into the string. Strings can also be built up using the
append command.
Tcl supports two other variable types: lists and arrays.
In a list of variables, one variable consists of a list of values. For example,
there could be a list variable allowed_modes which is a list of
three items: initialisation, scaling and refinement.
There are two ways to assign a list variable, i.e.
set allowed_modes { initialisation scaling refinement }
and
set allowed_modes [list initialisation scaling refinement]
In the first example, the list of possible allowed modes are enclosed in curly
braces. In the second example, the list command is used explicitly
and must be enclosed by square brackets (discussed
below).
You are strongly
recommended to use the second method as there are situations where the
first will not work correctly. There are several other commands you may
need to use to manipulate lists: lappend lindex llength lsearch lsort
lrange (see the Tcl documentation for more info).
Tcl supports arrays but these are not numerically indexed like Fortran
arrays. The name of an array element can be any text string so if you have
an array called refine_params, it could have elements called NCYCLES
or MODE which could be assigned values with commands like:
set refine_params(NCYCLES) 25
or
set refine_params(MODE) refinement
These values can then be used in commands like:
set refine_params(TITLE) "This is $refine_params(NCYCLES) cycles
of $refine_params(MODE)"
It is acceptable for array elements to have simple integer element names,
e.g. refine_params(1) and refine_params(2), but there is no notion in Tcl
that the element named '2' comes after the element named '1'. It is also
possible to imitate multi-dimensional arrays by using array element names
such as '1,1' , '1,2' , '2,1' .... Here the comma in the element name is treated
as just another character.
Nested Commands and Some Useful Commands
In the example above of assigning a list value:
set allowed_modes [list initialisation scaling refinement]
two Tcl commands are used: set and list. The
latter is an example of a nested command which is delimited by
square brackets. Everything
within the square brackets is interpreted and the result substituted into
the outer command. The square brackets are essential for the correct interpretation
of the whole command.
Here is a very brief review of some of the commands you might see or
use while working with CCP4i - see the Tcl documentation for details.
All mathematical expressions are evaluated by the expr command.
I.e. to find half of the value of variable length:
set half [expr $length /2.0]
expr supports some built-in functions such as log, sqrt, sin. So to find
the value of pi:
set pi [expr 2.0*asin(1.0)]
Tcl has a regular expression command regexp which is very powerful
(and complex) but mostly used very simply within CCP4i. The command returns
a value of 1 (true) if some part of the input string matches the test pattern,
or a value of 0 (false) if it does not match. For example, to test if the
value of the variable command includes the pattern 'refi':
set if_match [regexp refi $command]
There are a series of commands for handling text strings which all begin
with the word string. For example, to find the length of the string
in the variable 'title':
set length [string length $title]
Procedures
In Tcl a procedure (equivalent to a Fortran subroutine) is defined with
the following syntax:
The command proc is followed by three elements: the procedure
name, a list of arguments enclosed in curly braces, and the script which
forms the body of the procedure which is also enclosed in curly braces.
Some features of Tcl to note:
There is considerable flexiblity in Tcl over line layout. I have tried
to stick to some conventions which make scripts readable; I hope you find
these tolerable enough to use the same.
Procedures can have a variable number of arguments. You will use some
CCP4i library routines which have variable numbers of arguments but you
probably will not need to write procedures which have this feature.
The continuation character is a backslash (\) which must be the last
character on a line. Task window files can be made much more readable by
using generous spacing of commands over several lines and so using a lot
of continuation characters. But beware: forgetting the continuation character
or having an extra space after the backslash are common mistakes when writing
task window files!
The 'comment' character is #. If the first character of a line is
#, the rest of the line is ignored. Beware: a weird feature of Tcl is
that it does 'see' curly braces in a line commencing with a # and is liable
to give an error message complaining about unmatched parentheses or, worse
still, not give an error message.