Taxa, Trees, Characters ˇ

 

Scripting and Macros

Mesquite's scripting system allows modules and other objects to be scripted using text commands. Mesquite uses scripting by text commands as follows:


The text commands are sent to modules or other objects. The particular text commands to which a module or other object responds will depend on the object. When Mesquite shows a web page for the first time, it attempts to compile automatically documentation for scripting commands that is available. This includes commands predefined by the scripting language, and commands belonging to particular modules. This compiled documentation is available from the web page linked from the "Scripting Commands" menu item in the Help menu when Mesquite is running.
Mesquite's scripting language is not as human-friendly as it might be at present, especially in its handling of variables and aspects such as the lack of "else" statements. Since the vast majority of Mesquite scripts won't be written by humans but by Mesquite itself, that is not such a liability as it might seem. We hope to reform the scripting language in the future.

Macros

Scripts performing some special function can be written and distributed by programmers to end users as "Macros". For some calculations or display functions, the number of different analyses a user might like to do are too many to be easily supported by a graphical user interface. For instance, the user might like to print the ancestral state reconstruction of a character using a series of different stepmatrices. One can invent many such scenarios in which something repetitious is needed, and a module would be hard-pressed to maintain each as an option. Thus, small scripts using Mesquite's scripting language can be written and placed in the "macros" folder. These macros will appear as options in an appropriate place, depending upon where they are applicable. When the user selects the menu item, the script is executed.
Macros can also be automatically composed by Mesquite. As noted above, Mesquite composes a script to place in NEXUS files that it saves. This script applies only to the particular saved file. In some contexts, you can ask Mesquite to save a script as a macro file. This is currently available in only a few contexts. Save Window as Macro in the Analysis menu and Window menu save macros that attempt to reproduce the condition (including analyses) of the foremost window. This is useful to reproduce a complex chart with a different data file, for example. Save Macro For Tree Drawing in the Display menu of a Tree Window creates a macro by which you can later reproduce the current appearance of the tree drawing (background color, font, tree form, orientation, and so on). Save Tree Analysis As Macro in the Tree menu of a Tree window creates a macro by which to reproduce a particular analysis with the tree. Macros so created are stored in Mesquite_Support_Files/Mesquite_Prefs/macros, and could be (for instance) shared by users.

Learning about scripting

Users can learn about the scripting language from this web page, but also by inspection of existing scripts. Some sources of scripts to examine are:
Another way to learn about the language and particular scripting commands is to look at the web pages linked from the "Scripting Commands" menu item in the Help menu when Mesquite is running. In particular, examine the page on universal commands, which shows basic commands available regardless of the object being scripted, including the basic flow control and variable-defining commands of the system. (We cannot provide a link here to this web page because this web page is created by Mesquite when it runs, and is placed in a location that depends on your particular computer. After running Mesquite once, you may want to find some of these files and save a bookmark/alias/shortcut to them — the file on basic scripting commands is named 'puppeteer.html').

Commands within scripts

In general, a command found within a script takes the following form:
commandName  argument1 argument2 ...;
The commandName is a single word (token); the arguments can be multiple tokens, so long as the module knows how to interpret them. Typically each argument is a single token (though this may be string of multiple tokens converted to a single token by quotation).

Scripts

A script consists of a series of commands. At each stage in the script, there is an implicit recipient of the command given (for instance, a module or a window). For instance, here is a script within the MESQUITE block of a NEXUS file. To the right of the commands are comments to explain them.

Begin MESQUITE;
  getNumberOfDataSets;      [file coordinator queried for number of data sets]
  Integer.dataSets *it;     [storing number of data sets in integer variable 'dataSets']
  getEmployee 'Data Window Coordinator'; [querying for reference to Data Window Coordinator module]
  tell It;                  [commands to follow will be sent to the Data Window Coordinator]
    Integer.dataNum 0;      [Define integer variable 'dataNum' and assign it 0]
    for *Integer.dataSets;  [for loop; cycle as many times as there are data sets]
      showDataWindow *Integer.dataNum;  [commands to make a data window for dataset]
      tell It;              [commands to follow will be sent to module that makes data window]
        showWindow;         [tells the module to make the data window visible]
      endTell;              [finished sending commands to the module that makes the data window]
      increment.dataNum;    [add 1 to the variable 'dataNum']
    endFor;                 [end of the for loop]
  endTell;                  [finished sending commands to the Data Window Coordinator]
  getNumberOfTaxas;         [file coordinator queried for number of sets of taxa]
  Integer.taxaSets *it;     [storing number of sets of taxa in integer variable 'taxaSets']
  getEmployee 'Tree Window Coordinator';  [querying for reference to Tree Window Coordinator module]
  tell It;                  [commands to follow will be sent to the Tree Window Coordinator]
    Integer.taxaNum 0;      [Define integer variable 'taxaNum' and assign it 0]
    for *Integer.taxaSets;  [for loop; cycle as many times as there are sets of taxa]
      makeTreeWindow *Integer.taxaNum;  [commands to make a tree window for set of taxa]
      tell It;              [commands to follow will be sent to module that makes tree window]
        getTreeWindow;      [queries the module to return a reference to the tree window itself]
        tell It;            [commands to follow will be sent to the tree window]
          newAssistant 'Trace Character History';  [the tree window is asked to hire a module]
        endTell;            [finished sending commands to the tree window]
        showWindow;         [tells the module to make the tree window visible]
      endTell;              [finished sending commands to the module that makes the tree window]
      increment.taxaNum;    [add 1 to the variable 'taxaNum']
    endFor;                 [end of the for loop]
  endTell;                  [finished sending commands to the Tree Window Coordinator]
END;

This MESQUITE block causes Mesquite to show a data window for each of the data sets, and a tree window for each of the Taxa blocks; the tree windows are shown with a character traced.
This script illustrates some of the features of Mesquite's scripting language:
Some of the lines of this script are commands unique to particular commandable objects (getNumberDataSets, getEmployee, showDataWindow, etc.); others are predefined by the scripting language (e.g., Integer, tell, for). More details on particular commands can be found in the web pages linked from the "Scripting Commands" menu item in the Help menu when Mesquite is running. Some details are found below.

Variables: Integers, Strings and Objects

Three sorts of variables are supported. Reference to each requires the type of variable with name appended, as in "Integer.numberOfCharacters" or "Object.treeDrawCoordinator". The generic variable "it" refers to the object last returned by a command.
When the variable is passed as an argument for a command, it should be preceeded by anasterisk. This allows the system to know that a variable, and not a constant string, is being passeed.

Numerical variables

Two sorts of numerical variables are supported: Integer and Number. The former contain whole numbers. The latter can contain whole or decimal numbers. Reference to each requires the type of variable with name appended, as in "Integer.numberOfCharacters" or "Object.treeDrawCoordinator". The generic variable "it" refers to the object last returned by a command.
When the variable is passed as an argument for a command, it should be preceeded by an asterisk. This allows the system to know that a variable, and not a constant string, is being passeed. The commands concerning variables are:

String variables

One sort of variable contains a string of text. The command to define and assign values to a string variable is:

Object variables

One sort of variable contains a objects (such as modules, or windows). The command to define and assign values to an object variable is:

The variable "It"

Standard Mesquite Commands to modules return an object. In the scripting language, this returned object is stored in the variable "It". Thus, after a command "getNumberDataSets" to the FileCoordinator, the FileCoordinator returns an Integer variable containing the number of data sets. This can be stored in an Integer variable by following the command by "Integer.numDataSets *it". Likewise, "tell" often makes use of "it".

Flow and command control

As noted above Mesquite's scripting language has flow control as well as control of the object to be commanded.

Using "tell" to direct commands

Commands are directed toward commandable objects, including modules, windows, and others. Since different objects might use the same command names, the object to which a command is directed must be indicated. In the scripting language, at any point there is an implicit object being commanded. Subsequent commands are directed to a different object using the "tell" command, which must be balanced by "endTell". At the root level, the FileCoordinator is being commanded.

Flow control

Flow control statements include "if", "for", and "while". Others are available (such as ifnot,stop, exitTell). Details on these can be found via the web page shown by selecting Scripting Commands from the Help menu while Mesquite is running.

Debugging

There are a number of commands that are useful for debugging. For instance, if the Command "debug" is placed in the block, a debugging mode will be enabled which reports in the console more details about the commands as they are executed. More information about such commands can be found by selecting the "Scripting Commands" menu item under the Help menu when Mesquite is running.

Examples

Here are three simple example scripts that you can send to the Tree window usingWindow>Scripting>Send Script. Open a tree window, turn on Trace Character History, and then paste one of these scripts into the Send Script dialog box. The first script scrolls from tree to tree, for each recording in a file "results.txt" the reconstruction of ancestral states.


String.resultsFile 'results.txt';
saveMessageToFile *String.resultsFile 'RESULTS with different trees';
appendReturnToFile *String.resultsFile;
getWindow;
tell It;
    getNumTrees;
    Integer.numReps *It;
    ifNotCombinable *Integer.numReps;
        Integer.numReps 10; [in case indefinite number of trees]
    endIf;
endTell;
 
Integer.count 0;
for *Integer.numReps;
    increment.count;
    getWindow;
    tell It;
        setTreeNumber *Integer.count;
    endTell;
    getEmployee #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
    tell It;
        getLastResult;
        String.result *It;
        appendMessageToFile *String.resultsFile *String.result;
        appendReturnToFile *String.resultsFile;
    endTell;
endFor;


This second script scrolls from character to character, for each recording the ancestral states in a file "results.txt":


String.resultsFile 'results.txt';
saveMessageToFile *String.resultsFile 'RESULTS with different characters';
appendReturnToFile *String.resultsFile;
getEmployee #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
tell It;
    getNumHistories;
    Integer.numReps *It;
    ifNotCombinable *Integer.numReps;
        Integer.numReps 10; [in case indefinite number of characters]
    endIf;
endTell;
 
Integer.count 0;
for *Integer.numReps;
    increment.count;
    getEmployee #mesquite.ancstates.TraceCharacterHistory.TraceCharacterHistory;
    tell It;
        setCharacter *Integer.count;
    endTell;
    getEmployee #mesquite.ancstates.RecAncestralStates.RecAncestralStates;
    tell It;
        getLastResult;
        String.result *It;
        appendMessageToFile *String.resultsFile *String.result;
        appendReturnToFile *String.resultsFile;
    endTell;
endFor;


The third script scrolls from tree to tree, printing each one.

getWindow;
tell It;
    getNumTrees;
    Integer.numReps *It;
    ifNotCombinable *Integer.numReps;
        Integer.numReps 10; [in case indefinite number of trees]
    endIf;
endTell;
for *Integer.numReps;
    getWindow;
    tell It;
        setTreeNumber *Integer.count;
        printToFit;
    endTell;
endFor;

Technical Details

(See the developer's documentation.) The Puppeteer is in charge of defining the basic language as it relates to variables and flow control. For an object to be scriptable, it must be of the Commandable interface. Commands internally in Mesquite are remembered in objects called MesquiteCommands.