[med-svn] [beast2-mcmc] 01/03: Imported Upstream version 2.3.2+dfsg

Andreas Tille tille at debian.org
Mon Nov 30 21:08:27 UTC 2015


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository beast2-mcmc.

commit 5067c09383b7697737f83b52cdb36ae64a885d57
Author: Andreas Tille <tille at debian.org>
Date:   Mon Nov 30 22:06:03 2015 +0100

    Imported Upstream version 2.3.2+dfsg
---
 build.xml                                          |   4 +-
 .../figures/BEAUti_DataPartitions.png              | Bin 85593 -> 44401 bytes
 doc/tutorials/STARBEAST/StarBEAST_tutorial.bib     |  20 +
 doc/tutorials/STARBEAST/StarBEAST_tutorial.tex     |  72 +++-
 doc/tutorials/STARBEAST/figures/BEAST.png          | Bin 98804 -> 101788 bytes
 lib/antlr-runtime-4.5.jar                          | Bin 374042 -> 0 bytes
 release/Linux/bin/loganalyser                      |  33 ++
 release/common/README.txt                          |  16 +-
 release/common/VERSION HISTORY.txt                 |  32 +-
 release/common/tools/DensiTree.jar                 | Bin 2325714 -> 0 bytes
 src/beast/app/BEASTVersion.java                    |   4 +-
 src/beast/app/beastapp/BeastMain.java              |   9 +-
 src/beast/app/beauti/BeautiAlignmentProvider.java  |   9 +-
 src/beast/app/beauti/BeautiDoc.java                |  13 +-
 src/beast/app/beauti/BeautiSubTemplate.java        |  22 ++
 src/beast/app/beauti/PriorInputEditor.java         |  52 ++-
 src/beast/app/beauti/SiteModelInputEditor.java     |   3 +
 src/beast/app/beauti/TaxonSetInputEditor.java      |   4 +
 src/beast/app/beauti/TipDatesInputEditor.java      |  52 ++-
 src/beast/app/draw/IntegerListInputEditor.java     | 419 +++++++++++++++++++++
 src/beast/app/draw/ParameterInputEditor.java       |  27 +-
 src/beast/app/tools/LogCombiner.java               |  10 +
 src/beast/app/tools/LogCombinerDialog.java         |   2 +-
 src/beast/core/Logger.java                         |   2 +
 src/beast/core/MCMC.java                           |   4 +-
 src/beast/core/State.java                          |   2 +-
 src/beast/evolution/operators/NodeReheight.java    |   9 +
 src/beast/evolution/operators/SubtreeSlide.java    |  23 +-
 src/beast/evolution/operators/TreeOperator.java    |   4 +-
 src/beast/evolution/speciation/RandomGeneTree.java |   5 +-
 .../GeneralSubstitutionModel.java                  |  13 +-
 src/beast/evolution/tree/RandomTree.java           | 192 +++++++---
 src/beast/evolution/tree/TreeInterface.java        |   2 +-
 src/beast/math/distributions/MRCAPrior.java        | 121 ++++--
 src/beast/math/statistic/RPNcalculator.java        |  13 +
 src/beast/util/AddOnManager.java                   |  80 ++--
 src/beast/util/LogAnalyser.java                    | 120 +++++-
 src/beast/util/TreeParser.java                     |  22 +-
 src/beast/util/XMLProducer.java                    |   2 +-
 src/test/beast/util/TreeParserTest.java            |   3 +-
 40 files changed, 1207 insertions(+), 213 deletions(-)

diff --git a/build.xml b/build.xml
index 1994e77..a20c428 100644
--- a/build.xml
+++ b/build.xml
@@ -215,8 +215,8 @@
 
 
     <!-- Release -->
-    <property name="version" value="2.3.1" />
-    <property name="version_number" value="2.3.1" />
+    <property name="version" value="2.3.2" />
+    <property name="version_number" value="2.3.2" />
     <property name="release_dir" value="release" />
     <property name="copyright" value="Beast 2 development team 2011-2015" />
 
diff --git a/doc/tutorials/DivergenceDating/figures/BEAUti_DataPartitions.png b/doc/tutorials/DivergenceDating/figures/BEAUti_DataPartitions.png
index 635ebb9..14e3d01 100644
Binary files a/doc/tutorials/DivergenceDating/figures/BEAUti_DataPartitions.png and b/doc/tutorials/DivergenceDating/figures/BEAUti_DataPartitions.png differ
diff --git a/doc/tutorials/STARBEAST/StarBEAST_tutorial.bib b/doc/tutorials/STARBEAST/StarBEAST_tutorial.bib
index 71b868a..c8b6a80 100644
--- a/doc/tutorials/STARBEAST/StarBEAST_tutorial.bib
+++ b/doc/tutorials/STARBEAST/StarBEAST_tutorial.bib
@@ -30,3 +30,23 @@
 	Volume = {57},
 	Year = {2008}}
 
+
+ at article{beast,
+        Author = {Bouckaert, Remco R. and Heled, Joseph and K{\"u}hnert, Denise 
+and Vaughan, Tim and Wu, Chieh-Hsi and Xie, Dong and Suchard, Marc A and Rambaut
+, Andrew and Drummond, Alexei J},
+        Date-Added = {2014-05-21 03:24:22 +0000},
+        Date-Modified = {2014-07-06 03:46:41 +0000},
+        Doi = {10.1371/journal.pcbi.1003537},
+        Journal = {PLoS Comput Biol},
+        Journal-Full = {PLoS computational biology},
+        Month = {Apr},
+        Number = {4},
+        Pages = {e1003537},
+        Pmc = {PMC3985171},
+        Pmid = {24722319},
+        Pst = {epublish},
+        Title = {BEAST 2: a software platform for Bayesian evolutionary analysis},
+        Volume = {10},
+        Year = {2014},
+        Bdsk-Url-1 = {http://dx.doi.org/10.1371/journal.pcbi.1003537}}
diff --git a/doc/tutorials/STARBEAST/StarBEAST_tutorial.tex b/doc/tutorials/STARBEAST/StarBEAST_tutorial.tex
index 488525d..efbdac7 100644
--- a/doc/tutorials/STARBEAST/StarBEAST_tutorial.tex
+++ b/doc/tutorials/STARBEAST/StarBEAST_tutorial.tex
@@ -17,7 +17,7 @@
 }
 
 % BEAST book specific commands
-\newcommand{\BEASTVersion}{2.2.x}
+\newcommand{\BEASTVersion}{2.3.x}
 \newcommand{\TracerVersion}{1.6}
 \newcommand{\FigTreeVersion}{1.4.2}
 
@@ -42,12 +42,12 @@ You will need the following software at your disposal:
 
 \begin{itemize}
 
-\item {\bf BEAST} - this package contains the BEAST program, BEAUti, TreeAnnotator and other utility programs. This tutorial is written for BEAST v{\BEASTVersion}, which has support for multiple partitions. It is available for download from \\* \texttt{http://www.beast2.org}.
+\item {\bf BEAST} \cite{beast}- this package contains the BEAST program, BEAUti, TreeAnnotator and other utility programs. This tutorial is written for BEAST v{\BEASTVersion}, which has support for multiple partitions. It is available for download from \texttt{http://beast2.org}.
 \item {\bf Tracer} - this program is used to explore the output of BEAST (and other Bayesian MCMC programs). It graphically and
 quantitively summarizes the distributions of continuous parameters and provides diagnostic information. At the time of
-writing, the current version is v{\TracerVersion}. It is available for download from \texttt{http://beast.bio.ed.ac.uk/}.
+writing, the current version is v{\TracerVersion}. It is available for download from \texttt{http://tree.bio.ed.ac.uk/software/figtree/}.
 \item {\bf FigTree} - this is an application for displaying and printing molecular phylogenies, in particular those obtained using
-BEAST. At the time of writing, the current version is v{\FigTreeVersion}. It is available for download from \texttt{http://tree.bio.ed.ac.uk/}.
+BEAST. At the time of writing, the current version is v{\FigTreeVersion}. It is available for download from \texttt{http://tree.bio.ed.ac.uk/software/tracer/}.
 \end{itemize}
 
 \section{*BEAST}
@@ -62,7 +62,7 @@ Run BEAUti by double clicking on its icon.
 
 \subsubsection*{Set up BEAUti for *BEAST}
 
-*BEAST uses a different template from the standard. This means that to use BEAUti for *BEAST, the first thing to do is change the template. Choose the File/Templates/StarBeast item. When changing a template, BEAUti deletes all previously imported data and start with a new empty template. So, if you already loaded some data, a warning message pops up indicating that this data will be lost if you switch templates.
+*BEAST uses a different template from the standard. This means that to use BEAUti for *BEAST, the first thing to do is change the template. Choose the File/Template/StarBeast item. When changing a template, BEAUti deletes all previously imported data and start with a new empty template. So, if you already loaded some data, a warning message pops up indicating that this data will be lost if you switch templates.
 
 \begin{figure}
 \centering
@@ -289,7 +289,7 @@ look something like this:
 
 {\tiny   
 \begin{verbatim}
-                        BEAST v2.2.0, 2002-2014
+                      BEAST v2.3.1, 2002-2015
              Bayesian Evolutionary Analysis Sampling Trees
                        Designed and developed by
  Remco Bouckaert, Alexei J. Drummond, Andrew Rambaut & Marc A. Suchard
@@ -471,7 +471,7 @@ but there is some support (over 16\%) that it is not.
 \item Drag the clade monticola and idahoensis up so that the 95\% HPD bar does not overlap with the one for mazama, monticola, idahoensis and talpoidis. Increase font size of the label for better readability.
 \end{itemize}
 
-The image should look something like Figure \ref{fig.DensiTree}
+The image should look something like Figure \ref{fig.DensiTree}.
 
 \begin{figure}
 \centering
@@ -501,7 +501,7 @@ option for the top. This looks a bit prettier, but may not be quite accurate.
 \includeimage[scale=0.18]{figures/species_population2}
 \end{figure}
 
-Alternatively, a consensus tree can be generated by biopy (\url{http://code.google.com/p/biopy/})
+Alternatively, a consensus tree can be generated by biopy (\url{https://github.com/jheled/biopy})
 with using 1-norm left, and 2-norm right.
 
 \begin{figure}
@@ -527,6 +527,62 @@ Using BEAUti, set up the same analysis but under the MCMC options, select the {\
 distribution and compare the summary to the posterior summary tree.
 
 
+
+\section*{Bonus: Species delimitation using STACEY}
+
+Arguably, some of the gopher species in the dataset analysed so far belongs to a single species, judging from the posterior tree distribution in Figure \ref{fig.DensiTree}. To test this, we can run the same analysis as above with STACEY, which stands for Species Tree And Classification Estimation, Yarely. You need the following:
+\begin{itemize}
+\item STACEY package, easiest installed using the package manager from the BEAUti File/Manage packages menu.
+\item {\tt SpeciesDelimitationAnalyser}, available by downloading\\ {\tt http://www.indriid.com/2014/speciesDA.jar}.
+\end{itemize}
+
+You can find more documentation on how to set up an analysis and optimise some settings in the STACEY package documentation, which is part of the STACEY package (in the directory $<$BEAST package directory$>$/2.3/STACEY/doc/ where $<$BEAST package directory$>$ depends on the OS you are using. To find it, click the button with the question mark in the package manager dialog in BEAUti).
+
+To set up the analysis in BEAUti do the same as for the *BEAST analysis with the following changes:
+\begin{itemize}
+\item use the STACEY template instead of the StarBeast template.
+\item do {\bf not} change the tree prior in the priors tab.
+\item for the tutorial, set the chain length to 2 million for a coffee break of about 2 minutes, or higher to get more acceptable ESSs (and a longer coffee break).
+\end{itemize}
+
+Save the XML file and run it with BEAST.
+
+Analyse the log file using 
+\begin{verbatim}
+java -jar /path/to/speciesDA.jar -burnin 10 species_123456.trees out.txt
+\end{verbatim}
+where the number 123455 should be equal to the seed used to run BEAST. This creates a file {\tt out.txt} which looks something like this:
+
+\newpage
+{\tiny
+\begin{verbatim}
+count      fraction               similarity             nclusters  talpoides idahoensis townsendii umbrinus monticola bottae heterodus mazama 
+16         0.08376963350785341    165.85714285714275     5          1    4    5    5    4    5    2    3    
+19         0.09947643979057591    151.21428571428558     5          4    1    5    5    2    5    3    4    
+104        0.5445026178010471     139.92857142857142     6          1    2    6    6    3    6    4    5    
+2          0.010471204188481676   21.53571428571428      5          1    2    5    5    4    5    3    4    
+11         0.05759162303664921    17.5                   5          4    1    5    5    4    5    2    3    
+1          0.005235602094240838   15.85714285714286      6          5    1    2    6    5    6    3    4    
+2          0.010471204188481676   15.000000000000002     4          3    3    4    4    3    4    1    2    
+6          0.031413612565445025   14.57142857142857      7          1    2    3    7    4    7    5    6    
+10         0.05235602094240838    10.0                   4          2    3    4    4    3    4    1    2    
+2          0.010471204188481676   8.5                    5          1    4    5    5    2    5    3    4    
+1          0.005235602094240838   7.607142857142858      8          1    2    3    4    5    6    7    8    
+2          0.010471204188481676   4.7857142857142865     4          3    3    4    4    1    4    2    3    
+3          0.015706806282722512   3.9642857142857144     5          4    4    5    5    1    5    2    3    
+2          0.010471204188481676   3.857142857142857      6          1    5    2    6    5    6    3    4    
+2          0.010471204188481676   2.928571428571429      7          1    2    7    3    4    7    5    6    
+2          0.010471204188481676   2.0                    6          5    1    2    6    3    6    4    5    
+2          0.010471204188481676   2.0                    4          3    1    4    4    3    4    2    3    
+2          0.010471204188481676   2.0                    4          1    3    4    4    3    4    2    3    
+1          0.005235602094240838   1.0                    7          1    2    7    7    3    4    5    6    
+1          0.005235602094240838   1.0                    4          2    2    4    4    3    4    1    3 
+\end{verbatim}
+}
+
+Note that the third line (with count=104) suggests more than half the time the taxa townsendi, umbrinus and bottea form a single species.
+
+
 \bibliographystyle{plain}
 \bibliography{StarBEAST_tutorial}
 
diff --git a/doc/tutorials/STARBEAST/figures/BEAST.png b/doc/tutorials/STARBEAST/figures/BEAST.png
index cfef1e6..beecda9 100644
Binary files a/doc/tutorials/STARBEAST/figures/BEAST.png and b/doc/tutorials/STARBEAST/figures/BEAST.png differ
diff --git a/lib/antlr-runtime-4.5.jar b/lib/antlr-runtime-4.5.jar
deleted file mode 100644
index a35fee1..0000000
Binary files a/lib/antlr-runtime-4.5.jar and /dev/null differ
diff --git a/release/Linux/bin/loganalyser b/release/Linux/bin/loganalyser
new file mode 100755
index 0000000..a45478d
--- /dev/null
+++ b/release/Linux/bin/loganalyser
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+if [ -z "$BEAST" ]; then
+	## resolve links - $0 may be a link to application
+	PRG="$0"
+
+	# need this for relative symlinks
+	while [ -h "$PRG" ] ; do
+	    ls=`ls -ld "$PRG"`
+	    link=`expr "$ls" : '.*-> \(.*\)$'`
+	    if expr "$link" : '/.*' > /dev/null; then
+		PRG="$link"
+	    else
+		PRG="`dirname "$PRG"`/$link"
+	    fi
+	done
+
+	# make it fully qualified
+	saveddir=`pwd`
+	BEAST0=`dirname "$PRG"`/..
+	BEAST=`cd "$BEAST0" && pwd`
+	cd "$saveddir"
+fi
+
+BEAST_LIB="$BEAST/lib"
+
+if [ -z "$JAVA_HOME" ]; then
+  JAVA=java
+else
+  JAVA=$JAVA_HOME/bin/java
+fi
+$JAVA -Xms256m -Xmx4g -Djava.library.path="$BEAST_LIB" -cp "$BEAST_LIB/beast.jar" beast.util.LogAnalyser $*
+
diff --git a/release/common/README.txt b/release/common/README.txt
index d115a3f..a19fbfb 100644
--- a/release/common/README.txt
+++ b/release/common/README.txt
@@ -1,7 +1,7 @@
-                    BEAST v2.3.1 2015
+                    BEAST v2.3.2 2015
                  Beast 2 development team 2011-2015
 
-Last updated: September 2015
+Last updated: December 2015
 
 Contents:
 1) INTRODUCTION
@@ -91,12 +91,11 @@ BEAUti program from a NEXUS format file.
 For documentation on creating and tuning the input files look at the
 documentation and tutorials on-line at:
 
-Help -      <http://www.beast2.org/>
-FAQ -       <http://www.beast2.org/wiki/index.php/FAQ>
-Tutorials - <http://www.beast2.org/wiki/index.php/Main_Page#BEAST_2_Tutorials>
+Help -      <http://beast2.org/>
+FAQ -       <http://beast2.org/faq/>
+Tutorials - <http://beast2.org/tutorials/>
 
 BEAST arguments:
-
     -window Provide a console window
     -options Display an options dialog
     -working Change working directory to input file's directory
@@ -105,6 +104,7 @@ BEAST arguments:
     -statefile Specify the filename for storing/restoring the state
     -overwrite Allow overwriting of log files
     -resume Allow appending of log files
+    -validate Parse the XML, but do not run -- useful for debugging XML
     -errors Specify maximum number of numerical errors before stopping
     -threads The number of computational threads to use (default auto)
     -java Use Java only, no native implementations
@@ -155,7 +155,7 @@ BEAGLE by default and this can speed up running BEAST considerably. The
 BEAGLE library needs to be installed separately from BEAST, and can be 
 obtained from:
 
-http://code.google.com/p/beagle-lib/
+https://github.com/beagle-dev/beagle-lib/blob/master/README.md
 
 
 ___________________________________________________________________________
@@ -187,7 +187,7 @@ The BEAST users' mailing-list
 
 The website for beast is here:
 
-<http://www.beast2.org/>
+<http://beast2.org/>
 
 Source code distributed under the GNU Lesser General Public License:
 
diff --git a/release/common/VERSION HISTORY.txt b/release/common/VERSION HISTORY.txt
index 23f6246..586abd6 100644
--- a/release/common/VERSION HISTORY.txt	
+++ b/release/common/VERSION HISTORY.txt	
@@ -1,20 +1,40 @@
-                    BEAST v2.3.1 2015
+                    BEAST v2.3.2 2015
                  Beast 2 development team 2011-2015
 Version History
-Last updated: September 2015
+Last updated: December 2015
 
 All issues can be viewed at https://github.com/CompEvol/beast2/issues
 ================================================================================
+Version 2.3.2 December 2015
+	BEAUti
+		path corrected so Standard and StarBeast templates are visible under templates menu
+		import of traits from file when partions are split fixed
+		cloning of scripts with partition information fixed
+		set up weights of FixedMeanRate operator when ascertainment correction is applied
+		allows ParameterInputEditor to edit Parameter inputs
+		
+	BEAST
+		add "-validate" command line option for parsing XML files without running them
+		more efficient MRCAPrior
+		more robust RandomTree
+	
+	LogCombiner
+		ensured logcombiner burn in editing finished properly
+		
+	LogAnalyser now has one line per file mode, and CLI script added for ease of launch
+		
+	More sensible error messages (in TreeParser, RPNCalculator, NodeReheight, and more).
+
 Version 2.3.1 September 2015
-        BEAUti fixes
-           robustify (un)linking
+     BEAUti
+       robustify (un)linking
 	   improved Fasta import
 
 	BEAST
 	   support for uncertain alignments (see examples/testJukesCantorShortUncertain.xml) 
-           improved error messages
+       improved error messages
 
-        TreeAnnotator allows lower memory consumption
+    TreeAnnotator allows lower memory consumption
 
 	AppStore, LogCombiners, LogAnalyser improved command line interface 
 
diff --git a/release/common/tools/DensiTree.jar b/release/common/tools/DensiTree.jar
deleted file mode 100644
index 2aad9cc..0000000
Binary files a/release/common/tools/DensiTree.jar and /dev/null differ
diff --git a/src/beast/app/BEASTVersion.java b/src/beast/app/BEASTVersion.java
index 30cfa0a..e9fd538 100644
--- a/src/beast/app/BEASTVersion.java
+++ b/src/beast/app/BEASTVersion.java
@@ -19,11 +19,11 @@ public class BEASTVersion extends Version {
     /**
      * Version string: assumed to be in format x.x.x
      */
-    private static final String VERSION = "2.3.1";
+    private static final String VERSION = "2.3.2";
 
     private static final String DATE_STRING = "2002-2015";
 
-    private static final boolean IS_PRERELEASE = false;
+    private static final boolean IS_PRERELEASE = true;
 
     private static final String BEAST2_WEBPAGE = "http://beast2.org/";
     
diff --git a/src/beast/app/beastapp/BeastMain.java b/src/beast/app/beastapp/BeastMain.java
index f47ddcd..ff89f9d 100644
--- a/src/beast/app/beastapp/BeastMain.java
+++ b/src/beast/app/beastapp/BeastMain.java
@@ -250,6 +250,7 @@ public class BeastMain {
                         new Arguments.StringOption("statefile", "STATEFILE", "Specify the filename for storing/restoring the state"),
                         new Arguments.Option("overwrite", "Allow overwriting of log files"),
                         new Arguments.Option("resume", "Allow appending of log files"),
+                        new Arguments.Option("validate", "Parse the XML, but do not run -- useful for debugging XML"),
                         // RRB: not sure what effect this option has
                         new Arguments.IntegerOption("errors", "Specify maximum number of numerical errors before stopping"),
                         new Arguments.IntegerOption("threads", "The number of computational threads to use (default auto)"),
@@ -291,6 +292,7 @@ public class BeastMain {
         final boolean window = arguments.hasOption("window");
         final boolean options = arguments.hasOption("options");
         final boolean working = arguments.hasOption("working");
+        final boolean doNotRun = arguments.hasOption("validate");
         String fileNamePrefix = null;
         String stateFileName = null;
         //boolean allowOverwrite = arguments.hasOption("overwrite");
@@ -592,8 +594,11 @@ public class BeastMain {
             MCMCargs.add(inputFile.getAbsolutePath());
             beastMCMC.parseArgs(MCMCargs.toArray(new String[0]));
             
-
-            new BeastMain(beastMCMC, consoleApp, maxErrorCount);
+            if (!doNotRun) {
+            	new BeastMain(beastMCMC, consoleApp, maxErrorCount);
+            } else {
+            	Log.info.println("Done!");
+            }
         } catch (RuntimeException rte) {
             if (window) {
                 // This sleep for 2 seconds is to ensure that the final message
diff --git a/src/beast/app/beauti/BeautiAlignmentProvider.java b/src/beast/app/beauti/BeautiAlignmentProvider.java
index c346df3..820e165 100644
--- a/src/beast/app/beauti/BeautiAlignmentProvider.java
+++ b/src/beast/app/beauti/BeautiAlignmentProvider.java
@@ -57,7 +57,7 @@ public class BeautiAlignmentProvider extends BEASTObject {
 	List<BEASTInterface> getAlignments(BeautiDoc doc) {
         File [] files = beast.app.util.Utils.getLoadFiles("Load Alignment File",
                 new File(Beauti.g_sDir), "Alignment files", "xml", 
-                "fas","fst","fasta","fna","ffn","faa","frn",
+                "fa","fas","fst","fasta","fna","ffn","faa","frn",
                 "nex","nxs","nexus");
         if (files != null && files.length > 0) {
             return getAlignments(doc, files);
@@ -134,6 +134,7 @@ public class BeautiAlignmentProvider extends BEASTObject {
 					selectedPlugins.add(alignment);
 					break;
 
+				case ".fa":
 				case ".fas":
 				case ".fasta":
 				case ".fst":
@@ -145,6 +146,12 @@ public class BeautiAlignmentProvider extends BEASTObject {
 					Alignment.sortByTaxonName(alignment.sequenceInput.get());
 					selectedPlugins.add(alignment);
 					break;
+
+                default:
+                    JOptionPane.showMessageDialog(null,
+                            "Unsupported sequence file extension.",
+                            "Error", JOptionPane.ERROR_MESSAGE);
+                    break;
 			}
         }
         for (BEASTInterface plugin : selectedPlugins) {
diff --git a/src/beast/app/beauti/BeautiDoc.java b/src/beast/app/beauti/BeautiDoc.java
index c86e7b1..7b44194 100644
--- a/src/beast/app/beauti/BeautiDoc.java
+++ b/src/beast/app/beauti/BeautiDoc.java
@@ -1859,10 +1859,17 @@ public class BeautiDoc extends BEASTObject implements RequiredInputProvider {
                         // handle Plugin
                     	BEASTInterface value = getCopyValue((BEASTInterface) input.get(), copySet, partitionContext, doc);
                         copy.setInputValue(input.getName(), value);
-                    } else {
+                    } else if (input.get() instanceof String) {
+                		// may need to replace partition info
+                		String s = (String) input.get();
+                		s = s.replaceAll("\\.c:[a-zA-Z0-9_]*", ".c:" + partitionContext.clockModel);
+                		s = s.replaceAll("\\.s:[a-zA-Z0-9_]*", ".s:" + partitionContext.siteModel);
+                		s = s.replaceAll("\\.t:[a-zA-Z0-9_]*", ".t:" + partitionContext.tree);
+                		copy.setInputValue(input.getName(), s);
+                	} else {
                         // it is a primitive value
-                        copy.setInputValue(input.getName(), input.get());
-                    }
+                		copy.setInputValue(input.getName(), input.get());
+                	}
                 }
             }
 
diff --git a/src/beast/app/beauti/BeautiSubTemplate.java b/src/beast/app/beauti/BeautiSubTemplate.java
index cf834b9..164051b 100644
--- a/src/beast/app/beauti/BeautiSubTemplate.java
+++ b/src/beast/app/beauti/BeautiSubTemplate.java
@@ -45,6 +45,10 @@ public class BeautiSubTemplate extends BEASTObject {
     public Input<String> sXMLInput = new Input<String>("value", "collection of objects to be created in Beast2 xml format", Validate.REQUIRED);
     public Input<List<BeautiConnector>> connectorsInput = new Input<List<BeautiConnector>>("connect", "Specifies which part of the template get connected to the main network", new ArrayList<BeautiConnector>());
     public Input<String> suppressedInputs = new Input<String>("suppressInputs", "comma separated list of inputs that should not be shown");
+    public Input<String> inlineInput = new Input<String>("inlineInputs", "comma separated list of inputs that should " +
+            "go inline, e.g. beast.evolution.sitemodel.SiteModel.substModel");
+    public Input<String> collapsedInput = new Input<String>("collapsedInputs", "comma separated list of inputs that should " +
+            "go inline, but are initially collapsed, e.g. beast.core.MCMC.logger");
 
     Class<?> _class = null;
     Object instance;
@@ -353,6 +357,7 @@ public class BeautiSubTemplate extends BEASTObject {
                     doc.tipTextMap.put(ID, tipText);
                 }
             }
+
             if (suppressedInputs.get() != null) {
                 String[] inputs = suppressedInputs.get().split(",");
                 for (String input : inputs) {
@@ -360,6 +365,23 @@ public class BeautiSubTemplate extends BEASTObject {
                     doc.beautiConfig.suppressPlugins.add(input);
                 }
             }
+
+            if (inlineInput.get() != null) {
+                String[] inputs = inlineInput.get().split(",");
+                for (String input : inputs) {
+                    input = input.trim();
+                    doc.beautiConfig.inlinePlugins.add(input);
+                }
+            }
+
+            if (collapsedInput.get() != null) {
+                String[] inputs = collapsedInput.get().split(",");
+                for (String input : inputs) {
+                    input = input.trim();
+                    doc.beautiConfig.collapsedPlugins.add(input);
+                }
+            }
+
         } catch (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
diff --git a/src/beast/app/beauti/PriorInputEditor.java b/src/beast/app/beauti/PriorInputEditor.java
index b6463e0..09ba5fd 100644
--- a/src/beast/app/beauti/PriorInputEditor.java
+++ b/src/beast/app/beauti/PriorInputEditor.java
@@ -15,6 +15,7 @@ import beast.app.draw.InputEditor;
 import beast.app.draw.BEASTObjectDialog;
 import beast.core.Input;
 import beast.core.BEASTInterface;
+import beast.core.parameter.IntegerParameter;
 import beast.core.parameter.RealParameter;
 import beast.math.distributions.Prior;
 
@@ -83,20 +84,36 @@ public class PriorInputEditor extends InputEditor.Base {
             // add range button for real parameters
             RealParameter p = (RealParameter) prior.m_x.get();
             JButton rangeButton = new JButton(paramToString(p));
-            rangeButton.addActionListener(new ActionListener() {
-                @Override
-                public void actionPerformed(ActionEvent e) {
-                    JButton rangeButton = (JButton) e.getSource();
-
-                    List<?> list = (List<?>) m_input.get();
-                    Prior prior = (Prior) list.get(itemNr);
-                    RealParameter p = (RealParameter) prior.m_x.get();
-                    BEASTObjectDialog dlg = new BEASTObjectDialog(p, RealParameter.class, doc);
-                    if (dlg.showDialog()) {
-                        dlg.accept(p, doc);
-                        rangeButton.setText(paramToString(p));
-                        refreshPanel();
-                    }
+            rangeButton.addActionListener(e -> {
+                JButton rangeButton1 = (JButton) e.getSource();
+
+                List<?> list = (List<?>) m_input.get();
+                Prior prior1 = (Prior) list.get(itemNr);
+                RealParameter p1 = (RealParameter) prior1.m_x.get();
+                BEASTObjectDialog dlg = new BEASTObjectDialog(p1, RealParameter.class, doc);
+                if (dlg.showDialog()) {
+                    dlg.accept(p1, doc);
+                    rangeButton1.setText(paramToString(p1));
+                    refreshPanel();
+                }
+            });
+            itemBox.add(Box.createHorizontalStrut(10));
+            itemBox.add(rangeButton);
+        } else if (prior.m_x.get() instanceof IntegerParameter) {
+            // add range button for real parameters
+            IntegerParameter p = (IntegerParameter) prior.m_x.get();
+            JButton rangeButton = new JButton(paramToString(p));
+            rangeButton.addActionListener(e -> {
+                JButton rangeButton1 = (JButton) e.getSource();
+
+                List<?> list = (List<?>) m_input.get();
+                Prior prior1 = (Prior) list.get(itemNr);
+                IntegerParameter p1 = (IntegerParameter) prior1.m_x.get();
+                BEASTObjectDialog dlg = new BEASTObjectDialog(p1, IntegerParameter.class, doc);
+                if (dlg.showDialog()) {
+                    dlg.accept(p1, doc);
+                    rangeButton1.setText(paramToString(p1));
+                    refreshPanel();
                 }
             });
             itemBox.add(Box.createHorizontalStrut(10));
@@ -123,4 +140,11 @@ public class PriorInputEditor extends InputEditor.Base {
                 "," + (upper == null ? "\u221E" : upper + "") + "]";
     }
 
+    String paramToString(IntegerParameter p) {
+        Integer lower = p.lowerValueInput.get();
+        Integer upper = p.upperValueInput.get();
+        return "initial = " + Arrays.toString(p.valuesInput.get().toArray()) +
+                " [" + (lower == null ? "-\u221E" : lower + "") +
+                "," + (upper == null ? "\u221E" : upper + "") + "]";
+    }
 }
diff --git a/src/beast/app/beauti/SiteModelInputEditor.java b/src/beast/app/beauti/SiteModelInputEditor.java
index f77a2c2..7db776b 100644
--- a/src/beast/app/beauti/SiteModelInputEditor.java
+++ b/src/beast/app/beauti/SiteModelInputEditor.java
@@ -230,6 +230,9 @@ public class SiteModelInputEditor extends BEASTObjectInputEditor {
 				GenericTreeLikelihood treelikelihood = (GenericTreeLikelihood) d;
 	    		Alignment data = treelikelihood.dataInput.get(); 
 	    		int weight = data.getSiteCount();
+	    		if (data.isAscertained) {
+	    			weight -= data.getExcludedPatternCount();
+	    		}
 	    		if (treelikelihood.siteModelInput.get() instanceof SiteModel) {
 		    		SiteModel siteModel = (SiteModel) treelikelihood.siteModelInput.get();
 		    		RealParameter mutationRate = siteModel.muParameterInput.get();
diff --git a/src/beast/app/beauti/TaxonSetInputEditor.java b/src/beast/app/beauti/TaxonSetInputEditor.java
index 8fe3a57..27a615c 100644
--- a/src/beast/app/beauti/TaxonSetInputEditor.java
+++ b/src/beast/app/beauti/TaxonSetInputEditor.java
@@ -26,6 +26,7 @@ import beast.core.Input;
 import beast.core.BEASTObject;
 import beast.core.BEASTInterface;
 import beast.evolution.alignment.Alignment;
+import beast.evolution.alignment.FilteredAlignment;
 import beast.evolution.alignment.Sequence;
 import beast.evolution.alignment.Taxon;
 import beast.evolution.alignment.TaxonSet;
@@ -376,6 +377,9 @@ public class TaxonSetInputEditor extends InputEditor.Base {
         Set<Taxon> taxa = new HashSet<Taxon>();
         Set<String> taxonIDs = new HashSet<String>();
         for (Alignment alignment : getDoc().alignments) {
+        	if (alignment instanceof FilteredAlignment) {
+        		alignment = ((FilteredAlignment)alignment).alignmentInput.get();
+        	}
             for (Sequence sequence : alignment.sequenceInput.get()) {
                 String sID = sequence.taxonInput.get();
                 if (!taxonIDs.contains(sID)) {
diff --git a/src/beast/app/beauti/TipDatesInputEditor.java b/src/beast/app/beauti/TipDatesInputEditor.java
index 65e66c0..3cd5eb3 100644
--- a/src/beast/app/beauti/TipDatesInputEditor.java
+++ b/src/beast/app/beauti/TipDatesInputEditor.java
@@ -4,10 +4,11 @@ import java.awt.Color;
 import java.awt.Component;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.EventObject;
-import java.util.List;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.*;
 
 import javax.swing.Box;
 import javax.swing.JButton;
@@ -37,6 +38,8 @@ public class TipDatesInputEditor extends BEASTObjectInputEditor {
     }
     private static final long serialVersionUID = 1L;
 
+    DateFormat dateFormat = DateFormat.getDateInstance();
+
     @Override
     public Class<?> type() {
         return Tree.class;
@@ -459,18 +462,45 @@ public class TipDatesInputEditor extends BEASTObjectInputEditor {
             return Double.parseDouble(sStr);
         } catch (NumberFormatException e) {
             // does not look like a number, try parsing it as a date
-            try {
                 if (sStr.matches(".*[a-zA-Z].*")) {
                     sStr = sStr.replace('/', '-');
                 }
-                long date = Date.parse(sStr);
-                return 1970.0 + date / (60.0 * 60 * 24 * 365 * 1000);
-            } catch (Exception e2) {
-                // does not look like a date, give up
-            }
 
+            //try {
+
+                // unfortunately this deprecated date parser is the most flexible around at the moment...
+                long time = Date.parse(sStr);
+                Date date = new Date(time);
+
+                // AJD
+                // Ideally we would use a non-deprecated method like this one instead but it seems to have
+                // far less support for different date formats.
+                // for example it fails on "12-Oct-2014"
+                //dateFormat.setLenient(true);
+                //Date date = dateFormat.parse(sStr);
+
+                Calendar calendar = dateFormat.getCalendar();
+                calendar.setTime(date);
+
+                // full year (e.g 2015)
+                int year = calendar.get(Calendar.YEAR);
+                double days = calendar.get(Calendar.DAY_OF_YEAR);
+
+                double daysInYear = 365.0;
+
+                if (calendar instanceof GregorianCalendar &&(((GregorianCalendar) calendar).isLeapYear(year))) {
+                    daysInYear = 366.0;
+                }
+
+                double dateAsDecimal = year + days/daysInYear;
+
+                return dateAsDecimal;
+            //}
+            //catch (ParseException e1) {
+            //    System.err.println("*** WARNING: Failed to parse '" + sStr + "' as date using dateFormat " + dateFormat);
+            //}
         }
-        return 0;
+        //return 0;
     } // parseStrings
 
     private String normalize(String sStr) {
diff --git a/src/beast/app/draw/IntegerListInputEditor.java b/src/beast/app/draw/IntegerListInputEditor.java
new file mode 100644
index 0000000..894bb9e
--- /dev/null
+++ b/src/beast/app/draw/IntegerListInputEditor.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2015 Tim Vaughan <tgvaughan at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package beast.app.draw;
+
+import beast.app.beauti.BeautiDoc;
+import beast.app.beauti.BeautiPanel;
+import beast.app.beauti.BeautiPanelConfig;
+import beast.core.BEASTInterface;
+import beast.core.Input;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.ListSelectionListener;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+
+public class IntegerListInputEditor extends ListInputEditor {
+	private static final long serialVersionUID = 1L;
+
+	public IntegerListInputEditor(BeautiDoc doc) {
+		super(doc);
+	}
+
+    @Override
+    public Class<?> type() {
+        return List.class;
+    }
+
+    /**
+     * return type of the list *
+     */
+    public Class<?> baseType() {
+        return Integer.class;
+    }
+    
+
+    
+    @SuppressWarnings("unchecked")
+	@Override
+    protected void initEntry() {
+        if (m_input.get() != null) {
+        	String str = "";
+        	for (Integer d : (List<Integer>) m_input.get()) {
+        		str += d + " ";
+        	}
+        	str = str.substring(0, str.length() - 1);
+            m_entry.setText(str);
+        }
+    }
+    
+        /**
+         * the input to be edited *
+         */
+        protected Input<?> m_input;
+
+        /**
+         * parent plugin *
+         */
+        protected BEASTInterface m_plugin;
+
+        /**
+         * text field used for primitive input editors *
+         */
+        protected JTextField m_entry;
+        
+        protected int itemNr;
+
+        public JTextField getEntry() {
+            return m_entry;
+        }
+
+        JLabel m_inputLabel;
+        protected static Dimension PREFERRED_SIZE = new Dimension(200, 25);
+        protected static Dimension MAX_SIZE = new Dimension(1024, 25);
+
+        /**
+         * flag to indicate label, edit and validate buttons/labels should be added *
+         */
+        protected boolean m_bAddButtons = true;
+
+        /**
+         * label that shows up when validation fails *
+         */
+        protected SmallLabel m_validateLabel;
+
+        /**
+         * document that we are editing *
+         */
+        protected BeautiDoc doc;
+
+        /**
+         * list of objects that want to be notified of the validation state when it changes *
+         */
+        List<InputEditor> m_validateListeners;
+
+        public void addValidationListener(InputEditor validateListener) {
+            if (m_validateListeners == null) {
+                m_validateListeners = new ArrayList<InputEditor>();
+            }
+            m_validateListeners.add(validateListener);
+        }
+
+        public void notifyValidationListeners(ValidationStatus state) {
+            if (m_validateListeners != null) {
+                for (InputEditor listener : m_validateListeners) {
+                    listener.startValidating(state);
+                }
+            }
+        }
+
+    	protected BeautiDoc getDoc() {
+            if (doc == null) {
+                Component c = this;
+                while (c.getParent() != null) {
+                    c = c.getParent();
+                    if (c instanceof BeautiPanel) {
+                        doc = ((BeautiPanel) c).getDoc();
+                    }
+                }
+            }
+            return doc;
+        }
+
+
+        public Class<?>[] types() {
+            Class<?>[] types = new Class<?>[1];
+            types[0] = type();
+            return types;
+        }
+
+        /**
+         * construct an editor consisting of a label and input entry *
+         */
+        public void init(Input<?> input, BEASTInterface plugin, int itemNr, ExpandOption bExpandOption, boolean bAddButtons) {
+            m_bAddButtons = bAddButtons;
+            m_input = input;
+            m_plugin = plugin;
+            this.itemNr= itemNr;
+            
+            addInputLabel();
+
+            setUpEntry();
+
+            add(m_entry);
+            add(Box.createHorizontalGlue());
+            addValidationLabel();
+        } // init
+
+        void setUpEntry() {
+            m_entry = new JTextField();
+            m_entry.setName(m_input.getName());
+            m_entry.setMinimumSize(PREFERRED_SIZE);
+            m_entry.setPreferredSize(PREFERRED_SIZE);
+            m_entry.setSize(PREFERRED_SIZE);
+            initEntry();
+            m_entry.setToolTipText(m_input.getHTMLTipText());
+            m_entry.setMaximumSize(MAX_SIZE);
+
+            m_entry.getDocument().addDocumentListener(new DocumentListener() {
+                @Override
+                public void removeUpdate(DocumentEvent e) {
+                    processEntry();
+                }
+
+                @Override
+                public void insertUpdate(DocumentEvent e) {
+                    processEntry();
+                }
+
+                @Override
+                public void changedUpdate(DocumentEvent e) {
+                    processEntry();
+                }
+            });
+        }
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+    	protected void setValue(Object o) throws Exception {
+        	if (itemNr < 0) {
+        		m_input.setValue(o, m_plugin);
+        	} else {
+        		// set value of an item in a list
+        		List list = (List) m_input.get();
+        		Object other = list.get(itemNr);
+        		if (other != o) {
+        			if (other instanceof BEASTInterface) {
+        				BEASTInterface.getOutputs(other).remove(m_plugin);
+        			}
+        			list.set(itemNr, o);
+        			if (o instanceof BEASTInterface) {
+        				BEASTInterface.getOutputs(o).add(m_plugin);
+        			}
+        		}
+        	}
+        }
+        
+        protected void processEntry() {
+            try {
+            	setValue(m_entry.getText());
+                validateInput();
+                m_entry.requestFocusInWindow();
+            } catch (Exception ex) {
+//    			JOptionPane.showMessageDialog(null, "Error while setting " + m_input.getName() + ": " + ex.getMessage() +
+//    					" Leaving value at " + m_input.get());
+//    			m_entry.setText(m_input.get() + "");
+                if (m_validateLabel != null) {
+                    m_validateLabel.setVisible(true);
+                    m_validateLabel.setToolTipText("<html><p>Parsing error: " + ex.getMessage() + ". Value was left at " + m_input.get() + ".</p></html>");
+                    m_validateLabel.m_circleColor = Color.orange;
+                }
+                repaint();
+            }
+        }
+
+        protected void addInputLabel() {
+            if (m_bAddButtons) {
+                String sName = formatName(m_input.getName());
+                addInputLabel(sName, m_input.getHTMLTipText());
+            }
+        }
+
+        protected String formatName(String sName) {
+    	    if (doc.beautiConfig.inputLabelMap.containsKey(m_plugin.getClass().getName() + "." + sName)) {
+    	        sName = doc.beautiConfig.inputLabelMap.get(m_plugin.getClass().getName() + "." + sName);
+    	    } else {
+    	        sName = sName.replaceAll("([a-z])([A-Z])", "$1 $2");
+    	        sName = sName.substring(0, 1).toUpperCase() + sName.substring(1);
+    	    }
+    	    return sName;
+        }
+
+        protected void addInputLabel(String sLabel, String sTipText) {
+            if (m_bAddButtons) {
+                m_inputLabel = new JLabel(sLabel);
+                m_inputLabel.setToolTipText(sTipText);
+                m_inputLabel.setHorizontalTextPosition(JLabel.RIGHT);
+                //Dimension size = new Dimension(g_nLabelWidth, 20);
+                Dimension size = new Dimension(200, 20);
+                m_inputLabel.setMaximumSize(size);
+                m_inputLabel.setMinimumSize(size);
+                m_inputLabel.setPreferredSize(size);
+                m_inputLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+
+//                m_inputLabel.setSize(size);
+//                m_inputLabel.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
+                // RRB: temporary
+                //m_inputLabel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
+                add(m_inputLabel);
+            }
+        }
+
+        protected void addValidationLabel() {
+            if (m_bAddButtons) {
+                m_validateLabel = new SmallLabel("x", new Color(200, 0, 0));
+                add(m_validateLabel);
+                m_validateLabel.setVisible(true);
+                validateInput();
+            }
+        }
+
+        /* check the input is valid, continue checking recursively */
+        protected void validateAllEditors() {
+            for (InputEditor editor : doc.currentInputEditors) {
+                editor.validateInput();
+            }
+        }
+
+        @Override
+        public void validateInput() {
+            try {
+                m_input.validate();
+                if (m_entry != null && !m_input.canSetValue(m_entry.getText(), m_plugin)) {
+                    throw new Exception("invalid value");
+                }
+                // recurse
+                try {
+                    validateRecursively(m_input, new HashSet<Input<?>>());
+                } catch (Exception e) {
+                    notifyValidationListeners(ValidationStatus.HAS_INVALIDMEMBERS);
+                    if (m_validateLabel != null) {
+                        m_validateLabel.setVisible(true);
+                        m_validateLabel.setToolTipText("<html><p>Recursive error in " + e.getMessage() + "</p></html>");
+                        m_validateLabel.m_circleColor = Color.orange;
+                    }
+                    repaint();
+                    return;
+                }
+                if (m_validateLabel != null) {
+                    m_validateLabel.setVisible(false);
+                }
+                notifyValidationListeners(ValidationStatus.IS_VALID);
+            } catch (Exception e) {
+                System.err.println("Validation message: " + e.getMessage());
+                if (m_validateLabel != null) {
+                    m_validateLabel.setToolTipText(e.getMessage());
+                    m_validateLabel.m_circleColor = Color.red;
+                    m_validateLabel.setVisible(true);
+                }
+                notifyValidationListeners(ValidationStatus.IS_INVALID);
+            }
+            repaint();
+        }
+
+        /* Recurse in any of the input plugins
+          * and validate its inputs */
+        void validateRecursively(Input<?> input, Set<Input<?>> done) throws Exception {
+            if (done.contains(input)) {
+                // this prevent cycles to lock up validation
+                return;
+            } else {
+                done.add(input);
+            }
+            if (input.get() != null) {
+                if (input.get() instanceof BEASTInterface) {
+                    BEASTInterface plugin = ((BEASTInterface) input.get());
+                    for (Input<?> input2 : plugin.listInputs()) {
+                        try {
+                            input2.validate();
+                        } catch (Exception e) {
+                            throw new Exception(((BEASTInterface) input.get()).getID() + "</p><p> " + e.getMessage());
+                        }
+                        validateRecursively(input2, done);
+                    }
+                }
+                if (input.get() instanceof List<?>) {
+                    for (Object o : (List<?>) input.get()) {
+                        if (o != null && o instanceof BEASTInterface) {
+                            BEASTInterface plugin = (BEASTInterface) o;
+                            for (Input<?> input2 : plugin.listInputs()) {
+                                try {
+                                    input2.validate();
+                                } catch (Exception e) {
+                                    throw new Exception(((BEASTInterface) o).getID() + " " + e.getMessage());
+                                }
+                                validateRecursively(input2, done);
+                            }
+                        }
+                    }
+                }
+            }
+        } // validateRecursively
+
+        @Override
+        public void startValidating(ValidationStatus state) {
+            validateInput();
+        }
+
+
+        public void refreshPanel() {
+            Component c = this;
+            while (c.getParent() != null) {
+                c = c.getParent();
+                if (c instanceof ListSelectionListener) {
+                    ((ListSelectionListener) c).valueChanged(null);
+                }
+            }
+        }
+
+        /**
+         * synchronise values in panel with current network *
+         */
+        protected void sync() {
+            Component c = this;
+            while (c.getParent() != null) {
+                c = c.getParent();
+                if (c instanceof BeautiPanel) {
+                    BeautiPanel panel = (BeautiPanel) c;
+                    BeautiPanelConfig cfgPanel = panel.config;
+                    cfgPanel.sync(panel.iPartition);
+                }
+            }
+        }
+
+        // we should leave it to the component to set its own border
+        @Deprecated
+        public void setBorder(Border border) {
+    		super.setBorder(border);
+        }
+
+        @Override
+        public void setDoc(BeautiDoc doc) {
+        	this.doc = doc;
+        }
+
+        // what is this method for? We should leave repainting to the standard mechanism
+        @Deprecated
+    	public void repaint() {
+    	this.repaint(0);
+    		super.repaint();
+    	}
+
+    	public Component getComponent() {
+    		return this;
+    	}
+
+}
diff --git a/src/beast/app/draw/ParameterInputEditor.java b/src/beast/app/draw/ParameterInputEditor.java
index 7649008..122455d 100644
--- a/src/beast/app/draw/ParameterInputEditor.java
+++ b/src/beast/app/draw/ParameterInputEditor.java
@@ -23,6 +23,7 @@ import beast.core.Input;
 import beast.core.Operator;
 import beast.core.BEASTObject;
 import beast.core.BEASTInterface;
+import beast.core.parameter.Parameter;
 import beast.core.parameter.RealParameter;
 import beast.evolution.branchratemodel.BranchRateModel;
 import beast.math.distributions.ParametricDistribution;
@@ -44,7 +45,7 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
 
     @Override
     public Class<?> type() {
-        return RealParameter.class;
+        return Parameter.Base.class;
     }
     
     
@@ -58,16 +59,16 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
     protected void initEntry() {
         if (m_input.get() != null) {
         	if (itemNr < 0) {
-        		RealParameter parameter = (RealParameter) m_input.get();
+        		Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
         		String s = "";
-        		for (Double d : parameter.valuesInput.get()) {
+        		for (Object d : parameter.valuesInput.get()) {
         			s += d + " ";
         		}
         		m_entry.setText(s);
         	} else {
-        		RealParameter parameter = (RealParameter) ((List)m_input.get()).get(itemNr);
+        		Parameter.Base<?> parameter = (Parameter.Base<?>) ((List)m_input.get()).get(itemNr);
         		String s = "";
-        		for (Double d : parameter.valuesInput.get()) {
+        		for (Object d : parameter.valuesInput.get()) {
         			s += d + " ";
         		}
         		m_entry.setText(s);
@@ -79,9 +80,9 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
     protected void processEntry() {
         try {
             String sValue = m_entry.getText();
-            RealParameter parameter = (RealParameter) m_input.get();
+            Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
         	String oldValue = "";
-    		for (Double d : parameter.valuesInput.get()) {
+    		for (Object d : parameter.valuesInput.get()) {
     			oldValue += d + " ";
     		}
             int oldDim = parameter.getDimension();
@@ -107,11 +108,11 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
     @Override
     protected void addComboBox(JComponent box, Input<?> input, BEASTInterface plugin) {
         Box paramBox = Box.createHorizontalBox();
-        RealParameter parameter = null;
+        Parameter.Base<?> parameter = null;
         if (itemNr >= 0) {
-        	parameter = (RealParameter) ((List) input.get()).get(itemNr);
+        	parameter = (Parameter.Base<?>) ((List) input.get()).get(itemNr);
         } else {
-        	parameter = (RealParameter) input.get();
+        	parameter = (Parameter.Base<?>) input.get();
         }
 
         if (parameter == null) {
@@ -183,7 +184,7 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
                 @Override
                 public void actionPerformed(ActionEvent e) {
                     try {
-                        RealParameter parameter = (RealParameter) m_input.get();
+                        Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
                         parameter.isEstimatedInput.setValue(m_isEstimatedBox.isSelected(), parameter);
                         if (isParametricDistributionParameter) {
                         	String sID = parameter.getID();
@@ -268,9 +269,9 @@ public class ParameterInputEditor extends BEASTObjectInputEditor {
 
     @Override
     void refresh() {
-        RealParameter parameter = (RealParameter) m_input.get();
+        Parameter.Base<?> parameter = (Parameter.Base<?>) m_input.get();
 		String s = "";
-		for (Double d : parameter.valuesInput.get()) {
+		for (Object d : parameter.valuesInput.get()) {
 			s += d + " ";
 		}
 		m_entry.setText(s);
diff --git a/src/beast/app/tools/LogCombiner.java b/src/beast/app/tools/LogCombiner.java
index 43ec931..1ecea3c 100644
--- a/src/beast/app/tools/LogCombiner.java
+++ b/src/beast/app/tools/LogCombiner.java
@@ -6,6 +6,8 @@ import beast.util.LogAnalyser;
 import jam.console.ConsoleApplication;
 
 import javax.swing.*;
+import javax.swing.table.TableCellEditor;
+
 import java.io.*;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
@@ -431,6 +433,14 @@ public class LogCombiner extends LogAnalyser {
                     return;
                 }
 
+                // issue #437: ensure the table editor finished.
+                // this way, the latest entered burn-in is captured, otherwise 
+                // the last editing action may be ignored
+                TableCellEditor editor = dialog.filesTable.getCellEditor();
+                if (editor != null) {
+                    editor.stopCellEditing();
+                }
+
                 combiner.m_bIsTreeLog = dialog.isTreeFiles();
                 combiner.m_bUseDecimalFormat = dialog.convertToDecimal();
                 if (combiner.m_bUseDecimalFormat) {
diff --git a/src/beast/app/tools/LogCombinerDialog.java b/src/beast/app/tools/LogCombinerDialog.java
index 99d54b2..8f3ddc2 100644
--- a/src/beast/app/tools/LogCombinerDialog.java
+++ b/src/beast/app/tools/LogCombinerDialog.java
@@ -59,7 +59,7 @@ public class LogCombinerDialog {
 
     private final OptionsPanel optionPanel;
 
-    private JTable filesTable = null;
+    JTable filesTable = null;
     private FilesTableModel filesTableModel = null;
 
     private final JComboBox fileTypeCombo = new JComboBox(new String[]{"Log Files", "Tree Files"});
diff --git a/src/beast/core/Logger.java b/src/beast/core/Logger.java
index 8a9f97d..c312bdc 100644
--- a/src/beast/core/Logger.java
+++ b/src/beast/core/Logger.java
@@ -286,6 +286,8 @@ public class Logger extends BEASTObject {
         				}
     				}
 					partitionPrefix = getprefix(partitionPrefix, prefix);
+					// get rid of braces
+					partitionPrefix = partitionPrefix.replaceAll("[\\(\\)]","");
     			}
     		}
     	}
diff --git a/src/beast/core/MCMC.java b/src/beast/core/MCMC.java
index be60f0d..67564be 100644
--- a/src/beast/core/MCMC.java
+++ b/src/beast/core/MCMC.java
@@ -533,7 +533,9 @@ public class MCMC extends Runnable {
      * incorrectly recalculated posteriors *
      */
     protected void reportLogLikelihoods(final Distribution distr, final String tabString) {
-        System.err.println(tabString + "P(" + distr.getID() + ") = " + distr.logP + " (was " + distr.storedLogP + ")");
+        final double full =  distr.logP, last = distr.storedLogP;
+        final String changed = full == last ? "" : "  **";
+        System.err.println(tabString + "P(" + distr.getID() + ") = " + full + " (was " + last + ")" + changed);
         if (distr instanceof CompoundDistribution) {
             for (final Distribution distr2 : ((CompoundDistribution) distr).pDistributions.get()) {
                 reportLogLikelihoods(distr2, tabString + "\t");
diff --git a/src/beast/core/State.java b/src/beast/core/State.java
index 4df6b68..1973bae 100644
--- a/src/beast/core/State.java
+++ b/src/beast/core/State.java
@@ -622,7 +622,7 @@ public class State extends BEASTObject {
 	public double robustlyCalcNonStochasticPosterior(Distribution posterior) throws Exception {
         store(-1);
         setEverythingDirty(true);
-        //state.storeCalculationNodes();
+        storeCalculationNodes();
         checkCalculationNodesDirtiness();
         final double fLogLikelihood = posterior.getNonStochasticLogP();
         setEverythingDirty(false);
diff --git a/src/beast/evolution/operators/NodeReheight.java b/src/beast/evolution/operators/NodeReheight.java
index 8866818..4336762 100644
--- a/src/beast/evolution/operators/NodeReheight.java
+++ b/src/beast/evolution/operators/NodeReheight.java
@@ -9,6 +9,7 @@ import java.util.Map;
 import beast.core.Description;
 import beast.core.Input;
 import beast.core.Input.Validate;
+import beast.core.util.Log;
 import beast.evolution.alignment.Taxon;
 import beast.evolution.alignment.TaxonSet;
 import beast.evolution.tree.Node;
@@ -37,6 +38,14 @@ public class NodeReheight extends TreeOperator {
         /** maps gene taxa names to species number **/
         final Map<String, Integer> taxonMap = new HashMap<String, Integer>();
         final List<Taxon> list = taxonSetInput.get().taxonsetInput.get();
+        
+        if (list.size() <= 1) {
+        	Log.warning.println("NodeReheight operator requires at least 2 taxa while the taxon set (id=" + taxonSetInput.get().getID() +") has only " + list.size() + " taxa. "
+        			+ "If the XML file was set up in BEAUti, this probably means a taxon assignment needs to be set up in the taxonset panel.");
+        	// assume we are in BEAUti, back off for now
+        	return;
+        }
+        
         for (int i = 0; i < list.size(); i++) {
             final Taxon taxa = list.get(i);
             // cast should be ok if taxon-set is the set for the species tree
diff --git a/src/beast/evolution/operators/SubtreeSlide.java b/src/beast/evolution/operators/SubtreeSlide.java
index 90eeffd..2190b18 100644
--- a/src/beast/evolution/operators/SubtreeSlide.java
+++ b/src/beast/evolution/operators/SubtreeSlide.java
@@ -73,13 +73,16 @@ public class SubtreeSlide extends TreeOperator {
     public Input<Double> sizeInput = new Input<Double>("size", "size of the slide, default 1.0", 1.0);
     public Input<Boolean> gaussianInput = new Input<Boolean>("gaussian", "Gaussian (=true=default) or uniform delta", true);
     public Input<Boolean> optimiseInput = new Input<Boolean>("optimise", "flag to indicate that the scale factor is automatically changed in order to achieve a good acceptance rate (default true)", true);
-
+    public Input<Double> limitInput = new Input<Double>("limit", "limit on step size, default disable, " +
+            "i.e. -1. (when positive, gets multiplied by tree-height/log2(n-taxa).", -1.0);
     // shadows size
     double fSize;
+    private double limit;
 
     @Override
     public void initAndValidate() {
         fSize = sizeInput.get();
+        limit = limitInput.get();
     }
 
     /**
@@ -94,7 +97,7 @@ public class SubtreeSlide extends TreeOperator {
         double logq;
 
         Node i;
-        final boolean  markClades = markCladesInput.get();
+        final boolean markClades = markCladesInput.get();
         // 1. choose a random node avoiding root
         final int nNodes = tree.getNodeCount();
         do {
@@ -247,10 +250,22 @@ public class SubtreeSlide extends TreeOperator {
      */
     @Override
     public void optimize(final double logAlpha) {
-        if (optimiseInput.get()) {
+        if (optimiseInput.get() && ! Double.isInfinite(logAlpha) ) {
             double fDelta = calcDelta(logAlpha);
             fDelta += Math.log(fSize);
-            fSize = Math.exp(fDelta);
+            final double f = Math.exp(fDelta);
+//            double f = Math.exp(fDelta);
+            if( limit > 0 ) {
+                final Tree tree = treeInput.get();
+                final double h = tree.getRoot().getHeight();
+                final double k = Math.log(tree.getLeafNodeCount()) / Math.log(2);
+                final double lim = (h / k) * limit;
+                if( f <= lim ) {
+                    fSize = f;
+                }
+            } else {
+               fSize = f;
+            }
         }
     }
 
diff --git a/src/beast/evolution/operators/TreeOperator.java b/src/beast/evolution/operators/TreeOperator.java
index 6493c30..b187bf9 100644
--- a/src/beast/evolution/operators/TreeOperator.java
+++ b/src/beast/evolution/operators/TreeOperator.java
@@ -36,8 +36,8 @@ import beast.evolution.tree.Tree;
 @Description("This operator changes a beast.tree.")
 abstract public class TreeOperator extends Operator {
     public Input<Tree> treeInput = new Input<Tree>("tree", "beast.tree on which this operation is performed", Validate.REQUIRED);
-    public Input<Boolean> markCladesInput = new Input<>("markclades", "Mark nodes whose clade (tips of the " +
-            "subtree under the node) has changed by the move", false);
+    public Input<Boolean> markCladesInput = new Input<>("markclades", "Mark all ancestors of nodes changed by the operator as changed," +
+            " up to the MRCA of all nodes changed by the operator.", false);
 
     /**
      * @param parent the parent
diff --git a/src/beast/evolution/speciation/RandomGeneTree.java b/src/beast/evolution/speciation/RandomGeneTree.java
index b187f34..2d02194 100644
--- a/src/beast/evolution/speciation/RandomGeneTree.java
+++ b/src/beast/evolution/speciation/RandomGeneTree.java
@@ -24,7 +24,7 @@ public class RandomGeneTree extends RandomTree {
     }
 
     @Override
-    public Node simulateCoalescent(List<Node> nodes, PopulationFunction demographic) {
+    public Node simulateCoalescentWithMax(List<Node> nodes, PopulationFunction demographic, final double maxHeight) {
         // sanity check - disjoint trees
 
 //        if( ! Tree.Utils.allDisjoint(nodes) ) {
@@ -39,7 +39,7 @@ public class RandomGeneTree extends RandomTree {
 
         for (int attempts = 0; attempts < 1000; ++attempts) {
             try {
-                final List<Node> rootNode = simulateCoalescent(nodes, demographic, fLowestHeight, Double.POSITIVE_INFINITY);
+                final List<Node> rootNode = simulateCoalescent(nodes, demographic, fLowestHeight, maxHeight);
                 if (rootNode.size() == 1) {
                     return rootNode.get(0);
                 }
@@ -50,5 +50,4 @@ public class RandomGeneTree extends RandomTree {
 
         throw new RuntimeException("failed to merge trees after 1000 tries!");
     }
-
 }
diff --git a/src/beast/evolution/substitutionmodel/GeneralSubstitutionModel.java b/src/beast/evolution/substitutionmodel/GeneralSubstitutionModel.java
index a48861d..2d6e9b7 100644
--- a/src/beast/evolution/substitutionmodel/GeneralSubstitutionModel.java
+++ b/src/beast/evolution/substitutionmodel/GeneralSubstitutionModel.java
@@ -213,7 +213,9 @@ public class GeneralSubstitutionModel extends SubstitutionModel.Base {
     @Override
     public void store() {
         storedUpdateMatrix = updateMatrix;
-        storedEigenDecomposition = eigenDecomposition.copy();
+        if( eigenDecomposition != null ) {
+            storedEigenDecomposition = eigenDecomposition.copy();
+        }
 //        System.arraycopy(relativeRates, 0, storedRelativeRates, 0, relativeRates.length);
 
         super.store();
@@ -231,10 +233,11 @@ public class GeneralSubstitutionModel extends SubstitutionModel.Base {
 //        double[] tmp1 = storedRelativeRates;
 //        storedRelativeRates = relativeRates;
 //        relativeRates = tmp1;
-
-        EigenDecomposition tmp = storedEigenDecomposition;
-        storedEigenDecomposition = eigenDecomposition;
-        eigenDecomposition = tmp;
+        if( storedEigenDecomposition != null ) {
+            EigenDecomposition tmp = storedEigenDecomposition;
+            storedEigenDecomposition = eigenDecomposition;
+            eigenDecomposition = tmp;
+        }
         super.restore();
 
     }
diff --git a/src/beast/evolution/tree/RandomTree.java b/src/beast/evolution/tree/RandomTree.java
index ad965d6..285abcd 100644
--- a/src/beast/evolution/tree/RandomTree.java
+++ b/src/beast/evolution/tree/RandomTree.java
@@ -33,7 +33,6 @@ import beast.core.Input;
 import beast.core.StateNode;
 import beast.core.StateNodeInitialiser;
 import beast.core.util.Log;
-import beast.core.BEASTObject;
 import beast.core.BEASTInterface;
 import beast.core.Input.Validate;
 import beast.evolution.alignment.Alignment;
@@ -57,12 +56,6 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
 
     // total nr of taxa
     int nrOfTaxa;
-    // list of bitset representation of the taxon sets
-    List<Set<String>> taxonSets;
-    // the first m_nIsMonophyletic of the m_bTaxonSets are monophyletic, while the remainder are not
-    int isMonophyletic;
-    // list of parametric distribution constraining the MRCA of taxon sets, null if not present
-    List<ParametricDistribution> distributions;
 
     class Bound {
         Double upper = Double.POSITIVE_INFINITY;
@@ -73,7 +66,23 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         }
     }
 
+    // Location of last monophyletic clade in the lists below, which are grouped together at the start.
+    // (i.e. the first isMonophyletic of the TaxonSets are monophyletic, while the remainder are not).
+    int lastMonophyletic;
+
+    // taxonSets,distributions, m_bounds and taxonSetIDs are indexed together (four values associated with this clade, a set of taxa.
+
+    // taxon sets of clades that has a constraint of calibrations. Monophyletic constraints may be nested, and are sorted by the code to be at a
+    // higher index, i.e iterating from zero up does post-order (descendants before parent).
+    List<Set<String>> taxonSets;
+
+    // list of parametric distribution constraining the MRCA of taxon sets, null if not present
+    List<ParametricDistribution> distributions;
+
+    // hard bound for the set, if any
     List<Bound> m_bounds;
+
+    // The prior element involved, if any
     List<String> taxonSetIDs;
 
     List<Integer>[] children;
@@ -112,32 +121,32 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
     }
 
     // taxonset intersection test
-    private boolean intersects(final BitSet bitSet, final BitSet bitSet2) {
-        for (int k = bitSet.nextSetBit(0); k >= 0; k = bitSet.nextSetBit(k + 1)) {
-            if (bitSet2.get(k)) {
-                return true;
-            }
-        }
-        return false;
-    }
+//    private boolean intersects(final BitSet bitSet, final BitSet bitSet2) {
+//        for (int k = bitSet.nextSetBit(0); k >= 0; k = bitSet.nextSetBit(k + 1)) {
+//            if (bitSet2.get(k)) {
+//                return true;
+//            }
+//        }
+//        return false;
+//    }
 
     // returns true if bitSet is a subset of bitSet2
-    private boolean isSubset(final BitSet bitSet, final BitSet bitSet2) {
-        boolean bIsSubset = true;
-        for (int k = bitSet.nextSetBit(0); bIsSubset && k >= 0; k = bitSet.nextSetBit(k + 1)) {
-            bIsSubset = bitSet2.get(k);
-        }
-        return bIsSubset;
-    }
+//    private boolean isSubset(final BitSet bitSet, final BitSet bitSet2) {
+//        boolean bIsSubset = true;
+//        for (int k = bitSet.nextSetBit(0); bIsSubset && k >= 0; k = bitSet.nextSetBit(k + 1)) {
+//            bIsSubset = bitSet2.get(k);
+//        }
+//        return bIsSubset;
+//    }
 
-    //@Override
+    @Override
     public void initStateNodes() throws Exception {
         // find taxon sets we are dealing with
         taxonSets = new ArrayList<>();
         m_bounds = new ArrayList<>();
         distributions = new ArrayList<>();
         taxonSetIDs = new ArrayList<>();
-        isMonophyletic = 0;
+        lastMonophyletic = 0;
 
         if (taxaInput.get() != null) {
             sTaxa.addAll(taxaInput.get().getTaxaNames());
@@ -207,11 +216,11 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
 	
 	            if (prior.isMonophyleticInput.get()) {
 	                // add any monophyletic constraint
-	                taxonSets.add(isMonophyletic, bTaxa);
-	                distributions.add(isMonophyletic, distr);
-	                m_bounds.add(isMonophyletic, bounds);
+	                taxonSets.add(lastMonophyletic, bTaxa);
+	                distributions.add(lastMonophyletic, distr);
+	                m_bounds.add(lastMonophyletic, bounds);
 	                taxonSetIDs.add(prior.getID());
-	                isMonophyletic++;
+	                lastMonophyletic++;
 	            } else {
 	                // only calibrations with finite bounds are added
 	                if (!Double.isInfinite(bounds.lower) || !Double.isInfinite(bounds.upper)) {
@@ -226,12 +235,12 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
 
         // assume all calibration constraints are MonoPhyletic
         // TODO: verify that this is a reasonable assumption
-        isMonophyletic = taxonSets.size();
+        lastMonophyletic = taxonSets.size();
 
 
         // sort constraints such that if taxon set i is subset of taxon set j, then i < j
-        for (int i = 0; i < isMonophyletic; i++) {
-            for (int j = i + 1; j < isMonophyletic; j++) {
+        for (int i = 0; i < lastMonophyletic; i++) {
+            for (int j = i + 1; j < lastMonophyletic; j++) {
 
                 Set<String> intersection = new HashSet<>(taxonSets.get(i));
                 intersection.retainAll(taxonSets.get(j));
@@ -258,15 +267,16 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
             }
         }
 
-        // build tree of mono constraints such that i is parent of j => j is subset of i
-        final int[] nParent = new int[isMonophyletic];
-        children = new List[isMonophyletic + 1];
-        for (int i = 0; i < isMonophyletic + 1; i++) {
+        // build tree of mono constraints such that j is parent of i if i is a subset of j but i+1,i+2,...,j-1 are not.
+        // The last one, standing for the virtual "root" of all monophyletic clades is not associated with an actual clade
+        final int[] nParent = new int[lastMonophyletic];
+        children = new List[lastMonophyletic + 1];
+        for (int i = 0; i < lastMonophyletic + 1; i++) {
             children[i] = new ArrayList<Integer>();
         }
-        for (int i = 0; i < isMonophyletic; i++) {
+        for (int i = 0; i < lastMonophyletic; i++) {
             int j = i + 1;
-            while (j < isMonophyletic && !taxonSets.get(j).containsAll(taxonSets.get(i))) {
+            while (j < lastMonophyletic && !taxonSets.get(j).containsAll(taxonSets.get(i))) {
                 j++;
             }
             nParent[i] = j;
@@ -274,8 +284,8 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         }
 
         // make sure upper bounds of a child does not exceed the upper bound of its parent
-        for (int i = 0; i < isMonophyletic; i++) {
-            if (nParent[i] < isMonophyletic) {
+        for (int i = lastMonophyletic-1; i >= 0 ;--i) {
+            if (nParent[i] < lastMonophyletic ) {
                 if (m_bounds.get(i).upper > m_bounds.get(nParent[i]).upper) {
                     m_bounds.get(i).upper = m_bounds.get(nParent[i]).upper - 1e-100;
                 }
@@ -293,11 +303,60 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         nodeCount = 2 * sTaxa.size() - 1;
         internalNodeCount = sTaxa.size() - 1;
         leafNodeCount = sTaxa.size();
+
+        HashMap<String,Integer> taxonToNR = null;
+        // preserve node numbers where possible
+        if (m_initial.get() != null) {
+            if( leafNodeCount == m_initial.get().getLeafNodeCount() ) {
+                // dont ask me how the initial tree is rubbish  (i.e. 0:0.0)
+                taxonToNR = new HashMap<>();
+                for (Node n : m_initial.get().getExternalNodes()) {
+                    taxonToNR.put(n.getID(), n.getNr());
+                }
+            }
+        } else {
+            taxonToNR = new HashMap<>();
+            String[] taxa = getTaxaNames();
+            for(int k = 0; k < taxa.length; ++k) {
+                taxonToNR.put(taxa[k], k);
+            }
+        }
+        // multiple simulation tries may produce an excess of nodes with invalid nr's. reset those.
+        setNodesNrs(root, 0, new int[1], taxonToNR);
+
         initArrays();
 
         if (m_initial.get() != null) {
             m_initial.get().assignFromWithoutID(this);
         }
+        for(int k = 0; k < lastMonophyletic; ++k) {
+            final MRCAPrior p = calibrations.get(k);
+            if( p.isMonophyleticInput.get() ) {
+                final TaxonSet taxonSet = p.taxonsetInput.get();
+                final Set<String> bTaxa = new HashSet<>();
+                bTaxa.addAll(taxonSet.asStringList());
+                int c = traverse(root, bTaxa, taxonSet.getTaxonCount(), new int[1]);
+                boolean b = c == nrOfTaxa + 127;
+            }
+        }
+    }
+
+    private int setNodesNrs(final Node node, int internalNodeCount, int[] n, Map<String,Integer> initial) {
+        if( node.isLeaf() )  {
+            if( initial != null ) {
+                node.setNr(initial.get(node.getID()));
+            } else {
+                node.setNr(n[0]);
+                n[0] += 1;
+            }
+        } else {
+            for (final Node child : node.getChildren()) {
+                internalNodeCount = setNodesNrs(child, internalNodeCount, n, initial);
+            }
+            node.setNr(nrOfTaxa + internalNodeCount);
+            internalNodeCount += 1;
+        }
+        return internalNodeCount;
     }
 
     private void scaleToFit(double scale, Node node) {
@@ -360,7 +419,7 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
                 for (Node node: candidates) {
                     allCandidates.put(node.getID(),node);
                 }
-                root = simulateCoalescent(isMonophyletic, allCandidates, candidates, demoFunction);
+                root = simulateCoalescent(lastMonophyletic, allCandidates, candidates, demoFunction);
                 return;
             } catch (ConstraintViolatedException e) {
                 // need to generate another tree
@@ -375,6 +434,7 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
             	Log.warning.println("WARNING: Expect BEAST to crash if this is not fixed."); 
             }
         }
+        throw new RuntimeException("Failed to generate a random tree (probably a bug).");
     }
     
     /**
@@ -415,7 +475,8 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
             }
         }
 
-        final Node MRCA = simulateCoalescent(remainingCandidates, demoFunction);
+        final double upper = iIsMonophyleticNode < m_bounds.size() ?  m_bounds.get(iIsMonophyleticNode).upper : Double.POSITIVE_INFINITY;
+        final Node MRCA = simulateCoalescentWithMax(remainingCandidates, demoFunction, upper);
         return MRCA;
     }
 
@@ -438,7 +499,19 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
      *         coalescent under the given demographic model.
      * @throws beast.evolution.tree.RandomTree.ConstraintViolatedException
      */
-    public Node simulateCoalescent(final List<Node> nodes, final PopulationFunction demographic) throws ConstraintViolatedException {
+//    public Node simulateCoalescent(final List<Node> nodes, final PopulationFunction demographic) throws ConstraintViolatedException {
+//        return simulateCoalescentWithMax(nodes, demographic, Double.POSITIVE_INFINITY);
+//    }
+
+    /**
+     * @param nodes
+     * @param demographic
+     * @return the root node of the given array of nodes after simulation of the
+     *         coalescent under the given demographic model.
+     * @throws beast.evolution.tree.RandomTree.ConstraintViolatedException
+     */
+    public Node simulateCoalescentWithMax(final List<Node> nodes, final PopulationFunction demographic,
+                                          final double maxHeight) throws ConstraintViolatedException {
         // sanity check - disjoint trees
 
         // if( ! Tree.Utils.allDisjoint(nodes) ) {
@@ -450,12 +523,36 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         }
 
         for (int attempts = 0; attempts < 1000; ++attempts) {
-            final List<Node> rootNode = simulateCoalescent(nodes, demographic, 0.0, Double.POSITIVE_INFINITY);
+            final List<Node> rootNode = simulateCoalescent(nodes, demographic, 0.0, maxHeight);
             if (rootNode.size() == 1) {
                 return rootNode.get(0);
             }
         }
 
+        if( Double.isFinite(maxHeight) ){
+            double h = -1;
+
+            for( Node n : nodeList ) {
+                h = Math.max(h, n.getHeight());
+            }
+            assert h < maxHeight;
+            double dt = (maxHeight - h)/ (nodeList.size() + 1);
+            while (nodeList.size() > 1) {
+                int k = nodeList.size() - 1;
+                final Node left = nodeList.remove(k);
+                final Node right = nodeList.get(k-1);
+                final Node newNode = new Node();
+                newNode.setNr(nextNodeNr++);   // multiple tries may generate an excess of nodes assert(nextNodeNr <= nrOfTaxa*2-1);
+                newNode.setHeight(h + dt);
+                newNode.setLeft(left);
+                left.setParent(newNode);
+                newNode.setRight(right);
+                right.setParent(newNode);
+                nodeList.set(k-1, newNode);
+            }
+            assert (nodeList.size() == 1);
+            return nodeList.get(0);
+        }
         throw new RuntimeException("failed to merge trees after 1000 tries!");
     }
 
@@ -519,13 +616,6 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
         }
 
         return nodeList;
-
-        // Node[] nodesLeft = new Node[nodeList.size()];
-        // for (int i = 0; i < nodesLeft.length; i++) {
-        // nodesLeft[i] = nodeList.get(i);
-        // }
-        //
-        // return nodesLeft;
     }
 
     /**
@@ -584,7 +674,7 @@ public class RandomTree extends Tree implements StateNodeInitialiser {
 
         final Node newNode = new Node();
 //		System.err.println(2 * m_taxa.get().getNrTaxa() - nodeList.size());
-        newNode.setNr(nextNodeNr++);
+        newNode.setNr(nextNodeNr++);   // multiple tries may generate an excess of nodes assert(nextNodeNr <= nrOfTaxa*2-1);
         newNode.setHeight(height);
         newNode.setLeft(left);
         left.setParent(newNode);
diff --git a/src/beast/evolution/tree/TreeInterface.java b/src/beast/evolution/tree/TreeInterface.java
index 856e2cb..c59c211 100644
--- a/src/beast/evolution/tree/TreeInterface.java
+++ b/src/beast/evolution/tree/TreeInterface.java
@@ -40,7 +40,7 @@ public interface TreeInterface {
      * @param nodes array to fill (null will result in creating a new one)
      * @return tree nodes in post-order, children before parents
      */
-    default public Node[] listNodesPostOrder(Node node, Node[] nodes) {
+    default Node[] listNodesPostOrder(Node node, Node[] nodes) {
         if (node == null) {
             node = getRoot();
         }
diff --git a/src/beast/math/distributions/MRCAPrior.java b/src/beast/math/distributions/MRCAPrior.java
index 081368a..d41c0b2 100644
--- a/src/beast/math/distributions/MRCAPrior.java
+++ b/src/beast/math/distributions/MRCAPrior.java
@@ -50,6 +50,8 @@ public class MRCAPrior extends Distribution {
     boolean isMonophyletic = false;
     boolean onlyUseTips = false;
     boolean useOriginate = false;
+    
+    boolean initialised = false;
 
     @Override
     public void initAndValidate() throws Exception {
@@ -84,28 +86,7 @@ public class MRCAPrior extends Distribution {
             throw new Exception("Taxonset must be specified OR tipsonly be set to true");
         }
         
-        // determine which taxa are in the set
-        taxonIndex = new int[nrOfTaxa];
-        if ( set != null )  {  // m_taxonset.get() != null) {
-            isInTaxaSet.clear();
-            int k = 0;
-            for (final String sTaxon : set) {
-                final int iTaxon = sTaxaNames.indexOf(sTaxon);
-                if (iTaxon < 0) {
-                    throw new Exception("Cannot find taxon " + sTaxon + " in data");
-                }
-                if (isInTaxaSet.contains(sTaxon)) {
-                    throw new Exception("Taxon " + sTaxon + " is defined multiple times, while they should be unique");
-                }
-                isInTaxaSet.add(sTaxon);
-                taxonIndex[k++] = iTaxon;
-            }
-        } else {
-            for (int i = 0; i < nrOfTaxa; i++) {
-                taxonIndex[i] = i;
-            }
-        }
-        
+       
         if (useOriginate && onlyUseTips) {
         	throw new Exception("'useOriginate' and 'tipsOnly' cannot be both true");
         }
@@ -115,8 +96,55 @@ public class MRCAPrior extends Distribution {
 
     }
 
+    boolean [] nodesTraversed;
+    int nseen;
+
+    private Node getCommonAncestor(Node n1, Node n2) {
+        // assert n1.getTree() == n2.getTree();
+        if( ! nodesTraversed[n1.getNr()] ) {
+           nodesTraversed[n1.getNr()] = true;
+            nseen += 1;
+        }
+        if( ! nodesTraversed[n2.getNr()] ) {
+            nodesTraversed[n2.getNr()] = true;
+            nseen += 1;
+        }
+        while (n1 != n2) {
+            if (n1.getHeight() < n2.getHeight()) {
+                n1 = n1.getParent();
+                if( ! nodesTraversed[n1.getNr()] ) {
+                    nodesTraversed[n1.getNr()] = true;
+                    nseen += 1;
+                }
+            } else {
+                n2 = n2.getParent();
+                if( ! nodesTraversed[n2.getNr()] ) {
+                     nodesTraversed[n2.getNr()] = true;
+                     nseen += 1;
+                 }
+            }
+        }
+        return n1;
+    }
+
+    // A lightweight version for finding the most recent common ancestor of a group of taxa.
+    // return the node-ref of the MRCA.
+
+    // would be nice to use nodeRef's, but they are not preserved :(
+    public Node getCommonAncestor() {
+        Node cur = tree.getNode(taxonIndex[0]);
+
+        for (int k = 1; k < taxonIndex.length; ++k) {
+            cur = getCommonAncestor(cur, tree.getNode(taxonIndex[k]));
+        }
+        return cur;
+    }
+
     @Override
     public double calculateLogP() throws Exception {
+    	if (!initialised) {
+    		initialise();
+    	}
         logP = 0;
         if (onlyUseTips) {
             // tip date
@@ -130,7 +158,15 @@ public class MRCAPrior extends Distribution {
             return logP;
         } else {
             // internal node
-            calcMRCAtime(tree.getRoot(), new int[1]);
+            if( false) {
+                calcMRCAtime(tree.getRoot(), new int[1]);
+            } else {
+                nodesTraversed = new boolean[tree.getNodeCount()];
+                nseen = 0;
+                final Node m = getCommonAncestor();
+                MRCATime = m.getDate();
+                isMonophyletic = nseen == 2 * taxonIndex.length - 1;
+            }
         }
         if (isMonophyleticInput.get() && !isMonophyletic) {
             logP = Double.NEGATIVE_INFINITY;
@@ -142,7 +178,41 @@ public class MRCAPrior extends Distribution {
         return logP;
     }
 
-    /**
+    private void initialise() {
+        // determine which taxa are in the set
+    	
+        List<String> set = null;
+        if (taxonsetInput.get() != null) {
+            set = taxonsetInput.get().asStringList();
+        }
+        final List<String> sTaxaNames = new ArrayList<>();
+        for (final String sTaxon : tree.getTaxaNames()) {
+            sTaxaNames.add(sTaxon);
+        }
+
+        taxonIndex = new int[nrOfTaxa];
+        if ( set != null )  {  // m_taxonset.get() != null) {
+            isInTaxaSet.clear();
+            int k = 0;
+            for (final String sTaxon : set) {
+                final int iTaxon = sTaxaNames.indexOf(sTaxon);
+                if (iTaxon < 0) {
+                    throw new RuntimeException("Cannot find taxon " + sTaxon + " in data");
+                }
+                if (isInTaxaSet.contains(sTaxon)) {
+                    throw new RuntimeException("Taxon " + sTaxon + " is defined multiple times, while they should be unique");
+                }
+                isInTaxaSet.add(sTaxon);
+                taxonIndex[k++] = iTaxon;
+            }
+        } else {
+            for (int i = 0; i < nrOfTaxa; i++) {
+                taxonIndex[i] = i;
+            }
+        }
+ 	}
+
+	/**
      * Recursively visit all leaf nodes, and collect number of taxa in the taxon
      * set. When all taxa in the set are visited, record the time.
      * *
@@ -216,6 +286,9 @@ public class MRCAPrior extends Distribution {
      */
     @Override
     public void init(final PrintStream out) throws Exception {
+    	if (!initialised) {
+    		initialise();
+    	}
         if (onlyUseTips) {
             if (dist != null) {
                 out.print("logP(mrca(" + getID() + "))\t");
diff --git a/src/beast/math/statistic/RPNcalculator.java b/src/beast/math/statistic/RPNcalculator.java
index 3107179..2decd81 100644
--- a/src/beast/math/statistic/RPNcalculator.java
+++ b/src/beast/math/statistic/RPNcalculator.java
@@ -68,6 +68,19 @@ public class RPNcalculator extends CalculationNode implements Loggable, Function
             vars[i] = new RPNexpressionCalculator.GetVariable() {
                 public double get(final String name) {
                     final Object[] values = ((Object[]) variables.get(name));
+                    if (values == null) {
+                    	String ids = "";
+                        for (final Parameter p : parametersInput.get()) {
+                    		ids += p.getID() +", ";
+                    	}
+                    	if (parametersInput.get().size() > 0) {
+                    		ids = ids.substring(0, ids.length() - 2);
+                    	}
+                    	throw new RuntimeException("Something went wront with the RPNCalculator with id=" + getID() +".\n"
+                    			+ "There might be a typo on the expression.\n" +
+                    			"It should only contain these: " + ids +"\n"
+                    					+ "but contains " + name);
+                    }
                     if (values[0] instanceof Boolean)
                         return ((Boolean) values[values.length > 1 ? index : 0] ? 1. : 0.);
                     if (values[0] instanceof Integer)
diff --git a/src/beast/util/AddOnManager.java b/src/beast/util/AddOnManager.java
index ed2a965..962319c 100644
--- a/src/beast/util/AddOnManager.java
+++ b/src/beast/util/AddOnManager.java
@@ -32,11 +32,13 @@ package beast.util;
 
 
 import beast.app.BEASTVersion;
+import beast.app.beastapp.BeastMain;
 import beast.app.util.Arguments;
 import beast.app.util.Utils;
 import beast.core.Description;
 import beast.core.util.Log;
 import beast.evolution.alignment.Alignment;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -48,6 +50,7 @@ import javax.swing.*;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+
 import java.io.*;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -87,8 +90,8 @@ public class AddOnManager {
     public static final String NOT_INSTALLED = "un-installed";
     
     public static final String NO_CONNECTION_MESSAGE = "Could not get an internet connection. "
-    		+ "The BEAST Pacakage Manager needs internet access in order to list available packages and download them for installation. "
-    		+ "Possibly, some software (like security software, or a firewall) blocks the BEAST Pacakage Manager.  "
+    		+ "The BEAST Package Manager needs internet access in order to list available packages and download them for installation. "
+    		+ "Possibly, some software (like security software, or a firewall) blocks the BEAST Package Manager.  "
     		+ "If so, you need to reconfigure such software to allow access.";
     		
 
@@ -112,8 +115,10 @@ public class AddOnManager {
         // http://stackoverflow.com/questions/7615645/ssl-handshake-alert-unrecognized-name-error-since-upgrade-to-java-1-7-0
         System.setProperty("jsse.enableSNIExtension", "false");
 
-        List<String> URLs = new ArrayList<String>();
-        URLs.add(PACKAGES_XML);
+        List<String> URLs = new ArrayList<>();
+        // hack for v2.3.2 only -- to share repository file, saving lots of edits for package releases
+        // next version should have single package file to cover all version
+        URLs.add(PACKAGES_XML.replaceAll("2.3.2", "2.3.1"));
 
         File beastProps = new File(getPackageUserDir() + "/beauti.properties");
         // check beast.properties file exists in package directory
@@ -201,7 +206,7 @@ public class AddOnManager {
      */
     public static List<Package> getPackages() throws IOException, ParserConfigurationException, SAXException {
 
-        List<Package> packages = new ArrayList<Package>();
+        List<Package> packages = new ArrayList<>();
         List<String> sURLs = getPackagesURL();
 
         for (String sURL : sURLs) {
@@ -218,13 +223,7 @@ public class AddOnManager {
         }
         
         // Ensure package list is in alphabetical order
-        Collections.sort(packages, new Comparator<Package>() {
-
-            @Override
-            public int compare(Package p1, Package p2) {
-                return p1.packageName.toLowerCase().compareTo(p2.packageName.toLowerCase());
-            }
-        });
+        Collections.sort(packages, (p1, p2) -> p1.packageName.toLowerCase().compareTo(p2.packageName.toLowerCase()));
         
         return packages;
     }
@@ -355,7 +354,7 @@ public class AddOnManager {
             sDir = customDir + "/" + sName;
         }
         File dir = new File(sDir);
-        List<File> deleteFailed = new ArrayList<File>();
+        List<File> deleteFailed = new ArrayList<>();
         deleteRecursively(dir, deleteFailed);
 
         // write deleteFailed to file
@@ -384,7 +383,7 @@ public class AddOnManager {
 
     /** pretty format aPackage information in list of string form as produced by getAddOns() **/
     public static String formatPackageInfo(Package aPackage) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append(aPackage.packageName);
         if (aPackage.packageName.length() < 12) {
             buf.append("             ".substring(aPackage.packageName.length()));
@@ -505,6 +504,34 @@ public class AddOnManager {
     }
 
     /**
+     * Returns directory where BEAST installation resides, based on the location of the jar containing the
+     * BeastMain class file.  This assumes that the parent directory of the beast.jar is the base install
+     * directory.
+     *
+     * @return string representation of BEAST install directory or null if this directory cannot be identified.
+     */
+    public static String getBEASTInstallDir() {
+
+        // Allow users to explicitly set install directory - handy for programmers
+        if (System.getProperty("beast.install.dir") != null)
+            return System.getProperty("beast.install.dir");
+
+        URL u = BeastMain.class.getProtectionDomain().getCodeSource().getLocation();
+		String s = u.getPath();
+        File beastJar = new File(s);
+        Log.trace.println("BeastMain found in " + beastJar.getPath());
+        if (!beastJar.getName().toLowerCase().endsWith(".jar")) {
+        	return null;
+        }
+
+        if (beastJar.getParentFile() != null) {
+            return beastJar.getParentFile().getParent();
+        } else {
+            return null;
+        }
+    }
+
+    /**
      * @return file containing list of files that need to be deleted
      * but could not be deleted. This can happen when uninstalling packages
      * on windows, which locks jar files loaded by java.
@@ -534,9 +561,14 @@ public class AddOnManager {
 
         // add user package directory
         sDirs.add(getPackageUserDir());
+
         // add application package directory
         sDirs.add(getPackageSystemDir());
 
+        // add BEAST installation directory
+        if (getBEASTInstallDir() != null)
+            sDirs.add(getBEASTInstallDir());
+
         // pick up directories in class path, useful when running in an IDE
         String strClassPath = System.getProperty("java.class.path");
         String [] paths = strClassPath.split(":");
@@ -683,9 +715,9 @@ public class AddOnManager {
      * @param sDirs
      */
     private static void checkDependencies(List<String> sDirs) {
-        HashMap<String, Double> packageVersion = new HashMap<String, Double>();
+        HashMap<String, Double> packageVersion = new HashMap<>();
         packageVersion.put("beast2", beastVersion.parseVersion(beastVersion.getVersion()));
-        List<PackageDependency> dependencies = new ArrayList<PackageDependency>();
+        List<PackageDependency> dependencies = new ArrayList<>();
 
         // gather version and dependency info for all packages
         for (String sDir : sDirs) {
@@ -776,8 +808,8 @@ public class AddOnManager {
         // ClassLoader.getSystemClassLoader();
         URLClassLoader sysLoader = (URLClassLoader) clu.getClass().getClassLoader();
         URL urls[] = sysLoader.getURLs();
-        for (int i = 0; i < urls.length; i++) {
-            if (urls[i].toString().toLowerCase().equals(u.toString().toLowerCase())) {
+        for (URL url : urls) {
+            if (url.toString().toLowerCase().equals(u.toString().toLowerCase())) {
                 Log.debug.println("URL " + u + " is already in the CLASSPATH");
                 return;
             }
@@ -811,7 +843,7 @@ public class AddOnManager {
             }
         }
 
-        all_classes = new ArrayList<String>();
+        all_classes = new ArrayList<>();
         String pathSep = System.getProperty("path.separator");
         String classpath = System.getProperty("java.class.path");
 
@@ -956,7 +988,7 @@ public class AddOnManager {
         List<String> result;
         Class<?> cls;
 
-        result = new ArrayList<String>();
+        result = new ArrayList<>();
 
         try {
             cls = Class.forName(classname);
@@ -980,7 +1012,7 @@ public class AddOnManager {
         List<String> result;
         Class<?> cls;
 
-        result = new ArrayList<String>();
+        result = new ArrayList<>();
 
         try {
             cls = Class.forName(classname);
@@ -1006,9 +1038,9 @@ public class AddOnManager {
         int i;
         HashSet<String> names;
 
-        result = new ArrayList<String>();
+        result = new ArrayList<>();
 
-        names = new HashSet<String>();
+        names = new HashSet<>();
         for (i = 0; i < pkgnames.length; i++) {
             names.addAll(find(cls, pkgnames[i]));
         }
@@ -1033,7 +1065,7 @@ public class AddOnManager {
             loadAllClasses();
         }
 
-        List<String> result = new ArrayList<String>();
+        List<String> result = new ArrayList<>();
         for (int i = all_classes.size() - 1; i >= 0; i--) {
             String sClass = all_classes.get(i);
             sClass = sClass.replaceAll("/", ".");
diff --git a/src/beast/util/LogAnalyser.java b/src/beast/util/LogAnalyser.java
index dc999f0..0b9e34f 100644
--- a/src/beast/util/LogAnalyser.java
+++ b/src/beast/util/LogAnalyser.java
@@ -17,9 +17,6 @@ import static beast.util.OutputUtils.format;
 
 
 public class LogAnalyser {
-    // MAX_LAG typical = 2000; = maximum lag for ESS, TODO not used
-    protected final static int MAX_LAG = 2000;
-
     public static final int BURN_IN_PERCENTAGE = 10; // default
 
     protected final String sFile;
@@ -36,7 +33,6 @@ public class LogAnalyser {
         REAL, INTEGER, BOOL, NOMINAL
     }
 
-    ;
     protected type[] m_types;
     /**
      * range of a column, if it is not a REAL *
@@ -58,6 +54,11 @@ public class LogAnalyser {
      */
     protected String m_sPreAmble;
 
+    /**
+     * If set, analyzer works in "quiet" mode.
+     */
+    protected boolean quiet = false;
+
     final protected static String BAR = "|---------|---------|---------|---------|---------|---------|---------|---------|";
 
     public LogAnalyser() {
@@ -86,6 +87,13 @@ public class LogAnalyser {
         calcStats();
     }
 
+    public LogAnalyser(String sFile, int nBurnInPercentage, boolean quiet) throws Exception {
+        this.sFile = sFile;
+        this.quiet = quiet;
+        readLogFile(sFile, nBurnInPercentage);
+        calcStats();
+    }
+
     public LogAnalyser(String sFile) throws Exception {
         this(sFile, BURN_IN_PERCENTAGE);
     }
@@ -93,7 +101,7 @@ public class LogAnalyser {
     protected void readLogFile(String sFile, int nBurnInPercentage) throws Exception {
         log("\nLoading " + sFile);
         BufferedReader fin = new BufferedReader(new FileReader(sFile));
-        String sStr = null;
+        String sStr;
         m_sPreAmble = "";
         m_sLabels = null;
         int nData = 0;
@@ -135,7 +143,7 @@ public class LogAnalyser {
                             m_fTraces[i][nData] = Double.parseDouble(sStr2);
                         } catch (Exception e) {
                             if (m_ranges[i] == null) {
-                                m_ranges[i] = new ArrayList<String>();
+                                m_ranges[i] = new ArrayList<>();
                             }
                             if (!m_ranges[i].contains(sStr2)) {
                                 m_ranges[i].add(sStr2);
@@ -233,11 +241,8 @@ public class LogAnalyser {
                 m_fMedian[i] = Double.NaN;
                 m_f95HPDlow[i] = Double.NaN;
                 m_f95HPDup[i] = Double.NaN;
-                ;
                 m_fACT[i] = Double.NaN;
-                ;
                 m_fESS[i] = Double.NaN;
-                ;
                 m_fGeometricMean[i] = Double.NaN;
             }
             while (nStars < 80 * (i + 1) / nItems) {
@@ -443,12 +448,64 @@ public class LogAnalyser {
         }
     }
 
+    /**
+     * Display header used in one-line mode.
+     *
+     * @param out output stream
+     */
+    public void printOneLineHeader(PrintStream out) {
+
+        String[] postFix = {
+                "mean", "stderr", "stddev",
+                "median", "95%HPDlo", "95%HPDup",
+                "ACT", "ESS", "geometric-mean"
+        };
+
+        for (int paramIdx=1; paramIdx<m_sLabels.length; paramIdx++) {
+            for (int i=0; i<postFix.length; i++) {
+                if (paramIdx> 1 || i>0)
+                    out.print("\t");
+
+                out.print(m_sLabels[paramIdx] + "." + postFix[i]);
+            }
+        }
+
+        out.println();
+    }
+
+    /**
+     * Display results for single log on one line.
+     *
+     * @param out output stream
+     */
+    public void printOneLine(PrintStream out) {
+
+        for (int paramIdx=1; paramIdx<m_sLabels.length; paramIdx++) {
+            if (paramIdx>1)
+                out.print("\t");
+
+            out.print(m_fMean[paramIdx] + "\t");
+            out.print(m_fStdError[paramIdx] + "\t");
+            out.print(m_fStdDev[paramIdx] + "\t");
+            out.print(m_fMedian[paramIdx] + "\t");
+            out.print(m_f95HPDlow[paramIdx] + "\t");
+            out.print(m_f95HPDup[paramIdx] + "\t");
+            out.print(m_fACT[paramIdx] + "\t");
+            out.print(m_fESS[paramIdx] + "\t");
+            out.print(m_fGeometricMean[paramIdx]);
+        }
+
+        out.println();
+    }
+
     protected void log(String s) {
-        System.err.print(s);
+        if (!quiet)
+            System.err.print(s);
     }
 
     protected void logln(String s) {
-        System.err.println(s);
+        if (!quiet)
+            System.err.println(s);
     }
 
     static void printUsageAndExit() {
@@ -456,6 +513,10 @@ public class LogAnalyser {
     	System.out.println("-burnin <burninPercentage>");
     	System.out.println("--burnin <burninPercentage>");
     	System.out.println("-b <burninPercentage> percentage of log file to disregard, default " + BURN_IN_PERCENTAGE);
+        System.out.println("-oneline Display only one line of output per file.\n" +
+                "         Header is generated from the first file only.\n" +
+                "         (Implies quiet mode.)");
+        System.out.println("-quiet Quiet mode.  Avoid printing status updates to stderr.");
     	System.out.println("-help");
     	System.out.println("--help");
     	System.out.println("-h print this message");
@@ -471,11 +532,13 @@ public class LogAnalyser {
             LogAnalyser analyser;
             	// process args
             	int burninPercentage = BURN_IN_PERCENTAGE;
+                boolean oneLine = false;
+                boolean quiet = true;
             	List<String> files = new ArrayList<>();
             	int i = 0;
             	while (i < args.length) {
             		String arg = args[i];
-            		switch (arg) {
+                    switch (arg) {
             		case "-b":
             		case "-burnin":
             		case "--burnin":
@@ -486,6 +549,17 @@ public class LogAnalyser {
             			burninPercentage = Integer.parseInt(args[i+1]);
             			i += 2;
             			break;
+
+                    case "-oneline":
+                        oneLine = true;
+                        i += 1;
+                        break;
+
+                    case "-quiet":
+                        quiet = true;
+                        i += 1;
+                        break;
+
             		case "-h":
             		case "-help":
             		case "--help":
@@ -508,14 +582,26 @@ public class LogAnalyser {
 	                if (file == null) {
 	                    return;
 	                }
-	                analyser = new LogAnalyser(file.getAbsolutePath(), burninPercentage);
+	                analyser = new LogAnalyser(file.getAbsolutePath(), burninPercentage, quiet);
 	                analyser.print(System.out);
             	} else {
             		// process files
-            		for (String file : files) {
-    	                analyser = new LogAnalyser(file, burninPercentage);
-    	                analyser.print(System.out);
-            		}
+                    if (oneLine) {
+                        for (int idx=0; idx<files.size(); idx++) {
+                            analyser = new LogAnalyser(files.get(idx), burninPercentage, true);
+
+                            if (idx == 0)
+                                analyser.printOneLineHeader(System.out);
+
+                            analyser.printOneLine(System.out);
+                        }
+
+                    } else {
+                        for (String file : files) {
+                            analyser = new LogAnalyser(file, burninPercentage, quiet);
+                            analyser.print(System.out);
+                        }
+                    }
             }
         } catch (Exception e) {
             e.printStackTrace();
diff --git a/src/beast/util/TreeParser.java b/src/beast/util/TreeParser.java
index 3031f84..eba871d 100644
--- a/src/beast/util/TreeParser.java
+++ b/src/beast/util/TreeParser.java
@@ -28,6 +28,7 @@ import beast.core.Description;
 import beast.core.Input;
 import beast.core.StateNode;
 import beast.core.StateNodeInitialiser;
+import beast.core.util.Log;
 import beast.evolution.alignment.Alignment;
 import beast.evolution.alignment.TaxonSet;
 import beast.evolution.tree.Node;
@@ -42,6 +43,8 @@ import org.antlr.v4.runtime.misc.ParseCancellationException;
 import org.antlr.v4.runtime.tree.ParseTree;
 import java.text.DecimalFormat;
 import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 @Description("Create beast.tree by parsing from a specification of a beast.tree in Newick format " +
         "(includes parsing of any meta data in the Newick string).")
@@ -141,7 +144,14 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
             final Node dummy = new Node();
             setRoot(dummy);
         } else {
-            setRoot(parseNewick(newickInput.get()));
+            try {
+                setRoot(parseNewick(newickInput.get()));
+            } catch (ParseCancellationException e) {
+                throw new RuntimeException(
+                        "TreeParser cannot make sense of the Newick string " +
+                                "provided.  It gives the following clue:\n" +
+                                e.getMessage());
+            }
         }
 
         super.initAndValidate();
@@ -315,7 +325,6 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
      *
      * @param newick string to parse
      * @return root node of tree
-     * @throws Exception if anything goes wrong during the parse.
      */
     public Node parseNewick(String newick) {
         ANTLRInputStream input = new ANTLRInputStream(newick);
@@ -327,7 +336,7 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
                                     Object offendingSymbol,
                                     int line, int charPositionInLine,
                                     String msg, RecognitionException e) {
-                throw new RuntimeException("TreeParser: Error parsing character "
+                throw new ParseCancellationException("Error parsing character "
                         + charPositionInLine + " of Newick string: " + msg);
             }
         };
@@ -389,8 +398,6 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
      */
     class NewickASTVisitor extends NewickBaseVisitor<Node> {
 
-        private List<Exception> raisedExceptions = new ArrayList<>();
-
         private int numberedNodeCount = 0;
 
         @Override
@@ -423,7 +430,7 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
 
         @Override
         public Node visitNode(NewickParser.NodeContext ctx) {
-            Node node = new Node();
+            Node node = newNode();
 
             for (NewickParser.NodeContext ctxChild : ctx.node()) {
                 node.addChild(visit(ctxChild));
@@ -505,6 +512,9 @@ public class TreeParser extends Tree implements StateNodeInitialiser {
             if (node.getChildCount()==1 && !allowSingleChildInput.get())
                 throw new ParseCancellationException("Node with single child found.");
 
+            if (node.getChildCount()>2)
+                throw new ParseCancellationException("Node with two or more children found.");
+
             return node;
         }
 
diff --git a/src/beast/util/XMLProducer.java b/src/beast/util/XMLProducer.java
index 7192a97..a3cc5c4 100644
--- a/src/beast/util/XMLProducer.java
+++ b/src/beast/util/XMLProducer.java
@@ -818,7 +818,7 @@ public class XMLProducer extends XMLParser {
         buf.append("<").append(sElementName);
 
         boolean bSkipInputs = false;
-        if (isDone.contains(plugin)) {
+        if (isDone.stream().anyMatch(x -> x == plugin)) {
             // XML is already produced, we can idref it
             buf.append(" idref='" + normalise(plugin.getID()) + "'");
             bSkipInputs = true;
diff --git a/src/test/beast/util/TreeParserTest.java b/src/test/beast/util/TreeParserTest.java
index 886d62f..d2d1eb2 100644
--- a/src/test/beast/util/TreeParserTest.java
+++ b/src/test/beast/util/TreeParserTest.java
@@ -2,7 +2,6 @@ package test.beast.util;
 
 import beast.util.TreeParser;
 import junit.framework.TestCase;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
 import org.junit.Test;
 
 
@@ -99,7 +98,7 @@ public class TreeParserTest extends TestCase {
         try {
             boolean isLabeled = true;
             TreeParser treeParser = new TreeParser(newick, false, false, isLabeled, 1);
-        } catch (ParseCancellationException e) {
+        } catch (RuntimeException e) {
             e.printStackTrace();
             exceptionRaised = true;
         }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/beast2-mcmc.git



More information about the debian-med-commit mailing list