BEAST Apps for the AppStore

4 August 2014 by Remco Bouckaert

Say, you have some post-processing classes written for your package and you want to make it available to users. Since the class is in your package, say mypackage.addon.jar and most likely you need classes from BEAST-core or other packages, it is a nuisance to set the class path from the command line. You’ll and up having to do something like

java -cp /path/to/beast/lib/beast.jar:~/.beast/2.1/MyPackage/lib/mypackage.addon.jar arg1 arg2 arg3

This is especially cumbersome to explain to users since these paths depend on where BEAST is installed and where packages are installed. These paths are operating system dependent. One solution to this is to use the BEAST AppStore. This is an application that comes with BEAST. It picks up information from the version.xml file. You specify an addonapp element with a description, class, default arguments and an icon. For example, the model-selection package contains an application to run a path sampling analysis, which is encoded like so:

<addon name='MODEL-SELECTION' version='1.0.2'>
    <depends on='beast2' atleast='2.1.2'/>
    <addonapp description="Path sampler"

When you start the AppStore, it will look like this:

If you launch it from the AppStore, you probably want to launch it as a GUI, since Windows and Mac users won’t be able to see any terminal input otherwise. You can write your own GUI in Swing or JavaFX if you like, but there are a few helper classes that make it very easy to write GUI applications with BEAST. The recipe is as follows:

  1. Create a class for your App that derives from beast.core.Runnable.
  2. Specify Inputs for each of the arguments for your application.
  3. Implement the run() method to pick up values from inputs and run your app.
  4. Create a class to launch the App.
  5. Update the version.xml file

Path sample analyser application

Step 1: create class for App

The path sample analyser lives in the class beast.inference.PathSampleAnalyser and derives from beast.core.Runnable.

@Description("Reads logs produces through PathSampler and estimates marginal likelihood")
public class PathSampleAnalyser extends beast.core.Runnable {

Step 2: specify inputs

For the path sample analyser, we need a root directory, alpha, number of steps and burnin as a percentage. So, we add the following Inputs to the class.

public Input<String> rootDirInput = new Input<String>("rootdir", "root directory for storing particle states and log files (default /tmp)", "/tmp");
public Input<Double> alphaInput = new Input<Double>("alpha", "alpha parameter of Beta(alpha,1) distribution used to space out steps, default 0.3" +
		"If alpha <= 0, uniform intervals are used.", 0.3);
public Input<Integer> stepsInput = new Input<Integer>("nrOfSteps", "the number of steps to use, default 8", 8);
public Input<Integer> burnInPercentageInput = new Input<Integer>("burnInPercentage", "burn-In Percentage used for analysing log files", 50);

Step 3: implement run() method

The actual post-processing happens in the method estimateMarginalLikelihood. The run method just gather info from the inputs and passes it to that worker method.

public void run() throws Exception {
    // do the work

    double marginalL = estimateMarginalLikelihood(

	// report the result       

	System.out.println("marginal L estimate = " + marginalL);

Step 4: Create launcher class

Create a class to launch the App. This is the class that you register in the version.xml file. The following bit of code can be used as a template for your own app — just replace the class for the analyser variable and update name and title. It uses two utility classes and (currently in the model-selection package, but it should probably move somewhere else). You can also suppress inputs that you do not want to expose to the user.



//command line interface to PathSampleAnalyser

public class PathSampleAnalyser {
	public static void main(final String[] args) throws Exception {
		Application main = null;
		try {
			// create the runnable class with application that we want to launch

			beast.inference.PathSampleAnalyser analyser = new beast.inference.PathSampleAnalyser();
			// need to set the ID of the BEAST-object

			// then initialise

			// create BeautiDoc and beauti configuration

			BeautiDoc doc = new BeautiDoc();
			doc.beautiConfig = new BeautiConfig();

			// This is how you suppress an input that we don't want to expose to the user

			// doc.beautiConfig.suppressPlugins.add(analyser.getClass().getName() + ".input-name");

			// create panel with entries for the application

			BEASTObjectPanel panel = new BEASTObjectPanel(analyser, analyser.getClass(), doc);
			// wrap panel in a dialog

			BEASTObjectDialog dialog = new BEASTObjectDialog(panel, null);
			if (dialog.showDialog()) {
				dialog.accept(analyser, doc);

				// create a console to show standard error and standard output

				analyser.consoleApp = new ConsoleApp("PathSampleAnalyser", // name 

						"Path Sample Analyser: " + analyser.rootDirInput.get() // console title

		} catch (Exception e) {
			if (main != null) {


Update the version.xml file

Add an addonapp element to the version.xml file, so the AppStore can pick it up.

    <addonapp description="Path Sample Analyser"

When launching the PathSampleAnalyser from the AppStore, it looks like this: