Using Triana

for Gravity from the ground up

version 1.0
© 2003 Bernard Schutz

A brief introduction to the Triana programming environment.



Contents


What is Triana?

Triana is a computer program that helps users to develop and run their own programs. Triana is called an "environment": users work within it to accomplish their programming goals because it is easier to do this than to program the computer directly to do what they want. Triana has been developed by scientists at Cardiff University in Wales, initially as part of the GEO600 gravitational wave detector software development activities. More recently the Triana project has developed capabilities that serve a much wider range of users. Triana is written in the Java programming language, but it can support and run programs written in other languages as well.

All the programs for the book Gravity from the ground up are included in the version of Triana that users can download from the book's website. Also included are tools for displaying the results of the programs, either as graphs or as lists of numbers in files Triana supports all readers of the book, from those who do not want to do know how the programs work to those who want to modify and extend the programs or even create new ones. Here are ways in which Triana can help users at different levels:



Using Triana

Triana has a simple drag-and-drop model, in which the user selects an icon from a list of programs (called units) already available in Triana (arranged in groups called toolboxes), drags the icon into a working space within the Triana window, then drags an icon to display the output (as a graph or as a text file, in the simplest cases), and draws a line from the program icon to the display icon. Each of the dragging and drawing operations should be done while holding down the left mouse button while moving the mouse. Releasing the button finishes the operation.

When an icon is dragged into the working area, it is displayed as a rectangle with the name of the unit written in it. It may be shown with one or more small black squares on its right edge; these are called output nodes and represent the places where data leaves the unit. Similarly, each icon may have black squares on its left edge, which are called input nodes, and they are places where data comes in. For the network to function at least one output must be connected to an input, but not all nodes need to be connected if you do not want to use the data they represent. The number and function of the output nodes for the programs are described in the help files for the programs.

To run the network, press the "Play" button (the green triangle on the left in the top row of buttons). Triana executes the program and produces the requested display of information. The steps involved in creating and running the first of the programs for Gravity from the ground up are shown in the following succession of screen-shots of the Triana window.



Once you have a working network of units, you may want to change things. Here are several tips:

Triana has several features that make even these simple procedures a little easier.

Getting data from program units

The first time you get data from the units you should display it graphically using SGTGrapher. This unit will display on a single graph all data that it receives from its input node(s). For some units, you have a choice of output data: the unit will produce one of the choices at any time, but not all. This happens when the data have different dimensions, and therefore should not be displayed on the same graph. However, you can still see them at the same time. Simply create two duplicate networks in the same working space, consisting of the program unit and the grapher, and choose different outputs for the program units. When you run the networks, you will get two different graphs with the related data.

SGTGrapher has various options for altering how the data are displayed. These are accessible from its "Plot" menu. You can choose linear or logarithmic scales for either or both axes, and you can choose things like line colors, line styles, or even whether to plot lines or individual points or both. You can force Triana to display the x- and y-axes using the same scale (useful if the graph is giving you a view of a region of space in which particles are orbiting). You can print the graph or (if you have configured a printer on your computer that saves a postscript file) output to a postscript file. If the numbers labeling the axes are hard to read because they are too long and overlap, then SGTGrapher's "Plot" menu allows you to tell Triana to take out common factors of ten or subtract a common large value from the scale display values.

There are times when you might want to output the numbers output by the program unit rather than look at the graph. You may be interested in the exact values of the data, or you might want to save the data so you can input it to a graphing program that produces better graphs than SGTGrapher can. To get the numbers, use the unit CurveToFile instead of SGTGrapher. Double-click on this and enter the name of the file you want the data to be written into. When you run this network, no graph will appear, but the file will be written with the data in two columns, which represent the x- and y-values of the data points. Use a separate CurveToFile unit for each of the output nodes if a program unit has more than one. Notice that the icon for CurveToFile in the toolbox is different from most of the others. That is because it is a group unit, as described above.
 


Advanced use of Triana: changing programs

Most of the help files have a section called "Suggested modifications ..." in which users who are more ambitious are pointed in diretions that would either improve the efficiency of the programs or enlarge the scope of the physical situations that the program would cover. In this section we look at how to "open the hood" of the Triana units and change the code that makes them work. To do this you need to have the full Java development kit (SDK) installed on your computer. See the website for the book to find out how to obtain this. It is free, but it is a large package and takes some time to download if you don't have a fast connection. Triana requires SDK version 1.4 or later.

Terminology. Let us first establish some Triana terminology. The left-hand pane of the Triana window is the toolbox window. The programs are groups into toolboxes, and the programs themselves are called tools. When you drag a tool into the working space in the main part of the Triana window, we call it a unit. The words tool and unit are used almost interchangably. When you look at the code of a tool you will see that it actually consists of several program units. In Java these are called methods, while in the C programming language they would be called functions and in FORTRAN they would be called subroutines or functions.

Editing the code. To change a program, go to the toolbox containing the tool you want to modify, and then right-click on the tool's icon in the toolbox. You will get a menu that includes "Edit Source". Choose this, and Triana will open an editing window. It will either use its built-in editor or one you have previously directed it to use by giving the full path to the editor code under the main menu option "Triana/Triana Options ..." and the tab "External Tools".

The first thing you will notice is that the code for the unit contains a lot more methods and other statements than are shown in the listing in the help file for that program. The help file shows you all the code that you need for doing the calculation that the unit is supposed to do. But the code for the unit has also to help do all the things that Triana does for you automatically. These include popping up the parameter window when you want it, initializing the unit so it starts right, coping with situations where you might want to push the "stop",  "reset", or "flush" buttons on the Triana main window (which basically are emergency measures that you are unlikely to need unless you program the unit wrongly!), checking the type of data that leaves a unit to make sure that the receiving unit knows what to do with it, and so on.

Parts of the code you need to look at. You are of course welcome to scan through all these other methods to see what they do, but in the end you will only have to deal with code in a few places. When Triana creates a brand new unit (as described in the following section) it even writes almost all the code for you automatically. Here are the key features of the code that you need to deal with:

  1. The method process contains the main code for the unit. Triana calls this method each time it wants to run the unit. The units containing the programs for Gravity from the ground up do not have input nodes: they all generate their own data without importing data. Therefore they are run only when you press the "Start" button on the main Triana window. Each process method ends with an output step, where the unit is instructed to send the data to the output node(s), where Triana will ship it off to whatever unit is connected to the node(s). Before that, the code in process does whatever is needed to generate the data. The help files all show the complete code for process, and this is the method you will need to modify to implement changes in the way the unit works.
  2. The parameters are an important part of the way the unit works. Modifications of units are far simpler if you do not modify the parameters, because parameter handling in Triana is necessarily somewhat involved. Parameters have to be available to the user in the parameter window, their default values have to be known to the unit in case it is reset (which puts the values of parameters back to their defaults), and the unit needs to learn when the user has modified the parameter values in the parameter window so it can use the new values.

    The parameters are simply variables within the unit that are defined outside any of the methods in the unit. According to the rules of Java, this means that every method in the unit can access these variables: their names are globally defined within the unit. (Normally, a variable defined in one method is unknown to other methods; by defining variables outside of the methods we create memory that all methods can use if they want.) Parameters can be of any Java type: ints, doubles, character strings, even more complicated data objects.

    Outside the unit, however, Triana does not have access to these variables, and in particular it does not know what data type a parameter is. Triana passes information about the values of parameters between the parameter window and the unit's own code using character strings. Thus, if a parameter is a double that the user defines to have the value 1.0, then Triana actually passes a character string containing the characters "1.0" back to the unit, and the unit has to convert this into a binary number and assign it to the parameter.

    To facilitate this data passing, each variable has a keyword name, which is a character string that serves to identify it to the unit and to the parameter window and to any other part of Triana that needs to deal with it. Normally, programmers use the same name for the keyword as the internal name in the unit. In MercPert, for example, there is a double called mSun, for example, which is to hold the mass of the Sun. This is known to the parameter window by the character string "mSun". This is sensible, but it could have been defined to be anything else, like "parameter1", and parameter passing would work just as well.

    So here is how this parameter defining and passing works. If you want to add or modify parameters you need to make changes in each of these places. Examples are drawn from the code for MercPert.
    1. Parameters are defined in the code for the unit at the very beginning, in a section that begins with the comment
    2.     // parameter data type definitions
      This code is reproduced in the help file for the unit. Parameter values are not given here. The purpose of this code is simply to establish storage locations in the unit's memory where these parameter values can be held and be accessible to all the methods of the unit.
    3. The method init is called by Triana when the unit is first dragged out of the toolbox and into the working area. It sets up the initial values of parameters and defines what will be shown in the parameter window. For intiializing parameters it uses lines like
    4.     defineParameter("mSun", "1.0", USER_ACCESSIBLE);
      This is a call to a method defineParameter that is not part of the unit's code, but is defined in a different part of Triana. It associates the default value of 1.0 as a character string (for passing) with the keyword for the parameter mSun, which is the character string "mSun". The final argument of this method is USER_ACCESSIBLE, which tells Triana that users can modify this parameter. (Triana can use parameters in other ways as well, which we do not need to go into. All the parameters in the programs for Gravity from the ground up are accessible to users.)

      :Later in init there is the line
          guilines += "Give the mass of central body (the Sun) in solar masses $title mSun TextField 1.0\n";
      which is the code that Triana uses in order to build the parameter window in which users can change the parameter values. It consistes of a single character string that Triana takes apart into several pieces. The first piece is simply the words that are written into the parameter window to guide the user in what the parameter means. These words end with the keyword "$title". What follows that is the keyword name of the parameter for data passing, which in this case is the character string "mSun". This is followed by another keyword "TextField" which tells Triana to allow the user to enter the values in the parameter window simply by typing them into a little text window. (Other parameters in other units have different ways of entering data, such as choice boxes or sliders, and these use different keywords here.) Finally the line ends with a character string giving the default value of the parameter "1.0". This must be consistent with the value defined in the earlier defineParameter line, shown above. If you redefine the default value make sure you change it in both places.
    5. The next place parameters turn up is in the reset method, which is called in emergencies. It needs to re-initialize the parameters. In MercPert for example this contains the line
    6.     mSun = new Double((String) getParameter("mSun")).doubleValue();
      This line tells Triana to invoke the method getParameter (which is defined elsewhere in Triana) to get the character string "value" of the parameter whose keyword name is "mSun", and convert it into the binary representation of a double, which is then assigned to the variable mSun. This rather complicated statement invokes a Java utility function that does the conversion of a character string into a binary.
    7. Finally, the unit contains the method that is used to associate the keyword character-string name of the variable with the variable itself within the unit. This happens in the method parameterUpdate. The statement in MercPert for the variable mSun is
    8.     if (paramname.equals("mSun"))
              mSun = new Double((String) value).doubleValue();
      The variable paramname is a character string that is an argument of parameterUpdate, so it is passed to this method when Triana calls it, for example after the user changes the value of the parameter in the parameter window. The format of this line is the same as in the reset method except that the character-string value of the parameter is held here in the variable named value, which is another argument of this method.
    9. In MercPert we have to do a little work on some of the parameters to get the information out of them that we need. This is done by the method decodeParameterString, which is not a standard Triana method but is part of the code created specially for this unit and for other units that need to do similar things.
  3. There are other possible places where you need to understand how Triana works with units.
    1. In the init method there are lines that define the maximum and minimum number of output and input nodes. Normally you will not need to change these.
    2. When a unit wants to do output, the simplest way is to use the method called output. This works only if there is only one data set to be output. If, as in MercPert, there are more than one, then you have to assign them to different output nodes, and this is done with the method outputAtNode. The code is pretty self-explanatory.
    3. The variable that is given to the output methods to pass on to the next unit is not a simple internal variable. Triana uses specific objects that are designed not only to transport data but to tell the grapher units enough information to allow them to be graphed. Gravity from the ground up uses the data type Curve, which is defined elsewhere in Triana. To create a Curve for passing data, you use the syntax
    4.     new Curve( x, y )
      in which a new Object of this type is created from two double[] arrays called x and y, which hold the x- and y-coordinate values of the points to be plotted on the curve. When a Curve Object arrives at, for example, SGTGrapher, it automatically plots the data in the right way.
Re-compiling the code. When you have finished modifying the code (and saved it in the file bearing the name of the tool and the extension ".java"), then it has to be re-compiled and re-integrated into the Triana environment, so that all of Triana knows how to work with the unit. A lot of things happen behind the scenes, but you don't have to worry about them. First, in the main menu "Options/Triana Options ...", go to the "external Tools" tab and fill in the path for the javac compiler, which comes with the full Java development kit. You go to the directory where you put the kit, go to the "bin" directory, and find the file called "javac" or "javac.exe", depending on what operating system you are using. Write the full path to this file into the options window.

The compile wizard. Next, go to Triana's main menu bar, select the "Tools" menu, choose "Compile Unit/Generate Tool XML ...", and look at the window (called the compile wizard) that pops up. It seems rather complicated, but it will largely fill itself in if you do the right things. First, make sure that the third line shows the path to the toolboxes you are using, which is generally the default value that comes up. Then in the second line click on the little square window containing "...", which opens a file browser where you select the source file for the tool you are modifying. You will have to follow the path from the toolbox name through the directory "src" to the list of files of type ".java". Select the one you have modified and press "OK". This fills in all the relevant lines of the compile wizard. Just press "OK" again at the bottom of the compile wizard. Triana will invoke your javac compiler. If you have not made any errors in coding the changes, Triana will show you a window confirming that the compilation has gone well. You are done!

Coping with errors. If you are unlucky enough to have had errors, Triana will keep the compile wizard window open and also show you a window containing the error messages from the javac compiler. Make the corrections required and then hit "OK" again in the wizard window. You may have to go through this cycle several times if you have made complicated changes or if you are a novice programmer and need to learn from your mistakes!!

When the compiling is finishes, you should be able to pull the unit out of the toolbox and use it with the grapher or other output units. It is possible that, when you start the network, you will get further error messages. These are called "run-time errors", and represent things that go wrong, not because you have made a mistake in using the Java language, but because you have made a mistake in the way different parts of the program interact with one another so that the normal execution could not proceed. The javac compile cannot anticipate all such possibilities. Sometimes Triana pops up an error message, other times the program stops and you have to look at the command window within which Triana is running for the error message output. These generally are very helpful, pointing you to exactly the line in your code where the problem was encountered. You need to change your code, re-compile, and re-run in order to fix such problems.
 


The ultimate: creating new units in Triana

Programmers who have gained confidence with Triana by modifying code, as in the last section, may want to go further and create programs to do different things from the ones provided for Gravity from the ground up. Triana provides tools to help with this process too. Not only does it provide an extra unit-creation wizard, but it provides extensive help documentation for all aspects of the process.

The unit creation wizard. The main additional tool is the unit creation wizard. This is a more elaborate affair than the compile wizard. Go to the main Triana menu bar, select "Tools", and select "New Unit". This opens the wizard in a separate window. As with the compile wizard, first go to the third line and choose the main toolbox path that you want the unit to be in. You can add units to the standard Triana toolboxes, but you may want to create your own toolbox for tools you created. You do this in the main "Tools/Edit Toolbox Path" menu. Having set up a directory, which can be anywhere on your disk, for new tools, select this in the third line of the first window of the wizard. Then, again as for compiling, select the box "..." in the second line, and within the file browser find the toolbox name in which you will store the new tool. Then enter the name of the new unit into the first line of this window. Fill in other other lines, like the author name, the popup description (which will appear when you hover the mouse over the unit), the date, and the name of the help file (which you should always write). Then choose options regarding the number of input and output nodes, which depends on what you want the unit to do. Then press "Next".

The window changes into one that allows you to define the data types the new unit will input and output. If you want to deviate from the pattern of this book (no input, Curve output) then you should read the documentation that comes with Triana to see what data types are available. After selecting the types, press "Next" again.

The next window allows you to define the parameters you will use in the new unit. All the properties of the parameters are decided here. You may add parameter, remove mistaken ones, and change their properties at any time, even coming back to this screen from later ones by using the "Back" button. Of course you do not need to define any parameters if you do not need them.

The next window allows you to set up the way the parameter window of your unit will work. Select "GUI Builder Interface". For each of the parameters you have defined to be user accessible, Triana will allow you to specify the text that appears in the window near the parameter (enter this in the "Title" field), to enter the default value of the parameter, and to select how changes in this value are to be made in the parameter window (a text entry, a slider, a choice box, etc.). When you have entered the information for all parameters, select "Preview GUI" to make sure the window looks as you want it. Then press "Next". You will get a final confirmation screen.

What happens next. When you finish this wizard, Triana will create several files for you, including the ".java" file containing the source code. It will have all the code for parameter handling that was described in the previous section, and all the other auxilliary code you need. It will contain a process method, but it will be essentially empty. This is where you have to write the code for what you want the unit to do. The toolbox will contain the icon of your unit, but you will not be able to drag it into the working space yet because you have not compiled it.

The remaining work is just like the work for changing a unit, described in the previous section. You go to the icon of your new unit in the toolbox, and open the editor. Then you create the code for your unit, not forgetting the final output step! Then compile it and run it!

Congratulations! If you have succeeded in this task, then you are a real Triana programmer. You might want to go to the Triana website and download the full version, which contains a wealth of tools that are not part of the distribution for this book. These do image processing, text processing, signal processing, sound processing, and other jobs. Welcome to the Triana developer community!