From: Andrew Dalke (dalke_at_ks.uiuc.edu)
Date: Fri Apr 04 1997 - 18:27:57 CST

  This week's VMDTech, by Jeff Ulrich, will discuss how to do
"something" as the result of picking an atom with the mouse and end up
showing how to have VMD control a web viewer when an atom is picked
with the mouse. This shows one way to extend the user interface via
the Tcl "trace" command. Next week we'll go into more details about
what other traceable information is available for scripts to use.

  For the new people who just joined the list, VMDTech is a weekly
article we write for the list concerning some detail or topic of VMD
that we believe will be helpful to most users. We will also include
much of this material in the new version of the documentation, so
please tell us if there are any problems. Back issues of VMDTech are
available from the vmd-l mailing list archives, which is available
from
        http://www.ks.uiuc.edu/Research/vmd/mailing_list/ .

  As a development note, this week we managed to get VMD working with
Tk (in addition to the normal XForms GUI). If anyone is interested in
using this option, please contact me.

                                                Andrew Dalke
                                                dalke_at_ks.uiuc.edu
====================================================================
                        Tracing Atom Picks

Section 1 - Syntax and description of 'trace'
---------------------------------------------
The 'trace' command allows you to monitor the usage of Tcl variables.
For instance, you may wish to call a procedure whenever the value of a
certain variable is modified or accessed. Or, you may want to make a
variable be of integer type only. As a third example, you may want to
propogate the changes in a variable to other parts of your program
(i.e. to the graphical interface). All of these things can be done
with 'trace.'

The trace command takes four parameters.

        trace variable <variable-name> <operation> <procedure-name>

The words 'trace' and 'variable' are required. <variable-name> is the
name of the variable to set a trace on. <operation> can be one of
three letters: 'w', 'r', or 'u'. These three letters stand for
'write', 'read', and 'unset' respectively. They determine which
actions upon the variable should be traced. <procedure-name> is the
procedure to call when <operation> is performed upon <variable-name>.
The code corresponding to <procedure-name> needs to follow some
special syntax of its own. Here is a template showing an example of
the necessary syntax for a procedure named 'sample':
 
        proc sample {name element operation} {puts "Trace worked"}

If you cut and paste this line into the VMD console, along with the
command

        trace variable monitor w sample

then any subsequent attempts to write to the variable 'monitor' will
be accompanied by a call to the procedure 'sample', which in this case
simply prints out "Trace worked". Try it by entering this:

        set sample xyzzy

Notice that the procedure 'sample' takes three arguments. Even if you
never use any of these arguments, you must still include them in any
procedure that is to be called by a trace (or use "args"). This is
because Tcl automatically passes the name of the variable which
invoked the trace, the element number (if an array), and the operation
(r, w, or u) which triggered the call to the trace procedure. In the
beginning, you will probably have little use for any of these three
variables, but just to give you an idea of how they might be useful,
copy and paste the following:

        proc identify_action {name element operation} {
                switch $operation {
                  w {puts "I noticed that you are writing to $name"}
                  r {puts "I noticed that you are reading from $name"}
                  u {puts "Say goodbye to the value of $name"}
                }
        }
        trace variable action w identify_action
        trace variable action r identify_action
        trace variable action u identify_action

Then enter
        set action 1
        puts $action
        unset action
and see what happens.

Two final notes regarding the syntax of the 'trace' statement. To
delete any previously defined trace, type

        trace vdelete <variable-name> <operation> <procedure-name>

That is, type exactly that which you used to define the trace, but
replace the word "variable" with "vdelete". Also, if at any time you
would like to see which procedures a variable is traced to, type

        trace vinfo <variable-name>

For the remainder of this VMDTech article, we will work only with the
'w' operation, which will call a procedure when a traced variable is
written to.

Ousterhout's and Welsh's books also describe the details on how to use
the trace command.

Section 2 -- Some Interesting VMD Variables to Trace
----------------------------------------------------
VMD maintains a number of parameters that can be useful for invoking
procedures that respond to user actions. Some of them are
vmd_pick_atom, vmd_pick_mol, vmd_frame and vmd_event, but this VMDTech
will only discuss the first two.

The variable "vmd_pick_atom" contains the index of the atom most
recently picked by the mouse, where the first atom has an index of 0.
Likewise, vmd_pick_mol contains the molecule id corresponding to the
molecule in which the most recently picked atom resides. Every time
you select an atom with the mouse, these variables are set to reflect
the new information.

For instance, load a molecule and click on any atom in it. Enter the
following line:

        puts "You picked atom $vmd_pick_atom in molecule $vmd_pick_mol"

By placing traces on these parameters, you will be able to invoke
useful procedures when the variables are updated. Lets see how we
might obtain a more useful description of the atoms when we click on
them. We will begin by indicating a 'write trace' on the variable
vmd_pick_atom:
        
        trace variable vmd_pick_atom w atom_info

Since this variable is updated automatically by VMD each time a new
atom is picked, defining this trace is equivalent to saying "Each time
I pick an atom, call the procedure atom_info." It is in atom_info
that we will print out our extended description of the atom. Since
this procedure doesn't use the arguments passed to it, the formal
parameter list is just "args", which will take any input.

        proc atom_info {args} {
                # Indicate that vmd_pick_atom and vmd_pick_mol
                # are globals, so that their values can be accessed in
                # the body of this procedure.
                global vmd_pick_atom vmd_pick_mol
                # Retrieve atom properties...
                set sel [atomselect $vmd_pick_mol "index $vmd_pick_atom"]
                set position [$sel get {x y z}]
                set name [$sel get name]
                set mass [$sel get mass]
                set residue [$sel get resname]
                # and print them out
                puts "Atom Index: $vmd_pick_atom"
                puts "Atom Name: $name"
                puts "Atom Position: $position"
                puts "Atom Mass: $mass"
                puts "In Residue: $residue"
        }

If you cut and paste the trace command and the atom_info procedure
into the console, then any subsequent clicks on an atom will give you
more detailed descriptions about that atom.

Of course, printing this information all the time gets annoying, so
here is how to turn it off

        # delete the former reference to tidy things up
        trace vdelete vmd_pick_atom w atom_info

As a variant, suppose that we wanted to learn about the center of mass
of a residue simply by clicking any atom within it. Then the
following lines will do the job:

        # print residue center-of-mass on atom clicks
        trace variable vmd_pick_atom w get_COM

        proc get_COM {name element op} {
                global vmd_pick_atom vmd_pick_mol
                set selection [atomselect $vmd_pick_mol \
                        "same residue as index $vmd_pick_atom"]
                # some error checking
                if {[$selection num] <= 0} {
                    error "center_of_mass: needs a selection with atoms"
                }
                set COM [measure center $selection weight mass]
                puts "center-of-mass is: $COM"
        }

WARNING:

  For these variables to be useful, both vmd_pick_atom and
vmd_pick_mol must be set. However, VMD sets the molecule id first and
then sets the atom id. These are not atomic actions, meaning that if
you do the trace on the molecule id you will have the new molecule id
but the old atom it. This doesn't do what you want it to do so always
put the trace on "vmd_pick_atom".

Section 3 -- Controlling Web Browsers using Trace -- Hypermolecules
---------------------------------------------------------------------------

  VMD has a few hooks built into it which allow you to use the trace
command to control web browsers such as Netscape and Mosaic (see the
previous VMDTech titled "VMD 1.2b1 is now available" for more
information on the details). When these hooks are active, you can
associate atom picks with URL addresses to load. Different parts of
the molecule can correspond to different URLs so that clicks on these
different parts will yield specialized information. One can imagine
many uses for this feature:

        o Teaching - click on an atom and bring up a web page
          describing the element and/or residue

        o Collaborations - click on an atom in a part of the system
          you are studying and bring up a web page describing your
          research.

        o Research - click on an atom and bring up a web page which
          lists (via a search engine) previous studies done on the
          molecule.

In the file $env(VMDDIR)/scripts/vmd/www.tcl of your vmd installation,
you will find a number of procedures setting up the syntax for these
'hyper references'. Brief descriptions of these procedures follow:

        hyperref < "on" | "off" | "invert" >
        This turns the hyperref feature on or off. When hyperref is
        on, clicking on an atom with an associated URL will load the
        in the web browser. The on/off status can be toggled with
        the Alt-h key. By default it is turned off.

        hyperselection <molecule id> <selection text> <URL>
        Associates a URL with a given selection of atoms. For
        instance, by typing:

            hyperselection top "segname ALP1" http://www.ks.uiuc.edu/

        you will link each atom in the segment ALP1 to the web address
        for the Theoretical Biophysics Group at the University of
        Illinois.

        vmd_hyperref_update - This is the function called by the Tcl
        trace routine whenever you click on an atom with hyperref on.
        It checks the index for the atom you clicked on in order to
        see if it has been linked to a web page. If so, it directs
        the browser to load that page.

To (hopefully) clear up any mystery in hyperreferencing, this is how
things will usually work. Hyperreferencing is turned off by default.
Pressing 'Alt-h' from within the display window of VMD, puts a trace
on vmd_pick_atom using the following command:

        trace variable vmd_pick_atom w vmd_hyperref_update

so that subsequent atom-clicks will call the procedure
vmd_hyperref_update. If hyperref was on, then this trace is deleted
in the same manner that our earlier examples were destroyed, using the
command:

        trace vdelete vmd_pick_atom w vmd_hyperref_update

vmd_hyperref_update is the procedure that checks if a given atom has a
URL associated with it and loads the appropriate web page. The
procedure "hyperselection" doesn't really have much to do with the
trace feature at all. It simply sets up the relationships between the
molecule and atom indicies and the URLs.

As an example of how hyperreferencing works, load a molecule then cut
and paste the following lines into your VMD console.

        proc hyperref_aminoacids {molid} {
            set base_url http://www.chemie.fu-berlin.de/chemistry/bio/aminoacid
            set map(ALA) alanin.html
            set map(ARG) arginin.html
            set map(ASN) asparagin.html
            set map(ASP) asp.html
            set map(CYS) cystein.html
            set map(GLN) glutamin.html
            set map(GLU) glu.html
             set map(GLY) glycin.html
             set map(HIS) histidin.html
             set map(ILE) ile.html
             set map(LEU) leucin.html
             set map(LYS) lysin.html
             set map(MET) met.html
             set map(PHE) phe.html
             set map(PRO) prolin.html
             set map(SER) serin.html
             set map(THR) threonin.html
             set map(TRP) trp.html
             set map(TYR) tyrosin.html
             set map(VAL) valin.html
            foreach aa [array names map] {
                puts "Mapping resname $aa to $base_url/$map($aa)"
                hyperselection $molid "resname $aa" $base_url/$map($aa)
             }
        }
        hyperref_aminoacids {top}

These lines simply associate each of the different amino acid types
making up your molecule with the web pages of Burkhard Kirste at the
Free University of Berlin that describe the detailed properties of the
amino acids. After you have pasted the above code, ensure that
hyperref is on by hitting Alt-h until the message
        
        vmd > Hypertext atom picking is turned on

shows up in the console. From that point on until you hit Alt-h
again, you will find that atom-clicks load web pages describing the
amino acid associated with the atom. Of course, since these pages are
located in Germany, they take a while for most people to use.

Good luck,
Jeff Ulrich <ulrich_at_ks.uiuc.edu>
=========================================================================